summaryrefslogtreecommitdiff
path: root/drivers/gpu
diff options
context:
space:
mode:
authorRodrigo Vivi <rodrigo.vivi@intel.com>2026-04-08 15:56:19 -0400
committerRodrigo Vivi <rodrigo.vivi@intel.com>2026-04-08 15:56:19 -0400
commitaf35e741e2f2dbef75500921e8fce17cf4f08fbd (patch)
tree155265a00862346154abd483cb51b3aab270b5c6 /drivers/gpu
parent5150b57dacf9563ab29661c8e8a37a73f5a9fc54 (diff)
parent4516432284e1b2ad9e70de8067f779c9c1072189 (diff)
Merge drm/drm-next into drm-xe-next
Sync drm-xe-next with drm-next to unblock some topic branches. Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/Kconfig7
-rw-r--r--drivers/gpu/drm/Kconfig.debug1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/Makefile2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu.h7
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v12_1.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c459
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.h4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c12
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c112
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c108
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.h8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_device.c34
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c72
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c18
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_eviction_fence.c237
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_eviction_fence.h55
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c44
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gart.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c98
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c39
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c48
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.h26
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_object.c3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c7
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_reg_access.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c131
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h9
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c11
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c110
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c606
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c9
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c188
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h19
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c12
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c16
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v12_1.c80
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v12_1_pkt.h223
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfxhub_v12_1.c193
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c78
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v12_1.c29
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c136
-rw-r--r--drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_2.c840
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_2.h111
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mes_userqueue.c16
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mes_v12_1.c392
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c46
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c17
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmhub_v3_0.c16
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_1.c17
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_2.c9
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmhub_v3_3.c55
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmhub_v4_1_0.c15
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmhub_v4_2_0.c194
-rw-r--r--drivers/gpu/drm/amd/amdgpu/psp_v11_0.c3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v7_1.c21
-rw-r--r--drivers/gpu/drm/amd/amdgpu/soc_v1_0.c69
-rw-r--r--drivers/gpu/drm/amd/amdgpu/soc_v1_0.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/umc_v12_0.c113
-rw-r--r--drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c19
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v5_0_2.c1219
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v5_0_2.h29
-rw-r--r--drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c6
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_chardev.c6
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_events.c12
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_events.h3
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_int_process_v10.c6
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_int_process_v11.c6
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_int_process_v12_1.c46
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c6
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_migrate.c2
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c23
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_priv.h6
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_process.c3
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c3
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_queue.c11
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_svm.c33
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/Makefile3
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c172
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h22
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c6
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c7
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h1
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c90
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h6
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c52
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.c598
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.h151
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c4
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c33
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h63
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c6
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c25
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.h17
-rw-r--r--drivers/gpu/drm/amd/display/dc/basics/dce_calcs.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/basics/vector.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/bios/bios_parser.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c9
-rw-r--r--drivers/gpu/drm/amd/display/dc/bios/command_table2.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c13
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c10
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c10
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c10
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.c292
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.h9
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc.c143
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_resource.c13
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_state.c77
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_stream.c43
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_surface.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc.h18
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c38
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h9
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_helper.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_hw_types.h6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_spl_translate.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_types.h8
-rw-r--r--drivers/gpu/drm/amd/display/dc/dccg/dcn31/dcn31_dccg.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dccg/dcn32/dcn32_dccg.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_abm.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_audio.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c10
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_i2c.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_i2c_sw.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c65
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_opp.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_transform.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dmub_abm_lcd.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c10
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c9
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c9
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dwb_scl.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn314/dcn314_dio_stream_encoder.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_stream_encoder.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_stream_encoder.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/virtual/virtual_link_encoder.c65
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/virtual/virtual_stream_encoder.c111
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calcs.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn10/dcn10_fpu.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c21
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c23
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c24
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c24
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn314/display_rq_dlg_calc_314.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c29
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c14
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/Makefile74
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_translation_helper.c39
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_utils.c15
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper.c380
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper.h30
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper_fpu.c381
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper_fpu.h60
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_soc_parameter_types.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.c54
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn4.c20
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn4.c9
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn42.c9
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml2_dc_resource_mgmt.c30
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml2_mall_phantom.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml2_translation_helper.c12
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml2_utils.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.c23
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper_fpu.c9
-rw-r--r--drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp_dscl.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp.c11
-rw-r--r--drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp_cm.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp_cm.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_cm.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dsc/dsc.h5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dwb/dcn30/dcn30_dwb.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_translate_dcn42.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubbub/dcn31/dcn31_hubbub.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubbub/dcn35/dcn35_hubbub.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubbub/dcn42/dcn42_hubbub.c65
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubp/dcn10/dcn10_hubp.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubp/dcn30/dcn30_hubp.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubp/dcn35/dcn35_hubp.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c10
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.c36
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.h6
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c40
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dce120/dce120_hwseq.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c23
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c13
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn303/dcn303_hwseq.c11
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c21
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c28
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.c33
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/core_types.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/transform.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c12
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c10
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn20/irq_service_dcn20.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn30/irq_service_dcn30.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn302/irq_service_dcn302.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn303/irq_service_dcn303.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn31/irq_service_dcn31.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn314/irq_service_dcn314.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn315/irq_service_dcn315.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn32/irq_service_dcn32.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn35/irq_service_dcn35.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn351/irq_service_dcn351.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn36/irq_service_dcn36.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn401/irq_service_dcn401.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn42/irq_service_dcn42.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dpia.c22
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_dp.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_virtual.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/link_detection.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/link_validation.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_128b_132b.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dpcd.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/mpc/dcn30/dcn30_mpc.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/mpc/dcn32/dcn32_mpc.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/opp/dcn10/dcn10_opp.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/optc/dcn30/dcn30_optc.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/pg/dcn42/dcn42_pg_cntl.c9
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c15
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dce110/dce110_resource.c11
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.c12
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dce120/dce120_resource.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dce60/dce60_resource.c14
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dce80/dce80_resource.c13
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.c55
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c69
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c44
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c70
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c50
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn301/dcn301_resource.c48
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c47
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c47
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c55
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c49
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c51
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c52
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c49
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource_helpers.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c46
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c61
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c61
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c52
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c43
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c39
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn42/dcn42_soc_and_ip_translator.c9
-rw-r--r--drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h2
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c20
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c1
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c23
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.c17
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c18
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.c22
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn42.c37
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn42.h136
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_reg.c4
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c8
-rw-r--r--drivers/gpu/drm/amd/display/modules/color/color_gamma.c2
-rw-r--r--drivers/gpu/drm/amd/display/modules/freesync/freesync.c6
-rw-r--r--drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h1
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_4_2_0_offset.h6
-rw-r--r--drivers/gpu/drm/amd/include/atomfirmware.h5
-rw-r--r--drivers/gpu/drm/amd/include/kgd_pp_interface.h67
-rw-r--r--drivers/gpu/drm/amd/pm/amdgpu_pm.c59
-rw-r--r--drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c4
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr.c15
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c123
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.h1
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.c83
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.h2
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h2
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c15
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c8
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h1
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu15_driver_if_v15_0_8.h295
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v15_0_8_pmfw.h427
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v15_0_8_ppsmc.h100
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h19
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/smu_v11_0.h14
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/smu_v12_0.h2
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h2
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h7
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/smu_v15_0.h57
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c5
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c3
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c21
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c25
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c76
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c3
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c2
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c37
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c2
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c45
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c35
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c2
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_5_ppt.c2
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c106
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c35
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c2
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c61
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c18
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c38
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu15/Makefile2
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0.c212
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_0_ppt.c3
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c2270
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.h313
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c35
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h2
-rw-r--r--drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.c31
-rw-r--r--drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.h1
-rw-r--r--drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_process.c10
-rw-r--r--drivers/gpu/drm/amd/ras/rascore/ras_core.c33
-rw-r--r--drivers/gpu/drm/amd/ras/rascore/ras_umc.c2
-rw-r--r--drivers/gpu/drm/arm/display/include/malidp_product.h1
-rw-r--r--drivers/gpu/drm/arm/display/komeda/d71/d71_component.c14
-rw-r--r--drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c1
-rw-r--r--drivers/gpu/drm/arm/display/komeda/komeda_crtc.c2
-rw-r--r--drivers/gpu/drm/arm/display/komeda/komeda_drv.c1
-rw-r--r--drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h5
-rw-r--r--drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c2
-rw-r--r--drivers/gpu/drm/arm/display/komeda/komeda_private_obj.c16
-rw-r--r--drivers/gpu/drm/ast/ast_dp501.c2
-rw-r--r--drivers/gpu/drm/bridge/Kconfig11
-rw-r--r--drivers/gpu/drm/bridge/Makefile1
-rw-r--r--drivers/gpu/drm/bridge/adv7511/adv7511_drv.c2
-rw-r--r--drivers/gpu/drm/bridge/analogix/analogix_dp_core.c135
-rw-r--r--drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c24
-rw-r--r--drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h2
-rw-r--r--drivers/gpu/drm/bridge/inno-hdmi.c6
-rw-r--r--drivers/gpu/drm/bridge/ite-it6263.c2
-rw-r--r--drivers/gpu/drm/bridge/lontium-lt8713sx.c598
-rw-r--r--drivers/gpu/drm/bridge/samsung-dsim.c7
-rw-r--r--drivers/gpu/drm/bridge/synopsys/dw-dp.c71
-rw-r--r--drivers/gpu/drm/bridge/synopsys/dw-hdmi.c16
-rw-r--r--drivers/gpu/drm/bridge/ti-sn65dsi83.c13
-rw-r--r--drivers/gpu/drm/bridge/waveshare-dsi.c8
-rw-r--r--drivers/gpu/drm/ci/arm64.config6
-rw-r--r--drivers/gpu/drm/ci/build.sh13
-rw-r--r--drivers/gpu/drm/ci/build.yml22
-rw-r--r--drivers/gpu/drm/ci/container.yml28
-rw-r--r--drivers/gpu/drm/ci/gitlab-ci.yml96
-rwxr-xr-xdrivers/gpu/drm/ci/igt_runner.sh6
-rw-r--r--drivers/gpu/drm/ci/image-tags.yml22
-rwxr-xr-xdrivers/gpu/drm/ci/lava-submit.sh101
-rw-r--r--drivers/gpu/drm/ci/static-checks.yml1
-rw-r--r--drivers/gpu/drm/ci/test.yml119
-rw-r--r--drivers/gpu/drm/ci/xfails/amdgpu-stoney-fails.txt13
-rw-r--r--drivers/gpu/drm/ci/xfails/amdgpu-stoney-flakes.txt7
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-amly-fails.txt27
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-apl-fails.txt24
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-cml-fails.txt37
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-cml-flakes.txt7
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-glk-fails.txt22
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-jsl-fails.txt27
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-kbl-fails.txt5
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-tgl-fails.txt5
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-tgl-flakes.txt6
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-whl-fails.txt13
-rw-r--r--drivers/gpu/drm/ci/xfails/mediatek-mt8173-fails.txt12
-rw-r--r--drivers/gpu/drm/ci/xfails/mediatek-mt8173-flakes.txt35
-rw-r--r--drivers/gpu/drm/ci/xfails/msm-apq8016-fails.txt4
-rw-r--r--drivers/gpu/drm/ci/xfails/msm-apq8096-fails.txt2
-rw-r--r--drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-fails.txt5
-rw-r--r--drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-fails.txt5
-rw-r--r--drivers/gpu/drm/ci/xfails/msm-sm8350-hdk-fails.txt1
-rw-r--r--drivers/gpu/drm/ci/xfails/panfrost-mt8183-fails.txt1
-rw-r--r--drivers/gpu/drm/ci/xfails/panfrost-rk3288-fails.txt1
-rw-r--r--drivers/gpu/drm/ci/xfails/panfrost-rk3399-fails.txt1
-rw-r--r--drivers/gpu/drm/ci/xfails/panthor-rk3588-fails.txt5
-rw-r--r--drivers/gpu/drm/ci/xfails/panthor-rk3588-skips.txt20
-rw-r--r--drivers/gpu/drm/ci/xfails/rockchip-rk3288-fails.txt15
-rw-r--r--drivers/gpu/drm/ci/xfails/rockchip-rk3288-flakes.txt21
-rw-r--r--drivers/gpu/drm/ci/xfails/rockchip-rk3399-fails.txt12
-rw-r--r--drivers/gpu/drm/ci/xfails/rockchip-rk3399-flakes.txt35
-rw-r--r--drivers/gpu/drm/ci/xfails/rockchip-rk3588-fails.txt9
-rw-r--r--drivers/gpu/drm/ci/xfails/rockchip-rk3588-skips.txt14
-rw-r--r--drivers/gpu/drm/ci/xfails/virtio_gpu-none-fails.txt66
-rw-r--r--drivers/gpu/drm/ci/xfails/vkms-none-fails.txt2
-rw-r--r--drivers/gpu/drm/display/drm_bridge_connector.c4
-rw-r--r--drivers/gpu/drm/display/drm_dp_mst_topology.c1
-rw-r--r--drivers/gpu/drm/display/drm_dp_tunnel.c2
-rw-r--r--drivers/gpu/drm/display/drm_hdmi_helper.c7
-rw-r--r--drivers/gpu/drm/display/drm_hdmi_state_helper.c60
-rw-r--r--drivers/gpu/drm/drm_atomic.c30
-rw-r--r--drivers/gpu/drm/drm_atomic_state_helper.c1
-rw-r--r--drivers/gpu/drm/drm_atomic_uapi.c4
-rw-r--r--drivers/gpu/drm/drm_blend.c39
-rw-r--r--drivers/gpu/drm/drm_bridge.c53
-rw-r--r--drivers/gpu/drm/drm_colorop.c28
-rw-r--r--drivers/gpu/drm/drm_connector.c16
-rw-r--r--drivers/gpu/drm/drm_crtc.c6
-rw-r--r--drivers/gpu/drm/drm_drv.c2
-rw-r--r--drivers/gpu/drm/drm_edid.c18
-rw-r--r--drivers/gpu/drm/drm_gem.c11
-rw-r--r--drivers/gpu/drm/drm_gem_atomic_helper.c22
-rw-r--r--drivers/gpu/drm/drm_gem_dma_helper.c23
-rw-r--r--drivers/gpu/drm/drm_gem_shmem_helper.c45
-rw-r--r--drivers/gpu/drm/drm_ioc32.c2
-rw-r--r--drivers/gpu/drm/drm_mipi_dbi.c376
-rw-r--r--drivers/gpu/drm/drm_mode_config.c6
-rw-r--r--drivers/gpu/drm/drm_modeset_helper.c3
-rw-r--r--drivers/gpu/drm/drm_pagemap_util.c14
-rw-r--r--drivers/gpu/drm/drm_prime.c2
-rw-r--r--drivers/gpu/drm/drm_simple_kms_helper.c83
-rw-r--r--drivers/gpu/drm/drm_syncobj.c4
-rw-r--r--drivers/gpu/drm/gud/gud_drv.c9
-rw-r--r--drivers/gpu/drm/gud/gud_internal.h4
-rw-r--r--drivers/gpu/drm/gud/gud_pipe.c54
-rw-r--r--drivers/gpu/drm/i915/Makefile1
-rw-r--r--drivers/gpu/drm/i915/display/g4x_dp.c2
-rw-r--r--drivers/gpu/drm/i915/display/icl_dsi.c21
-rw-r--r--drivers/gpu/drm/i915/display/icl_dsi_regs.h3
-rw-r--r--drivers/gpu/drm/i915/display/intel_cdclk.c54
-rw-r--r--drivers/gpu/drm/i915/display/intel_cx0_phy.c10
-rw-r--r--drivers/gpu/drm/i915/display/intel_cx0_phy.h1
-rw-r--r--drivers/gpu/drm/i915/display/intel_ddi.c26
-rw-r--r--drivers/gpu/drm/i915/display/intel_de.c178
-rw-r--r--drivers/gpu/drm/i915/display/intel_de.h121
-rw-r--r--drivers/gpu/drm/i915/display/intel_display.c43
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_device.c28
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_device.h1
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_types.h4
-rw-r--r--drivers/gpu/drm/i915/display/intel_dmc.c19
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c32
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_tunnel.c20
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_tunnel.h11
-rw-r--r--drivers/gpu/drm/i915/display/intel_dpll.c26
-rw-r--r--drivers/gpu/drm/i915/display/intel_dpll_mgr.c186
-rw-r--r--drivers/gpu/drm/i915/display/intel_dpll_mgr.h1
-rw-r--r--drivers/gpu/drm/i915/display/intel_dsi.h7
-rw-r--r--drivers/gpu/drm/i915/display/intel_dsi_vbt.c12
-rw-r--r--drivers/gpu/drm/i915/display/intel_gmbus.c6
-rw-r--r--drivers/gpu/drm/i915/display/intel_lt_phy.c193
-rw-r--r--drivers/gpu/drm/i915/display/intel_lt_phy.h23
-rw-r--r--drivers/gpu/drm/i915/display/intel_modeset_verify.c1
-rw-r--r--drivers/gpu/drm/i915/display/intel_pch.c93
-rw-r--r--drivers/gpu/drm/i915/display/intel_pch.h1
-rw-r--r--drivers/gpu/drm/i915/display/intel_plane.c61
-rw-r--r--drivers/gpu/drm/i915/display/intel_psr.c15
-rw-r--r--drivers/gpu/drm/i915/display/intel_quirks.c25
-rw-r--r--drivers/gpu/drm/i915/display/intel_quirks.h1
-rw-r--r--drivers/gpu/drm/i915/display/skl_watermark.c160
-rw-r--r--drivers/gpu/drm/i915/display/vlv_dsi.c2
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c2
-rw-r--r--drivers/gpu/drm/i915/gvt/edid.c18
-rw-r--r--drivers/gpu/drm/i915/i915_initial_plane.c3
-rw-r--r--drivers/gpu/drm/i915/i915_wait_util.h2
-rw-r--r--drivers/gpu/drm/i915/intel_clock_gating.c86
-rw-r--r--drivers/gpu/drm/i915/intel_step.h57
-rw-r--r--drivers/gpu/drm/i915/intel_uncore.c72
-rw-r--r--drivers/gpu/drm/i915/selftests/intel_uncore.c62
-rw-r--r--drivers/gpu/drm/imagination/Makefile1
-rw-r--r--drivers/gpu/drm/imagination/pvr_ccb.c5
-rw-r--r--drivers/gpu/drm/imagination/pvr_device.c17
-rw-r--r--drivers/gpu/drm/imagination/pvr_dump.c113
-rw-r--r--drivers/gpu/drm/imagination/pvr_dump.h17
-rw-r--r--drivers/gpu/drm/imagination/pvr_fw_startstop.c100
-rw-r--r--drivers/gpu/drm/imagination/pvr_power.c51
-rw-r--r--drivers/gpu/drm/imagination/pvr_rogue_fwif.h8
-rw-r--r--drivers/gpu/drm/imagination/pvr_rogue_fwif_shared.h18
-rw-r--r--drivers/gpu/drm/imx/ipuv3/Kconfig1
-rw-r--r--drivers/gpu/drm/imx/ipuv3/ipuv3-plane.c23
-rw-r--r--drivers/gpu/drm/imx/ipuv3/parallel-display.c15
-rw-r--r--drivers/gpu/drm/ingenic/ingenic-drm-drv.c2
-rw-r--r--drivers/gpu/drm/ingenic/ingenic-ipu.c2
-rw-r--r--drivers/gpu/drm/mediatek/Makefile1
-rw-r--r--drivers/gpu/drm/mediatek/mtk_crtc.c1
-rw-r--r--drivers/gpu/drm/mediatek/mtk_disp_ovl.c12
-rw-r--r--drivers/gpu/drm/mediatek/mtk_dp.c4
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_drv.c26
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_drv.h1
-rw-r--r--drivers/gpu/drm/mediatek/mtk_dsi.c44
-rw-r--r--drivers/gpu/drm/mediatek/mtk_gem.c231
-rw-r--r--drivers/gpu/drm/mediatek/mtk_gem.h17
-rw-r--r--drivers/gpu/drm/mediatek/mtk_hdmi_v2.c8
-rw-r--r--drivers/gpu/drm/meson/meson_dw_mipi_dsi.c6
-rw-r--r--drivers/gpu/drm/msm/Makefile1
-rw-r--r--drivers/gpu/drm/msm/adreno/a2xx_gpummu.c2
-rw-r--r--drivers/gpu/drm/msm/adreno/a4xx_gpu.c6
-rw-r--r--drivers/gpu/drm/msm/adreno/a5xx_gpu.c12
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_catalog.c246
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gmu.c140
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gmu.h9
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gpu.c170
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gpu.h7
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c20
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_hfi.c33
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_hfi.h155
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_preempt.c77
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_preempt.h82
-rw-r--r--drivers/gpu/drm/msm/adreno/a8xx_gpu.c186
-rw-r--r--drivers/gpu/drm/msm/adreno/a8xx_preempt.c259
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_device.c1
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.c19
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.h13
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_10_0_sm8650.h6
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_0_sm8750.h6
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_2_glymur.h10
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_4_eliza.h363
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_13_0_kaanapali.h6
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_14_msm8937.h3
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_15_msm8917.h3
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_16_msm8953.h10
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_7_msm8996.h3
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h3
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_2_sdm660.h3
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_3_sdm630.h3
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h5
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_1_sdm670.h3
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h6
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h4
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_2_sm7150.h6
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_3_sm6150.h6
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_4_sm6125.h4
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h6
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_2_sc7180.h4
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_3_sm6115.h3
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_4_sm6350.h4
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_5_qcm2290.h3
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_9_sm6375.h3
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_0_sm8350.h6
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h4
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h28
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h18
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_4_sa8775p.h17
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h18
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_1_sar2130p.h18
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h23
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c57
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h2
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c6
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c2
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c7
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c36
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h9
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c2
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c26
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h1
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c21
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h2
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h6
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp_v13.c4
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c3
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h1
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c76
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h4
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c303
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c52
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h19
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c163
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.h4
-rw-r--r--drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c94
-rw-r--r--drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.c90
-rw-r--r--drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.h1
-rw-r--r--drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c1
-rw-r--r--drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c8
-rw-r--r--drivers/gpu/drm/msm/dp/dp_ctrl.c18
-rw-r--r--drivers/gpu/drm/msm/dp/dp_display.c1
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi.c1
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_cfg.c4
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_cfg.h2
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_host.c85
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy.c1
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c38
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi.c35
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi.h6
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_audio.c5
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_bridge.c8
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_hpd.c4
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_i2c.c12
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_phy.c3
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c2
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_phy_8x60.c2
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_phy_8x74.c2
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c7
-rw-r--r--drivers/gpu/drm/msm/msm_fb.c7
-rw-r--r--drivers/gpu/drm/msm/msm_gem.c3
-rw-r--r--drivers/gpu/drm/msm/msm_gem.h1
-rw-r--r--drivers/gpu/drm/msm/msm_gem_shrinker.c5
-rw-r--r--drivers/gpu/drm/msm/msm_gem_submit.c4
-rw-r--r--drivers/gpu/drm/msm/msm_gem_vma.c17
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.c53
-rw-r--r--drivers/gpu/drm/msm/msm_mdss.c9
-rw-r--r--drivers/gpu/drm/msm/registers/adreno/a6xx.xml4
-rw-r--r--drivers/gpu/drm/msm/registers/adreno/a6xx_gmu.xml6
-rw-r--r--drivers/gpu/drm/msm/registers/display/dsi.xml5
-rw-r--r--drivers/gpu/drm/nova/gem.rs5
-rw-r--r--drivers/gpu/drm/omapdrm/omap_drv.c22
-rw-r--r--drivers/gpu/drm/panel/Kconfig46
-rw-r--r--drivers/gpu/drm/panel/Makefile6
-rw-r--r--drivers/gpu/drm/panel/panel-edp.c3
-rw-r--r--drivers/gpu/drm/panel/panel-himax-hx83102.c151
-rw-r--r--drivers/gpu/drm/panel/panel-himax-hx83121a.c749
-rw-r--r--drivers/gpu/drm/panel/panel-ilitek-ili9806e-core.c134
-rw-r--r--drivers/gpu/drm/panel/panel-ilitek-ili9806e-core.h15
-rw-r--r--drivers/gpu/drm/panel/panel-ilitek-ili9806e-dsi.c (renamed from drivers/gpu/drm/panel/panel-ilitek-ili9806e.c)153
-rw-r--r--drivers/gpu/drm/panel/panel-ilitek-ili9806e-spi.c323
-rw-r--r--drivers/gpu/drm/panel/panel-novatek-nt36672a.c94
-rw-r--r--drivers/gpu/drm/panel/panel-samsung-s6e8fc0-m1906f9.c301
-rw-r--r--drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c1
-rw-r--r--drivers/gpu/drm/panel/panel-simple.c37
-rw-r--r--drivers/gpu/drm/panthor/panthor_drv.c134
-rw-r--r--drivers/gpu/drm/panthor/panthor_fw.c4
-rw-r--r--drivers/gpu/drm/radeon/si_dpm.c4
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rcar_cmm.c26
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rcar_cmm.h18
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rcar_du_crtc.c16
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rcar_du_crtc.h3
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rcar_du_drv.h8
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rcar_du_kms.c52
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rcar_du_vsp.c16
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rcar_du_vsp.h2
-rw-r--r--drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c3
-rw-r--r--drivers/gpu/drm/rockchip/analogix_dp-rockchip.c4
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_vop2.c24
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_vop2.h4
-rw-r--r--drivers/gpu/drm/sitronix/st7586.c198
-rw-r--r--drivers/gpu/drm/sitronix/st7735r.c142
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_backend.c30
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c2
-rw-r--r--drivers/gpu/drm/sun4i/sun8i_mixer.c27
-rw-r--r--drivers/gpu/drm/sun4i/sun8i_ui_layer.c16
-rw-r--r--drivers/gpu/drm/sun4i/sun8i_vi_layer.c27
-rw-r--r--drivers/gpu/drm/sysfb/efidrm.c46
-rw-r--r--drivers/gpu/drm/tegra/hub.c22
-rw-r--r--drivers/gpu/drm/tests/drm_connector_test.c80
-rw-r--r--drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c182
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_panel.c408
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_panel_legacy.c4
-rw-r--r--drivers/gpu/drm/tiny/hx8357d.c138
-rw-r--r--drivers/gpu/drm/tiny/ili9163.c138
-rw-r--r--drivers/gpu/drm/tiny/ili9225.c192
-rw-r--r--drivers/gpu/drm/tiny/ili9341.c138
-rw-r--r--drivers/gpu/drm/tiny/ili9486.c139
-rw-r--r--drivers/gpu/drm/tiny/mi0283qt.c138
-rw-r--r--drivers/gpu/drm/tiny/panel-mipi-dbi.c141
-rw-r--r--drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c41
-rw-r--r--drivers/gpu/drm/ttm/tests/ttm_device_test.c2
-rw-r--r--drivers/gpu/drm/ttm/tests/ttm_pool_test.c32
-rw-r--r--drivers/gpu/drm/ttm/ttm_backup.c6
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo.c6
-rw-r--r--drivers/gpu/drm/ttm/ttm_pool.c217
-rw-r--r--drivers/gpu/drm/tyr/driver.rs100
-rw-r--r--drivers/gpu/drm/tyr/file.rs36
-rw-r--r--drivers/gpu/drm/tyr/gem.rs18
-rw-r--r--drivers/gpu/drm/tyr/gpu.rs58
-rw-r--r--drivers/gpu/drm/tyr/regs.rs16
-rw-r--r--drivers/gpu/drm/tyr/tyr.rs4
-rw-r--r--drivers/gpu/drm/v3d/v3d_drv.c55
-rw-r--r--drivers/gpu/drm/v3d/v3d_drv.h46
-rw-r--r--drivers/gpu/drm/v3d/v3d_fence.c2
-rw-r--r--drivers/gpu/drm/v3d/v3d_gem.c43
-rw-r--r--drivers/gpu/drm/v3d/v3d_irq.c2
-rw-r--r--drivers/gpu/drm/v3d/v3d_sched.c133
-rw-r--r--drivers/gpu/drm/v3d/v3d_submit.c6
-rw-r--r--drivers/gpu/drm/v3d/v3d_sysfs.c2
-rw-r--r--drivers/gpu/drm/vc4/vc4_hdmi.c18
-rw-r--r--drivers/gpu/drm/vc4/vc4_hdmi.h2
-rw-r--r--drivers/gpu/drm/vc4/vc4_kms.c4
-rw-r--r--drivers/gpu/drm/verisilicon/vs_dc.c2
-rw-r--r--drivers/gpu/drm/vkms/vkms_composer.c10
-rw-r--r--drivers/gpu/drm/vkms/vkms_crtc.c3
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.h93
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c3
-rw-r--r--drivers/gpu/drm/xe/Makefile1
-rw-r--r--drivers/gpu/drm/xe/compat-i915-headers/intel_step.h3
-rw-r--r--drivers/gpu/drm/xe/compat-i915-headers/intel_uncore.h31
-rw-r--r--drivers/gpu/drm/xe/xe_device.c9
-rw-r--r--drivers/gpu/nova-core/Kconfig2
-rw-r--r--drivers/gpu/nova-core/dma.rs54
-rw-r--r--drivers/gpu/nova-core/driver.rs17
-rw-r--r--drivers/gpu/nova-core/falcon.rs789
-rw-r--r--drivers/gpu/nova-core/falcon/gsp.rs27
-rw-r--r--drivers/gpu/nova-core/falcon/hal.rs6
-rw-r--r--drivers/gpu/nova-core/falcon/hal/ga102.rs70
-rw-r--r--drivers/gpu/nova-core/falcon/hal/tu102.rs12
-rw-r--r--drivers/gpu/nova-core/falcon/sec2.rs17
-rw-r--r--drivers/gpu/nova-core/fb.rs101
-rw-r--r--drivers/gpu/nova-core/fb/hal/ga100.rs37
-rw-r--r--drivers/gpu/nova-core/fb/hal/ga102.rs7
-rw-r--r--drivers/gpu/nova-core/fb/hal/tu102.rs17
-rw-r--r--drivers/gpu/nova-core/firmware.rs194
-rw-r--r--drivers/gpu/nova-core/firmware/booter.rs87
-rw-r--r--drivers/gpu/nova-core/firmware/fwsec.rs181
-rw-r--r--drivers/gpu/nova-core/firmware/fwsec/bootloader.rs350
-rw-r--r--drivers/gpu/nova-core/firmware/gsp.rs118
-rw-r--r--drivers/gpu/nova-core/firmware/riscv.rs10
-rw-r--r--drivers/gpu/nova-core/gfw.rs11
-rw-r--r--drivers/gpu/nova-core/gpu.rs66
-rw-r--r--drivers/gpu/nova-core/gsp.rs144
-rw-r--r--drivers/gpu/nova-core/gsp/boot.rs82
-rw-r--r--drivers/gpu/nova-core/gsp/cmdq.rs482
-rw-r--r--drivers/gpu/nova-core/gsp/cmdq/continuation.rs307
-rw-r--r--drivers/gpu/nova-core/gsp/commands.rs23
-rw-r--r--drivers/gpu/nova-core/gsp/fw.rs348
-rw-r--r--drivers/gpu/nova-core/gsp/fw/commands.rs17
-rw-r--r--drivers/gpu/nova-core/gsp/fw/r570_144/bindings.rs1
-rw-r--r--drivers/gpu/nova-core/gsp/sequencer.rs22
-rw-r--r--drivers/gpu/nova-core/nova_core.rs54
-rw-r--r--drivers/gpu/nova-core/num.rs80
-rw-r--r--drivers/gpu/nova-core/regs.rs549
-rw-r--r--drivers/gpu/nova-core/regs/macros.rs739
811 files changed, 25662 insertions, 10657 deletions
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 5386248e75b6..8f5a8d3012e4 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -268,6 +268,13 @@ config DRM_GEM_SHMEM_HELPER
help
Choose this if you need the GEM shmem helper functions
+config RUST_DRM_GEM_SHMEM_HELPER
+ bool
+ depends on DRM && MMU
+ select DRM_GEM_SHMEM_HELPER
+ help
+ Choose this if you need the GEM shmem helper functions In Rust
+
config DRM_SUBALLOC_HELPER
tristate
depends on DRM
diff --git a/drivers/gpu/drm/Kconfig.debug b/drivers/gpu/drm/Kconfig.debug
index 3b7886865335..1f4c98cbf090 100644
--- a/drivers/gpu/drm/Kconfig.debug
+++ b/drivers/gpu/drm/Kconfig.debug
@@ -85,7 +85,6 @@ config DRM_KUNIT_TEST
config DRM_TTM_KUNIT_TEST
tristate "KUnit tests for TTM" if !KUNIT_ALL_TESTS
- default n
depends on DRM && KUNIT && MMU && (UML || COMPILE_TEST)
select DRM_TTM
select DRM_BUDDY
diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile
index 9c9c73b73ac8..6a7e9bfec59e 100644
--- a/drivers/gpu/drm/amd/amdgpu/Makefile
+++ b/drivers/gpu/drm/amd/amdgpu/Makefile
@@ -213,6 +213,7 @@ amdgpu-y += \
vcn_v4_0_5.o \
vcn_v5_0_0.o \
vcn_v5_0_1.o \
+ vcn_v5_0_2.o \
amdgpu_jpeg.o \
jpeg_v1_0.o \
jpeg_v2_0.o \
@@ -223,6 +224,7 @@ amdgpu-y += \
jpeg_v4_0_5.o \
jpeg_v5_0_0.o \
jpeg_v5_0_1.o \
+ jpeg_v5_0_2.o \
jpeg_v5_3_0.o
# add VPE block
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 59731014a55a..49e7881750fa 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -327,6 +327,7 @@ struct kfd_vm_fault_info;
struct amdgpu_hive_info;
struct amdgpu_reset_context;
struct amdgpu_reset_control;
+struct amdgpu_coredump_info;
enum amdgpu_cp_irq {
AMDGPU_CP_IRQ_GFX_ME0_PIPE0_EOP = 0,
@@ -689,6 +690,7 @@ enum amdgpu_uid_type {
AMDGPU_UID_TYPE_XCD,
AMDGPU_UID_TYPE_AID,
AMDGPU_UID_TYPE_SOC,
+ AMDGPU_UID_TYPE_MID,
AMDGPU_UID_TYPE_MAX
};
@@ -1147,6 +1149,11 @@ struct amdgpu_device {
struct amdgpu_reset_domain *reset_domain;
+#ifdef CONFIG_DEV_COREDUMP
+ struct amdgpu_coredump_info *coredump;
+ struct work_struct coredump_work;
+#endif
+
struct mutex benchmark_mutex;
bool scpm_enabled;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
index 40c22438b1d2..4f27c75abedb 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
@@ -692,9 +692,9 @@ int amdgpu_amdkfd_submit_ib(struct amdgpu_device *adev,
goto err_ib_sched;
}
- /* Drop the initial kref_init count (see drm_sched_main as example) */
- dma_fence_put(f);
ret = dma_fence_wait(f, false);
+ /* Drop the returned fence reference after the wait completes */
+ dma_fence_put(f);
err_ib_sched:
amdgpu_job_free(job);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v12_1.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v12_1.c
index 965c7e688535..bcb180f9d3ff 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v12_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v12_1.c
@@ -330,7 +330,7 @@ static uint32_t kgd_gfx_v12_1_set_address_watch(struct amdgpu_device *adev,
watch_address_cntl = 0;
watch_address_low = lower_32_bits(watch_address);
- watch_address_high = upper_32_bits(watch_address) & 0xffff;
+ watch_address_high = upper_32_bits(watch_address) & 0x1ffffff;
watch_address_cntl = REG_SET_FIELD(watch_address_cntl,
TCP_WATCH0_CNTL,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c
index 7f4751e5caaf..cd9aa5b45e94 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c
@@ -373,249 +373,280 @@ int amdgpu_atomfirmware_get_uma_carveout_info(struct amdgpu_device *adev,
return -ENODEV;
}
-int
-amdgpu_atomfirmware_get_vram_info(struct amdgpu_device *adev,
+int amdgpu_atomfirmware_get_integrated_system_info(struct amdgpu_device *adev,
int *vram_width, int *vram_type,
int *vram_vendor)
{
struct amdgpu_mode_info *mode_info = &adev->mode_info;
- int index, i = 0;
+ int index;
u16 data_offset, size;
union igp_info *igp_info;
- union vram_info *vram_info;
- union umc_info *umc_info;
- union vram_module *vram_module;
u8 frev, crev;
u8 mem_type;
- u8 mem_vendor;
u32 mem_channel_number;
u32 mem_channel_width;
- u32 module_id;
- if (adev->flags & AMD_IS_APU)
- index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
+ index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
integratedsysteminfo);
- else {
- switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
- case IP_VERSION(12, 0, 0):
- case IP_VERSION(12, 0, 1):
- index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, umc_info);
+ if (amdgpu_atom_parse_data_header(mode_info->atom_context,
+ index, &size,
+ &frev, &crev, &data_offset)) {
+ igp_info = (union igp_info *)
+ (mode_info->atom_context->bios + data_offset);
+ switch (frev) {
+ case 1:
+ switch (crev) {
+ case 11:
+ case 12:
+ mem_channel_number = igp_info->v11.umachannelnumber;
+ if (!mem_channel_number)
+ mem_channel_number = 1;
+ mem_type = igp_info->v11.memorytype;
+ if (mem_type == LpDdr5MemType)
+ mem_channel_width = 32;
+ else
+ mem_channel_width = 64;
+ if (vram_width)
+ *vram_width = mem_channel_number * mem_channel_width;
+ if (vram_type)
+ *vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ case 2:
+ switch (crev) {
+ case 1:
+ case 2:
+ mem_channel_number = igp_info->v21.umachannelnumber;
+ if (!mem_channel_number)
+ mem_channel_number = 1;
+ mem_type = igp_info->v21.memorytype;
+ if (mem_type == LpDdr5MemType)
+ mem_channel_width = 32;
+ else
+ mem_channel_width = 64;
+ if (vram_width)
+ *vram_width = mem_channel_number * mem_channel_width;
+ if (vram_type)
+ *vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
+ break;
+ case 3:
+ mem_channel_number = igp_info->v23.umachannelnumber;
+ if (!mem_channel_number)
+ mem_channel_number = 1;
+ mem_type = igp_info->v23.memorytype;
+ if (mem_type == LpDdr5MemType)
+ mem_channel_width = 32;
+ else
+ mem_channel_width = 64;
+ if (vram_width)
+ *vram_width = mem_channel_number * mem_channel_width;
+ if (vram_type)
+ *vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
+ break;
+ default:
+ return -EINVAL;
+ }
break;
default:
- index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, vram_info);
+ return -EINVAL;
}
+ } else {
+ return -EINVAL;
}
+ return 0;
+}
+
+int amdgpu_atomfirmware_get_umc_info(struct amdgpu_device *adev,
+ int *vram_width, int *vram_type,
+ int *vram_vendor)
+{
+ struct amdgpu_mode_info *mode_info = &adev->mode_info;
+ int index;
+ u16 data_offset, size;
+ union umc_info *umc_info;
+ u8 frev, crev;
+ u8 mem_type;
+ u8 mem_vendor;
+ u32 mem_channel_number;
+ u32 mem_channel_width;
+
+ index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, umc_info);
+
if (amdgpu_atom_parse_data_header(mode_info->atom_context,
index, &size,
&frev, &crev, &data_offset)) {
- if (adev->flags & AMD_IS_APU) {
- igp_info = (union igp_info *)
- (mode_info->atom_context->bios + data_offset);
- switch (frev) {
- case 1:
- switch (crev) {
- case 11:
- case 12:
- mem_channel_number = igp_info->v11.umachannelnumber;
- if (!mem_channel_number)
- mem_channel_number = 1;
- mem_type = igp_info->v11.memorytype;
- if (mem_type == LpDdr5MemType)
- mem_channel_width = 32;
- else
- mem_channel_width = 64;
- if (vram_width)
- *vram_width = mem_channel_number * mem_channel_width;
- if (vram_type)
- *vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
- break;
- default:
- return -EINVAL;
- }
- break;
- case 2:
- switch (crev) {
- case 1:
- case 2:
- mem_channel_number = igp_info->v21.umachannelnumber;
- if (!mem_channel_number)
- mem_channel_number = 1;
- mem_type = igp_info->v21.memorytype;
- if (mem_type == LpDdr5MemType)
- mem_channel_width = 32;
- else
- mem_channel_width = 64;
- if (vram_width)
- *vram_width = mem_channel_number * mem_channel_width;
- if (vram_type)
- *vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
- break;
- case 3:
- mem_channel_number = igp_info->v23.umachannelnumber;
- if (!mem_channel_number)
- mem_channel_number = 1;
- mem_type = igp_info->v23.memorytype;
- if (mem_type == LpDdr5MemType)
- mem_channel_width = 32;
- else
- mem_channel_width = 64;
- if (vram_width)
- *vram_width = mem_channel_number * mem_channel_width;
- if (vram_type)
- *vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
- break;
- default:
- return -EINVAL;
- }
+ umc_info = (union umc_info *)(mode_info->atom_context->bios + data_offset);
+
+ if (frev == 4) {
+ switch (crev) {
+ case 0:
+ mem_channel_number = le32_to_cpu(umc_info->v40.channel_num);
+ mem_type = le32_to_cpu(umc_info->v40.vram_type);
+ mem_channel_width = le32_to_cpu(umc_info->v40.channel_width);
+ mem_vendor = RREG32(adev->bios_scratch_reg_offset + 4) & 0xF;
+ if (vram_vendor)
+ *vram_vendor = mem_vendor;
+ if (vram_type)
+ *vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
+ if (vram_width)
+ *vram_width = mem_channel_number * (1 << mem_channel_width);
break;
default:
return -EINVAL;
}
} else {
- switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
- case IP_VERSION(12, 0, 0):
- case IP_VERSION(12, 0, 1):
- umc_info = (union umc_info *)(mode_info->atom_context->bios + data_offset);
-
- if (frev == 4) {
- switch (crev) {
- case 0:
- mem_channel_number = le32_to_cpu(umc_info->v40.channel_num);
- mem_type = le32_to_cpu(umc_info->v40.vram_type);
- mem_channel_width = le32_to_cpu(umc_info->v40.channel_width);
- mem_vendor = RREG32(adev->bios_scratch_reg_offset + 4) & 0xF;
- if (vram_vendor)
- *vram_vendor = mem_vendor;
- if (vram_type)
- *vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
- if (vram_width)
- *vram_width = mem_channel_number * (1 << mem_channel_width);
- break;
- default:
- return -EINVAL;
- }
- } else
- return -EINVAL;
+ return -EINVAL;
+ }
+ } else {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int amdgpu_atomfirmware_get_vram_info(struct amdgpu_device *adev,
+ int *vram_width, int *vram_type,
+ int *vram_vendor)
+{
+ struct amdgpu_mode_info *mode_info = &adev->mode_info;
+ int index, i = 0;
+ u16 data_offset, size;
+ union vram_info *vram_info;
+ union vram_module *vram_module;
+ u8 frev, crev;
+ u8 mem_type;
+ u8 mem_vendor;
+ u32 mem_channel_number;
+ u32 mem_channel_width;
+ u32 module_id;
+
+ index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, vram_info);
+
+ if (amdgpu_atom_parse_data_header(mode_info->atom_context,
+ index, &size,
+ &frev, &crev, &data_offset)) {
+ vram_info = (union vram_info *)
+ (mode_info->atom_context->bios + data_offset);
+
+ module_id = (RREG32(adev->bios_scratch_reg_offset + 4) & 0x00ff0000) >> 16;
+ if (frev == 3) {
+ switch (crev) {
+ /* v30 */
+ case 0:
+ vram_module = (union vram_module *)vram_info->v30.vram_module;
+ mem_vendor = (vram_module->v30.dram_vendor_id) & 0xF;
+ if (vram_vendor)
+ *vram_vendor = mem_vendor;
+ mem_type = vram_info->v30.memory_type;
+ if (vram_type)
+ *vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
+ mem_channel_number = vram_info->v30.channel_num;
+ mem_channel_width = vram_info->v30.channel_width;
+ if (vram_width)
+ *vram_width = mem_channel_number * 16;
break;
default:
- vram_info = (union vram_info *)
- (mode_info->atom_context->bios + data_offset);
-
- module_id = (RREG32(adev->bios_scratch_reg_offset + 4) & 0x00ff0000) >> 16;
- if (frev == 3) {
- switch (crev) {
- /* v30 */
- case 0:
- vram_module = (union vram_module *)vram_info->v30.vram_module;
- mem_vendor = (vram_module->v30.dram_vendor_id) & 0xF;
- if (vram_vendor)
- *vram_vendor = mem_vendor;
- mem_type = vram_info->v30.memory_type;
- if (vram_type)
- *vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
- mem_channel_number = vram_info->v30.channel_num;
- mem_channel_width = vram_info->v30.channel_width;
- if (vram_width)
- *vram_width = mem_channel_number * 16;
- break;
- default:
- return -EINVAL;
- }
- } else if (frev == 2) {
- switch (crev) {
- /* v23 */
- case 3:
- if (module_id > vram_info->v23.vram_module_num)
- module_id = 0;
- vram_module = (union vram_module *)vram_info->v23.vram_module;
- while (i < module_id) {
- vram_module = (union vram_module *)
- ((u8 *)vram_module + vram_module->v9.vram_module_size);
- i++;
- }
- mem_type = vram_module->v9.memory_type;
- if (vram_type)
- *vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
- mem_channel_number = vram_module->v9.channel_num;
- mem_channel_width = vram_module->v9.channel_width;
- if (vram_width)
- *vram_width = mem_channel_number * (1 << mem_channel_width);
- mem_vendor = (vram_module->v9.vender_rev_id) & 0xF;
- if (vram_vendor)
- *vram_vendor = mem_vendor;
- break;
- /* v24 */
- case 4:
- if (module_id > vram_info->v24.vram_module_num)
- module_id = 0;
- vram_module = (union vram_module *)vram_info->v24.vram_module;
- while (i < module_id) {
- vram_module = (union vram_module *)
- ((u8 *)vram_module + vram_module->v10.vram_module_size);
- i++;
- }
- mem_type = vram_module->v10.memory_type;
- if (vram_type)
- *vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
- mem_channel_number = vram_module->v10.channel_num;
- mem_channel_width = vram_module->v10.channel_width;
- if (vram_width)
- *vram_width = mem_channel_number * (1 << mem_channel_width);
- mem_vendor = (vram_module->v10.vender_rev_id) & 0xF;
- if (vram_vendor)
- *vram_vendor = mem_vendor;
- break;
- /* v25 */
- case 5:
- if (module_id > vram_info->v25.vram_module_num)
- module_id = 0;
- vram_module = (union vram_module *)vram_info->v25.vram_module;
- while (i < module_id) {
- vram_module = (union vram_module *)
- ((u8 *)vram_module + vram_module->v11.vram_module_size);
- i++;
- }
- mem_type = vram_module->v11.memory_type;
- if (vram_type)
- *vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
- mem_channel_number = vram_module->v11.channel_num;
- mem_channel_width = vram_module->v11.channel_width;
- if (vram_width)
- *vram_width = mem_channel_number * (1 << mem_channel_width);
- mem_vendor = (vram_module->v11.vender_rev_id) & 0xF;
- if (vram_vendor)
- *vram_vendor = mem_vendor;
- break;
- /* v26 */
- case 6:
- if (module_id > vram_info->v26.vram_module_num)
- module_id = 0;
- vram_module = (union vram_module *)vram_info->v26.vram_module;
- while (i < module_id) {
- vram_module = (union vram_module *)
- ((u8 *)vram_module + vram_module->v9.vram_module_size);
- i++;
- }
- mem_type = vram_module->v9.memory_type;
- if (vram_type)
- *vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
- mem_channel_number = vram_module->v9.channel_num;
- mem_channel_width = vram_module->v9.channel_width;
- if (vram_width)
- *vram_width = mem_channel_number * (1 << mem_channel_width);
- mem_vendor = (vram_module->v9.vender_rev_id) & 0xF;
- if (vram_vendor)
- *vram_vendor = mem_vendor;
- break;
- default:
- return -EINVAL;
- }
- } else {
- /* invalid frev */
- return -EINVAL;
+ return -EINVAL;
+ }
+ } else if (frev == 2) {
+ switch (crev) {
+ /* v23 */
+ case 3:
+ if (module_id > vram_info->v23.vram_module_num)
+ module_id = 0;
+ vram_module = (union vram_module *)vram_info->v23.vram_module;
+ while (i < module_id) {
+ vram_module = (union vram_module *)
+ ((u8 *)vram_module + vram_module->v9.vram_module_size);
+ i++;
}
+ mem_type = vram_module->v9.memory_type;
+ if (vram_type)
+ *vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
+ mem_channel_number = vram_module->v9.channel_num;
+ mem_channel_width = vram_module->v9.channel_width;
+ if (vram_width)
+ *vram_width = mem_channel_number * (1 << mem_channel_width);
+ mem_vendor = (vram_module->v9.vender_rev_id) & 0xF;
+ if (vram_vendor)
+ *vram_vendor = mem_vendor;
+ break;
+ /* v24 */
+ case 4:
+ if (module_id > vram_info->v24.vram_module_num)
+ module_id = 0;
+ vram_module = (union vram_module *)vram_info->v24.vram_module;
+ while (i < module_id) {
+ vram_module = (union vram_module *)
+ ((u8 *)vram_module + vram_module->v10.vram_module_size);
+ i++;
+ }
+ mem_type = vram_module->v10.memory_type;
+ if (vram_type)
+ *vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
+ mem_channel_number = vram_module->v10.channel_num;
+ mem_channel_width = vram_module->v10.channel_width;
+ if (vram_width)
+ *vram_width = mem_channel_number * (1 << mem_channel_width);
+ mem_vendor = (vram_module->v10.vender_rev_id) & 0xF;
+ if (vram_vendor)
+ *vram_vendor = mem_vendor;
+ break;
+ /* v25 */
+ case 5:
+ if (module_id > vram_info->v25.vram_module_num)
+ module_id = 0;
+ vram_module = (union vram_module *)vram_info->v25.vram_module;
+ while (i < module_id) {
+ vram_module = (union vram_module *)
+ ((u8 *)vram_module + vram_module->v11.vram_module_size);
+ i++;
+ }
+ mem_type = vram_module->v11.memory_type;
+ if (vram_type)
+ *vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
+ mem_channel_number = vram_module->v11.channel_num;
+ mem_channel_width = vram_module->v11.channel_width;
+ if (vram_width)
+ *vram_width = mem_channel_number * (1 << mem_channel_width);
+ mem_vendor = (vram_module->v11.vender_rev_id) & 0xF;
+ if (vram_vendor)
+ *vram_vendor = mem_vendor;
+ break;
+ /* v26 */
+ case 6:
+ if (module_id > vram_info->v26.vram_module_num)
+ module_id = 0;
+ vram_module = (union vram_module *)vram_info->v26.vram_module;
+ while (i < module_id) {
+ vram_module = (union vram_module *)
+ ((u8 *)vram_module + vram_module->v9.vram_module_size);
+ i++;
+ }
+ mem_type = vram_module->v9.memory_type;
+ if (vram_type)
+ *vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
+ mem_channel_number = vram_module->v9.channel_num;
+ mem_channel_width = vram_module->v9.channel_width;
+ if (vram_width)
+ *vram_width = mem_channel_number * (1 << mem_channel_width);
+ mem_vendor = (vram_module->v9.vender_rev_id) & 0xF;
+ if (vram_vendor)
+ *vram_vendor = mem_vendor;
+ break;
+ default:
+ return -EINVAL;
}
+ } else {
+ /* invalid frev */
+ return -EINVAL;
}
+
+ } else {
+ return -EINVAL;
}
return 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.h
index 67c8d105729b..0760e4510513 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.h
@@ -30,6 +30,10 @@ uint32_t amdgpu_atomfirmware_query_firmware_capability(struct amdgpu_device *ade
bool amdgpu_atomfirmware_gpu_virtualization_supported(struct amdgpu_device *adev);
void amdgpu_atomfirmware_scratch_regs_init(struct amdgpu_device *adev);
int amdgpu_atomfirmware_allocate_fb_scratch(struct amdgpu_device *adev);
+int amdgpu_atomfirmware_get_integrated_system_info(struct amdgpu_device *adev,
+ int *vram_width, int *vram_type, int *vram_vendor);
+int amdgpu_atomfirmware_get_umc_info(struct amdgpu_device *adev,
+ int *vram_width, int *vram_type, int *vram_vendor);
int amdgpu_atomfirmware_get_vram_info(struct amdgpu_device *adev,
int *vram_width, int *vram_type, int *vram_vendor);
int amdgpu_atomfirmware_get_uma_carveout_info(struct amdgpu_device *adev,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c
index 4662bfbe70b2..43864df8af04 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c
@@ -36,6 +36,7 @@
#define AMDGPU_BO_LIST_MAX_PRIORITY 32u
#define AMDGPU_BO_LIST_NUM_BUCKETS (AMDGPU_BO_LIST_MAX_PRIORITY + 1)
+#define AMDGPU_BO_LIST_MAX_ENTRIES (128 * 1024)
static void amdgpu_bo_list_free_rcu(struct rcu_head *rcu)
{
@@ -188,6 +189,9 @@ int amdgpu_bo_create_list_entry_array(struct drm_amdgpu_bo_list_in *in,
const uint32_t bo_number = in->bo_number;
struct drm_amdgpu_bo_list_entry *info;
+ if (bo_number > AMDGPU_BO_LIST_MAX_ENTRIES)
+ return -EINVAL;
+
/* copy the handle array from userspace to a kernel buffer */
if (likely(info_size == bo_info_size)) {
info = vmemdup_array_user(uptr, bo_number, info_size);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
index aabe9d58c3dc..b04fa9fd90b7 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
@@ -1231,6 +1231,8 @@ static enum drm_mode_status amdgpu_connector_dvi_mode_valid(struct drm_connector
case CONNECTOR_OBJECT_ID_HDMI_TYPE_B:
max_digital_pixel_clock_khz = max_dvi_single_link_pixel_clock * 2;
break;
+ default:
+ return MODE_BAD;
}
/* When the display EDID claims that it's an HDMI display,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
index 70ea9b0831a0..b24d5d21be5f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
@@ -908,9 +908,8 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
goto out_free_user_pages;
amdgpu_bo_list_for_each_entry(e, p->bo_list) {
- /* One fence for TTM and one for each CS job */
r = drm_exec_prepare_obj(&p->exec, &e->bo->tbo.base,
- 1 + p->gang_size);
+ TTM_NUM_MOVE_FENCES + p->gang_size);
drm_exec_retry_on_contention(&p->exec);
if (unlikely(r))
goto out_free_user_pages;
@@ -920,7 +919,7 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
if (p->uf_bo) {
r = drm_exec_prepare_obj(&p->exec, &p->uf_bo->tbo.base,
- 1 + p->gang_size);
+ TTM_NUM_MOVE_FENCES + p->gang_size);
drm_exec_retry_on_contention(&p->exec);
if (unlikely(r))
goto out_free_user_pages;
@@ -1740,6 +1739,13 @@ int amdgpu_cs_wait_fences_ioctl(struct drm_device *dev, void *data,
struct drm_amdgpu_fence *fences;
int r;
+ /*
+ * fence_count must be non-zero; dma_fence_wait_any_timeout()
+ * does not accept an empty fence array.
+ */
+ if (!wait->in.fence_count)
+ return -EINVAL;
+
/* Get the fences from userspace */
fences = memdup_array_user(u64_to_user_ptr(wait->in.fences),
wait->in.fence_count,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
index aa9239b310a3..092fd3309099 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
@@ -618,6 +618,110 @@ out:
}
/**
+ * amdgpu_debugfs_regs_pcie64_read - Read from a 64-bit PCIE register
+ *
+ * @f: open file handle
+ * @buf: User buffer to store read data in
+ * @size: Number of bytes to read
+ * @pos: Offset to seek to
+ */
+static ssize_t amdgpu_debugfs_regs_pcie64_read(struct file *f, char __user *buf,
+ size_t size, loff_t *pos)
+{
+ struct amdgpu_device *adev = file_inode(f)->i_private;
+ ssize_t result = 0;
+ int r;
+
+ if (size & 0x7 || *pos & 0x7)
+ return -EINVAL;
+
+ r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
+ if (r < 0) {
+ pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
+ return r;
+ }
+
+ r = amdgpu_virt_enable_access_debugfs(adev);
+ if (r < 0) {
+ pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
+ return r;
+ }
+
+ while (size) {
+ uint64_t value;
+
+ value = RREG64_PCIE_EXT(*pos);
+
+ r = put_user(value, (uint64_t *)buf);
+ if (r)
+ goto out;
+
+ result += 8;
+ buf += 8;
+ *pos += 8;
+ size -= 8;
+ }
+
+ r = result;
+out:
+ pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
+ amdgpu_virt_disable_access_debugfs(adev);
+ return r;
+}
+
+/**
+ * amdgpu_debugfs_regs_pcie64_write - Write to a 64-bit PCIE register
+ *
+ * @f: open file handle
+ * @buf: User buffer to write data from
+ * @size: Number of bytes to write
+ * @pos: Offset to seek to
+ */
+static ssize_t amdgpu_debugfs_regs_pcie64_write(struct file *f, const char __user *buf,
+ size_t size, loff_t *pos)
+{
+ struct amdgpu_device *adev = file_inode(f)->i_private;
+ ssize_t result = 0;
+ int r;
+
+ if (size & 0x7 || *pos & 0x7)
+ return -EINVAL;
+
+ r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
+ if (r < 0) {
+ pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
+ return r;
+ }
+
+ r = amdgpu_virt_enable_access_debugfs(adev);
+ if (r < 0) {
+ pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
+ return r;
+ }
+
+ while (size) {
+ uint64_t value;
+
+ r = get_user(value, (uint64_t *)buf);
+ if (r)
+ goto out;
+
+ WREG64_PCIE_EXT(*pos, value);
+
+ result += 8;
+ buf += 8;
+ *pos += 8;
+ size -= 8;
+ }
+
+ r = result;
+out:
+ pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
+ amdgpu_virt_disable_access_debugfs(adev);
+ return r;
+}
+
+/**
* amdgpu_debugfs_regs_didt_read - Read from a DIDT register
*
* @f: open file handle
@@ -1525,6 +1629,12 @@ static const struct file_operations amdgpu_debugfs_regs_pcie_fops = {
.write = amdgpu_debugfs_regs_pcie_write,
.llseek = default_llseek
};
+static const struct file_operations amdgpu_debugfs_regs_pcie64_fops = {
+ .owner = THIS_MODULE,
+ .read = amdgpu_debugfs_regs_pcie64_read,
+ .write = amdgpu_debugfs_regs_pcie64_write,
+ .llseek = default_llseek
+};
static const struct file_operations amdgpu_debugfs_regs_smc_fops = {
.owner = THIS_MODULE,
.read = amdgpu_debugfs_regs_smc_read,
@@ -1587,6 +1697,7 @@ static const struct file_operations *debugfs_regs[] = {
&amdgpu_debugfs_gprwave_fops,
&amdgpu_debugfs_regs_didt_fops,
&amdgpu_debugfs_regs_pcie_fops,
+ &amdgpu_debugfs_regs_pcie64_fops,
&amdgpu_debugfs_regs_smc_fops,
&amdgpu_debugfs_gca_config_fops,
&amdgpu_debugfs_sensors_fops,
@@ -1604,6 +1715,7 @@ static const char * const debugfs_regs_names[] = {
"amdgpu_gprwave",
"amdgpu_regs_didt",
"amdgpu_regs_pcie",
+ "amdgpu_regs_pcie64",
"amdgpu_regs_smc",
"amdgpu_gca_config",
"amdgpu_sensors",
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c
index 160f0704d1d3..fddf4e1252bd 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c
@@ -32,8 +32,16 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check,
bool vram_lost, struct amdgpu_job *job)
{
}
+void amdgpu_coredump_init(struct amdgpu_device *adev)
+{
+}
+void amdgpu_coredump_fini(struct amdgpu_device *adev)
+{
+}
#else
+#define AMDGPU_CORE_DUMP_SIZE_MAX (256 * 1024 * 1024)
+
const char *hw_ip_names[MAX_HWIP] = {
[GC_HWIP] = "GC",
[HDP_HWIP] = "HDP",
@@ -187,20 +195,22 @@ static void amdgpu_devcoredump_fw_info(struct amdgpu_device *adev,
drm_printf(p, "VPE feature version: %u, fw version: 0x%08x\n",
adev->vpe.feature_version, adev->vpe.fw_version);
- drm_printf(p, "\nVBIOS Information\n");
- drm_printf(p, "vbios name : %s\n", ctx->name);
- drm_printf(p, "vbios pn : %s\n", ctx->vbios_pn);
- drm_printf(p, "vbios version : %d\n", ctx->version);
- drm_printf(p, "vbios ver_str : %s\n", ctx->vbios_ver_str);
- drm_printf(p, "vbios date : %s\n", ctx->date);
+ if (adev->bios) {
+ drm_printf(p, "\nVBIOS Information\n");
+ drm_printf(p, "vbios name : %s\n", ctx->name);
+ drm_printf(p, "vbios pn : %s\n", ctx->vbios_pn);
+ drm_printf(p, "vbios version : %d\n", ctx->version);
+ drm_printf(p, "vbios ver_str : %s\n", ctx->vbios_ver_str);
+ drm_printf(p, "vbios date : %s\n", ctx->date);
+ }else {
+ drm_printf(p, "\nVBIOS Information: NA\n");
+ }
}
static ssize_t
-amdgpu_devcoredump_read(char *buffer, loff_t offset, size_t count,
- void *data, size_t datalen)
+amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_info *coredump)
{
struct drm_printer p;
- struct amdgpu_coredump_info *coredump = data;
struct drm_print_iterator iter;
struct amdgpu_vm_fault_info *fault_info;
struct amdgpu_ip_block *ip_block;
@@ -208,7 +218,6 @@ amdgpu_devcoredump_read(char *buffer, loff_t offset, size_t count,
iter.data = buffer;
iter.offset = 0;
- iter.start = offset;
iter.remain = count;
p = drm_coredump_printer(&iter);
@@ -322,9 +331,63 @@ amdgpu_devcoredump_read(char *buffer, loff_t offset, size_t count,
return count - iter.remain;
}
+static ssize_t
+amdgpu_devcoredump_read(char *buffer, loff_t offset, size_t count,
+ void *data, size_t datalen)
+{
+ struct amdgpu_coredump_info *coredump = data;
+ ssize_t byte_copied;
+
+ if (!coredump)
+ return -ENODEV;
+
+ if (!coredump->formatted)
+ return -ENODEV;
+
+ if (offset >= coredump->formatted_size)
+ return 0;
+
+ byte_copied = count < coredump->formatted_size - offset ? count :
+ coredump->formatted_size - offset;
+ memcpy(buffer, coredump->formatted + offset, byte_copied);
+
+ return byte_copied;
+}
+
static void amdgpu_devcoredump_free(void *data)
{
- kfree(data);
+ struct amdgpu_coredump_info *coredump = data;
+
+ kvfree(coredump->formatted);
+ kvfree(data);
+}
+
+static void amdgpu_devcoredump_deferred_work(struct work_struct *work)
+{
+ struct amdgpu_device *adev = container_of(work, typeof(*adev), coredump_work);
+ struct amdgpu_coredump_info *coredump = adev->coredump;
+
+ /* Do a one-time preparation of the coredump output because
+ * repeatingly calling drm_coredump_printer is very slow.
+ */
+ coredump->formatted_size = amdgpu_devcoredump_format(
+ NULL, AMDGPU_CORE_DUMP_SIZE_MAX, coredump);
+ coredump->formatted = kvzalloc(coredump->formatted_size, GFP_KERNEL);
+ if (!coredump->formatted) {
+ amdgpu_devcoredump_free(coredump);
+ goto end;
+ }
+
+ amdgpu_devcoredump_format(coredump->formatted, coredump->formatted_size, coredump);
+
+ /* If there's an existing coredump for this device, the free function will be
+ * called immediately so coredump might be invalid after the call to dev_coredumpm.
+ */
+ dev_coredumpm(coredump->adev->dev, THIS_MODULE, coredump, 0, GFP_NOWAIT,
+ amdgpu_devcoredump_read, amdgpu_devcoredump_free);
+
+end:
+ adev->coredump = NULL;
}
void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check,
@@ -334,6 +397,10 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check,
struct amdgpu_coredump_info *coredump;
struct drm_sched_job *s_job;
+ /* No need to generate a new coredump if there's one in progress already. */
+ if (work_pending(&adev->coredump_work))
+ return;
+
coredump = kzalloc_obj(*coredump, GFP_NOWAIT);
if (!coredump)
return;
@@ -360,11 +427,26 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check,
ktime_get_ts64(&coredump->reset_time);
- dev_coredumpm(dev->dev, THIS_MODULE, coredump, 0, GFP_NOWAIT,
- amdgpu_devcoredump_read, amdgpu_devcoredump_free);
+ /* Update the current coredump pointer (no lock needed, this function can only be called
+ * from a single thread)
+ */
+ adev->coredump = coredump;
+ /* Kick off coredump formatting to a worker thread. */
+ queue_work(system_unbound_wq, &adev->coredump_work);
drm_info(dev, "AMDGPU device coredump file has been created\n");
drm_info(dev, "Check your /sys/class/drm/card%d/device/devcoredump/data\n",
dev->primary->index);
}
+
+void amdgpu_coredump_init(struct amdgpu_device *adev)
+{
+ INIT_WORK(&adev->coredump_work, amdgpu_devcoredump_deferred_work);
+}
+
+void amdgpu_coredump_fini(struct amdgpu_device *adev)
+{
+ /* Finish deferred coredump formatting before HW/IP teardown. */
+ flush_work(&adev->coredump_work);
+}
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.h
index ef9772c6bcc9..f8f2f4df129b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.h
@@ -35,12 +35,20 @@ struct amdgpu_coredump_info {
struct amdgpu_device *adev;
struct amdgpu_task_info reset_task_info;
struct timespec64 reset_time;
+
bool skip_vram_check;
bool reset_vram_lost;
struct amdgpu_ring *ring;
+ /* Readable form of coredevdump, generate once to speed up
+ * reading it (see drm_coredump_printer's documentation).
+ */
+ ssize_t formatted_size;
+ char *formatted;
};
#endif
void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check,
bool vram_lost, struct amdgpu_job *job);
+void amdgpu_coredump_init(struct amdgpu_device *adev);
+void amdgpu_coredump_fini(struct amdgpu_device *adev);
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 711b4502653a..9c936519bb2b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -3498,7 +3498,8 @@ fail:
static int amdgpu_device_get_job_timeout_settings(struct amdgpu_device *adev)
{
- char *input = amdgpu_lockup_timeout;
+ char buf[AMDGPU_MAX_TIMEOUT_PARAM_LENGTH];
+ char *input = buf;
char *timeout_setting = NULL;
int index = 0;
long timeout;
@@ -3508,9 +3509,17 @@ static int amdgpu_device_get_job_timeout_settings(struct amdgpu_device *adev)
adev->gfx_timeout = adev->compute_timeout = adev->sdma_timeout =
adev->video_timeout = msecs_to_jiffies(2000);
- if (!strnlen(input, AMDGPU_MAX_TIMEOUT_PARAM_LENGTH))
+ if (!strnlen(amdgpu_lockup_timeout, AMDGPU_MAX_TIMEOUT_PARAM_LENGTH))
return 0;
+ /*
+ * strsep() destructively modifies its input by replacing delimiters
+ * with '\0'. Use a stack copy so the global module parameter buffer
+ * remains intact for multi-GPU systems where this function is called
+ * once per device.
+ */
+ strscpy(buf, amdgpu_lockup_timeout, sizeof(buf));
+
while ((timeout_setting = strsep(&input, ",")) &&
strnlen(timeout_setting, AMDGPU_MAX_TIMEOUT_PARAM_LENGTH)) {
ret = kstrtol(timeout_setting, 0, &timeout);
@@ -3781,6 +3790,8 @@ int amdgpu_device_init(struct amdgpu_device *adev,
INIT_WORK(&adev->xgmi_reset_work, amdgpu_device_xgmi_reset_func);
INIT_WORK(&adev->userq_reset_work, amdgpu_userq_reset_work);
+ amdgpu_coredump_init(adev);
+
adev->gfx.gfx_off_req_count = 1;
adev->gfx.gfx_off_residency = 0;
adev->gfx.gfx_off_entrycount = 0;
@@ -3878,9 +3889,21 @@ int amdgpu_device_init(struct amdgpu_device *adev,
amdgpu_gmc_noretry_set(adev);
/* Need to get xgmi info early to decide the reset behavior*/
if (adev->gmc.xgmi.supported) {
- r = adev->gfxhub.funcs->get_xgmi_info(adev);
- if (r)
- return r;
+ if (adev->gfxhub.funcs &&
+ adev->gfxhub.funcs->get_xgmi_info) {
+ r = adev->gfxhub.funcs->get_xgmi_info(adev);
+ if (r)
+ return r;
+ }
+ }
+
+ if (adev->gmc.xgmi.connected_to_cpu) {
+ if (adev->mmhub.funcs &&
+ adev->mmhub.funcs->get_xgmi_info) {
+ r = adev->mmhub.funcs->get_xgmi_info(adev);
+ if (r)
+ return r;
+ }
}
/* enable PCIE atomic ops */
@@ -4202,6 +4225,7 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev)
if (pci_dev_is_disconnected(adev->pdev))
amdgpu_amdkfd_device_fini_sw(adev);
+ amdgpu_coredump_fini(adev);
amdgpu_device_ip_fini_early(adev);
amdgpu_irq_fini_hw(adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
index f9f785c5d8ac..8ec5465c3349 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
@@ -112,8 +112,10 @@
#include "smuio_v15_0_8.h"
#include "vcn_v5_0_0.h"
#include "vcn_v5_0_1.h"
+#include "vcn_v5_0_2.h"
#include "jpeg_v5_0_0.h"
#include "jpeg_v5_0_1.h"
+#include "jpeg_v5_0_2.h"
#include "jpeg_v5_3_0.h"
#include "amdgpu_ras_mgr.h"
@@ -296,13 +298,17 @@ static int amdgpu_discovery_get_tmr_info(struct amdgpu_device *adev,
if (vram_size)
adev->discovery.offset = (vram_size << 20) - DISCOVERY_TMR_OFFSET;
- if (amdgpu_sriov_vf(adev) && adev->virt.is_dynamic_crit_regn_enabled) {
- adev->discovery.offset =
- adev->virt.crit_regn_tbl[AMD_SRIOV_MSG_IPD_TABLE_ID].offset;
- adev->discovery.size =
- adev->virt.crit_regn_tbl[AMD_SRIOV_MSG_IPD_TABLE_ID].size_kb << 10;
- if (!adev->discovery.offset || !adev->discovery.size)
- return -EINVAL;
+ if (amdgpu_sriov_vf(adev)) {
+ if (adev->virt.is_dynamic_crit_regn_enabled) {
+ adev->discovery.offset =
+ adev->virt.crit_regn_tbl[AMD_SRIOV_MSG_IPD_TABLE_ID].offset;
+ adev->discovery.size =
+ adev->virt.crit_regn_tbl[AMD_SRIOV_MSG_IPD_TABLE_ID].size_kb << 10;
+ if (!adev->discovery.offset || !adev->discovery.size)
+ return -EINVAL;
+ } else {
+ goto out;
+ }
} else {
tmr_size = RREG32(mmDRIVER_SCRATCH_2);
if (tmr_size) {
@@ -318,11 +324,11 @@ static int amdgpu_discovery_get_tmr_info(struct amdgpu_device *adev,
ret = amdgpu_acpi_get_tmr_info(adev, &tmr_offset, &tmr_size);
if (ret)
return ret;
- adev->discovery.size = (u32)tmr_size;
+ adev->discovery.size = DISCOVERY_TMR_SIZE;
adev->discovery.offset = tmr_offset + tmr_size - DISCOVERY_TMR_OFFSET;
}
}
-
+out:
adev->discovery.bin = kzalloc(adev->discovery.size, GFP_KERNEL);
if (!adev->discovery.bin)
return -ENOMEM;
@@ -556,7 +562,7 @@ static int amdgpu_discovery_table_check(struct amdgpu_device *adev,
checksum = le16_to_cpu(info->checksum);
switch (table_id) {
- case IP_DISCOVERY:
+ case IP_DISCOVERY: {
struct ip_discovery_header *ihdr =
(struct ip_discovery_header *)(discovery_bin + offset);
act_val = le32_to_cpu(ihdr->signature);
@@ -564,7 +570,8 @@ static int amdgpu_discovery_table_check(struct amdgpu_device *adev,
table_size = le16_to_cpu(ihdr->size);
table_name = "data table";
break;
- case GC:
+ }
+ case GC: {
struct gpu_info_header *ghdr =
(struct gpu_info_header *)(discovery_bin + offset);
act_val = le32_to_cpu(ghdr->table_id);
@@ -572,7 +579,8 @@ static int amdgpu_discovery_table_check(struct amdgpu_device *adev,
table_size = le16_to_cpu(ghdr->size);
table_name = "gc table";
break;
- case HARVEST_INFO:
+ }
+ case HARVEST_INFO: {
struct harvest_info_header *hhdr =
(struct harvest_info_header *)(discovery_bin + offset);
act_val = le32_to_cpu(hhdr->signature);
@@ -580,7 +588,8 @@ static int amdgpu_discovery_table_check(struct amdgpu_device *adev,
table_size = sizeof(struct harvest_table);
table_name = "harvest table";
break;
- case VCN_INFO:
+ }
+ case VCN_INFO: {
struct vcn_info_header *vhdr =
(struct vcn_info_header *)(discovery_bin + offset);
act_val = le32_to_cpu(vhdr->table_id);
@@ -588,7 +597,8 @@ static int amdgpu_discovery_table_check(struct amdgpu_device *adev,
table_size = le32_to_cpu(vhdr->size_bytes);
table_name = "vcn table";
break;
- case MALL_INFO:
+ }
+ case MALL_INFO: {
struct mall_info_header *mhdr =
(struct mall_info_header *)(discovery_bin + offset);
act_val = le32_to_cpu(mhdr->table_id);
@@ -597,6 +607,7 @@ static int amdgpu_discovery_table_check(struct amdgpu_device *adev,
table_name = "mall table";
check_table = false;
break;
+ }
default:
dev_err(adev->dev, "invalid ip discovery table id %d specified\n", table_id);
check_table = false;
@@ -1383,6 +1394,9 @@ static void amdgpu_discovery_sysfs_fini(struct amdgpu_device *adev)
struct list_head *el, *tmp;
struct kset *die_kset;
+ if (!ip_top)
+ return;
+
die_kset = &ip_top->die_kset;
spin_lock(&die_kset->list_lock);
list_for_each_prev_safe(el, tmp, &die_kset->list) {
@@ -1407,9 +1421,13 @@ void amdgpu_discovery_dump(struct amdgpu_device *adev, struct drm_printer *p)
struct ip_hw_instance *ip_inst;
int i = 0, j;
+ if (!ip_top)
+ return;
+
die_kset = &ip_top->die_kset;
drm_printf(p, "\nHW IP Discovery\n");
+
spin_lock(&die_kset->list_lock);
list_for_each(el_die, &die_kset->list) {
drm_printf(p, "die %d\n", i++);
@@ -1966,11 +1984,10 @@ static int amdgpu_discovery_refresh_nps_info(struct amdgpu_device *adev,
int amdgpu_discovery_get_nps_info(struct amdgpu_device *adev,
uint32_t *nps_type,
- struct amdgpu_gmc_memrange **ranges,
+ struct amdgpu_gmc_memrange *ranges,
int *range_cnt, bool refresh)
{
uint8_t *discovery_bin = adev->discovery.bin;
- struct amdgpu_gmc_memrange *mem_ranges;
struct table_info *info;
union nps_info *nps_info;
union nps_info nps_data;
@@ -2008,20 +2025,22 @@ int amdgpu_discovery_get_nps_info(struct amdgpu_device *adev,
switch (le16_to_cpu(nps_info->v1.header.version_major)) {
case 1:
- mem_ranges = kvzalloc_objs(*mem_ranges, nps_info->v1.count);
- if (!mem_ranges)
- return -ENOMEM;
*nps_type = nps_info->v1.nps_type;
+ if (*range_cnt < nps_info->v1.count) {
+ dev_dbg(adev->dev,
+ "not enough space for nps ranges: %d < %d\n",
+ *range_cnt, nps_info->v1.count);
+ return -ENOSPC;
+ }
*range_cnt = nps_info->v1.count;
for (i = 0; i < *range_cnt; i++) {
- mem_ranges[i].base_address =
+ ranges[i].base_address =
nps_info->v1.instance_info[i].base_address;
- mem_ranges[i].limit_address =
+ ranges[i].limit_address =
nps_info->v1.instance_info[i].limit_address;
- mem_ranges[i].nid_mask = -1;
- mem_ranges[i].flags = 0;
+ ranges[i].nid_mask = -1;
+ ranges[i].flags = 0;
}
- *ranges = mem_ranges;
break;
default:
dev_err(adev->dev, "Unhandled NPS info table %d.%d\n",
@@ -2323,6 +2342,7 @@ static int amdgpu_discovery_set_smu_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &smu_v14_0_ip_block);
break;
case IP_VERSION(15, 0, 0):
+ case IP_VERSION(15, 0, 8):
amdgpu_device_ip_block_add(adev, &smu_v15_0_ip_block);
break;
default:
@@ -2640,6 +2660,10 @@ static int amdgpu_discovery_set_mm_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &vcn_v5_0_1_ip_block);
amdgpu_device_ip_block_add(adev, &jpeg_v5_0_1_ip_block);
break;
+ case IP_VERSION(5, 0, 2):
+ amdgpu_device_ip_block_add(adev, &vcn_v5_0_2_ip_block);
+ amdgpu_device_ip_block_add(adev, &jpeg_v5_0_2_ip_block);
+ break;
default:
dev_err(adev->dev,
"Failed to add vcn/jpeg ip block(UVD_HWIP:0x%x)\n",
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.h
index a7aeb47887a3..0ff1a7923eed 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.h
@@ -46,7 +46,7 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev);
int amdgpu_discovery_get_nps_info(struct amdgpu_device *adev,
uint32_t *nps_type,
- struct amdgpu_gmc_memrange **ranges,
+ struct amdgpu_gmc_memrange *ranges,
int *range_cnt, bool refresh);
void amdgpu_discovery_dump(struct amdgpu_device *adev, struct drm_printer *p);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 03814a23eb54..8ed637f92322 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -839,8 +839,8 @@ module_param_named_unsafe(no_queue_eviction_on_vm_fault, amdgpu_no_queue_evictio
/**
* DOC: mtype_local (int)
*/
-int amdgpu_mtype_local;
-MODULE_PARM_DESC(mtype_local, "MTYPE for local memory (0 = MTYPE_RW (default), 1 = MTYPE_NC, 2 = MTYPE_CC)");
+int amdgpu_mtype_local = -1;
+MODULE_PARM_DESC(mtype_local, "MTYPE for local memory (default: ASIC dependent, 0 = MTYPE_RW, 1 = MTYPE_NC, 2 = MTYPE_CC)");
module_param_named_unsafe(mtype_local, amdgpu_mtype_local, int, 0444);
/**
@@ -2683,8 +2683,12 @@ static int amdgpu_pmops_freeze(struct device *dev)
if (r)
return r;
- if (amdgpu_acpi_should_gpu_reset(adev))
- return amdgpu_asic_reset(adev);
+ if (amdgpu_acpi_should_gpu_reset(adev)) {
+ amdgpu_device_lock_reset_domain(adev->reset_domain);
+ r = amdgpu_asic_reset(adev);
+ amdgpu_device_unlock_reset_domain(adev->reset_domain);
+ return r;
+ }
return 0;
}
@@ -2952,9 +2956,11 @@ static int amdgpu_drm_release(struct inode *inode, struct file *filp)
int idx;
if (fpriv && drm_dev_enter(dev, &idx)) {
- fpriv->evf_mgr.fd_closing = true;
- amdgpu_eviction_fence_destroy(&fpriv->evf_mgr);
+ amdgpu_evf_mgr_shutdown(&fpriv->evf_mgr);
+ amdgpu_userq_mgr_cancel_resume(&fpriv->userq_mgr);
+ amdgpu_evf_mgr_flush_suspend(&fpriv->evf_mgr);
amdgpu_userq_mgr_fini(&fpriv->userq_mgr);
+ amdgpu_evf_mgr_fini(&fpriv->evf_mgr);
drm_dev_exit(idx);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_eviction_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_eviction_fence.c
index 3b588c7740ec..4c5e38dea4c2 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_eviction_fence.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_eviction_fence.c
@@ -25,9 +25,6 @@
#include <drm/drm_exec.h>
#include "amdgpu.h"
-#define work_to_evf_mgr(w, name) container_of(w, struct amdgpu_eviction_fence_mgr, name)
-#define evf_mgr_to_fpriv(e) container_of(e, struct amdgpu_fpriv, evf_mgr)
-
static const char *
amdgpu_eviction_fence_get_driver_name(struct dma_fence *fence)
{
@@ -43,127 +40,93 @@ amdgpu_eviction_fence_get_timeline_name(struct dma_fence *f)
return ef->timeline_name;
}
-int
-amdgpu_eviction_fence_replace_fence(struct amdgpu_eviction_fence_mgr *evf_mgr,
- struct drm_exec *exec)
+static bool amdgpu_eviction_fence_enable_signaling(struct dma_fence *f)
{
- struct amdgpu_eviction_fence *old_ef, *new_ef;
- struct drm_gem_object *obj;
- unsigned long index;
- int ret;
-
- if (evf_mgr->ev_fence &&
- !dma_fence_is_signaled(&evf_mgr->ev_fence->base))
- return 0;
- /*
- * Steps to replace eviction fence:
- * * lock all objects in exec (caller)
- * * create a new eviction fence
- * * update new eviction fence in evf_mgr
- * * attach the new eviction fence to BOs
- * * release the old fence
- * * unlock the objects (caller)
- */
- new_ef = amdgpu_eviction_fence_create(evf_mgr);
- if (!new_ef) {
- DRM_ERROR("Failed to create new eviction fence\n");
- return -ENOMEM;
- }
-
- /* Update the eviction fence now */
- spin_lock(&evf_mgr->ev_fence_lock);
- old_ef = evf_mgr->ev_fence;
- evf_mgr->ev_fence = new_ef;
- spin_unlock(&evf_mgr->ev_fence_lock);
+ struct amdgpu_eviction_fence *ev_fence = to_ev_fence(f);
- /* Attach the new fence */
- drm_exec_for_each_locked_object(exec, index, obj) {
- struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
-
- if (!bo)
- continue;
- ret = amdgpu_eviction_fence_attach(evf_mgr, bo);
- if (ret) {
- DRM_ERROR("Failed to attch new eviction fence\n");
- goto free_err;
- }
- }
-
- /* Free old fence */
- if (old_ef)
- dma_fence_put(&old_ef->base);
- return 0;
-
-free_err:
- kfree(new_ef);
- return ret;
+ schedule_work(&ev_fence->evf_mgr->suspend_work);
+ return true;
}
+static const struct dma_fence_ops amdgpu_eviction_fence_ops = {
+ .get_driver_name = amdgpu_eviction_fence_get_driver_name,
+ .get_timeline_name = amdgpu_eviction_fence_get_timeline_name,
+ .enable_signaling = amdgpu_eviction_fence_enable_signaling,
+};
+
static void
amdgpu_eviction_fence_suspend_worker(struct work_struct *work)
{
- struct amdgpu_eviction_fence_mgr *evf_mgr = work_to_evf_mgr(work, suspend_work.work);
- struct amdgpu_fpriv *fpriv = evf_mgr_to_fpriv(evf_mgr);
+ struct amdgpu_eviction_fence_mgr *evf_mgr =
+ container_of(work, struct amdgpu_eviction_fence_mgr,
+ suspend_work);
+ struct amdgpu_fpriv *fpriv =
+ container_of(evf_mgr, struct amdgpu_fpriv, evf_mgr);
struct amdgpu_userq_mgr *uq_mgr = &fpriv->userq_mgr;
- struct amdgpu_eviction_fence *ev_fence;
+ struct dma_fence *ev_fence;
+ bool cookie;
mutex_lock(&uq_mgr->userq_mutex);
- spin_lock(&evf_mgr->ev_fence_lock);
- ev_fence = evf_mgr->ev_fence;
- if (ev_fence)
- dma_fence_get(&ev_fence->base);
- else
- goto unlock;
- spin_unlock(&evf_mgr->ev_fence_lock);
- amdgpu_userq_evict(uq_mgr, ev_fence);
+ /*
+ * This is intentionally after taking the userq_mutex since we do
+ * allocate memory while holding this lock, but only after ensuring that
+ * the eviction fence is signaled.
+ */
+ cookie = dma_fence_begin_signalling();
- mutex_unlock(&uq_mgr->userq_mutex);
- dma_fence_put(&ev_fence->base);
- return;
+ ev_fence = amdgpu_evf_mgr_get_fence(evf_mgr);
+ amdgpu_userq_evict(uq_mgr);
+
+ /*
+ * Signaling the eviction fence must be done while holding the
+ * userq_mutex. Otherwise we won't resume the queues before issuing the
+ * next fence.
+ */
+ dma_fence_signal(ev_fence);
+ dma_fence_end_signalling(cookie);
+ dma_fence_put(ev_fence);
+
+ if (!evf_mgr->shutdown)
+ schedule_delayed_work(&uq_mgr->resume_work, 0);
-unlock:
- spin_unlock(&evf_mgr->ev_fence_lock);
mutex_unlock(&uq_mgr->userq_mutex);
}
-static bool amdgpu_eviction_fence_enable_signaling(struct dma_fence *f)
+int amdgpu_evf_mgr_attach_fence(struct amdgpu_eviction_fence_mgr *evf_mgr,
+ struct amdgpu_bo *bo)
{
- struct amdgpu_eviction_fence_mgr *evf_mgr;
- struct amdgpu_eviction_fence *ev_fence;
-
- if (!f)
- return true;
-
- ev_fence = to_ev_fence(f);
- evf_mgr = ev_fence->evf_mgr;
+ struct dma_fence *ev_fence = amdgpu_evf_mgr_get_fence(evf_mgr);
+ struct ttm_operation_ctx ctx = { false, false };
+ struct dma_resv *resv = bo->tbo.base.resv;
+ int ret;
- schedule_delayed_work(&evf_mgr->suspend_work, 0);
- return true;
-}
+ if (!dma_fence_is_signaled(ev_fence)) {
-static const struct dma_fence_ops amdgpu_eviction_fence_ops = {
- .get_driver_name = amdgpu_eviction_fence_get_driver_name,
- .get_timeline_name = amdgpu_eviction_fence_get_timeline_name,
- .enable_signaling = amdgpu_eviction_fence_enable_signaling,
-};
+ amdgpu_bo_placement_from_domain(bo, bo->allowed_domains);
+ ret = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
+ if (!ret)
+ dma_resv_add_fence(resv, ev_fence,
+ DMA_RESV_USAGE_BOOKKEEP);
+ } else {
+ ret = 0;
+ }
-void amdgpu_eviction_fence_signal(struct amdgpu_eviction_fence_mgr *evf_mgr,
- struct amdgpu_eviction_fence *ev_fence)
-{
- spin_lock(&evf_mgr->ev_fence_lock);
- dma_fence_signal(&ev_fence->base);
- spin_unlock(&evf_mgr->ev_fence_lock);
+ dma_fence_put(ev_fence);
+ return ret;
}
-struct amdgpu_eviction_fence *
-amdgpu_eviction_fence_create(struct amdgpu_eviction_fence_mgr *evf_mgr)
+int amdgpu_evf_mgr_rearm(struct amdgpu_eviction_fence_mgr *evf_mgr,
+ struct drm_exec *exec)
{
struct amdgpu_eviction_fence *ev_fence;
+ struct drm_gem_object *obj;
+ unsigned long index;
+ /* Create and initialize a new eviction fence */
ev_fence = kzalloc_obj(*ev_fence);
if (!ev_fence)
- return NULL;
+ return -ENOMEM;
ev_fence->evf_mgr = evf_mgr;
get_task_comm(ev_fence->timeline_name, current);
@@ -171,56 +134,22 @@ amdgpu_eviction_fence_create(struct amdgpu_eviction_fence_mgr *evf_mgr)
dma_fence_init64(&ev_fence->base, &amdgpu_eviction_fence_ops,
&ev_fence->lock, evf_mgr->ev_fence_ctx,
atomic_inc_return(&evf_mgr->ev_fence_seq));
- return ev_fence;
-}
-
-void amdgpu_eviction_fence_destroy(struct amdgpu_eviction_fence_mgr *evf_mgr)
-{
- struct amdgpu_eviction_fence *ev_fence;
-
- /* Wait for any pending work to execute */
- flush_delayed_work(&evf_mgr->suspend_work);
-
- spin_lock(&evf_mgr->ev_fence_lock);
- ev_fence = evf_mgr->ev_fence;
- spin_unlock(&evf_mgr->ev_fence_lock);
-
- if (!ev_fence)
- return;
-
- dma_fence_wait(&ev_fence->base, false);
-
- /* Last unref of ev_fence */
- dma_fence_put(&ev_fence->base);
-}
-int amdgpu_eviction_fence_attach(struct amdgpu_eviction_fence_mgr *evf_mgr,
- struct amdgpu_bo *bo)
-{
- struct amdgpu_eviction_fence *ev_fence;
- struct dma_resv *resv = bo->tbo.base.resv;
- int ret;
+ /* Remember it for newly added BOs */
+ dma_fence_put(evf_mgr->ev_fence);
+ evf_mgr->ev_fence = &ev_fence->base;
- if (!resv)
- return 0;
+ /* And add it to all existing BOs */
+ drm_exec_for_each_locked_object(exec, index, obj) {
+ struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
- ret = dma_resv_reserve_fences(resv, 1);
- if (ret) {
- DRM_DEBUG_DRIVER("Failed to resv fence space\n");
- return ret;
+ amdgpu_evf_mgr_attach_fence(evf_mgr, bo);
}
-
- spin_lock(&evf_mgr->ev_fence_lock);
- ev_fence = evf_mgr->ev_fence;
- if (ev_fence)
- dma_resv_add_fence(resv, &ev_fence->base, DMA_RESV_USAGE_BOOKKEEP);
- spin_unlock(&evf_mgr->ev_fence_lock);
-
return 0;
}
-void amdgpu_eviction_fence_detach(struct amdgpu_eviction_fence_mgr *evf_mgr,
- struct amdgpu_bo *bo)
+void amdgpu_evf_mgr_detach_fence(struct amdgpu_eviction_fence_mgr *evf_mgr,
+ struct amdgpu_bo *bo)
{
struct dma_fence *stub = dma_fence_get_stub();
@@ -229,13 +158,31 @@ void amdgpu_eviction_fence_detach(struct amdgpu_eviction_fence_mgr *evf_mgr,
dma_fence_put(stub);
}
-int amdgpu_eviction_fence_init(struct amdgpu_eviction_fence_mgr *evf_mgr)
+void amdgpu_evf_mgr_init(struct amdgpu_eviction_fence_mgr *evf_mgr)
{
- /* This needs to be done one time per open */
atomic_set(&evf_mgr->ev_fence_seq, 0);
evf_mgr->ev_fence_ctx = dma_fence_context_alloc(1);
- spin_lock_init(&evf_mgr->ev_fence_lock);
+ evf_mgr->ev_fence = dma_fence_get_stub();
- INIT_DELAYED_WORK(&evf_mgr->suspend_work, amdgpu_eviction_fence_suspend_worker);
- return 0;
+ INIT_WORK(&evf_mgr->suspend_work, amdgpu_eviction_fence_suspend_worker);
+}
+
+void amdgpu_evf_mgr_shutdown(struct amdgpu_eviction_fence_mgr *evf_mgr)
+{
+ evf_mgr->shutdown = true;
+ /* Make sure that the shutdown is visible to the suspend work */
+ flush_work(&evf_mgr->suspend_work);
+}
+
+void amdgpu_evf_mgr_flush_suspend(struct amdgpu_eviction_fence_mgr *evf_mgr)
+{
+ dma_fence_wait(rcu_dereference_protected(evf_mgr->ev_fence, true),
+ false);
+ /* Make sure that we are done with the last suspend work */
+ flush_work(&evf_mgr->suspend_work);
+}
+
+void amdgpu_evf_mgr_fini(struct amdgpu_eviction_fence_mgr *evf_mgr)
+{
+ dma_fence_put(evf_mgr->ev_fence);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_eviction_fence.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_eviction_fence.h
index fcd867b7147d..2a750add4e7b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_eviction_fence.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_eviction_fence.h
@@ -25,6 +25,8 @@
#ifndef AMDGPU_EV_FENCE_H_
#define AMDGPU_EV_FENCE_H_
+#include <linux/dma-fence.h>
+
struct amdgpu_eviction_fence {
struct dma_fence base;
spinlock_t lock;
@@ -35,35 +37,36 @@ struct amdgpu_eviction_fence {
struct amdgpu_eviction_fence_mgr {
u64 ev_fence_ctx;
atomic_t ev_fence_seq;
- spinlock_t ev_fence_lock;
- struct amdgpu_eviction_fence *ev_fence;
- struct delayed_work suspend_work;
- uint8_t fd_closing;
-};
-
-/* Eviction fence helper functions */
-struct amdgpu_eviction_fence *
-amdgpu_eviction_fence_create(struct amdgpu_eviction_fence_mgr *evf_mgr);
-void
-amdgpu_eviction_fence_destroy(struct amdgpu_eviction_fence_mgr *evf_mgr);
-
-int
-amdgpu_eviction_fence_attach(struct amdgpu_eviction_fence_mgr *evf_mgr,
- struct amdgpu_bo *bo);
+ /*
+ * Only updated while holding the VM resv lock.
+ * Only signaled while holding the userq mutex.
+ */
+ struct dma_fence __rcu *ev_fence;
+ struct work_struct suspend_work;
+ bool shutdown;
+};
-void
-amdgpu_eviction_fence_detach(struct amdgpu_eviction_fence_mgr *evf_mgr,
- struct amdgpu_bo *bo);
+static inline struct dma_fence *
+amdgpu_evf_mgr_get_fence(struct amdgpu_eviction_fence_mgr *evf_mgr)
+{
+ struct dma_fence *ev_fence;
-int
-amdgpu_eviction_fence_init(struct amdgpu_eviction_fence_mgr *evf_mgr);
+ rcu_read_lock();
+ ev_fence = dma_fence_get_rcu_safe(&evf_mgr->ev_fence);
+ rcu_read_unlock();
+ return ev_fence;
+}
-void
-amdgpu_eviction_fence_signal(struct amdgpu_eviction_fence_mgr *evf_mgr,
- struct amdgpu_eviction_fence *ev_fence);
+int amdgpu_evf_mgr_attach_fence(struct amdgpu_eviction_fence_mgr *evf_mgr,
+ struct amdgpu_bo *bo);
+int amdgpu_evf_mgr_rearm(struct amdgpu_eviction_fence_mgr *evf_mgr,
+ struct drm_exec *exec);
+void amdgpu_evf_mgr_detach_fence(struct amdgpu_eviction_fence_mgr *evf_mgr,
+ struct amdgpu_bo *bo);
+void amdgpu_evf_mgr_init(struct amdgpu_eviction_fence_mgr *evf_mgr);
+void amdgpu_evf_mgr_shutdown(struct amdgpu_eviction_fence_mgr *evf_mgr);
+void amdgpu_evf_mgr_flush_suspend(struct amdgpu_eviction_fence_mgr *evf_mgr);
+void amdgpu_evf_mgr_fini(struct amdgpu_eviction_fence_mgr *evf_mgr);
-int
-amdgpu_eviction_fence_replace_fence(struct amdgpu_eviction_fence_mgr *evf_mgr,
- struct drm_exec *exec);
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
index d209591e3710..8048a4c04b47 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
@@ -438,7 +438,7 @@ int amdgpu_fence_driver_start_ring(struct amdgpu_ring *ring,
* @ring: ring to init the fence driver on
*
* Init the fence driver for the requested ring (all asics).
- * Helper function for amdgpu_fence_driver_init().
+ * Helper function for amdgpu_fence_driver_sw_init().
*/
int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring)
{
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c
index 514bd302365f..841e1b3a017e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c
@@ -106,6 +106,7 @@ static bool is_fru_eeprom_supported(struct amdgpu_device *adev, u32 *fru_addr)
*fru_addr = FRU_EEPROM_MADDR_8;
return true;
case IP_VERSION(13, 0, 12):
+ case IP_VERSION(15, 0, 8):
if (fru_addr)
*fru_addr = FRU_EEPROM_MADDR_INV;
return true;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c
index e2d32c29668a..bc772ca3dab7 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c
@@ -404,6 +404,50 @@ void amdgpu_gart_map_vram_range(struct amdgpu_device *adev, uint64_t pa,
}
/**
+ * amdgpu_gart_map_gfx9_mqd - map mqd and ctrl_stack dma_addresses into GART entries
+ *
+ * @adev: amdgpu_device pointer
+ * @offset: offset into the GPU's gart aperture
+ * @pages: number of pages to bind
+ * @dma_addr: DMA addresses of pages
+ * @flags: page table entry flags
+ *
+ * Map the MQD and control stack addresses into GART entries with the correct
+ * memory types on gfxv9. The MQD occupies the first 4KB and is followed by
+ * the control stack. The MQD uses UC (uncached) memory, while the control stack
+ * uses NC (non-coherent) memory.
+ */
+void amdgpu_gart_map_gfx9_mqd(struct amdgpu_device *adev, uint64_t offset,
+ int pages, dma_addr_t *dma_addr, uint64_t flags)
+{
+ uint64_t page_base;
+ unsigned int i, j, t;
+ int idx;
+ uint64_t ctrl_flags = AMDGPU_PTE_MTYPE_VG10(flags, AMDGPU_MTYPE_NC);
+ void *dst;
+
+ if (!adev->gart.ptr)
+ return;
+
+ if (!drm_dev_enter(adev_to_drm(adev), &idx))
+ return;
+
+ t = offset / AMDGPU_GPU_PAGE_SIZE;
+ dst = adev->gart.ptr;
+ for (i = 0; i < pages; i++) {
+ page_base = dma_addr[i];
+ for (j = 0; j < AMDGPU_GPU_PAGES_IN_CPU_PAGE; j++, t++) {
+ if ((i == 0) && (j == 0))
+ amdgpu_gmc_set_pte_pde(adev, dst, t, page_base, flags);
+ else
+ amdgpu_gmc_set_pte_pde(adev, dst, t, page_base, ctrl_flags);
+ page_base += AMDGPU_GPU_PAGE_SIZE;
+ }
+ }
+ drm_dev_exit(idx);
+}
+
+/**
* amdgpu_gart_bind - bind pages into the gart page table
*
* @adev: amdgpu_device pointer
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.h
index d3118275ddae..6ebd2da32ea6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.h
@@ -62,6 +62,8 @@ void amdgpu_gart_unbind(struct amdgpu_device *adev, uint64_t offset,
void amdgpu_gart_map(struct amdgpu_device *adev, uint64_t offset,
int pages, dma_addr_t *dma_addr, uint64_t flags,
void *dst);
+void amdgpu_gart_map_gfx9_mqd(struct amdgpu_device *adev, uint64_t offset,
+ int pages, dma_addr_t *dma_addr, uint64_t flags);
void amdgpu_gart_bind(struct amdgpu_device *adev, uint64_t offset,
int pages, dma_addr_t *dma_addr, uint64_t flags);
void amdgpu_gart_map_vram_range(struct amdgpu_device *adev, uint64_t pa,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
index a6107109a2b8..5376035d32fe 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
@@ -30,6 +30,7 @@
#include <linux/pagemap.h>
#include <linux/pci.h>
#include <linux/dma-buf.h>
+#include <linux/dma-fence-unwrap.h>
#include <drm/amdgpu_drm.h>
#include <drm/drm_drv.h>
@@ -106,6 +107,7 @@ amdgpu_gem_update_timeline_node(struct drm_file *filp,
*chain = dma_fence_chain_alloc();
if (!*chain) {
drm_syncobj_put(*syncobj);
+ *syncobj = NULL;
return -ENOMEM;
}
@@ -258,18 +260,15 @@ static int amdgpu_gem_object_open(struct drm_gem_object *obj,
amdgpu_vm_bo_update_shared(abo);
bo_va = amdgpu_vm_bo_find(vm, abo);
- if (!bo_va)
+ if (!bo_va) {
bo_va = amdgpu_vm_bo_add(adev, vm, abo);
- else
+ r = amdgpu_evf_mgr_attach_fence(&fpriv->evf_mgr, abo);
+ if (r)
+ goto out_unlock;
+ } else {
++bo_va->ref_count;
-
- /* attach gfx eviction fence */
- r = amdgpu_eviction_fence_attach(&fpriv->evf_mgr, abo);
- if (r) {
- DRM_DEBUG_DRIVER("Failed to attach eviction fence to BO\n");
- amdgpu_bo_unreserve(abo);
- return r;
}
+
drm_exec_fini(&exec);
/* Validate and add eviction fence to DMABuf imports with dynamic
@@ -337,7 +336,7 @@ static void amdgpu_gem_object_close(struct drm_gem_object *obj,
}
if (!amdgpu_vm_is_bo_always_valid(vm, bo))
- amdgpu_eviction_fence_detach(&fpriv->evf_mgr, bo);
+ amdgpu_evf_mgr_detach_fence(&fpriv->evf_mgr, bo);
bo_va = amdgpu_vm_bo_find(vm, bo);
if (!bo_va || --bo_va->ref_count)
@@ -744,11 +743,10 @@ amdgpu_gem_va_update_vm(struct amdgpu_device *adev,
struct dma_fence *fence;
int r = 0;
- /* Always start from the VM's existing last update fence. */
- fence = dma_fence_get(vm->last_update);
-
+ /* If the VM is not ready return only a stub. */
if (!amdgpu_vm_ready(vm))
- return fence;
+ return dma_fence_get_stub();
+
/*
* First clean up any freed mappings in the VM.
@@ -757,7 +755,7 @@ amdgpu_gem_va_update_vm(struct amdgpu_device *adev,
* schedules GPU work. If nothing needs clearing, @fence can remain as
* the original vm->last_update.
*/
- r = amdgpu_vm_clear_freed(adev, vm, &fence);
+ r = amdgpu_vm_clear_freed(adev, vm, &vm->last_update);
if (r)
goto error;
@@ -774,47 +772,34 @@ amdgpu_gem_va_update_vm(struct amdgpu_device *adev,
if (r)
goto error;
- /*
- * Decide which fence best represents the last update:
- *
- * MAP/REPLACE:
- * - For always-valid mappings, use vm->last_update.
- * - Otherwise, export bo_va->last_pt_update.
- *
- * UNMAP/CLEAR:
- * Keep the fence returned by amdgpu_vm_clear_freed(). If no work was
- * needed, it can remain as vm->last_pt_update.
- *
- * The VM and BO update fences are always initialized to a valid value.
- * vm->last_update and bo_va->last_pt_update always start as valid fences.
- * and are never expected to be NULL.
- */
- switch (operation) {
- case AMDGPU_VA_OP_MAP:
- case AMDGPU_VA_OP_REPLACE:
+ if ((operation == AMDGPU_VA_OP_MAP ||
+ operation == AMDGPU_VA_OP_REPLACE) &&
+ !amdgpu_vm_is_bo_always_valid(vm, bo_va->base.bo)) {
+
/*
- * For MAP/REPLACE, return the page table update fence for the
- * mapping we just modified. bo_va is expected to be valid here.
+ * For MAP/REPLACE of non per-VM BOs we need to sync to both the
+ * bo_va->last_pt_update and vm->last_update or otherwise we
+ * potentially miss the PDE updates.
*/
- dma_fence_put(fence);
-
- if (amdgpu_vm_is_bo_always_valid(vm, bo_va->base.bo))
- fence = dma_fence_get(vm->last_update);
- else
- fence = dma_fence_get(bo_va->last_pt_update);
- break;
- case AMDGPU_VA_OP_UNMAP:
- case AMDGPU_VA_OP_CLEAR:
- default:
- /* keep @fence as returned by amdgpu_vm_clear_freed() */
- break;
+ fence = dma_fence_unwrap_merge(vm->last_update,
+ bo_va->last_pt_update);
+ if (!fence) {
+ /* As fallback in OOM situations */
+ dma_fence_wait(vm->last_update, false);
+ dma_fence_wait(bo_va->last_pt_update, false);
+ fence = dma_fence_get_stub();
+ }
+ } else {
+ fence = dma_fence_get(vm->last_update);
}
+ return fence;
+
error:
if (r && r != -ERESTARTSYS)
DRM_ERROR("Couldn't update BO_VA (%d)\n", r);
- return fence;
+ return dma_fence_get(vm->last_update);
}
int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
@@ -835,7 +820,6 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
struct amdgpu_bo_va *bo_va;
struct drm_syncobj *timeline_syncobj = NULL;
struct dma_fence_chain *timeline_chain = NULL;
- struct dma_fence *fence;
struct drm_exec exec;
uint64_t vm_size;
int r = 0;
@@ -887,6 +871,10 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
return -EINVAL;
}
+ if (args->flags & AMDGPU_VM_DELAY_UPDATE &&
+ args->vm_timeline_syncobj_out)
+ return -EINVAL;
+
if ((args->operation != AMDGPU_VA_OP_CLEAR) &&
!(args->flags & AMDGPU_VM_PAGE_PRT)) {
gobj = drm_gem_object_lookup(filp, args->handle);
@@ -976,11 +964,13 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
* that represents the last relevant update for this mapping. This
* fence can then be exported to the user-visible VM timeline.
*/
- if (!r && !(args->flags & AMDGPU_VM_DELAY_UPDATE) && !adev->debug_vm) {
+ if (!r && !(args->flags & AMDGPU_VM_DELAY_UPDATE) &&
+ (!adev->debug_vm || timeline_syncobj)) {
+ struct dma_fence *fence;
+
fence = amdgpu_gem_va_update_vm(adev, &fpriv->vm, bo_va,
args->operation);
-
- if (timeline_syncobj && fence) {
+ if (timeline_syncobj) {
if (!args->vm_timeline_point) {
/* Replace the existing fence when no point is given. */
drm_syncobj_replace_fence(timeline_syncobj,
@@ -991,6 +981,7 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
timeline_chain,
fence,
args->vm_timeline_point);
+ timeline_chain = NULL;
}
}
dma_fence_put(fence);
@@ -998,6 +989,9 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
}
error:
+ dma_fence_chain_free(timeline_chain);
+ if (timeline_syncobj)
+ drm_syncobj_put(timeline_syncobj);
drm_exec_fini(&exec);
error_put_gobj:
drm_gem_object_put(gobj);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
index 720ed3a2c78c..2785eda6fea5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
@@ -463,6 +463,7 @@ struct amdgpu_gfx {
struct amdgpu_irq_src cp_ecc_error_irq;
struct amdgpu_irq_src sq_irq;
struct amdgpu_irq_src rlc_gc_fed_irq;
+ struct amdgpu_irq_src rlc_poison_irq;
struct sq_work sq_work;
/* gfx status */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
index a0940db1cd36..ec74f3971732 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
@@ -34,6 +34,7 @@
#include "amdgpu_ras.h"
#include "amdgpu_reset.h"
#include "amdgpu_xgmi.h"
+#include "amdgpu_atomfirmware.h"
#include <drm/drm_drv.h>
#include <drm/ttm/ttm_tt.h>
@@ -1374,18 +1375,18 @@ int amdgpu_gmc_get_nps_memranges(struct amdgpu_device *adev,
struct amdgpu_mem_partition_info *mem_ranges,
uint8_t *exp_ranges)
{
- struct amdgpu_gmc_memrange *ranges;
+ struct amdgpu_gmc_memrange ranges[AMDGPU_MAX_MEM_RANGES];
int range_cnt, ret, i, j;
uint32_t nps_type;
bool refresh;
if (!mem_ranges || !exp_ranges)
return -EINVAL;
-
+ range_cnt = AMDGPU_MAX_MEM_RANGES;
refresh = (adev->init_lvl->level != AMDGPU_INIT_LEVEL_MINIMAL_XGMI) &&
(adev->gmc.reset_flags & AMDGPU_GMC_INIT_RESET_NPS);
- ret = amdgpu_discovery_get_nps_info(adev, &nps_type, &ranges,
- &range_cnt, refresh);
+ ret = amdgpu_discovery_get_nps_info(adev, &nps_type, ranges, &range_cnt,
+ refresh);
if (ret)
return ret;
@@ -1446,8 +1447,6 @@ int amdgpu_gmc_get_nps_memranges(struct amdgpu_device *adev,
if (!*exp_ranges)
*exp_ranges = range_cnt;
err:
- kvfree(ranges);
-
return ret;
}
@@ -1749,3 +1748,31 @@ int amdgpu_gmc_init_mem_ranges(struct amdgpu_device *adev)
return 0;
}
+
+int amdgpu_gmc_get_vram_info(struct amdgpu_device *adev,
+ int *vram_width, int *vram_type, int *vram_vendor)
+{
+ int ret = 0;
+
+ if (adev->flags & AMD_IS_APU)
+ return amdgpu_atomfirmware_get_integrated_system_info(adev,
+ vram_width, vram_type, vram_vendor);
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
+ case IP_VERSION(12, 0, 0):
+ case IP_VERSION(12, 0, 1):
+ return amdgpu_atomfirmware_get_umc_info(adev,
+ vram_width, vram_type, vram_vendor);
+ case IP_VERSION(9, 5, 0):
+ case IP_VERSION(9, 4, 4):
+ case IP_VERSION(9, 4, 3):
+ ret = amdgpu_atomfirmware_get_umc_info(adev,
+ vram_width, vram_type, vram_vendor);
+ if (vram_width && !ret)
+ *vram_width *= hweight32(adev->aid_mask);
+ return ret;
+ default:
+ return amdgpu_atomfirmware_get_vram_info(adev,
+ vram_width, vram_type, vram_vendor);
+ }
+ return 0;
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
index b9fdc3276e81..32e73e8ba778 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
@@ -482,4 +482,6 @@ amdgpu_gmc_query_memory_partition(struct amdgpu_device *adev);
int amdgpu_gmc_init_mem_ranges(struct amdgpu_device *adev);
void amdgpu_gmc_init_sw_mem_ranges(struct amdgpu_device *adev,
struct amdgpu_mem_partition_info *mem_ranges);
+int amdgpu_gmc_get_vram_info(struct amdgpu_device *adev,
+ int *vram_width, int *vram_type, int *vram_vendor);
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
index 64c519cd7395..569c5a89ff10 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
@@ -35,10 +35,13 @@
* PASIDs are global address space identifiers that can be shared
* between the GPU, an IOMMU and the driver. VMs on different devices
* may use the same PASID if they share the same address
- * space. Therefore PASIDs are allocated using a global IDA. VMs are
- * looked up from the PASID per amdgpu_device.
+ * space. Therefore PASIDs are allocated using IDR cyclic allocator
+ * (similar to kernel PID allocation) which naturally delays reuse.
+ * VMs are looked up from the PASID per amdgpu_device.
*/
-static DEFINE_IDA(amdgpu_pasid_ida);
+
+static DEFINE_IDR(amdgpu_pasid_idr);
+static DEFINE_SPINLOCK(amdgpu_pasid_idr_lock);
/* Helper to free pasid from a fence callback */
struct amdgpu_pasid_cb {
@@ -50,8 +53,8 @@ struct amdgpu_pasid_cb {
* amdgpu_pasid_alloc - Allocate a PASID
* @bits: Maximum width of the PASID in bits, must be at least 1
*
- * Allocates a PASID of the given width while keeping smaller PASIDs
- * available if possible.
+ * Uses kernel's IDR cyclic allocator (same as PID allocation).
+ * Allocates sequentially with automatic wrap-around.
*
* Returns a positive integer on success. Returns %-EINVAL if bits==0.
* Returns %-ENOSPC if no PASID was available. Returns %-ENOMEM on
@@ -59,14 +62,18 @@ struct amdgpu_pasid_cb {
*/
int amdgpu_pasid_alloc(unsigned int bits)
{
- int pasid = -EINVAL;
+ int pasid;
- for (bits = min(bits, 31U); bits > 0; bits--) {
- pasid = ida_alloc_range(&amdgpu_pasid_ida, 1U << (bits - 1),
- (1U << bits) - 1, GFP_KERNEL);
- if (pasid != -ENOSPC)
- break;
- }
+ if (bits == 0)
+ return -EINVAL;
+
+ spin_lock(&amdgpu_pasid_idr_lock);
+ /* TODO: Need to replace the idr with an xarry, and then
+ * handle the internal locking with ATOMIC safe paths.
+ */
+ pasid = idr_alloc_cyclic(&amdgpu_pasid_idr, NULL, 1,
+ 1U << bits, GFP_ATOMIC);
+ spin_unlock(&amdgpu_pasid_idr_lock);
if (pasid >= 0)
trace_amdgpu_pasid_allocated(pasid);
@@ -81,7 +88,10 @@ int amdgpu_pasid_alloc(unsigned int bits)
void amdgpu_pasid_free(u32 pasid)
{
trace_amdgpu_pasid_freed(pasid);
- ida_free(&amdgpu_pasid_ida, pasid);
+
+ spin_lock(&amdgpu_pasid_idr_lock);
+ idr_remove(&amdgpu_pasid_idr, pasid);
+ spin_unlock(&amdgpu_pasid_idr_lock);
}
static void amdgpu_pasid_free_cb(struct dma_fence *fence,
@@ -616,3 +626,15 @@ void amdgpu_vmid_mgr_fini(struct amdgpu_device *adev)
}
}
}
+
+/**
+ * amdgpu_pasid_mgr_cleanup - cleanup PASID manager
+ *
+ * Cleanup the IDR allocator.
+ */
+void amdgpu_pasid_mgr_cleanup(void)
+{
+ spin_lock(&amdgpu_pasid_idr_lock);
+ idr_destroy(&amdgpu_pasid_idr);
+ spin_unlock(&amdgpu_pasid_idr_lock);
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h
index b3649cd3af56..a57919478d3b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h
@@ -74,6 +74,7 @@ int amdgpu_pasid_alloc(unsigned int bits);
void amdgpu_pasid_free(u32 pasid);
void amdgpu_pasid_free_delayed(struct dma_resv *resv,
u32 pasid);
+void amdgpu_pasid_mgr_cleanup(void);
bool amdgpu_vmid_had_gpu_reset(struct amdgpu_device *adev,
struct amdgpu_vmid *id);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
index 7f19554b9ad1..06efce38f323 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -1522,10 +1522,7 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
"Failed to init usermode queue manager (%d), use legacy workload submission only\n",
r);
- r = amdgpu_eviction_fence_init(&fpriv->evf_mgr);
- if (r)
- goto error_vm;
-
+ amdgpu_evf_mgr_init(&fpriv->evf_mgr);
amdgpu_ctx_mgr_init(&fpriv->ctx_mgr, adev);
file_priv->driver_priv = fpriv;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.h
index 1ca9d4ed8063..6b8214650e5d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.h
@@ -63,14 +63,40 @@ struct amdgpu_mmhub_funcs {
uint64_t page_table_base);
void (*update_power_gating)(struct amdgpu_device *adev,
bool enable);
+ int (*get_xgmi_info)(struct amdgpu_device *adev);
+};
+
+struct amdgpu_mmhub_client_ids {
+ const char * const (*names)[2];
+ unsigned int size;
};
struct amdgpu_mmhub {
struct ras_common_if *ras_if;
const struct amdgpu_mmhub_funcs *funcs;
struct amdgpu_mmhub_ras *ras;
+ struct amdgpu_mmhub_client_ids client_ids;
};
+static inline void
+amdgpu_mmhub_init_client_info(struct amdgpu_mmhub *mmhub,
+ const char * const (*names)[2],
+ unsigned int size)
+{
+ mmhub->client_ids.names = names;
+ mmhub->client_ids.size = size;
+}
+
+static inline const char *
+amdgpu_mmhub_client_name(struct amdgpu_mmhub *mmhub,
+ u32 cid, bool is_write)
+{
+ if (cid < mmhub->client_ids.size)
+ return mmhub->client_ids.names[cid][is_write];
+
+ return NULL;
+}
+
int amdgpu_mmhub_ras_sw_init(struct amdgpu_device *adev);
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
index 90352284c5ee..51ab1a332615 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
@@ -44,6 +44,7 @@
#include <drm/display/drm_dp_mst_helper.h>
#include "modules/inc/mod_freesync.h"
#include "amdgpu_dm_irq_params.h"
+#include "amdgpu_dm_ism.h"
struct amdgpu_bo;
struct amdgpu_device;
@@ -486,6 +487,10 @@ struct amdgpu_crtc {
int deferred_flip_completion;
/* parameters access from DM IRQ handler */
struct dm_irq_params dm_irq_params;
+
+ /* DM idle state manager */
+ struct amdgpu_dm_ism ism;
+
/* pll sharing */
struct amdgpu_atom_ss ss;
bool ss_enabled;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
index cc004830a8a2..27f7567df7bf 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
@@ -1325,7 +1325,8 @@ void amdgpu_bo_release_notify(struct ttm_buffer_object *bo)
if (r)
goto out;
- r = amdgpu_fill_buffer(&adev->mman.clear_entity, abo, 0, &bo->base._resv,
+ r = amdgpu_fill_buffer(amdgpu_ttm_next_clear_entity(adev),
+ abo, 0, &bo->base._resv,
&fence, AMDGPU_KERNEL_JOB_ID_CLEAR_ON_RELEASE);
if (WARN_ON(r))
goto out;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
index 741d1919ef88..6edcb7713299 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
@@ -2250,6 +2250,7 @@ static bool amdgpu_ras_aca_is_supported(struct amdgpu_device *adev)
case IP_VERSION(13, 0, 6):
case IP_VERSION(13, 0, 12):
case IP_VERSION(13, 0, 14):
+ case IP_VERSION(13, 0, 15):
ret = true;
break;
default:
@@ -4000,6 +4001,7 @@ static bool amdgpu_ras_asic_supported(struct amdgpu_device *adev)
case IP_VERSION(13, 0, 6):
case IP_VERSION(13, 0, 12):
case IP_VERSION(13, 0, 14):
+ case IP_VERSION(13, 0, 15):
return true;
default:
return false;
@@ -4013,6 +4015,7 @@ static bool amdgpu_ras_asic_supported(struct amdgpu_device *adev)
case IP_VERSION(13, 0, 10):
case IP_VERSION(13, 0, 12):
case IP_VERSION(13, 0, 14):
+ case IP_VERSION(13, 0, 15):
case IP_VERSION(14, 0, 3):
return true;
default:
@@ -4182,7 +4185,8 @@ init_ras_enabled_flag:
adev->aca.is_enabled =
(amdgpu_ip_version(adev, MP0_HWIP, 0) == IP_VERSION(13, 0, 6) ||
amdgpu_ip_version(adev, MP0_HWIP, 0) == IP_VERSION(13, 0, 12) ||
- amdgpu_ip_version(adev, MP0_HWIP, 0) == IP_VERSION(13, 0, 14));
+ amdgpu_ip_version(adev, MP0_HWIP, 0) == IP_VERSION(13, 0, 14) ||
+ amdgpu_ip_version(adev, MP0_HWIP, 0) == IP_VERSION(13, 0, 15));
}
/* bad page feature is not applicable to specific app platform */
@@ -4270,6 +4274,7 @@ static void amdgpu_ras_init_reserved_vram_size(struct amdgpu_device *adev)
case IP_VERSION(13, 0, 2):
case IP_VERSION(13, 0, 6):
case IP_VERSION(13, 0, 12):
+ case IP_VERSION(13, 0, 15):
con->reserved_pages_in_bytes = AMDGPU_RAS_RESERVED_VRAM_SIZE_DEFAULT;
break;
case IP_VERSION(13, 0, 14):
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
index 44fba4b6aa92..cdf4909592d2 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
@@ -1558,6 +1558,8 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control)
unsigned char buf[RAS_TABLE_HEADER_SIZE] = { 0 };
struct amdgpu_ras_eeprom_table_header *hdr = &control->tbl_hdr;
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
+ int dev_var = adev->pdev->device & 0xF;
+ uint32_t vram_type = adev->gmc.vram_type;
int res;
if (amdgpu_ras_smu_eeprom_supported(adev))
@@ -1597,6 +1599,12 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control)
return amdgpu_ras_eeprom_reset_table(control);
}
+ if (!(adev->flags & AMD_IS_APU) && (dev_var == 0x5) &&
+ (vram_type == AMDGPU_VRAM_TYPE_HBM3E) &&
+ (hdr->version < RAS_TABLE_VER_V3)) {
+ return amdgpu_ras_eeprom_reset_table(control);
+ }
+
switch (hdr->version) {
case RAS_TABLE_VER_V2_1:
case RAS_TABLE_VER_V3:
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_reg_access.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_reg_access.c
index bf8645390bdc..540040c76058 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_reg_access.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_reg_access.c
@@ -314,7 +314,6 @@ uint64_t amdgpu_reg_get_smn_base64(struct amdgpu_device *adev,
"SMN base address query not supported for this device\n");
return 0;
}
- return 0;
}
return adev->reg.smn.get_smn_base(adev, block, die_inst);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c
index 341beec59537..0eecfaa3a94c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c
@@ -103,10 +103,8 @@ int amdgpu_sched_ioctl(struct drm_device *dev, void *data,
return -EINVAL;
}
- if (!amdgpu_ctx_priority_is_valid(args->in.priority)) {
- WARN(1, "Invalid context priority %d\n", args->in.priority);
+ if (!amdgpu_ctx_priority_is_valid(args->in.priority))
return -EINVAL;
- }
switch (args->in.op) {
case AMDGPU_SCHED_OP_PROCESS_PRIORITY_OVERRIDE:
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index b4ab309bf08a..afaaab6496de 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -387,9 +387,11 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo,
{
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev);
struct amdgpu_bo *abo = ttm_to_amdgpu_bo(bo);
+ struct amdgpu_ttm_buffer_entity *entity;
struct amdgpu_copy_mem src, dst;
struct dma_fence *fence = NULL;
int r;
+ u32 e;
src.bo = bo;
dst.bo = bo;
@@ -398,8 +400,12 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo,
src.offset = 0;
dst.offset = 0;
+ e = atomic_inc_return(&adev->mman.next_move_entity) %
+ adev->mman.num_move_entities;
+ entity = &adev->mman.move_entities[e];
+
r = amdgpu_ttm_copy_mem_to_mem(adev,
- &adev->mman.move_entity,
+ entity,
&src, &dst,
new_mem->size,
amdgpu_bo_encrypted(abo),
@@ -411,9 +417,7 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo,
if (old_mem->mem_type == TTM_PL_VRAM &&
(abo->flags & AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE)) {
struct dma_fence *wipe_fence = NULL;
-
- r = amdgpu_fill_buffer(&adev->mman.move_entity,
- abo, 0, NULL, &wipe_fence,
+ r = amdgpu_fill_buffer(entity, abo, 0, NULL, &wipe_fence,
AMDGPU_KERNEL_JOB_ID_MOVE_BLIT);
if (r) {
goto error;
@@ -854,25 +858,15 @@ static void amdgpu_ttm_gart_bind_gfx9_mqd(struct amdgpu_device *adev,
int num_xcc = max(1U, adev->gfx.num_xcc_per_xcp);
uint64_t page_idx, pages_per_xcc;
int i;
- uint64_t ctrl_flags = AMDGPU_PTE_MTYPE_VG10(flags, AMDGPU_MTYPE_NC);
pages_per_xcc = total_pages;
do_div(pages_per_xcc, num_xcc);
for (i = 0, page_idx = 0; i < num_xcc; i++, page_idx += pages_per_xcc) {
- /* MQD page: use default flags */
- amdgpu_gart_bind(adev,
+ amdgpu_gart_map_gfx9_mqd(adev,
gtt->offset + (page_idx << PAGE_SHIFT),
- 1, &gtt->ttm.dma_address[page_idx], flags);
- /*
- * Ctrl pages - modify the memory type to NC (ctrl_flags) from
- * the second page of the BO onward.
- */
- amdgpu_gart_bind(adev,
- gtt->offset + ((page_idx + 1) << PAGE_SHIFT),
- pages_per_xcc - 1,
- &gtt->ttm.dma_address[page_idx + 1],
- ctrl_flags);
+ pages_per_xcc, &gtt->ttm.dma_address[page_idx],
+ flags);
}
}
@@ -2345,8 +2339,9 @@ void amdgpu_ttm_fini(struct amdgpu_device *adev)
void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable)
{
struct ttm_resource_manager *man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM);
+ u32 num_clear_entities, num_move_entities;
uint64_t size;
- int r;
+ int r, i, j;
if (!adev->mman.initialized || amdgpu_in_reset(adev) ||
adev->mman.buffer_funcs_enabled == enable || adev->gmc.is_app_apu)
@@ -2361,6 +2356,8 @@ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable)
return;
}
+ num_clear_entities = 1;
+ num_move_entities = 1;
ring = adev->mman.buffer_funcs_ring;
sched = &ring->sched;
r = amdgpu_ttm_buffer_entity_init(&adev->mman.gtt_mgr,
@@ -2373,36 +2370,64 @@ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable)
return;
}
- r = amdgpu_ttm_buffer_entity_init(&adev->mman.gtt_mgr,
- &adev->mman.clear_entity,
- DRM_SCHED_PRIORITY_NORMAL,
- &sched, 1, 1);
- if (r < 0) {
- dev_err(adev->dev,
- "Failed setting up TTM BO clear entity (%d)\n", r);
+ adev->mman.clear_entities = kcalloc(num_clear_entities,
+ sizeof(struct amdgpu_ttm_buffer_entity),
+ GFP_KERNEL);
+ atomic_set(&adev->mman.next_clear_entity, 0);
+ if (!adev->mman.clear_entities)
goto error_free_default_entity;
+
+ adev->mman.num_clear_entities = num_clear_entities;
+
+ for (i = 0; i < num_clear_entities; i++) {
+ r = amdgpu_ttm_buffer_entity_init(
+ &adev->mman.gtt_mgr, &adev->mman.clear_entities[i],
+ DRM_SCHED_PRIORITY_NORMAL, &sched, 1, 1);
+
+ if (r < 0) {
+ for (j = 0; j < i; j++)
+ amdgpu_ttm_buffer_entity_fini(
+ &adev->mman.gtt_mgr, &adev->mman.clear_entities[j]);
+ kfree(adev->mman.clear_entities);
+ adev->mman.num_clear_entities = 0;
+ adev->mman.clear_entities = NULL;
+ goto error_free_default_entity;
+ }
}
- r = amdgpu_ttm_buffer_entity_init(&adev->mman.gtt_mgr,
- &adev->mman.move_entity,
- DRM_SCHED_PRIORITY_NORMAL,
- &sched, 1, 2);
- if (r < 0) {
- dev_err(adev->dev,
- "Failed setting up TTM BO move entity (%d)\n", r);
- goto error_free_clear_entity;
+ adev->mman.num_move_entities = num_move_entities;
+ atomic_set(&adev->mman.next_move_entity, 0);
+ for (i = 0; i < num_move_entities; i++) {
+ r = amdgpu_ttm_buffer_entity_init(
+ &adev->mman.gtt_mgr,
+ &adev->mman.move_entities[i],
+ DRM_SCHED_PRIORITY_NORMAL, &sched, 1, 2);
+
+ if (r < 0) {
+ for (j = 0; j < i; j++)
+ amdgpu_ttm_buffer_entity_fini(
+ &adev->mman.gtt_mgr, &adev->mman.move_entities[j]);
+ adev->mman.num_move_entities = 0;
+ goto error_free_clear_entities;
+ }
}
} else {
amdgpu_ttm_buffer_entity_fini(&adev->mman.gtt_mgr,
&adev->mman.default_entity);
- amdgpu_ttm_buffer_entity_fini(&adev->mman.gtt_mgr,
- &adev->mman.clear_entity);
- amdgpu_ttm_buffer_entity_fini(&adev->mman.gtt_mgr,
- &adev->mman.move_entity);
+ for (i = 0; i < adev->mman.num_clear_entities; i++)
+ amdgpu_ttm_buffer_entity_fini(&adev->mman.gtt_mgr,
+ &adev->mman.clear_entities[i]);
+ for (i = 0; i < adev->mman.num_move_entities; i++)
+ amdgpu_ttm_buffer_entity_fini(&adev->mman.gtt_mgr,
+ &adev->mman.move_entities[i]);
/* Drop all the old fences since re-creating the scheduler entities
* will allocate new contexts.
*/
ttm_resource_manager_cleanup(man);
+ kfree(adev->mman.clear_entities);
+ adev->mman.clear_entities = NULL;
+ adev->mman.num_clear_entities = 0;
+ adev->mman.num_move_entities = 0;
}
/* this just adjusts TTM size idea, which sets lpfn to the correct value */
@@ -2415,9 +2440,13 @@ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable)
return;
-error_free_clear_entity:
- amdgpu_ttm_buffer_entity_fini(&adev->mman.gtt_mgr,
- &adev->mman.clear_entity);
+error_free_clear_entities:
+ for (i = 0; i < adev->mman.num_clear_entities; i++)
+ amdgpu_ttm_buffer_entity_fini(&adev->mman.gtt_mgr,
+ &adev->mman.clear_entities[i]);
+ kfree(adev->mman.clear_entities);
+ adev->mman.clear_entities = NULL;
+ adev->mman.num_clear_entities = 0;
error_free_default_entity:
amdgpu_ttm_buffer_entity_fini(&adev->mman.gtt_mgr,
&adev->mman.default_entity);
@@ -2567,8 +2596,7 @@ int amdgpu_ttm_clear_buffer(struct amdgpu_bo *bo,
if (!fence)
return -EINVAL;
-
- entity = &adev->mman.clear_entity;
+ entity = &adev->mman.clear_entities[0];
*fence = dma_fence_get_stub();
amdgpu_res_first(bo->tbo.resource, 0, amdgpu_bo_size(bo), &cursor);
@@ -2620,11 +2648,8 @@ int amdgpu_fill_buffer(struct amdgpu_ttm_buffer_entity *entity,
struct amdgpu_res_cursor dst;
int r;
- if (!adev->mman.buffer_funcs_enabled) {
- dev_err(adev->dev,
- "Trying to clear memory with ring turned off.\n");
+ if (!entity)
return -EINVAL;
- }
amdgpu_res_first(bo->tbo.resource, 0, amdgpu_bo_size(bo), &dst);
@@ -2660,6 +2685,20 @@ error:
return r;
}
+struct amdgpu_ttm_buffer_entity *
+amdgpu_ttm_next_clear_entity(struct amdgpu_device *adev)
+{
+ struct amdgpu_mman *mman = &adev->mman;
+ u32 i;
+
+ if (mman->num_clear_entities == 0)
+ return NULL;
+
+ i = atomic_inc_return(&mman->next_clear_entity) %
+ mman->num_clear_entities;
+ return &mman->clear_entities[i];
+}
+
/**
* amdgpu_ttm_evict_resources - evict memory buffers
* @adev: amdgpu device object
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
index bf101215757e..3b1973611446 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
@@ -72,8 +72,12 @@ struct amdgpu_mman {
/* @default_entity: for workarounds, has no gart windows */
struct amdgpu_ttm_buffer_entity default_entity;
- struct amdgpu_ttm_buffer_entity clear_entity;
- struct amdgpu_ttm_buffer_entity move_entity;
+ struct amdgpu_ttm_buffer_entity *clear_entities;
+ atomic_t next_clear_entity;
+ u32 num_clear_entities;
+ struct amdgpu_ttm_buffer_entity move_entities[TTM_NUM_MOVE_FENCES];
+ atomic_t next_move_entity;
+ u32 num_move_entities;
struct amdgpu_vram_mgr vram_mgr;
struct amdgpu_gtt_mgr gtt_mgr;
@@ -191,6 +195,7 @@ int amdgpu_fill_buffer(struct amdgpu_ttm_buffer_entity *entity,
struct dma_resv *resv,
struct dma_fence **f,
u64 k_job_id);
+struct amdgpu_ttm_buffer_entity *amdgpu_ttm_next_clear_entity(struct amdgpu_device *adev);
int amdgpu_ttm_alloc_gart(struct ttm_buffer_object *bo);
void amdgpu_ttm_recover_gart(struct ttm_buffer_object *tbo);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
index 82333aeb4453..6d9e96fabd58 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
@@ -1150,7 +1150,7 @@ int amdgpu_ucode_create_bo(struct amdgpu_device *adev)
if ((adev->firmware.load_type != AMDGPU_FW_LOAD_DIRECT) &&
(adev->firmware.load_type != AMDGPU_FW_LOAD_RLC_BACKDOOR_AUTO)) {
amdgpu_bo_create_kernel(adev, adev->firmware.fw_size, PAGE_SIZE,
- (amdgpu_sriov_vf(adev) || adev->debug_use_vram_fw_buf) ?
+ (amdgpu_sriov_vf(adev) || adev->debug_use_vram_fw_buf || adev->gmc.xgmi.connected_to_cpu) ?
AMDGPU_GEM_DOMAIN_VRAM : AMDGPU_GEM_DOMAIN_GTT,
&adev->firmware.fw_buf,
&adev->firmware.fw_buf_mc,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c
index 4df0f9d5ad11..0238c2798de4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c
@@ -398,6 +398,17 @@ int amdgpu_umc_process_ecc_irq(struct amdgpu_device *adev,
return 0;
}
+int amdgpu_umc_uniras_process_ecc_irq(struct amdgpu_device *adev,
+ struct amdgpu_irq_src *source,
+ struct amdgpu_iv_entry *entry)
+{
+ struct ras_ih_info ih_info = {0};
+
+ ih_info.block = RAS_BLOCK_ID__UMC;
+ amdgpu_ras_mgr_dispatch_interrupt(adev, &ih_info);
+ return 0;
+}
+
int amdgpu_umc_fill_error_record(struct ras_err_data *err_data,
uint64_t err_addr,
uint64_t retired_page,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h
index 28dff750c47e..8494a55ebf76 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h
@@ -161,6 +161,9 @@ int amdgpu_umc_pasid_poison_handler(struct amdgpu_device *adev,
int amdgpu_umc_process_ecc_irq(struct amdgpu_device *adev,
struct amdgpu_irq_src *source,
struct amdgpu_iv_entry *entry);
+int amdgpu_umc_uniras_process_ecc_irq(struct amdgpu_device *adev,
+ struct amdgpu_irq_src *source,
+ struct amdgpu_iv_entry *entry);
int amdgpu_umc_fill_error_record(struct ras_err_data *err_data,
uint64_t err_addr,
uint64_t retired_page,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
index 6d964a6ee349..366728ed03e3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
@@ -156,7 +156,7 @@ static void amdgpu_userq_hang_detect_work(struct work_struct *work)
struct dma_fence *fence;
struct amdgpu_userq_mgr *uq_mgr;
- if (!queue || !queue->userq_mgr)
+ if (!queue->userq_mgr)
return;
uq_mgr = queue->userq_mgr;
@@ -472,17 +472,16 @@ void
amdgpu_userq_ensure_ev_fence(struct amdgpu_userq_mgr *uq_mgr,
struct amdgpu_eviction_fence_mgr *evf_mgr)
{
- struct amdgpu_eviction_fence *ev_fence;
+ struct dma_fence *ev_fence;
retry:
/* Flush any pending resume work to create ev_fence */
flush_delayed_work(&uq_mgr->resume_work);
mutex_lock(&uq_mgr->userq_mutex);
- spin_lock(&evf_mgr->ev_fence_lock);
- ev_fence = evf_mgr->ev_fence;
- spin_unlock(&evf_mgr->ev_fence_lock);
- if (!ev_fence || dma_fence_is_signaled(&ev_fence->base)) {
+ ev_fence = amdgpu_evf_mgr_get_fence(evf_mgr);
+ if (dma_fence_is_signaled(ev_fence)) {
+ dma_fence_put(ev_fence);
mutex_unlock(&uq_mgr->userq_mutex);
/*
* Looks like there was no pending resume work,
@@ -491,6 +490,7 @@ retry:
schedule_delayed_work(&uq_mgr->resume_work, 0);
goto retry;
}
+ dma_fence_put(ev_fence);
}
int amdgpu_userq_create_object(struct amdgpu_userq_mgr *uq_mgr,
@@ -600,6 +600,13 @@ amdgpu_userq_get_doorbell_index(struct amdgpu_userq_mgr *uq_mgr,
goto unpin_bo;
}
+ /* Validate doorbell_offset is within the doorbell BO */
+ if ((u64)db_info->doorbell_offset * db_size + db_size >
+ amdgpu_bo_size(db_obj->obj)) {
+ r = -EINVAL;
+ goto unpin_bo;
+ }
+
index = amdgpu_doorbell_index_on_bar(uq_mgr->adev, db_obj->obj,
db_info->doorbell_offset, db_size);
drm_dbg_driver(adev_to_drm(uq_mgr->adev),
@@ -623,13 +630,14 @@ amdgpu_userq_destroy(struct amdgpu_userq_mgr *uq_mgr, struct amdgpu_usermode_que
int r = 0;
cancel_delayed_work_sync(&uq_mgr->resume_work);
+
+ /* Cancel any pending hang detection work and cleanup */
+ cancel_delayed_work_sync(&queue->hang_detect_work);
+
mutex_lock(&uq_mgr->userq_mutex);
+ queue->hang_detect_fence = NULL;
amdgpu_userq_wait_for_last_fence(queue);
- /* Cancel any pending hang detection work and cleanup */
- if (queue->hang_detect_fence) {
- cancel_delayed_work_sync(&queue->hang_detect_work);
- queue->hang_detect_fence = NULL;
- }
+
r = amdgpu_bo_reserve(queue->db_obj.obj, true);
if (!r) {
amdgpu_bo_unpin(queue->db_obj.obj);
@@ -996,17 +1004,14 @@ amdgpu_userq_restore_all(struct amdgpu_userq_mgr *uq_mgr)
unsigned long queue_id;
int ret = 0, r;
+ mutex_lock(&uq_mgr->userq_mutex);
/* Resume all the queues for this process */
xa_for_each(&uq_mgr->userq_xa, queue_id, queue) {
- queue = amdgpu_userq_get(uq_mgr, queue_id);
- if (!queue)
- continue;
if (!amdgpu_userq_buffer_vas_mapped(queue)) {
drm_file_err(uq_mgr->file,
"trying restore queue without va mapping\n");
queue->state = AMDGPU_USERQ_STATE_INVALID_VA;
- amdgpu_userq_put(queue);
continue;
}
@@ -1014,8 +1019,8 @@ amdgpu_userq_restore_all(struct amdgpu_userq_mgr *uq_mgr)
if (r)
ret = r;
- amdgpu_userq_put(queue);
}
+ mutex_unlock(&uq_mgr->userq_mutex);
if (ret)
drm_file_err(uq_mgr->file, "Failed to map all the queues\n");
@@ -1040,12 +1045,12 @@ amdgpu_userq_bo_validate(struct amdgpu_device *adev, struct drm_exec *exec,
struct amdgpu_bo *bo;
int ret;
- spin_lock(&vm->invalidated_lock);
+ spin_lock(&vm->status_lock);
while (!list_empty(&vm->invalidated)) {
bo_va = list_first_entry(&vm->invalidated,
struct amdgpu_bo_va,
base.vm_status);
- spin_unlock(&vm->invalidated_lock);
+ spin_unlock(&vm->status_lock);
bo = bo_va->base.bo;
ret = drm_exec_prepare_obj(exec, &bo->tbo.base, 2);
@@ -1062,9 +1067,9 @@ amdgpu_userq_bo_validate(struct amdgpu_device *adev, struct drm_exec *exec,
if (ret)
return ret;
- spin_lock(&vm->invalidated_lock);
+ spin_lock(&vm->status_lock);
}
- spin_unlock(&vm->invalidated_lock);
+ spin_unlock(&vm->status_lock);
return 0;
}
@@ -1196,7 +1201,7 @@ retry_lock:
dma_fence_wait(bo_va->last_pt_update, false);
dma_fence_wait(vm->last_update, false);
- ret = amdgpu_eviction_fence_replace_fence(&fpriv->evf_mgr, &exec);
+ ret = amdgpu_evf_mgr_rearm(&fpriv->evf_mgr, &exec);
if (ret)
drm_file_err(uq_mgr->file, "Failed to replace eviction fence\n");
@@ -1216,26 +1221,25 @@ static void amdgpu_userq_restore_worker(struct work_struct *work)
{
struct amdgpu_userq_mgr *uq_mgr = work_to_uq_mgr(work, resume_work.work);
struct amdgpu_fpriv *fpriv = uq_mgr_to_fpriv(uq_mgr);
+ struct dma_fence *ev_fence;
int ret;
- flush_delayed_work(&fpriv->evf_mgr.suspend_work);
-
- mutex_lock(&uq_mgr->userq_mutex);
+ ev_fence = amdgpu_evf_mgr_get_fence(&fpriv->evf_mgr);
+ if (!dma_fence_is_signaled(ev_fence))
+ goto put_fence;
ret = amdgpu_userq_vm_validate(uq_mgr);
if (ret) {
drm_file_err(uq_mgr->file, "Failed to validate BOs to restore\n");
- goto unlock;
+ goto put_fence;
}
ret = amdgpu_userq_restore_all(uq_mgr);
- if (ret) {
+ if (ret)
drm_file_err(uq_mgr->file, "Failed to restore all queues\n");
- goto unlock;
- }
-unlock:
- mutex_unlock(&uq_mgr->userq_mutex);
+put_fence:
+ dma_fence_put(ev_fence);
}
static int
@@ -1248,13 +1252,9 @@ amdgpu_userq_evict_all(struct amdgpu_userq_mgr *uq_mgr)
amdgpu_userq_detect_and_reset_queues(uq_mgr);
/* Try to unmap all the queues in this process ctx */
xa_for_each(&uq_mgr->userq_xa, queue_id, queue) {
- queue = amdgpu_userq_get(uq_mgr, queue_id);
- if (!queue)
- continue;
r = amdgpu_userq_preempt_helper(queue);
if (r)
ret = r;
- amdgpu_userq_put(queue);
}
if (ret)
@@ -1287,35 +1287,26 @@ amdgpu_userq_wait_for_signal(struct amdgpu_userq_mgr *uq_mgr)
int ret;
xa_for_each(&uq_mgr->userq_xa, queue_id, queue) {
- queue = amdgpu_userq_get(uq_mgr, queue_id);
- if (!queue)
- continue;
-
struct dma_fence *f = queue->last_fence;
- if (!f || dma_fence_is_signaled(f)) {
- amdgpu_userq_put(queue);
+ if (!f || dma_fence_is_signaled(f))
continue;
- }
+
ret = dma_fence_wait_timeout(f, true, msecs_to_jiffies(100));
if (ret <= 0) {
drm_file_err(uq_mgr->file, "Timed out waiting for fence=%llu:%llu\n",
f->context, f->seqno);
- amdgpu_userq_put(queue);
+
return -ETIMEDOUT;
}
- amdgpu_userq_put(queue);
}
return 0;
}
void
-amdgpu_userq_evict(struct amdgpu_userq_mgr *uq_mgr,
- struct amdgpu_eviction_fence *ev_fence)
+amdgpu_userq_evict(struct amdgpu_userq_mgr *uq_mgr)
{
- struct amdgpu_fpriv *fpriv = uq_mgr_to_fpriv(uq_mgr);
- struct amdgpu_eviction_fence_mgr *evf_mgr = &fpriv->evf_mgr;
struct amdgpu_device *adev = uq_mgr->adev;
int ret;
@@ -1328,16 +1319,6 @@ amdgpu_userq_evict(struct amdgpu_userq_mgr *uq_mgr,
if (ret)
dev_err(adev->dev, "Failed to evict userqueue\n");
- /* Signal current eviction fence */
- amdgpu_eviction_fence_signal(evf_mgr, ev_fence);
-
- if (evf_mgr->fd_closing) {
- cancel_delayed_work_sync(&uq_mgr->resume_work);
- return;
- }
-
- /* Schedule a resume work */
- schedule_delayed_work(&uq_mgr->resume_work, 0);
}
int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr, struct drm_file *file_priv,
@@ -1352,6 +1333,11 @@ int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr, struct drm_file *f
return 0;
}
+void amdgpu_userq_mgr_cancel_resume(struct amdgpu_userq_mgr *userq_mgr)
+{
+ cancel_delayed_work_sync(&userq_mgr->resume_work);
+}
+
void amdgpu_userq_mgr_fini(struct amdgpu_userq_mgr *userq_mgr)
{
struct amdgpu_usermode_queue *queue;
@@ -1475,17 +1461,19 @@ int amdgpu_userq_start_sched_for_enforce_isolation(struct amdgpu_device *adev,
if (!adev->userq_halt_for_enforce_isolation)
dev_warn(adev->dev, "userq scheduling already started!\n");
+
adev->userq_halt_for_enforce_isolation = false;
+
xa_for_each(&adev->userq_doorbell_xa, queue_id, queue) {
uqm = queue->userq_mgr;
mutex_lock(&uqm->userq_mutex);
- if (((queue->queue_type == AMDGPU_HW_IP_GFX) ||
- (queue->queue_type == AMDGPU_HW_IP_COMPUTE)) &&
- (queue->xcp_id == idx)) {
+ if (((queue->queue_type == AMDGPU_HW_IP_GFX) ||
+ (queue->queue_type == AMDGPU_HW_IP_COMPUTE)) &&
+ (queue->xcp_id == idx)) {
r = amdgpu_userq_restore_helper(queue);
if (r)
ret = r;
- }
+ }
mutex_unlock(&uqm->userq_mutex);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
index 54e1997b3cc0..a4d44abf24fa 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
@@ -123,6 +123,7 @@ int amdgpu_userq_ioctl(struct drm_device *dev, void *data, struct drm_file *filp
int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr, struct drm_file *file_priv,
struct amdgpu_device *adev);
+void amdgpu_userq_mgr_cancel_resume(struct amdgpu_userq_mgr *userq_mgr);
void amdgpu_userq_mgr_fini(struct amdgpu_userq_mgr *userq_mgr);
int amdgpu_userq_create_object(struct amdgpu_userq_mgr *uq_mgr,
@@ -132,8 +133,7 @@ int amdgpu_userq_create_object(struct amdgpu_userq_mgr *uq_mgr,
void amdgpu_userq_destroy_object(struct amdgpu_userq_mgr *uq_mgr,
struct amdgpu_userq_obj *userq_obj);
-void amdgpu_userq_evict(struct amdgpu_userq_mgr *uq_mgr,
- struct amdgpu_eviction_fence *ev_fence);
+void amdgpu_userq_evict(struct amdgpu_userq_mgr *uq_mgr);
void amdgpu_userq_ensure_ev_fence(struct amdgpu_userq_mgr *userq_mgr,
struct amdgpu_eviction_fence_mgr *evf_mgr);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
index d8ce7b3733e7..fe6d83e859a0 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
@@ -597,11 +597,11 @@ exec_fini:
put_gobj_write:
for (i = 0; i < num_write_bo_handles; i++)
drm_gem_object_put(gobj_write[i]);
- kfree(gobj_write);
+ kvfree(gobj_write);
put_gobj_read:
for (i = 0; i < num_read_bo_handles; i++)
drm_gem_object_put(gobj_read[i]);
- kfree(gobj_read);
+ kvfree(gobj_read);
free_syncobj:
while (entry-- > 0)
if (syncobj[entry])
@@ -616,339 +616,405 @@ free_syncobj_handles:
return r;
}
-int amdgpu_userq_wait_ioctl(struct drm_device *dev, void *data,
- struct drm_file *filp)
+/* Count the number of expected fences so userspace can alloc a buffer */
+static int
+amdgpu_userq_wait_count_fences(struct drm_file *filp,
+ struct drm_amdgpu_userq_wait *wait_info,
+ u32 *syncobj_handles, u32 *timeline_points,
+ u32 *timeline_handles,
+ struct drm_gem_object **gobj_write,
+ struct drm_gem_object **gobj_read)
{
- struct drm_amdgpu_userq_wait *wait_info = data;
- const unsigned int num_write_bo_handles = wait_info->num_bo_write_handles;
- const unsigned int num_read_bo_handles = wait_info->num_bo_read_handles;
- struct drm_amdgpu_userq_fence_info *fence_info = NULL;
- struct amdgpu_fpriv *fpriv = filp->driver_priv;
- struct amdgpu_userq_mgr *userq_mgr = &fpriv->userq_mgr;
- struct drm_gem_object **gobj_write, **gobj_read;
- u32 *timeline_points, *timeline_handles;
- struct amdgpu_usermode_queue *waitq = NULL;
- u32 *syncobj_handles, num_syncobj;
- struct dma_fence **fences = NULL;
- u16 num_points, num_fences = 0;
+ int num_read_bo_handles, num_write_bo_handles;
+ struct dma_fence_unwrap iter;
+ struct dma_fence *fence, *f;
+ unsigned int num_fences = 0;
struct drm_exec exec;
- int r, i, cnt;
-
- if (!amdgpu_userq_enabled(dev))
- return -ENOTSUPP;
-
- if (wait_info->num_bo_write_handles > AMDGPU_USERQ_MAX_HANDLES ||
- wait_info->num_bo_read_handles > AMDGPU_USERQ_MAX_HANDLES)
- return -EINVAL;
-
- num_syncobj = wait_info->num_syncobj_handles;
- syncobj_handles = memdup_array_user(u64_to_user_ptr(wait_info->syncobj_handles),
- num_syncobj, sizeof(u32));
- if (IS_ERR(syncobj_handles))
- return PTR_ERR(syncobj_handles);
-
+ int i, r;
+
+ /*
+ * This needs to be outside of the lock provided by drm_exec for
+ * DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT to work correctly.
+ */
+
+ /* Count timeline fences */
+ for (i = 0; i < wait_info->num_syncobj_timeline_handles; i++) {
+ r = drm_syncobj_find_fence(filp, timeline_handles[i],
+ timeline_points[i],
+ DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT,
+ &fence);
+ if (r)
+ return r;
+
+ dma_fence_unwrap_for_each(f, &iter, fence)
+ num_fences++;
- num_points = wait_info->num_syncobj_timeline_handles;
- timeline_handles = memdup_array_user(u64_to_user_ptr(wait_info->syncobj_timeline_handles),
- num_points, sizeof(u32));
- if (IS_ERR(timeline_handles)) {
- r = PTR_ERR(timeline_handles);
- goto free_syncobj_handles;
+ dma_fence_put(fence);
}
- timeline_points = memdup_array_user(u64_to_user_ptr(wait_info->syncobj_timeline_points),
- num_points, sizeof(u32));
+ /* Count boolean fences */
+ for (i = 0; i < wait_info->num_syncobj_handles; i++) {
+ r = drm_syncobj_find_fence(filp, syncobj_handles[i], 0,
+ DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT,
+ &fence);
+ if (r)
+ return r;
- if (IS_ERR(timeline_points)) {
- r = PTR_ERR(timeline_points);
- goto free_timeline_handles;
+ num_fences++;
+ dma_fence_put(fence);
}
- r = drm_gem_objects_lookup(filp,
- u64_to_user_ptr(wait_info->bo_read_handles),
- num_read_bo_handles,
- &gobj_read);
- if (r)
- goto free_timeline_points;
-
- r = drm_gem_objects_lookup(filp,
- u64_to_user_ptr(wait_info->bo_write_handles),
- num_write_bo_handles,
- &gobj_write);
- if (r)
- goto put_gobj_read;
-
+ /* Lock all the GEM objects */
+ /* TODO: It is actually not necessary to lock them */
+ num_read_bo_handles = wait_info->num_bo_read_handles;
+ num_write_bo_handles = wait_info->num_bo_write_handles;
drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT,
- (num_read_bo_handles + num_write_bo_handles));
+ num_read_bo_handles + num_write_bo_handles);
- /* Lock all BOs with retry handling */
drm_exec_until_all_locked(&exec) {
- r = drm_exec_prepare_array(&exec, gobj_read, num_read_bo_handles, 1);
+ r = drm_exec_prepare_array(&exec, gobj_read,
+ num_read_bo_handles, 1);
drm_exec_retry_on_contention(&exec);
- if (r) {
- drm_exec_fini(&exec);
- goto put_gobj_write;
- }
+ if (r)
+ goto error_unlock;
- r = drm_exec_prepare_array(&exec, gobj_write, num_write_bo_handles, 1);
+ r = drm_exec_prepare_array(&exec, gobj_write,
+ num_write_bo_handles, 1);
drm_exec_retry_on_contention(&exec);
- if (r) {
- drm_exec_fini(&exec);
- goto put_gobj_write;
- }
+ if (r)
+ goto error_unlock;
}
- if (!wait_info->num_fences) {
- if (num_points) {
- struct dma_fence_unwrap iter;
- struct dma_fence *fence;
- struct dma_fence *f;
-
- for (i = 0; i < num_points; i++) {
- r = drm_syncobj_find_fence(filp, timeline_handles[i],
- timeline_points[i],
- DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT,
- &fence);
- if (r)
- goto exec_fini;
-
- dma_fence_unwrap_for_each(f, &iter, fence)
- num_fences++;
-
- dma_fence_put(fence);
- }
- }
+ /* Count read fences */
+ for (i = 0; i < num_read_bo_handles; i++) {
+ struct dma_resv_iter resv_cursor;
+ struct dma_fence *fence;
- /* Count syncobj's fence */
- for (i = 0; i < num_syncobj; i++) {
- struct dma_fence *fence;
+ dma_resv_for_each_fence(&resv_cursor, gobj_read[i]->resv,
+ DMA_RESV_USAGE_READ, fence)
+ num_fences++;
+ }
- r = drm_syncobj_find_fence(filp, syncobj_handles[i],
- 0,
- DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT,
- &fence);
- if (r)
- goto exec_fini;
+ /* Count write fences */
+ for (i = 0; i < num_write_bo_handles; i++) {
+ struct dma_resv_iter resv_cursor;
+ struct dma_fence *fence;
+ dma_resv_for_each_fence(&resv_cursor, gobj_write[i]->resv,
+ DMA_RESV_USAGE_WRITE, fence)
num_fences++;
- dma_fence_put(fence);
- }
+ }
- /* Count GEM objects fence */
- for (i = 0; i < num_read_bo_handles; i++) {
- struct dma_resv_iter resv_cursor;
- struct dma_fence *fence;
+ wait_info->num_fences = min(num_fences, USHRT_MAX);
+ r = 0;
- dma_resv_for_each_fence(&resv_cursor, gobj_read[i]->resv,
- DMA_RESV_USAGE_READ, fence)
- num_fences++;
- }
+error_unlock:
+ /* Unlock all the GEM objects */
+ drm_exec_fini(&exec);
+ return r;
+}
- for (i = 0; i < num_write_bo_handles; i++) {
- struct dma_resv_iter resv_cursor;
- struct dma_fence *fence;
+static int
+amdgpu_userq_wait_add_fence(struct drm_amdgpu_userq_wait *wait_info,
+ struct dma_fence **fences, unsigned int *num_fences,
+ struct dma_fence *fence)
+{
+ /* As fallback shouldn't userspace allocate enough space */
+ if (*num_fences >= wait_info->num_fences)
+ return dma_fence_wait(fence, true);
- dma_resv_for_each_fence(&resv_cursor, gobj_write[i]->resv,
- DMA_RESV_USAGE_WRITE, fence)
- num_fences++;
- }
+ fences[(*num_fences)++] = dma_fence_get(fence);
+ return 0;
+}
- /*
- * Passing num_fences = 0 means that userspace doesn't want to
- * retrieve userq_fence_info. If num_fences = 0 we skip filling
- * userq_fence_info and return the actual number of fences on
- * args->num_fences.
- */
- wait_info->num_fences = num_fences;
- } else {
- /* Array of fence info */
- fence_info = kmalloc_array(wait_info->num_fences, sizeof(*fence_info), GFP_KERNEL);
- if (!fence_info) {
- r = -ENOMEM;
- goto exec_fini;
- }
+static int
+amdgpu_userq_wait_return_fence_info(struct drm_file *filp,
+ struct drm_amdgpu_userq_wait *wait_info,
+ u32 *syncobj_handles, u32 *timeline_points,
+ u32 *timeline_handles,
+ struct drm_gem_object **gobj_write,
+ struct drm_gem_object **gobj_read)
+{
+ struct amdgpu_fpriv *fpriv = filp->driver_priv;
+ struct amdgpu_userq_mgr *userq_mgr = &fpriv->userq_mgr;
+ struct drm_amdgpu_userq_fence_info *fence_info;
+ int num_read_bo_handles, num_write_bo_handles;
+ struct amdgpu_usermode_queue *waitq;
+ struct dma_fence **fences, *fence, *f;
+ struct dma_fence_unwrap iter;
+ int num_points, num_syncobj;
+ unsigned int num_fences = 0;
+ struct drm_exec exec;
+ int i, cnt, r;
- /* Array of fences */
- fences = kmalloc_array(wait_info->num_fences, sizeof(*fences), GFP_KERNEL);
- if (!fences) {
- r = -ENOMEM;
- goto free_fence_info;
- }
+ fence_info = kmalloc_array(wait_info->num_fences, sizeof(*fence_info),
+ GFP_KERNEL);
+ if (!fence_info)
+ return -ENOMEM;
- /* Retrieve GEM read objects fence */
- for (i = 0; i < num_read_bo_handles; i++) {
- struct dma_resv_iter resv_cursor;
- struct dma_fence *fence;
+ fences = kmalloc_array(wait_info->num_fences, sizeof(*fences),
+ GFP_KERNEL);
+ if (!fences) {
+ r = -ENOMEM;
+ goto free_fence_info;
+ }
- dma_resv_for_each_fence(&resv_cursor, gobj_read[i]->resv,
- DMA_RESV_USAGE_READ, fence) {
- if (num_fences >= wait_info->num_fences) {
- r = -EINVAL;
- goto free_fences;
- }
+ /* Retrieve timeline fences */
+ num_points = wait_info->num_syncobj_timeline_handles;
+ for (i = 0; i < num_points; i++) {
+ r = drm_syncobj_find_fence(filp, timeline_handles[i],
+ timeline_points[i],
+ DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT,
+ &fence);
+ if (r)
+ goto free_fences;
- fences[num_fences++] = fence;
- dma_fence_get(fence);
+ dma_fence_unwrap_for_each(f, &iter, fence) {
+ r = amdgpu_userq_wait_add_fence(wait_info, fences,
+ &num_fences, f);
+ if (r) {
+ dma_fence_put(fence);
+ goto free_fences;
}
}
- /* Retrieve GEM write objects fence */
- for (i = 0; i < num_write_bo_handles; i++) {
- struct dma_resv_iter resv_cursor;
- struct dma_fence *fence;
+ dma_fence_put(fence);
+ }
- dma_resv_for_each_fence(&resv_cursor, gobj_write[i]->resv,
- DMA_RESV_USAGE_WRITE, fence) {
- if (num_fences >= wait_info->num_fences) {
- r = -EINVAL;
- goto free_fences;
- }
+ /* Retrieve boolean fences */
+ num_syncobj = wait_info->num_syncobj_handles;
+ for (i = 0; i < num_syncobj; i++) {
+ struct dma_fence *fence;
- fences[num_fences++] = fence;
- dma_fence_get(fence);
- }
- }
+ r = drm_syncobj_find_fence(filp, syncobj_handles[i], 0,
+ DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT,
+ &fence);
+ if (r)
+ goto free_fences;
- if (num_points) {
- struct dma_fence_unwrap iter;
- struct dma_fence *fence;
- struct dma_fence *f;
-
- for (i = 0; i < num_points; i++) {
- r = drm_syncobj_find_fence(filp, timeline_handles[i],
- timeline_points[i],
- DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT,
- &fence);
- if (r)
- goto free_fences;
-
- dma_fence_unwrap_for_each(f, &iter, fence) {
- if (num_fences >= wait_info->num_fences) {
- r = -EINVAL;
- dma_fence_put(fence);
- goto free_fences;
- }
-
- dma_fence_get(f);
- fences[num_fences++] = f;
- }
+ r = amdgpu_userq_wait_add_fence(wait_info, fences,
+ &num_fences, fence);
+ dma_fence_put(fence);
+ if (r)
+ goto free_fences;
- dma_fence_put(fence);
- }
- }
+ }
- /* Retrieve syncobj's fence */
- for (i = 0; i < num_syncobj; i++) {
- struct dma_fence *fence;
+ /* Lock all the GEM objects */
+ num_read_bo_handles = wait_info->num_bo_read_handles;
+ num_write_bo_handles = wait_info->num_bo_write_handles;
+ drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT,
+ num_read_bo_handles + num_write_bo_handles);
- r = drm_syncobj_find_fence(filp, syncobj_handles[i],
- 0,
- DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT,
- &fence);
- if (r)
- goto free_fences;
+ drm_exec_until_all_locked(&exec) {
+ r = drm_exec_prepare_array(&exec, gobj_read,
+ num_read_bo_handles, 1);
+ drm_exec_retry_on_contention(&exec);
+ if (r)
+ goto error_unlock;
- if (num_fences >= wait_info->num_fences) {
- r = -EINVAL;
- dma_fence_put(fence);
- goto free_fences;
- }
+ r = drm_exec_prepare_array(&exec, gobj_write,
+ num_write_bo_handles, 1);
+ drm_exec_retry_on_contention(&exec);
+ if (r)
+ goto error_unlock;
+ }
- fences[num_fences++] = fence;
+ /* Retrieve GEM read objects fence */
+ for (i = 0; i < num_read_bo_handles; i++) {
+ struct dma_resv_iter resv_cursor;
+ struct dma_fence *fence;
+
+ dma_resv_for_each_fence(&resv_cursor, gobj_read[i]->resv,
+ DMA_RESV_USAGE_READ, fence) {
+ r = amdgpu_userq_wait_add_fence(wait_info, fences,
+ &num_fences, fence);
+ if (r)
+ goto error_unlock;
}
+ }
- /*
- * Keep only the latest fences to reduce the number of values
- * given back to userspace.
- */
- num_fences = dma_fence_dedup_array(fences, num_fences);
+ /* Retrieve GEM write objects fence */
+ for (i = 0; i < num_write_bo_handles; i++) {
+ struct dma_resv_iter resv_cursor;
+ struct dma_fence *fence;
- waitq = amdgpu_userq_get(userq_mgr, wait_info->waitq_id);
- if (!waitq) {
- r = -EINVAL;
- goto free_fences;
+ dma_resv_for_each_fence(&resv_cursor, gobj_write[i]->resv,
+ DMA_RESV_USAGE_WRITE, fence) {
+ r = amdgpu_userq_wait_add_fence(wait_info, fences,
+ &num_fences, fence);
+ if (r)
+ goto error_unlock;
}
+ }
- for (i = 0, cnt = 0; i < num_fences; i++) {
- struct amdgpu_userq_fence_driver *fence_drv;
- struct amdgpu_userq_fence *userq_fence;
- u32 index;
-
- userq_fence = to_amdgpu_userq_fence(fences[i]);
- if (!userq_fence) {
- /*
- * Just waiting on other driver fences should
- * be good for now
- */
- r = dma_fence_wait(fences[i], true);
- if (r) {
- dma_fence_put(fences[i]);
- goto free_fences;
- }
-
- dma_fence_put(fences[i]);
- continue;
- }
+ drm_exec_fini(&exec);
- fence_drv = userq_fence->fence_drv;
+ /*
+ * Keep only the latest fences to reduce the number of values
+ * given back to userspace.
+ */
+ num_fences = dma_fence_dedup_array(fences, num_fences);
+
+ waitq = amdgpu_userq_get(userq_mgr, wait_info->waitq_id);
+ if (!waitq) {
+ r = -EINVAL;
+ goto free_fences;
+ }
+
+ for (i = 0, cnt = 0; i < num_fences; i++) {
+ struct amdgpu_userq_fence_driver *fence_drv;
+ struct amdgpu_userq_fence *userq_fence;
+ u32 index;
+
+ userq_fence = to_amdgpu_userq_fence(fences[i]);
+ if (!userq_fence) {
/*
- * We need to make sure the user queue release their reference
- * to the fence drivers at some point before queue destruction.
- * Otherwise, we would gather those references until we don't
- * have any more space left and crash.
+ * Just waiting on other driver fences should
+ * be good for now
*/
- r = xa_alloc(&waitq->fence_drv_xa, &index, fence_drv,
- xa_limit_32b, GFP_KERNEL);
+ r = dma_fence_wait(fences[i], true);
if (r)
- goto free_fences;
+ goto put_waitq;
- amdgpu_userq_fence_driver_get(fence_drv);
+ continue;
+ }
- /* Store drm syncobj's gpu va address and value */
- fence_info[cnt].va = fence_drv->va;
- fence_info[cnt].value = fences[i]->seqno;
+ fence_drv = userq_fence->fence_drv;
+ /*
+ * We need to make sure the user queue release their reference
+ * to the fence drivers at some point before queue destruction.
+ * Otherwise, we would gather those references until we don't
+ * have any more space left and crash.
+ */
+ r = xa_alloc(&waitq->fence_drv_xa, &index, fence_drv,
+ xa_limit_32b, GFP_KERNEL);
+ if (r)
+ goto put_waitq;
- dma_fence_put(fences[i]);
- /* Increment the actual userq fence count */
- cnt++;
- }
+ amdgpu_userq_fence_driver_get(fence_drv);
- wait_info->num_fences = cnt;
- /* Copy userq fence info to user space */
- if (copy_to_user(u64_to_user_ptr(wait_info->out_fences),
- fence_info, wait_info->num_fences * sizeof(*fence_info))) {
- r = -EFAULT;
- goto free_fences;
- }
+ /* Store drm syncobj's gpu va address and value */
+ fence_info[cnt].va = fence_drv->va;
+ fence_info[cnt].value = fences[i]->seqno;
+
+ /* Increment the actual userq fence count */
+ cnt++;
}
+ wait_info->num_fences = cnt;
+
+ /* Copy userq fence info to user space */
+ if (copy_to_user(u64_to_user_ptr(wait_info->out_fences),
+ fence_info, cnt * sizeof(*fence_info)))
+ r = -EFAULT;
+ else
+ r = 0;
+
+put_waitq:
+ amdgpu_userq_put(waitq);
free_fences:
- if (fences) {
- while (num_fences-- > 0)
- dma_fence_put(fences[num_fences]);
- kfree(fences);
- }
+ while (num_fences--)
+ dma_fence_put(fences[num_fences]);
+ kfree(fences);
+
free_fence_info:
kfree(fence_info);
-exec_fini:
+ return r;
+
+error_unlock:
drm_exec_fini(&exec);
-put_gobj_write:
- for (i = 0; i < num_write_bo_handles; i++)
- drm_gem_object_put(gobj_write[i]);
- kfree(gobj_write);
+ goto free_fences;
+}
+
+int amdgpu_userq_wait_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *filp)
+{
+ int num_points, num_syncobj, num_read_bo_handles, num_write_bo_handles;
+ u32 *syncobj_handles, *timeline_points, *timeline_handles;
+ struct drm_amdgpu_userq_wait *wait_info = data;
+ struct drm_gem_object **gobj_write;
+ struct drm_gem_object **gobj_read;
+ void __user *ptr;
+ int r;
+
+ if (!amdgpu_userq_enabled(dev))
+ return -ENOTSUPP;
+
+ if (wait_info->num_bo_write_handles > AMDGPU_USERQ_MAX_HANDLES ||
+ wait_info->num_bo_read_handles > AMDGPU_USERQ_MAX_HANDLES)
+ return -EINVAL;
+
+ num_syncobj = wait_info->num_syncobj_handles;
+ ptr = u64_to_user_ptr(wait_info->syncobj_handles);
+ syncobj_handles = memdup_array_user(ptr, num_syncobj, sizeof(u32));
+ if (IS_ERR(syncobj_handles))
+ return PTR_ERR(syncobj_handles);
+
+ num_points = wait_info->num_syncobj_timeline_handles;
+ ptr = u64_to_user_ptr(wait_info->syncobj_timeline_handles);
+ timeline_handles = memdup_array_user(ptr, num_points, sizeof(u32));
+ if (IS_ERR(timeline_handles)) {
+ r = PTR_ERR(timeline_handles);
+ goto free_syncobj_handles;
+ }
+
+ ptr = u64_to_user_ptr(wait_info->syncobj_timeline_points);
+ timeline_points = memdup_array_user(ptr, num_points, sizeof(u32));
+ if (IS_ERR(timeline_points)) {
+ r = PTR_ERR(timeline_points);
+ goto free_timeline_handles;
+ }
+
+ num_read_bo_handles = wait_info->num_bo_read_handles;
+ ptr = u64_to_user_ptr(wait_info->bo_read_handles);
+ r = drm_gem_objects_lookup(filp, ptr, num_read_bo_handles, &gobj_read);
+ if (r)
+ goto free_timeline_points;
+
+ num_write_bo_handles = wait_info->num_bo_write_handles;
+ ptr = u64_to_user_ptr(wait_info->bo_write_handles);
+ r = drm_gem_objects_lookup(filp, ptr, num_write_bo_handles,
+ &gobj_write);
+ if (r)
+ goto put_gobj_read;
+
+ /*
+ * Passing num_fences = 0 means that userspace doesn't want to
+ * retrieve userq_fence_info. If num_fences = 0 we skip filling
+ * userq_fence_info and return the actual number of fences on
+ * args->num_fences.
+ */
+ if (!wait_info->num_fences) {
+ r = amdgpu_userq_wait_count_fences(filp, wait_info,
+ syncobj_handles,
+ timeline_points,
+ timeline_handles,
+ gobj_write,
+ gobj_read);
+ } else {
+ r = amdgpu_userq_wait_return_fence_info(filp, wait_info,
+ syncobj_handles,
+ timeline_points,
+ timeline_handles,
+ gobj_write,
+ gobj_read);
+ }
+
+ while (num_write_bo_handles--)
+ drm_gem_object_put(gobj_write[num_write_bo_handles]);
+ kvfree(gobj_write);
+
put_gobj_read:
- for (i = 0; i < num_read_bo_handles; i++)
- drm_gem_object_put(gobj_read[i]);
- kfree(gobj_read);
+ while (num_read_bo_handles--)
+ drm_gem_object_put(gobj_read[num_read_bo_handles]);
+ kvfree(gobj_read);
+
free_timeline_points:
kfree(timeline_points);
free_timeline_handles:
kfree(timeline_handles);
free_syncobj_handles:
kfree(syncobj_handles);
-
- if (waitq)
- amdgpu_userq_put(waitq);
-
return r;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
index 75ae9b429420..03d95dca93d7 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
@@ -63,6 +63,7 @@
#define FIRMWARE_VCN4_0_6_1 "amdgpu/vcn_4_0_6_1.bin"
#define FIRMWARE_VCN5_0_0 "amdgpu/vcn_5_0_0.bin"
#define FIRMWARE_VCN5_0_1 "amdgpu/vcn_5_0_1.bin"
+#define FIRMWARE_VCN5_0_2 "amdgpu/vcn_5_0_2.bin"
#define FIRMWARE_VCN5_3_0 "amdgpu/vcn_5_3_0.bin"
MODULE_FIRMWARE(FIRMWARE_RAVEN);
@@ -91,6 +92,7 @@ MODULE_FIRMWARE(FIRMWARE_VCN4_0_6);
MODULE_FIRMWARE(FIRMWARE_VCN4_0_6_1);
MODULE_FIRMWARE(FIRMWARE_VCN5_0_0);
MODULE_FIRMWARE(FIRMWARE_VCN5_0_1);
+MODULE_FIRMWARE(FIRMWARE_VCN5_0_2);
MODULE_FIRMWARE(FIRMWARE_VCN5_3_0);
static void amdgpu_vcn_idle_work_handler(struct work_struct *work);
@@ -1095,7 +1097,8 @@ int amdgpu_vcn_unified_ring_test_ib(struct amdgpu_ring *ring, long timeout)
long r;
if ((amdgpu_ip_version(adev, UVD_HWIP, 0) != IP_VERSION(4, 0, 3)) &&
- (amdgpu_ip_version(adev, UVD_HWIP, 0) != IP_VERSION(5, 0, 1))) {
+ (amdgpu_ip_version(adev, UVD_HWIP, 0) != IP_VERSION(5, 0, 1)) &&
+ (amdgpu_ip_version(adev, UVD_HWIP, 0) != IP_VERSION(5, 0, 2))) {
r = amdgpu_vcn_enc_ring_test_ib(ring, timeout);
if (r)
goto error;
@@ -1132,7 +1135,8 @@ void amdgpu_vcn_setup_ucode(struct amdgpu_device *adev, int i)
return;
if ((amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(4, 0, 3) ||
- amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(5, 0, 1))
+ amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(5, 0, 1) ||
+ amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(5, 0, 2))
&& (i > 0))
return;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
index 275745aa5829..dba7ea16a10d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
@@ -605,10 +605,10 @@ static int amdgpu_virt_write_vf2pf_data(struct amdgpu_device *adev)
#ifdef MODULE
if (THIS_MODULE->version != NULL)
- strcpy(vf2pf_info->driver_version, THIS_MODULE->version);
+ strscpy(vf2pf_info->driver_version, THIS_MODULE->version);
else
#endif
- strcpy(vf2pf_info->driver_version, "N/A");
+ strscpy(vf2pf_info->driver_version, "N/A");
vf2pf_info->pf2vf_version_required = 0; // no requirement, guest understands all
vf2pf_info->driver_cert = 0;
@@ -950,11 +950,6 @@ int amdgpu_virt_init_critical_region(struct amdgpu_device *adev)
if (adev->virt.req_init_data_ver != GPU_CRIT_REGION_V2)
return 0;
- if (init_hdr_offset < 0) {
- dev_err(adev->dev, "Invalid init header offset\n");
- return -EINVAL;
- }
-
vram_size = RREG32(mmRCC_CONFIG_MEMSIZE);
if (!vram_size || vram_size == U32_MAX)
return -EINVAL;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
index 5cef8cd14148..e54295b56282 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
@@ -328,11 +328,9 @@ static int amdgpu_vkms_prepare_fb(struct drm_plane *plane,
return r;
}
- r = dma_resv_reserve_fences(rbo->tbo.base.resv, 1);
- if (r) {
- dev_err(adev->dev, "allocating fence slot failed (%d)\n", r);
+ r = dma_resv_reserve_fences(rbo->tbo.base.resv, TTM_NUM_MOVE_FENCES);
+ if (r)
goto error_unlock;
- }
if (plane->type != DRM_PLANE_TYPE_CURSOR)
domain = amdgpu_display_supported_domains(adev, rbo->flags);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index 76248a0276ef..73abac6be5b3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -139,6 +139,20 @@ static void amdgpu_vm_assert_locked(struct amdgpu_vm *vm)
}
/**
+ * amdgpu_vm_is_bo_always_valid - check if the BO is VM always valid
+ *
+ * @vm: VM to test against.
+ * @bo: BO to be tested.
+ *
+ * Returns true if the BO shares the dma_resv object with the root PD and is
+ * always guaranteed to be valid inside the VM.
+ */
+bool amdgpu_vm_is_bo_always_valid(struct amdgpu_vm *vm, struct amdgpu_bo *bo)
+{
+ return bo && bo->tbo.base.resv == vm->root.bo->tbo.base.resv;
+}
+
+/**
* amdgpu_vm_bo_evicted - vm_bo is evicted
*
* @vm_bo: vm_bo which is evicted
@@ -153,10 +167,12 @@ static void amdgpu_vm_bo_evicted(struct amdgpu_vm_bo_base *vm_bo)
vm_bo->moved = true;
amdgpu_vm_assert_locked(vm);
+ spin_lock(&vm_bo->vm->status_lock);
if (bo->tbo.type == ttm_bo_type_kernel)
list_move(&vm_bo->vm_status, &vm->evicted);
else
list_move_tail(&vm_bo->vm_status, &vm->evicted);
+ spin_unlock(&vm_bo->vm->status_lock);
}
/**
* amdgpu_vm_bo_moved - vm_bo is moved
@@ -169,7 +185,9 @@ static void amdgpu_vm_bo_evicted(struct amdgpu_vm_bo_base *vm_bo)
static void amdgpu_vm_bo_moved(struct amdgpu_vm_bo_base *vm_bo)
{
amdgpu_vm_assert_locked(vm_bo->vm);
+ spin_lock(&vm_bo->vm->status_lock);
list_move(&vm_bo->vm_status, &vm_bo->vm->moved);
+ spin_unlock(&vm_bo->vm->status_lock);
}
/**
@@ -183,7 +201,9 @@ static void amdgpu_vm_bo_moved(struct amdgpu_vm_bo_base *vm_bo)
static void amdgpu_vm_bo_idle(struct amdgpu_vm_bo_base *vm_bo)
{
amdgpu_vm_assert_locked(vm_bo->vm);
+ spin_lock(&vm_bo->vm->status_lock);
list_move(&vm_bo->vm_status, &vm_bo->vm->idle);
+ spin_unlock(&vm_bo->vm->status_lock);
vm_bo->moved = false;
}
@@ -197,9 +217,9 @@ static void amdgpu_vm_bo_idle(struct amdgpu_vm_bo_base *vm_bo)
*/
static void amdgpu_vm_bo_invalidated(struct amdgpu_vm_bo_base *vm_bo)
{
- spin_lock(&vm_bo->vm->invalidated_lock);
+ spin_lock(&vm_bo->vm->status_lock);
list_move(&vm_bo->vm_status, &vm_bo->vm->invalidated);
- spin_unlock(&vm_bo->vm->invalidated_lock);
+ spin_unlock(&vm_bo->vm->status_lock);
}
/**
@@ -212,9 +232,10 @@ static void amdgpu_vm_bo_invalidated(struct amdgpu_vm_bo_base *vm_bo)
*/
static void amdgpu_vm_bo_evicted_user(struct amdgpu_vm_bo_base *vm_bo)
{
- amdgpu_vm_assert_locked(vm_bo->vm);
vm_bo->moved = true;
+ spin_lock(&vm_bo->vm->status_lock);
list_move(&vm_bo->vm_status, &vm_bo->vm->evicted_user);
+ spin_unlock(&vm_bo->vm->status_lock);
}
/**
@@ -228,10 +249,13 @@ static void amdgpu_vm_bo_evicted_user(struct amdgpu_vm_bo_base *vm_bo)
static void amdgpu_vm_bo_relocated(struct amdgpu_vm_bo_base *vm_bo)
{
amdgpu_vm_assert_locked(vm_bo->vm);
- if (vm_bo->bo->parent)
+ if (vm_bo->bo->parent) {
+ spin_lock(&vm_bo->vm->status_lock);
list_move(&vm_bo->vm_status, &vm_bo->vm->relocated);
- else
+ spin_unlock(&vm_bo->vm->status_lock);
+ } else {
amdgpu_vm_bo_idle(vm_bo);
+ }
}
/**
@@ -245,7 +269,9 @@ static void amdgpu_vm_bo_relocated(struct amdgpu_vm_bo_base *vm_bo)
static void amdgpu_vm_bo_done(struct amdgpu_vm_bo_base *vm_bo)
{
amdgpu_vm_assert_locked(vm_bo->vm);
+ spin_lock(&vm_bo->vm->status_lock);
list_move(&vm_bo->vm_status, &vm_bo->vm->done);
+ spin_unlock(&vm_bo->vm->status_lock);
}
/**
@@ -259,13 +285,13 @@ static void amdgpu_vm_bo_reset_state_machine(struct amdgpu_vm *vm)
{
struct amdgpu_vm_bo_base *vm_bo, *tmp;
- spin_lock(&vm->invalidated_lock);
+ amdgpu_vm_assert_locked(vm);
+
+ spin_lock(&vm->status_lock);
list_splice_init(&vm->done, &vm->invalidated);
list_for_each_entry(vm_bo, &vm->invalidated, vm_status)
vm_bo->moved = true;
- spin_unlock(&vm->invalidated_lock);
- amdgpu_vm_assert_locked(vm);
list_for_each_entry_safe(vm_bo, tmp, &vm->idle, vm_status) {
struct amdgpu_bo *bo = vm_bo->bo;
@@ -275,13 +301,14 @@ static void amdgpu_vm_bo_reset_state_machine(struct amdgpu_vm *vm)
else if (bo->parent)
list_move(&vm_bo->vm_status, &vm_bo->vm->relocated);
}
+ spin_unlock(&vm->status_lock);
}
/**
* amdgpu_vm_update_shared - helper to update shared memory stat
* @base: base structure for tracking BO usage in a VM
*
- * Takes the vm stats_lock and updates the shared memory stat. If the basic
+ * Takes the vm status_lock and updates the shared memory stat. If the basic
* stat changed (e.g. buffer was moved) amdgpu_vm_update_stats need to be called
* as well.
*/
@@ -294,7 +321,7 @@ static void amdgpu_vm_update_shared(struct amdgpu_vm_bo_base *base)
bool shared;
dma_resv_assert_held(bo->tbo.base.resv);
- spin_lock(&vm->stats_lock);
+ spin_lock(&vm->status_lock);
shared = drm_gem_object_is_shared_for_memory_stats(&bo->tbo.base);
if (base->shared != shared) {
base->shared = shared;
@@ -306,7 +333,7 @@ static void amdgpu_vm_update_shared(struct amdgpu_vm_bo_base *base)
vm->stats[bo_memtype].drm.private += size;
}
}
- spin_unlock(&vm->stats_lock);
+ spin_unlock(&vm->status_lock);
}
/**
@@ -331,11 +358,11 @@ void amdgpu_vm_bo_update_shared(struct amdgpu_bo *bo)
* be bo->tbo.resource
* @sign: if we should add (+1) or subtract (-1) from the stat
*
- * Caller need to have the vm stats_lock held. Useful for when multiple update
+ * Caller need to have the vm status_lock held. Useful for when multiple update
* need to happen at the same time.
*/
static void amdgpu_vm_update_stats_locked(struct amdgpu_vm_bo_base *base,
- struct ttm_resource *res, int sign)
+ struct ttm_resource *res, int sign)
{
struct amdgpu_vm *vm = base->vm;
struct amdgpu_bo *bo = base->bo;
@@ -359,8 +386,7 @@ static void amdgpu_vm_update_stats_locked(struct amdgpu_vm_bo_base *base,
*/
if (bo->flags & AMDGPU_GEM_CREATE_DISCARDABLE)
vm->stats[res_memtype].drm.purgeable += size;
- if (!(bo->preferred_domains &
- amdgpu_mem_type_to_domain(res_memtype)))
+ if (!(bo->preferred_domains & amdgpu_mem_type_to_domain(res_memtype)))
vm->stats[bo_memtype].evicted += size;
}
}
@@ -379,9 +405,9 @@ void amdgpu_vm_update_stats(struct amdgpu_vm_bo_base *base,
{
struct amdgpu_vm *vm = base->vm;
- spin_lock(&vm->stats_lock);
+ spin_lock(&vm->status_lock);
amdgpu_vm_update_stats_locked(base, res, sign);
- spin_unlock(&vm->stats_lock);
+ spin_unlock(&vm->status_lock);
}
/**
@@ -407,10 +433,10 @@ void amdgpu_vm_bo_base_init(struct amdgpu_vm_bo_base *base,
base->next = bo->vm_bo;
bo->vm_bo = base;
- spin_lock(&vm->stats_lock);
+ spin_lock(&vm->status_lock);
base->shared = drm_gem_object_is_shared_for_memory_stats(&bo->tbo.base);
amdgpu_vm_update_stats_locked(base, bo->tbo.resource, +1);
- spin_unlock(&vm->stats_lock);
+ spin_unlock(&vm->status_lock);
if (!amdgpu_vm_is_bo_always_valid(vm, bo))
return;
@@ -469,25 +495,25 @@ int amdgpu_vm_lock_done_list(struct amdgpu_vm *vm, struct drm_exec *exec,
int ret;
/* We can only trust prev->next while holding the lock */
- spin_lock(&vm->invalidated_lock);
+ spin_lock(&vm->status_lock);
while (!list_is_head(prev->next, &vm->done)) {
bo_va = list_entry(prev->next, typeof(*bo_va), base.vm_status);
bo = bo_va->base.bo;
if (bo) {
amdgpu_bo_ref(bo);
- spin_unlock(&vm->invalidated_lock);
+ spin_unlock(&vm->status_lock);
ret = drm_exec_prepare_obj(exec, &bo->tbo.base, 1);
amdgpu_bo_unref(&bo);
if (unlikely(ret))
return ret;
- spin_lock(&vm->invalidated_lock);
+ spin_lock(&vm->status_lock);
}
prev = prev->next;
}
- spin_unlock(&vm->invalidated_lock);
+ spin_unlock(&vm->status_lock);
return 0;
}
@@ -583,7 +609,7 @@ int amdgpu_vm_validate(struct amdgpu_device *adev, struct amdgpu_vm *vm,
void *param)
{
uint64_t new_vm_generation = amdgpu_vm_generation(adev, vm);
- struct amdgpu_vm_bo_base *bo_base, *tmp;
+ struct amdgpu_vm_bo_base *bo_base;
struct amdgpu_bo *bo;
int r;
@@ -596,7 +622,13 @@ int amdgpu_vm_validate(struct amdgpu_device *adev, struct amdgpu_vm *vm,
return r;
}
- list_for_each_entry_safe(bo_base, tmp, &vm->evicted, vm_status) {
+ spin_lock(&vm->status_lock);
+ while (!list_empty(&vm->evicted)) {
+ bo_base = list_first_entry(&vm->evicted,
+ struct amdgpu_vm_bo_base,
+ vm_status);
+ spin_unlock(&vm->status_lock);
+
bo = bo_base->bo;
r = validate(param, bo);
@@ -609,21 +641,26 @@ int amdgpu_vm_validate(struct amdgpu_device *adev, struct amdgpu_vm *vm,
vm->update_funcs->map_table(to_amdgpu_bo_vm(bo));
amdgpu_vm_bo_relocated(bo_base);
}
+ spin_lock(&vm->status_lock);
}
+ while (ticket && !list_empty(&vm->evicted_user)) {
+ bo_base = list_first_entry(&vm->evicted_user,
+ struct amdgpu_vm_bo_base,
+ vm_status);
+ spin_unlock(&vm->status_lock);
- if (ticket) {
- list_for_each_entry_safe(bo_base, tmp, &vm->evicted_user,
- vm_status) {
- bo = bo_base->bo;
- dma_resv_assert_held(bo->tbo.base.resv);
+ bo = bo_base->bo;
+ dma_resv_assert_held(bo->tbo.base.resv);
- r = validate(param, bo);
- if (r)
- return r;
+ r = validate(param, bo);
+ if (r)
+ return r;
- amdgpu_vm_bo_invalidated(bo_base);
- }
+ amdgpu_vm_bo_invalidated(bo_base);
+
+ spin_lock(&vm->status_lock);
}
+ spin_unlock(&vm->status_lock);
amdgpu_vm_eviction_lock(vm);
vm->evicting = false;
@@ -652,7 +689,9 @@ bool amdgpu_vm_ready(struct amdgpu_vm *vm)
ret = !vm->evicting;
amdgpu_vm_eviction_unlock(vm);
+ spin_lock(&vm->status_lock);
ret &= list_empty(&vm->evicted);
+ spin_unlock(&vm->status_lock);
spin_lock(&vm->immediate.lock);
ret &= !vm->immediate.stopped;
@@ -946,13 +985,18 @@ int amdgpu_vm_update_pdes(struct amdgpu_device *adev,
struct amdgpu_vm *vm, bool immediate)
{
struct amdgpu_vm_update_params params;
- struct amdgpu_vm_bo_base *entry, *tmp;
+ struct amdgpu_vm_bo_base *entry;
bool flush_tlb_needed = false;
+ LIST_HEAD(relocated);
int r, idx;
amdgpu_vm_assert_locked(vm);
- if (list_empty(&vm->relocated))
+ spin_lock(&vm->status_lock);
+ list_splice_init(&vm->relocated, &relocated);
+ spin_unlock(&vm->status_lock);
+
+ if (list_empty(&relocated))
return 0;
if (!drm_dev_enter(adev_to_drm(adev), &idx))
@@ -968,7 +1012,7 @@ int amdgpu_vm_update_pdes(struct amdgpu_device *adev,
if (r)
goto error;
- list_for_each_entry(entry, &vm->relocated, vm_status) {
+ list_for_each_entry(entry, &relocated, vm_status) {
/* vm_flush_needed after updating moved PDEs */
flush_tlb_needed |= entry->moved;
@@ -984,7 +1028,9 @@ int amdgpu_vm_update_pdes(struct amdgpu_device *adev,
if (flush_tlb_needed)
atomic64_inc(&vm->tlb_seq);
- list_for_each_entry_safe(entry, tmp, &vm->relocated, vm_status) {
+ while (!list_empty(&relocated)) {
+ entry = list_first_entry(&relocated, struct amdgpu_vm_bo_base,
+ vm_status);
amdgpu_vm_bo_idle(entry);
}
@@ -1041,7 +1087,10 @@ amdgpu_vm_tlb_flush(struct amdgpu_vm_update_params *params,
}
/* Prepare a TLB flush fence to be attached to PTs */
- if (!params->unlocked) {
+ /* The check for need_tlb_fence should be dropped once we
+ * sort out the issues with KIQ/MES TLB invalidation timeouts.
+ */
+ if (!params->unlocked && vm->need_tlb_fence) {
amdgpu_vm_tlb_fence_create(params->adev, vm, fence);
/* Makes sure no PD/PT is freed before the flush */
@@ -1211,9 +1260,9 @@ error_free:
void amdgpu_vm_get_memory(struct amdgpu_vm *vm,
struct amdgpu_mem_stats stats[__AMDGPU_PL_NUM])
{
- spin_lock(&vm->stats_lock);
+ spin_lock(&vm->status_lock);
memcpy(stats, vm->stats, sizeof(*stats) * __AMDGPU_PL_NUM);
- spin_unlock(&vm->stats_lock);
+ spin_unlock(&vm->status_lock);
}
/**
@@ -1580,24 +1629,29 @@ int amdgpu_vm_handle_moved(struct amdgpu_device *adev,
struct amdgpu_vm *vm,
struct ww_acquire_ctx *ticket)
{
- struct amdgpu_bo_va *bo_va, *tmp;
+ struct amdgpu_bo_va *bo_va;
struct dma_resv *resv;
bool clear, unlock;
int r;
- list_for_each_entry_safe(bo_va, tmp, &vm->moved, base.vm_status) {
+ spin_lock(&vm->status_lock);
+ while (!list_empty(&vm->moved)) {
+ bo_va = list_first_entry(&vm->moved, struct amdgpu_bo_va,
+ base.vm_status);
+ spin_unlock(&vm->status_lock);
+
/* Per VM BOs never need to bo cleared in the page tables */
r = amdgpu_vm_bo_update(adev, bo_va, false);
if (r)
return r;
+ spin_lock(&vm->status_lock);
}
- spin_lock(&vm->invalidated_lock);
while (!list_empty(&vm->invalidated)) {
bo_va = list_first_entry(&vm->invalidated, struct amdgpu_bo_va,
base.vm_status);
resv = bo_va->base.bo->tbo.base.resv;
- spin_unlock(&vm->invalidated_lock);
+ spin_unlock(&vm->status_lock);
/* Try to reserve the BO to avoid clearing its ptes */
if (!adev->debug_vm && dma_resv_trylock(resv)) {
@@ -1629,9 +1683,9 @@ int amdgpu_vm_handle_moved(struct amdgpu_device *adev,
bo_va->base.bo->tbo.resource->mem_type == TTM_PL_SYSTEM))
amdgpu_vm_bo_evicted_user(&bo_va->base);
- spin_lock(&vm->invalidated_lock);
+ spin_lock(&vm->status_lock);
}
- spin_unlock(&vm->invalidated_lock);
+ spin_unlock(&vm->status_lock);
return 0;
}
@@ -2174,9 +2228,9 @@ void amdgpu_vm_bo_del(struct amdgpu_device *adev,
}
}
- spin_lock(&vm->invalidated_lock);
+ spin_lock(&vm->status_lock);
list_del(&bo_va->base.vm_status);
- spin_unlock(&vm->invalidated_lock);
+ spin_unlock(&vm->status_lock);
list_for_each_entry_safe(mapping, next, &bo_va->valids, list) {
list_del(&mapping->list);
@@ -2284,10 +2338,10 @@ void amdgpu_vm_bo_move(struct amdgpu_bo *bo, struct ttm_resource *new_mem,
for (bo_base = bo->vm_bo; bo_base; bo_base = bo_base->next) {
struct amdgpu_vm *vm = bo_base->vm;
- spin_lock(&vm->stats_lock);
+ spin_lock(&vm->status_lock);
amdgpu_vm_update_stats_locked(bo_base, bo->tbo.resource, -1);
amdgpu_vm_update_stats_locked(bo_base, new_mem, +1);
- spin_unlock(&vm->stats_lock);
+ spin_unlock(&vm->status_lock);
}
amdgpu_vm_bo_invalidate(bo, evicted);
@@ -2556,12 +2610,11 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm,
INIT_LIST_HEAD(&vm->relocated);
INIT_LIST_HEAD(&vm->moved);
INIT_LIST_HEAD(&vm->idle);
- spin_lock_init(&vm->invalidated_lock);
INIT_LIST_HEAD(&vm->invalidated);
+ spin_lock_init(&vm->status_lock);
INIT_LIST_HEAD(&vm->freed);
INIT_LIST_HEAD(&vm->done);
INIT_KFIFO(vm->faults);
- spin_lock_init(&vm->stats_lock);
r = amdgpu_vm_init_entities(adev, vm);
if (r)
@@ -2570,6 +2623,7 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm,
ttm_lru_bulk_move_init(&vm->lru_bulk_move);
vm->is_compute_context = false;
+ vm->need_tlb_fence = amdgpu_userq_enabled(&adev->ddev);
vm->use_cpu_for_update = !!(adev->vm_manager.vm_update_mode &
AMDGPU_VM_USE_CPU_FOR_GFX);
@@ -2707,6 +2761,7 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm)
dma_fence_put(vm->last_update);
vm->last_update = dma_fence_get_stub();
vm->is_compute_context = true;
+ vm->need_tlb_fence = true;
unreserve_bo:
amdgpu_bo_unreserve(vm->root.bo);
@@ -2861,6 +2916,7 @@ void amdgpu_vm_manager_fini(struct amdgpu_device *adev)
xa_destroy(&adev->vm_manager.pasids);
amdgpu_vmid_mgr_fini(adev);
+ amdgpu_pasid_mgr_cleanup();
}
/**
@@ -2936,14 +2992,14 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
if (!root)
return false;
- addr /= AMDGPU_GPU_PAGE_SIZE;
-
if (is_compute_context && !svm_range_restore_pages(adev, pasid, vmid,
- node_id, addr, ts, write_fault)) {
+ node_id, addr >> PAGE_SHIFT, ts, write_fault)) {
amdgpu_bo_unref(&root);
return true;
}
+ addr /= AMDGPU_GPU_PAGE_SIZE;
+
r = amdgpu_bo_reserve(root, true);
if (r)
goto error_unref;
@@ -3029,6 +3085,7 @@ void amdgpu_debugfs_vm_bo_info(struct amdgpu_vm *vm, struct seq_file *m)
amdgpu_vm_assert_locked(vm);
+ spin_lock(&vm->status_lock);
seq_puts(m, "\tIdle BOs:\n");
list_for_each_entry_safe(bo_va, tmp, &vm->idle, base.vm_status) {
if (!bo_va->base.bo)
@@ -3066,13 +3123,11 @@ void amdgpu_debugfs_vm_bo_info(struct amdgpu_vm *vm, struct seq_file *m)
id = 0;
seq_puts(m, "\tInvalidated BOs:\n");
- spin_lock(&vm->invalidated_lock);
list_for_each_entry_safe(bo_va, tmp, &vm->invalidated, base.vm_status) {
if (!bo_va->base.bo)
continue;
total_invalidated += amdgpu_bo_print_info(id++, bo_va->base.bo, m);
}
- spin_unlock(&vm->invalidated_lock);
total_invalidated_objs = id;
id = 0;
@@ -3082,6 +3137,7 @@ void amdgpu_debugfs_vm_bo_info(struct amdgpu_vm *vm, struct seq_file *m)
continue;
total_done += amdgpu_bo_print_info(id++, bo_va->base.bo, m);
}
+ spin_unlock(&vm->status_lock);
total_done_objs = id;
seq_printf(m, "\tTotal idle size: %12lld\tobjs:\t%d\n", total_idle,
@@ -3156,20 +3212,6 @@ void amdgpu_vm_update_fault_cache(struct amdgpu_device *adev,
xa_unlock_irqrestore(&adev->vm_manager.pasids, flags);
}
-/**
- * amdgpu_vm_is_bo_always_valid - check if the BO is VM always valid
- *
- * @vm: VM to test against.
- * @bo: BO to be tested.
- *
- * Returns true if the BO shares the dma_resv object with the root PD and is
- * always guaranteed to be valid inside the VM.
- */
-bool amdgpu_vm_is_bo_always_valid(struct amdgpu_vm *vm, struct amdgpu_bo *bo)
-{
- return bo && bo->tbo.base.resv == vm->root.bo->tbo.base.resv;
-}
-
void amdgpu_vm_print_task_info(struct amdgpu_device *adev,
struct amdgpu_task_info *task_info)
{
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
index 87b0617d4661..3b32f41c3655 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
@@ -173,7 +173,7 @@ struct amdgpu_bo_vm;
#define AMDGPU_VA_RESERVED_SEQ64_SIZE (2ULL << 20)
#define AMDGPU_VA_RESERVED_SEQ64_START(adev) (AMDGPU_VA_RESERVED_CSA_START(adev) \
- AMDGPU_VA_RESERVED_SEQ64_SIZE)
-#define AMDGPU_VA_RESERVED_TRAP_SIZE (2ULL << 12)
+#define AMDGPU_VA_RESERVED_TRAP_SIZE (1ULL << 16)
#define AMDGPU_VA_RESERVED_TRAP_START(adev) (AMDGPU_VA_RESERVED_SEQ64_START(adev) \
- AMDGPU_VA_RESERVED_TRAP_SIZE)
#define AMDGPU_VA_RESERVED_BOTTOM (1ULL << 16)
@@ -205,11 +205,11 @@ struct amdgpu_vm_bo_base {
/* protected by bo being reserved */
struct amdgpu_vm_bo_base *next;
- /* protected by vm reservation and invalidated_lock */
+ /* protected by vm status_lock */
struct list_head vm_status;
/* if the bo is counted as shared in mem stats
- * protected by vm BO being reserved */
+ * protected by vm status_lock */
bool shared;
/* protected by the BO being reserved */
@@ -345,8 +345,10 @@ struct amdgpu_vm {
bool evicting;
unsigned int saved_flags;
- /* Memory statistics for this vm, protected by stats_lock */
- spinlock_t stats_lock;
+ /* Lock to protect vm_bo add/del/move on all lists of vm */
+ spinlock_t status_lock;
+
+ /* Memory statistics for this vm, protected by status_lock */
struct amdgpu_mem_stats stats[__AMDGPU_PL_NUM];
/*
@@ -354,8 +356,6 @@ struct amdgpu_vm {
* PDs, PTs or per VM BOs. The state transits are:
*
* evicted -> relocated (PDs, PTs) or moved (per VM BOs) -> idle
- *
- * Lists are protected by the root PD dma_resv lock.
*/
/* Per-VM and PT BOs who needs a validation */
@@ -376,10 +376,7 @@ struct amdgpu_vm {
* state transits are:
*
* evicted_user or invalidated -> done
- *
- * Lists are protected by the invalidated_lock.
*/
- spinlock_t invalidated_lock;
/* BOs for user mode queues that need a validation */
struct list_head evicted_user;
@@ -444,6 +441,8 @@ struct amdgpu_vm {
struct ttm_lru_bulk_move lru_bulk_move;
/* Flag to indicate if VM is used for compute */
bool is_compute_context;
+ /* Flag to indicate if VM needs a TLB fence (KFD or KGD) */
+ bool need_tlb_fence;
/* Memory partition number, -1 means any partition */
int8_t mem_id;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
index 7bdd664f0770..31a437ce9570 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
@@ -544,7 +544,9 @@ static void amdgpu_vm_pt_free(struct amdgpu_vm_bo_base *entry)
entry->bo->vm_bo = NULL;
ttm_bo_set_bulk_move(&entry->bo->tbo, NULL);
+ spin_lock(&entry->vm->status_lock);
list_del(&entry->vm_status);
+ spin_unlock(&entry->vm->status_lock);
amdgpu_bo_unref(&entry->bo);
}
@@ -588,6 +590,7 @@ static void amdgpu_vm_pt_add_list(struct amdgpu_vm_update_params *params,
struct amdgpu_vm_pt_cursor seek;
struct amdgpu_vm_bo_base *entry;
+ spin_lock(&params->vm->status_lock);
for_each_amdgpu_vm_pt_dfs_safe(params->adev, params->vm, cursor, seek, entry) {
if (entry && entry->bo)
list_move(&entry->vm_status, &params->tlb_flush_waitlist);
@@ -595,6 +598,7 @@ static void amdgpu_vm_pt_add_list(struct amdgpu_vm_update_params *params,
/* enter start node now */
list_move(&cursor->entry->vm_status, &params->tlb_flush_waitlist);
+ spin_unlock(&params->vm->status_lock);
}
/**
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
index e36c287b3289..e63d05c477a0 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
@@ -472,12 +472,12 @@ static ssize_t amdgpu_xgmi_show_num_hops(struct device *dev,
struct drm_device *ddev = dev_get_drvdata(dev);
struct amdgpu_device *adev = drm_to_adev(ddev);
struct psp_xgmi_topology_info *top = &adev->psp.xgmi_context.top_info;
- int i;
+ int i, offset = 0;
for (i = 0; i < top->num_nodes; i++)
- sprintf(buf + 3 * i, "%02x ", top->nodes[i].num_hops);
+ offset += sysfs_emit_at(buf, offset, "%02x ", top->nodes[i].num_hops);
- return sysfs_emit(buf, "%s\n", buf);
+ return offset + sysfs_emit_at(buf, offset, "\n");
}
static ssize_t amdgpu_xgmi_show_num_links(struct device *dev,
@@ -487,12 +487,12 @@ static ssize_t amdgpu_xgmi_show_num_links(struct device *dev,
struct drm_device *ddev = dev_get_drvdata(dev);
struct amdgpu_device *adev = drm_to_adev(ddev);
struct psp_xgmi_topology_info *top = &adev->psp.xgmi_context.top_info;
- int i;
+ int i, offset = 0;
for (i = 0; i < top->num_nodes; i++)
- sprintf(buf + 3 * i, "%02x ", top->nodes[i].num_links);
+ offset += sysfs_emit_at(buf, offset, "%02x ", top->nodes[i].num_links);
- return sysfs_emit(buf, "%s\n", buf);
+ return offset + sysfs_emit_at(buf, offset, "\n");
}
static ssize_t amdgpu_xgmi_show_connected_port_num(struct device *dev,
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
index 1893ceeeb26c..8b60299b73ef 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
@@ -6752,7 +6752,7 @@ static void gfx_v10_0_gfx_mqd_set_priority(struct amdgpu_device *adev,
/* set up default queue priority level
* 0x0 = low priority, 0x1 = high priority
*/
- if (prop->hqd_pipe_priority == AMDGPU_GFX_PIPE_PRIO_HIGH)
+ if (prop->hqd_queue_priority == AMDGPU_GFX_QUEUE_PRIORITY_MAXIMUM)
priority = 1;
tmp = RREG32_SOC15(GC, 0, mmCP_GFX_HQD_QUEUE_PRIORITY);
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
index b1a1b8a10a08..ae39b9e1f7d6 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
@@ -1722,6 +1722,20 @@ static int gfx_v11_0_sw_init(struct amdgpu_ip_block *ip_block)
}
}
break;
+ case IP_VERSION(11, 5, 4):
+ adev->gfx.cleaner_shader_ptr = gfx_11_0_3_cleaner_shader_hex;
+ adev->gfx.cleaner_shader_size = sizeof(gfx_11_0_3_cleaner_shader_hex);
+ if (adev->gfx.me_fw_version >= 4 &&
+ adev->gfx.pfp_fw_version >= 7 &&
+ adev->gfx.mec_fw_version >= 5) {
+ adev->gfx.enable_cleaner_shader = true;
+ r = amdgpu_gfx_cleaner_shader_sw_init(adev, adev->gfx.cleaner_shader_size);
+ if (r) {
+ adev->gfx.enable_cleaner_shader = false;
+ dev_err(adev->dev, "Failed to initialize cleaner shader\n");
+ }
+ }
+ break;
default:
adev->gfx.enable_cleaner_shader = false;
break;
@@ -4088,7 +4102,7 @@ static void gfx_v11_0_gfx_mqd_set_priority(struct amdgpu_device *adev,
/* set up default queue priority level
* 0x0 = low priority, 0x1 = high priority
*/
- if (prop->hqd_pipe_priority == AMDGPU_GFX_PIPE_PRIO_HIGH)
+ if (prop->hqd_queue_priority == AMDGPU_GFX_QUEUE_PRIORITY_MAXIMUM)
priority = 1;
tmp = regCP_GFX_HQD_QUEUE_PRIORITY_DEFAULT;
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v12_1.c b/drivers/gpu/drm/amd/amdgpu/gfx_v12_1.c
index 4e02b62cdbb3..db49582a211f 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v12_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v12_1.c
@@ -45,6 +45,7 @@
#include "v12_structs.h"
#include "gfx_v12_1.h"
#include "mes_v12_1.h"
+#include "amdgpu_ras_mgr.h"
#define GFX12_MEC_HPD_SIZE 2048
#define NUM_SIMD_PER_CU_GFX12_1 4
@@ -136,7 +137,6 @@ static void gfx_v12_1_kiq_map_queues(struct amdgpu_ring *kiq_ring,
PACKET3_MAP_QUEUES_PIPE(ring->pipe) |
PACKET3_MAP_QUEUES_ME((me)) |
PACKET3_MAP_QUEUES_QUEUE_TYPE(0) | /*queue_type: normal compute queue */
- PACKET3_MAP_QUEUES_ALLOC_FORMAT(0) | /* alloc format: all_on_one_pipe */
PACKET3_MAP_QUEUES_ENGINE_SEL(eng_sel) |
PACKET3_MAP_QUEUES_NUM_QUEUES(1)); /* num_queues: must be 1 */
amdgpu_ring_write(kiq_ring, PACKET3_MAP_QUEUES_DOORBELL_OFFSET(ring->doorbell_index));
@@ -245,8 +245,7 @@ static void gfx_v12_1_wait_reg_mem(struct amdgpu_ring *ring, int eng_sel,
/* memory (1) or register (0) */
(WAIT_REG_MEM_MEM_SPACE(mem_space) |
WAIT_REG_MEM_OPERATION(opt) | /* wait */
- WAIT_REG_MEM_FUNCTION(3) | /* equal */
- WAIT_REG_MEM_ENGINE(eng_sel)));
+ WAIT_REG_MEM_FUNCTION(3))); /* equal */
if (mem_space)
BUG_ON(addr0 & 0x3); /* Dword align */
@@ -1186,6 +1185,13 @@ static int gfx_v12_1_sw_init(struct amdgpu_ip_block *ip_block)
if (r)
return r;
+ /* RLC POISON Error */
+ r = amdgpu_irq_add_id(adev, SOC_V1_0_IH_CLIENTID_RLC,
+ GFX_12_1_0__SRCID__RLC_POISON_INTERRUPT,
+ &adev->gfx.rlc_poison_irq);
+ if (r)
+ return r;
+
adev->gfx.gfx_current_status = AMDGPU_GFX_NORMAL_MODE;
r = gfx_v12_1_rlc_init(adev);
@@ -2631,24 +2637,6 @@ static void gfx_v12_1_xcc_disable_gpa_mode(struct amdgpu_device *adev,
WREG32_SOC15(GC, GET_INST(GC, xcc_id), regCPG_PSP_DEBUG, data);
}
-static void gfx_v12_1_xcc_setup_tcp_thrashing_ctrl(struct amdgpu_device *adev,
- int xcc_id)
-{
- uint32_t val;
-
- /* Set the TCP UTCL0 register to enable atomics */
- val = RREG32_SOC15(GC, GET_INST(GC, xcc_id),
- regTCP_UTCL0_THRASHING_CTRL);
- val = REG_SET_FIELD(val, TCP_UTCL0_THRASHING_CTRL, THRASHING_EN, 0x2);
- val = REG_SET_FIELD(val, TCP_UTCL0_THRASHING_CTRL,
- RETRY_FRAGMENT_THRESHOLD_UP_EN, 0x1);
- val = REG_SET_FIELD(val, TCP_UTCL0_THRASHING_CTRL,
- RETRY_FRAGMENT_THRESHOLD_DOWN_EN, 0x1);
-
- WREG32_SOC15(GC, GET_INST(GC, xcc_id),
- regTCP_UTCL0_THRASHING_CTRL, val);
-}
-
static void gfx_v12_1_xcc_enable_atomics(struct amdgpu_device *adev,
int xcc_id)
{
@@ -2697,7 +2685,6 @@ static void gfx_v12_1_init_golden_registers(struct amdgpu_device *adev)
for (i = 0; i < NUM_XCC(adev->gfx.xcc_mask); i++) {
gfx_v12_1_xcc_disable_burst(adev, i);
gfx_v12_1_xcc_enable_atomics(adev, i);
- gfx_v12_1_xcc_setup_tcp_thrashing_ctrl(adev, i);
gfx_v12_1_xcc_disable_early_write_ack(adev, i);
gfx_v12_1_xcc_disable_tcp_spill_cache(adev, i);
}
@@ -3431,11 +3418,10 @@ static void gfx_v12_1_ring_emit_fence(struct amdgpu_ring *ring, u64 addr,
static void gfx_v12_1_ring_emit_pipeline_sync(struct amdgpu_ring *ring)
{
- int usepfp = (ring->funcs->type == AMDGPU_RING_TYPE_GFX);
uint32_t seq = ring->fence_drv.sync_seq;
uint64_t addr = ring->fence_drv.gpu_addr;
- gfx_v12_1_wait_reg_mem(ring, usepfp, 1, 0, lower_32_bits(addr),
+ gfx_v12_1_wait_reg_mem(ring, 0, 1, 0, lower_32_bits(addr),
upper_32_bits(addr), seq, 0xffffffff, 4);
}
@@ -3474,8 +3460,7 @@ static void gfx_v12_1_ring_emit_fence_kiq(struct amdgpu_ring *ring, u64 addr,
/* write fence seq to the "addr" */
amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
- amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
- WRITE_DATA_DST_SEL(5) | WR_CONFIRM));
+ amdgpu_ring_write(ring, (WRITE_DATA_DST_SEL(5) | WR_CONFIRM));
amdgpu_ring_write(ring, lower_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(addr));
amdgpu_ring_write(ring, lower_32_bits(seq));
@@ -3483,8 +3468,7 @@ static void gfx_v12_1_ring_emit_fence_kiq(struct amdgpu_ring *ring, u64 addr,
if (flags & AMDGPU_FENCE_FLAG_INT) {
/* set register to trigger INT */
amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
- amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
- WRITE_DATA_DST_SEL(0) | WR_CONFIRM));
+ amdgpu_ring_write(ring, (WRITE_DATA_DST_SEL(0) | WR_CONFIRM));
amdgpu_ring_write(ring, SOC15_REG_OFFSET(GC, GET_INST(GC, 0), regCPC_INT_STATUS));
amdgpu_ring_write(ring, 0);
amdgpu_ring_write(ring, 0x20000000); /* src_id is 178 */
@@ -3543,9 +3527,7 @@ static void gfx_v12_1_ring_emit_reg_write_reg_wait(struct amdgpu_ring *ring,
uint32_t reg0, uint32_t reg1,
uint32_t ref, uint32_t mask)
{
- int usepfp = (ring->funcs->type == AMDGPU_RING_TYPE_GFX);
-
- gfx_v12_1_wait_reg_mem(ring, usepfp, 0, 1, reg0, reg1,
+ gfx_v12_1_wait_reg_mem(ring, 0, 0, 1, reg0, reg1,
ref, mask, 0x20);
}
@@ -3804,6 +3786,35 @@ static int gfx_v12_1_priv_inst_irq(struct amdgpu_device *adev,
return 0;
}
+static int gfx_v12_1_rlc_poison_irq(struct amdgpu_device *adev,
+ struct amdgpu_irq_src *source,
+ struct amdgpu_iv_entry *entry)
+{
+ uint32_t rlc_fed_status = 0;
+ uint32_t ras_blk = RAS_BLOCK_ID__GFX;
+ struct ras_ih_info ih_info = {0};
+ int i, num_xcc;
+
+ num_xcc = NUM_XCC(adev->gfx.xcc_mask);
+ for (i = 0; i < num_xcc; i++)
+ rlc_fed_status |= RREG32(SOC15_REG_OFFSET(GC,
+ GET_INST(GC, i), regRLC_RLCS_FED_STATUS));
+
+ if (!rlc_fed_status)
+ return 0;
+
+ if (REG_GET_FIELD(rlc_fed_status, RLC_RLCS_FED_STATUS, SDMA0_FED_ERR) ||
+ REG_GET_FIELD(rlc_fed_status, RLC_RLCS_FED_STATUS, SDMA1_FED_ERR))
+ ras_blk = RAS_BLOCK_ID__SDMA;
+
+ dev_warn(adev->dev, "RLC %d FED IRQ\n", ras_blk);
+
+ ih_info.block = ras_blk;
+ ih_info.reset = AMDGPU_RAS_GPU_RESET_MODE2_RESET;
+ amdgpu_ras_mgr_dispatch_interrupt(adev, &ih_info);
+ return 0;
+}
+
static void gfx_v12_1_emit_mem_sync(struct amdgpu_ring *ring)
{
const unsigned int gcr_cntl =
@@ -3928,6 +3939,10 @@ static const struct amdgpu_irq_src_funcs gfx_v12_1_priv_inst_irq_funcs = {
.process = gfx_v12_1_priv_inst_irq,
};
+static const struct amdgpu_irq_src_funcs gfx_v12_1_rlc_poison_irq_funcs = {
+ .process = gfx_v12_1_rlc_poison_irq,
+};
+
static void gfx_v12_1_set_irq_funcs(struct amdgpu_device *adev)
{
adev->gfx.eop_irq.num_types = AMDGPU_CP_IRQ_LAST;
@@ -3938,6 +3953,9 @@ static void gfx_v12_1_set_irq_funcs(struct amdgpu_device *adev)
adev->gfx.priv_inst_irq.num_types = 1;
adev->gfx.priv_inst_irq.funcs = &gfx_v12_1_priv_inst_irq_funcs;
+
+ adev->gfx.rlc_poison_irq.num_types = 1;
+ adev->gfx.rlc_poison_irq.funcs = &gfx_v12_1_rlc_poison_irq_funcs;
}
static void gfx_v12_1_set_imu_funcs(struct amdgpu_device *adev)
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v12_1_pkt.h b/drivers/gpu/drm/amd/amdgpu/gfx_v12_1_pkt.h
index 9a5c82c8db53..21a07530c64d 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v12_1_pkt.h
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v12_1_pkt.h
@@ -53,16 +53,10 @@
/* Packet 3 types */
#define PACKET3_NOP 0x10
-#define PACKET3_SET_BASE 0x11
-#define PACKET3_BASE_INDEX(x) ((x) << 0)
-#define CE_PARTITION_BASE 3
#define PACKET3_CLEAR_STATE 0x12
#define PACKET3_INDEX_BUFFER_SIZE 0x13
#define PACKET3_DISPATCH_DIRECT 0x15
#define PACKET3_DISPATCH_INDIRECT 0x16
-#define PACKET3_INDIRECT_BUFFER_END 0x17
-#define PACKET3_INDIRECT_BUFFER_CNST_END 0x19
-#define PACKET3_ATOMIC_GDS 0x1D
#define PACKET3_ATOMIC_MEM 0x1E
#define PACKET3_OCCLUSION_QUERY 0x1F
#define PACKET3_SET_PREDICATION 0x20
@@ -74,47 +68,42 @@
#define PACKET3_INDEX_BASE 0x26
#define PACKET3_DRAW_INDEX_2 0x27
#define PACKET3_CONTEXT_CONTROL 0x28
-#define PACKET3_INDEX_TYPE 0x2A
#define PACKET3_DRAW_INDIRECT_MULTI 0x2C
#define PACKET3_DRAW_INDEX_AUTO 0x2D
#define PACKET3_NUM_INSTANCES 0x2F
#define PACKET3_DRAW_INDEX_MULTI_AUTO 0x30
-#define PACKET3_INDIRECT_BUFFER_PRIV 0x32
-#define PACKET3_INDIRECT_BUFFER_CNST 0x33
-#define PACKET3_COND_INDIRECT_BUFFER_CNST 0x33
-#define PACKET3_STRMOUT_BUFFER_UPDATE 0x34
#define PACKET3_DRAW_INDEX_OFFSET_2 0x35
-#define PACKET3_DRAW_PREAMBLE 0x36
#define PACKET3_WRITE_DATA 0x37
-#define WRITE_DATA_DST_SEL(x) ((x) << 8)
+#define WRITE_DATA_DST_SEL(x) (((x) & 0xf) << 8)
/* 0 - register
- * 1 - memory (sync - via GRBM)
- * 2 - gl2
- * 3 - gds
+ * 1 - reserved
+ * 2 - tc_l2
+ * 3 - reserved
* 4 - reserved
- * 5 - memory (async - direct)
+ * 5 - memory (same as tc_l2)
+ * 6 - memory_mapped_adc_persistent_state
*/
-#define WR_ONE_ADDR (1 << 16)
+#define WRITE_DATA_SCOPE(x) (((x) & 0x3) << 12)
+#define WRITE_DATA_MODE(x) (((x) & 0x3) << 14)
+ /* 0 - local xcd
+ * 1 - remote/local aid
+ * 2 - remote xcd
+ * 3 - remote mid
+ */
+#define WRITE_DATA_ADDR_INCR (1 << 16)
+#define WRITE_DATA_MID_DIE_ID(x) (((x) & 0x3) << 18)
#define WR_CONFIRM (1 << 20)
-#define WRITE_DATA_CACHE_POLICY(x) ((x) << 25)
- /* 0 - LRU
- * 1 - Stream
- */
-#define WRITE_DATA_ENGINE_SEL(x) ((x) << 30)
- /* 0 - me
- * 1 - pfp
- * 2 - ce
+#define WRITE_DATA_XCD_DIE_ID(x) (((x) & 0xf) << 21)
+#define WRITE_DATA_TEMPORAL(x) (((x) & 0x3) << 25)
+ /* 0 - rt
+ * 1 - nt
+ * 2 - ht
+ * 3 - lu
*/
+#define WRITE_DATA_COOP_DISABLE (1 << 27)
#define PACKET3_DRAW_INDEX_INDIRECT_MULTI 0x38
-#define PACKET3_MEM_SEMAPHORE 0x39
-# define PACKET3_SEM_USE_MAILBOX (0x1 << 16)
-# define PACKET3_SEM_SEL_SIGNAL_TYPE (0x1 << 20) /* 0 = increment, 1 = write 1 */
-# define PACKET3_SEM_SEL_SIGNAL (0x6 << 29)
-# define PACKET3_SEM_SEL_WAIT (0x7 << 29)
-#define PACKET3_DRAW_INDEX_MULTI_INST 0x3A
-#define PACKET3_COPY_DW 0x3B
#define PACKET3_WAIT_REG_MEM 0x3C
-#define WAIT_REG_MEM_FUNCTION(x) ((x) << 0)
+#define WAIT_REG_MEM_FUNCTION(x) (((x) & 0x7) << 0)
/* 0 - always
* 1 - <
* 2 - <=
@@ -123,33 +112,66 @@
* 5 - >=
* 6 - >
*/
-#define WAIT_REG_MEM_MEM_SPACE(x) ((x) << 4)
+#define WAIT_REG_MEM_MEM_SPACE(x) (((x) & 0x3) << 4)
/* 0 - reg
* 1 - mem
*/
-#define WAIT_REG_MEM_OPERATION(x) ((x) << 6)
+#define WAIT_REG_MEM_OPERATION(x) (((x) & 0x3) << 6)
/* 0 - wait_reg_mem
* 1 - wr_wait_wr_reg
*/
-#define WAIT_REG_MEM_ENGINE(x) ((x) << 8)
- /* 0 - me
- * 1 - pfp
+#define WAIT_REG_MEM_MODE(x) (((x) & 0x3) << 10)
+ /* 0 - local xcd
+ * 1 - remote/local aid
+ * 2 - remote xcd
+ * 3 - remote mid
+ */
+#define WAIT_REG_MEM_MID_DIE_ID(x) (((x) & 0x3) << 12)
+#define WAIT_REG_MEM_XCD_DIE_ID(x) (((x) & 0xf) << 14)
+#define WAIT_REG_MEM_MES_INTR_PIPE(x) (((x) & 0x3) << 22)
+#define WAIT_REG_MEM_MES_ACTION(x) (((x) & 0x1) << 24)
+#define WAIT_REG_MEM_TEMPORAL(x) (((x) & 0x3) << 25)
+ /* 0 - rt
+ * 1 - nt
+ * 2 - ht
+ * 3 - lu
*/
#define PACKET3_INDIRECT_BUFFER 0x3F
#define INDIRECT_BUFFER_VALID (1 << 23)
-#define INDIRECT_BUFFER_CACHE_POLICY(x) ((x) << 28)
- /* 0 - LRU
- * 1 - Stream
- * 2 - Bypass
+#define INDIRECT_BUFFER_TEMPORAL(x) (x) << 28)
+ /* 0 - rt
+ * 1 - nt
+ * 2 - ht
+ * 3 - lu
*/
-#define INDIRECT_BUFFER_PRE_ENB(x) ((x) << 21)
-#define INDIRECT_BUFFER_PRE_RESUME(x) ((x) << 30)
#define PACKET3_COND_INDIRECT_BUFFER 0x3F
#define PACKET3_COPY_DATA 0x40
-#define PACKET3_CP_DMA 0x41
+#define COPY_DATA_SRC_SEL(x) (((x) & 0xf) << 0)
+#define COPY_DATA_DST_SEL(x) (((x) & 0xf) << 8)
+#define COPY_DATA_SRC_SCOPE(x) (((x) & 0x3) << 4)
+#define COPY_DATA_DST_SCOPE(x) (((x) & 0x3) << 27)
+#define COPY_DATA_MODE(x) (((x) & 0x3) << 6)
+ /* 0 - local xcd
+ * 1 - remote/local aid
+ * 2 - remote xcd
+ * 3 - remote mid
+ */
+#define COPY_DATA_SRC_TEMPORAL(x) (((x) & 0x3) << 13)
+#define COPY_DATA_DST_TEMPORAL(x) (((x) & 0x3) << 25)
+ /* 0 - rt
+ * 1 - nt
+ * 2 - ht
+ * 3 - lu
+ */
+#define COPY_DATA_COUNT_SEL (1 << 16)
+#define COPY_DATA_SRC_DST_REMOTE_MODE(x) (((x)) & 0x1 << 16)
+ /* 0 - src remote
+ * 1 - dst remote
+ */
+#define COPY_DATA_MID_DIE_ID(x) (((x) & 0x3) << 18)
+#define COPY_DATA_XCD_DIE_ID(x) (((x) & 0xf) << 21)
+#define COPY_DATA_PQ_EXE_STATUS (1 << 27)
#define PACKET3_PFP_SYNC_ME 0x42
-#define PACKET3_SURFACE_SYNC 0x43
-#define PACKET3_ME_INITIALIZE 0x44
#define PACKET3_COND_WRITE 0x45
#define PACKET3_EVENT_WRITE 0x46
#define EVENT_TYPE(x) ((x) << 0)
@@ -160,8 +182,6 @@
* 3 - SAMPLE_STREAMOUTSTAT*
* 4 - *S_PARTIAL_FLUSH
*/
-#define PACKET3_EVENT_WRITE_EOP 0x47
-#define PACKET3_EVENT_WRITE_EOS 0x48
#define PACKET3_RELEASE_MEM 0x49
#define PACKET3_RELEASE_MEM_EVENT_TYPE(x) ((x) << 0)
#define PACKET3_RELEASE_MEM_EVENT_INDEX(x) ((x) << 8)
@@ -180,27 +200,30 @@
* 2 - temporal__release_mem__ht
* 3 - temporal__release_mem__lu
*/
-#define PACKET3_RELEASE_MEM_EXECUTE (1 << 28)
+#define PACKET3_RELEASE_MEM_PQ_EXE_STATUS (1 << 28)
+#define PACKET3_RELEASE_MEM_GCR_GLK_INV (1 << 30)
-#define PACKET3_RELEASE_MEM_DATA_SEL(x) ((x) << 29)
- /* 0 - discard
- * 1 - send low 32bit data
- * 2 - send 64bit data
- * 3 - send 64bit GPU counter value
- * 4 - send 64bit sys counter value
+#define PACKET3_RELEASE_MEM_DST_SEL(x) ((x) << 16)
+ /* 0 - memory controller
+ * 1 - TC/L2
+ * 2 - register
*/
+#define PACKET3_RELEASE_MEM_MES_INTR_PIPE(x) ((x) << 20)
+#define PACKET3_RELEASE_MEM_MES_ACTION_ID(x) ((x) << 22)
#define PACKET3_RELEASE_MEM_INT_SEL(x) ((x) << 24)
/* 0 - none
* 1 - interrupt only (DATA_SEL = 0)
* 2 - interrupt when data write is confirmed
*/
-#define PACKET3_RELEASE_MEM_DST_SEL(x) ((x) << 16)
- /* 0 - MC
- * 1 - TC/L2
+#define PACKET3_RELEASE_MEM_ADD_DOOREBLL_OFFSET(x) (1 << 28)
+#define PACKET3_RELEASE_MEM_DATA_SEL(x) ((x) << 29)
+ /* 0 - discard
+ * 1 - send low 32bit data
+ * 2 - send 64bit data
+ * 3 - send 64bit GPU counter value
+ * 4 - send 64bit sys counter value
*/
-
-
#define PACKET3_PREAMBLE_CNTL 0x4A
# define PACKET3_PREAMBLE_BEGIN_CLEAR_STATE (2 << 28)
# define PACKET3_PREAMBLE_END_CLEAR_STATE (3 << 28)
@@ -218,26 +241,29 @@
/* 0 - ME
* 1 - PFP
*/
-# define PACKET3_DMA_DATA_SRC_CACHE_POLICY(x) ((x) << 13)
- /* 0 - LRU
- * 1 - Stream
+# define PACKET3_DMA_DATA_SRC_TEMPORAL(x) ((x) << 13)
+ /* 0 - rt
+ * 1 - nt
+ * 2 - ht
+ * 3 - lu
*/
-# define PACKET3_DMA_DATA_DST_SEL(x) ((x) << 20)
+# define PACKET3_DMA_DATA_SRC_SCOPE(x) ((x) << 15)
+# define PACKET3_DMA_DATA_DST_SEL(x) ((x) << 20)
/* 0 - DST_ADDR using DAS
* 1 - GDS
* 3 - DST_ADDR using L2
*/
-# define PACKET3_DMA_DATA_DST_CACHE_POLICY(x) ((x) << 25)
+# define PACKET3_DMA_DATA_DST_TEMPORAL(x) ((x) << 25)
/* 0 - LRU
* 1 - Stream
*/
-# define PACKET3_DMA_DATA_SRC_SEL(x) ((x) << 29)
+# define PACKET3_DMA_DATA_DST_SCOPE(x) ((x) << 27)
+# define PACKET3_DMA_DATA_SRC_SEL(x) ((x) << 29)
/* 0 - SRC_ADDR using SAS
* 1 - GDS
* 2 - DATA
* 3 - SRC_ADDR using L2
*/
-# define PACKET3_DMA_DATA_CP_SYNC (1 << 31)
/* COMMAND */
# define PACKET3_DMA_DATA_CMD_SAS (1 << 26)
/* 0 - memory
@@ -247,13 +273,11 @@
/* 0 - memory
* 1 - register
*/
-# define PACKET3_DMA_DATA_CMD_SAIC (1 << 28)
-# define PACKET3_DMA_DATA_CMD_DAIC (1 << 29)
-# define PACKET3_DMA_DATA_CMD_RAW_WAIT (1 << 30)
+# define PACKET3_DMA_DATA_CMD_SAIC (1 << 28)
+# define PACKET3_DMA_DATA_CMD_DAIC (1 << 29)
+# define PACKET3_DMA_DATA_CMD_RAW_WAIT (1 << 30)
+# define PACKET3_DMA_DATA_CMD_DIS_WC (1 << 30)
#define PACKET3_CONTEXT_REG_RMW 0x51
-#define PACKET3_GFX_CNTX_UPDATE 0x52
-#define PACKET3_BLK_CNTX_UPDATE 0x53
-#define PACKET3_INCR_UPDT_STATE 0x55
#define PACKET3_ACQUIRE_MEM 0x58
/* 1. HEADER
* 2. COHER_CNTL [30:0]
@@ -307,10 +331,7 @@
* 2: REVERSE
*/
#define PACKET3_ACQUIRE_MEM_GCR_RANGE_IS_PA (1 << 18)
-#define PACKET3_REWIND 0x59
-#define PACKET3_INTERRUPT 0x5A
#define PACKET3_GEN_PDEPTE 0x5B
-#define PACKET3_INDIRECT_BUFFER_PASID 0x5C
#define PACKET3_PRIME_UTCL2 0x5D
#define PACKET3_LOAD_UCONFIG_REG 0x5E
#define PACKET3_LOAD_SH_REG 0x5F
@@ -324,12 +345,6 @@
#define PACKET3_SET_CONTEXT_REG 0x69
#define PACKET3_SET_CONTEXT_REG_START 0x0000a000
#define PACKET3_SET_CONTEXT_REG_END 0x0000a400
-#define PACKET3_SET_CONTEXT_REG_INDEX 0x6A
-#define PACKET3_SET_VGPR_REG_DI_MULTI 0x71
-#define PACKET3_SET_SH_REG_DI 0x72
-#define PACKET3_SET_CONTEXT_REG_INDIRECT 0x73
-#define PACKET3_SET_SH_REG_DI_MULTI 0x74
-#define PACKET3_GFX_PIPE_LOCK 0x75
#define PACKET3_SET_SH_REG 0x76
#define PACKET3_SET_SH_REG_START 0x00002c00
#define PACKET3_SET_SH_REG_END 0x00003000
@@ -339,47 +354,19 @@
#define PACKET3_SET_UCONFIG_REG_START 0x0000c000
#define PACKET3_SET_UCONFIG_REG_END 0x0000c400
#define PACKET3_SET_UCONFIG_REG_INDEX 0x7A
-#define PACKET3_FORWARD_HEADER 0x7C
-#define PACKET3_SCRATCH_RAM_WRITE 0x7D
-#define PACKET3_SCRATCH_RAM_READ 0x7E
-#define PACKET3_LOAD_CONST_RAM 0x80
-#define PACKET3_WRITE_CONST_RAM 0x81
-#define PACKET3_DUMP_CONST_RAM 0x83
-#define PACKET3_INCREMENT_CE_COUNTER 0x84
-#define PACKET3_INCREMENT_DE_COUNTER 0x85
-#define PACKET3_WAIT_ON_CE_COUNTER 0x86
-#define PACKET3_WAIT_ON_DE_COUNTER_DIFF 0x88
-#define PACKET3_SWITCH_BUFFER 0x8B
#define PACKET3_DISPATCH_DRAW_PREAMBLE 0x8C
-#define PACKET3_DISPATCH_DRAW_PREAMBLE_ACE 0x8C
#define PACKET3_DISPATCH_DRAW 0x8D
-#define PACKET3_DISPATCH_DRAW_ACE 0x8D
-#define PACKET3_GET_LOD_STATS 0x8E
-#define PACKET3_DRAW_MULTI_PREAMBLE 0x8F
-#define PACKET3_FRAME_CONTROL 0x90
-# define FRAME_TMZ (1 << 0)
-# define FRAME_CMD(x) ((x) << 28)
- /*
- * x=0: tmz_begin
- * x=1: tmz_end
- */
#define PACKET3_INDEX_ATTRIBUTES_INDIRECT 0x91
#define PACKET3_WAIT_REG_MEM64 0x93
-#define PACKET3_COND_PREEMPT 0x94
#define PACKET3_HDP_FLUSH 0x95
-#define PACKET3_COPY_DATA_RB 0x96
#define PACKET3_INVALIDATE_TLBS 0x98
#define PACKET3_INVALIDATE_TLBS_DST_SEL(x) ((x) << 0)
#define PACKET3_INVALIDATE_TLBS_ALL_HUB(x) ((x) << 4)
#define PACKET3_INVALIDATE_TLBS_PASID(x) ((x) << 5)
#define PACKET3_INVALIDATE_TLBS_FLUSH_TYPE(x) ((x) << 29)
-#define PACKET3_AQL_PACKET 0x99
#define PACKET3_DMA_DATA_FILL_MULTI 0x9A
#define PACKET3_SET_SH_REG_INDEX 0x9B
-#define PACKET3_DRAW_INDIRECT_COUNT_MULTI 0x9C
-#define PACKET3_DRAW_INDEX_INDIRECT_COUNT_MULTI 0x9D
-#define PACKET3_DUMP_CONST_RAM_OFFSET 0x9E
#define PACKET3_LOAD_CONTEXT_REG_INDEX 0x9F
#define PACKET3_SET_RESOURCES 0xA0
/* 1. header
@@ -394,7 +381,6 @@
# define PACKET3_SET_RESOURCES_VMID_MASK(x) ((x) << 0)
# define PACKET3_SET_RESOURCES_UNMAP_LATENTY(x) ((x) << 16)
# define PACKET3_SET_RESOURCES_QUEUE_TYPE(x) ((x) << 29)
-#define PACKET3_MAP_PROCESS 0xA1
#define PACKET3_MAP_QUEUES 0xA2
/* 1. header
* 2. CONTROL
@@ -411,11 +397,10 @@
# define PACKET3_MAP_QUEUES_PIPE(x) ((x) << 16)
# define PACKET3_MAP_QUEUES_ME(x) ((x) << 18)
# define PACKET3_MAP_QUEUES_QUEUE_TYPE(x) ((x) << 21)
-# define PACKET3_MAP_QUEUES_ALLOC_FORMAT(x) ((x) << 24)
+# define PACKET3_MAP_QUEUES_QUEUE_GROUP(x) ((x) << 24)
# define PACKET3_MAP_QUEUES_ENGINE_SEL(x) ((x) << 26)
# define PACKET3_MAP_QUEUES_NUM_QUEUES(x) ((x) << 29)
/* CONTROL2 */
-# define PACKET3_MAP_QUEUES_CHECK_DISABLE(x) ((x) << 1)
# define PACKET3_MAP_QUEUES_DOORBELL_OFFSET(x) ((x) << 2)
#define PACKET3_UNMAP_QUEUES 0xA3
/* 1. header
@@ -464,12 +449,6 @@
# define PACKET3_QUERY_STATUS_PASID(x) ((x) << 0)
/* CONTROL2b */
# define PACKET3_QUERY_STATUS_DOORBELL_OFFSET(x) ((x) << 2)
-# define PACKET3_QUERY_STATUS_ENG_SEL(x) ((x) << 25)
-#define PACKET3_RUN_LIST 0xA5
-#define PACKET3_MAP_PROCESS_VM 0xA6
-/* GFX11 */
-#define PACKET3_SET_Q_PREEMPTION_MODE 0xF0
-# define PACKET3_SET_Q_PREEMPTION_MODE_IB_VMID(x) ((x) << 0)
-# define PACKET3_SET_Q_PREEMPTION_MODE_INIT_SHADOW_MEM (1 << 0)
+# define PACKET3_QUERY_STATUS_ENG_SEL(x) ((x) << 28)
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v12_1.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v12_1.c
index 4aa004ee2c4d..3544eb42dca6 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v12_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v12_1.c
@@ -146,71 +146,15 @@ static void gfxhub_v12_1_xcc_init_system_aperture_regs(struct amdgpu_device *ade
uint32_t tmp;
int i;
- for_each_inst(i, xcc_mask) {
- /* Program the AGP BAR */
- WREG32_SOC15_RLC(GC, GET_INST(GC, i),
- regGCMC_VM_AGP_BASE_LO32, 0);
- WREG32_SOC15_RLC(GC, GET_INST(GC, i),
- regGCMC_VM_AGP_BASE_HI32, 0);
- WREG32_SOC15_RLC(GC, GET_INST(GC, i),
- regGCMC_VM_AGP_BOT_LO32,
- lower_32_bits(adev->gmc.agp_start >> 24));
- WREG32_SOC15_RLC(GC, GET_INST(GC, i),
- regGCMC_VM_AGP_BOT_HI32,
- upper_32_bits(adev->gmc.agp_start >> 24));
- WREG32_SOC15_RLC(GC, GET_INST(GC, i),
- regGCMC_VM_AGP_TOP_LO32,
- lower_32_bits(adev->gmc.agp_end >> 24));
- WREG32_SOC15_RLC(GC, GET_INST(GC, i),
- regGCMC_VM_AGP_TOP_HI32,
- upper_32_bits(adev->gmc.agp_end >> 24));
+ /*TODO: revisit whether the SRIOV guest access to theseregisters
+ * is blocked by security policy or not */
+ if (amdgpu_sriov_vf(adev))
+ return;
- if (!amdgpu_sriov_vf(adev)) {
- /* Program the system aperture low logical page number. */
- WREG32_SOC15(GC, GET_INST(GC, i),
- regGCMC_VM_SYSTEM_APERTURE_LOW_ADDR_LO32,
- lower_32_bits(min(adev->gmc.fb_start, adev->gmc.agp_start) >> 18));
- WREG32_SOC15(GC, GET_INST(GC, i),
- regGCMC_VM_SYSTEM_APERTURE_LOW_ADDR_HI32,
- upper_32_bits(min(adev->gmc.fb_start, adev->gmc.agp_start) >> 18));
- WREG32_SOC15(GC, GET_INST(GC, i),
- regGCMC_VM_SYSTEM_APERTURE_HIGH_ADDR_LO32,
- lower_32_bits(max(adev->gmc.fb_end, adev->gmc.agp_end) >> 18));
- WREG32_SOC15(GC, GET_INST(GC, i),
- regGCMC_VM_SYSTEM_APERTURE_HIGH_ADDR_HI32,
- upper_32_bits(max(adev->gmc.fb_end, adev->gmc.agp_end) >> 18));
-
- /* Set default page address. */
- value = amdgpu_gmc_vram_mc2pa(adev, adev->mem_scratch.gpu_addr);
- WREG32_SOC15(GC, GET_INST(GC, i),
- regGCMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB,
- (u32)(value >> 12));
- WREG32_SOC15(GC, GET_INST(GC, i),
- regGCMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB,
- (u32)(value >> 44));
-
- /* Program "protection fault". */
- WREG32_SOC15(GC, GET_INST(GC, i),
- regGCVM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32,
- (u32)(adev->dummy_page_addr >> 12));
- WREG32_SOC15(GC, GET_INST(GC, i),
- regGCVM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32,
- (u32)((u64)adev->dummy_page_addr >> 44));
-
- tmp = RREG32_SOC15(GC, GET_INST(GC, i),
- regGCVM_L2_PROTECTION_FAULT_CNTL2);
- tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL2,
- ACTIVE_PAGE_MIGRATION_PTE_READ_RETRY, 1);
- tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL2,
- ENABLE_RETRY_FAULT_INTERRUPT, 0x1);
- WREG32_SOC15(GC, GET_INST(GC, i),
- regGCVM_L2_PROTECTION_FAULT_CNTL2, tmp);
- }
-
- /* In the case squeezing vram into GART aperture, we don't use
- * FB aperture and AGP aperture. Disable them.
- */
+ for_each_inst(i, xcc_mask) {
if (adev->gmc.pdb0_bo) {
+ /* Disable agp and system aperture
+ * when vmid0 page table is enabled */
WREG32_SOC15(GC, GET_INST(GC, i),
regGCMC_VM_FB_LOCATION_TOP_LO32, 0);
WREG32_SOC15(GC, GET_INST(GC, i),
@@ -225,7 +169,8 @@ static void gfxhub_v12_1_xcc_init_system_aperture_regs(struct amdgpu_device *ade
WREG32_SOC15(GC, GET_INST(GC, i),
regGCMC_VM_AGP_TOP_HI32, 0);
WREG32_SOC15(GC, GET_INST(GC, i),
- regGCMC_VM_AGP_BOT_LO32, 0xFFFFFFFF);
+ regGCMC_VM_AGP_BOT_LO32,
+ 0xFFFFFFFF);
WREG32_SOC15(GC, GET_INST(GC, i),
regGCMC_VM_AGP_BOT_HI32, 1);
WREG32_SOC15(GC, GET_INST(GC, i),
@@ -238,7 +183,69 @@ static void gfxhub_v12_1_xcc_init_system_aperture_regs(struct amdgpu_device *ade
regGCMC_VM_SYSTEM_APERTURE_HIGH_ADDR_LO32, 0);
WREG32_SOC15(GC, GET_INST(GC, i),
regGCMC_VM_SYSTEM_APERTURE_HIGH_ADDR_HI32, 0);
+ } else {
+ /* Program the AGP BAR */
+ WREG32_SOC15_RLC(GC, GET_INST(GC, i),
+ regGCMC_VM_AGP_BASE_LO32, 0);
+ WREG32_SOC15_RLC(GC, GET_INST(GC, i),
+ regGCMC_VM_AGP_BASE_HI32, 0);
+ WREG32_SOC15_RLC(GC, GET_INST(GC, i),
+ regGCMC_VM_AGP_BOT_LO32,
+ lower_32_bits(adev->gmc.agp_start >> 24));
+ WREG32_SOC15_RLC(GC, GET_INST(GC, i),
+ regGCMC_VM_AGP_BOT_HI32,
+ upper_32_bits(adev->gmc.agp_start >> 24));
+ WREG32_SOC15_RLC(GC, GET_INST(GC, i),
+ regGCMC_VM_AGP_TOP_LO32,
+ lower_32_bits(adev->gmc.agp_end >> 24));
+ WREG32_SOC15_RLC(GC, GET_INST(GC, i),
+ regGCMC_VM_AGP_TOP_HI32,
+ upper_32_bits(adev->gmc.agp_end >> 24));
+
+ /* Program the system aperture low logical page number. */
+ WREG32_SOC15(GC, GET_INST(GC, i),
+ regGCMC_VM_SYSTEM_APERTURE_LOW_ADDR_LO32,
+ lower_32_bits(min(adev->gmc.fb_start,
+ adev->gmc.agp_start) >> 18));
+ WREG32_SOC15(GC, GET_INST(GC, i),
+ regGCMC_VM_SYSTEM_APERTURE_LOW_ADDR_HI32,
+ upper_32_bits(min(adev->gmc.fb_start,
+ adev->gmc.agp_start) >> 18));
+ WREG32_SOC15(GC, GET_INST(GC, i),
+ regGCMC_VM_SYSTEM_APERTURE_HIGH_ADDR_LO32,
+ lower_32_bits(max(adev->gmc.fb_end,
+ adev->gmc.agp_end) >> 18));
+ WREG32_SOC15(GC, GET_INST(GC, i),
+ regGCMC_VM_SYSTEM_APERTURE_HIGH_ADDR_HI32,
+ upper_32_bits(max(adev->gmc.fb_end,
+ adev->gmc.agp_end) >> 18));
}
+
+ /* Set default page address. */
+ value = amdgpu_gmc_vram_mc2pa(adev, adev->mem_scratch.gpu_addr);
+ WREG32_SOC15(GC, GET_INST(GC, i),
+ regGCMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB,
+ (u32)(value >> 12));
+ WREG32_SOC15(GC, GET_INST(GC, i),
+ regGCMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB,
+ (u32)(value >> 44));
+
+ /* Program "protection fault". */
+ WREG32_SOC15(GC, GET_INST(GC, i),
+ regGCVM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32,
+ (u32)(adev->dummy_page_addr >> 12));
+ WREG32_SOC15(GC, GET_INST(GC, i),
+ regGCVM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32,
+ (u32)((u64)adev->dummy_page_addr >> 44));
+
+ tmp = RREG32_SOC15(GC, GET_INST(GC, i),
+ regGCVM_L2_PROTECTION_FAULT_CNTL2);
+ tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL2,
+ ACTIVE_PAGE_MIGRATION_PTE_READ_RETRY, 1);
+ tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL2,
+ ENABLE_RETRY_FAULT_INTERRUPT, 0x1);
+ WREG32_SOC15(GC, GET_INST(GC, i),
+ regGCVM_L2_PROTECTION_FAULT_CNTL2, tmp);
}
}
@@ -325,10 +332,18 @@ static void gfxhub_v12_1_xcc_init_cache_regs(struct amdgpu_device *adev,
WREG32_SOC15_RLC(GC, GET_INST(GC, i), regGCVM_L2_CNTL3, tmp);
tmp = regGCVM_L2_CNTL4_DEFAULT;
- tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL4,
- VMC_TAP_PDE_REQUEST_PHYSICAL, 1);
- tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL4,
- VMC_TAP_PTE_REQUEST_PHYSICAL, 1);
+ if (adev->gmc.xgmi.connected_to_cpu) {
+ tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL4,
+ VMC_TAP_PDE_REQUEST_PHYSICAL, 1);
+ tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL4,
+ VMC_TAP_PTE_REQUEST_PHYSICAL, 1);
+ } else {
+ tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL4,
+ VMC_TAP_PDE_REQUEST_PHYSICAL, 0);
+ tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL4,
+ VMC_TAP_PTE_REQUEST_PHYSICAL, 0);
+ }
+
WREG32_SOC15_RLC(GC, GET_INST(GC, i), regGCVM_L2_CNTL4, tmp);
tmp = regGCVM_L2_CNTL5_DEFAULT;
@@ -807,47 +822,6 @@ static void gfxhub_v12_1_init(struct amdgpu_device *adev)
gfxhub_v12_1_xcc_init(adev, xcc_mask);
}
-static int gfxhub_v12_1_get_xgmi_info(struct amdgpu_device *adev)
-{
- u32 max_num_physical_nodes;
- u32 max_physical_node_id;
- u32 xgmi_lfb_cntl;
- u32 max_region;
- u64 seg_size;
-
- xgmi_lfb_cntl = RREG32_SOC15(GC, GET_INST(GC, 0),
- regGCMC_VM_XGMI_LFB_CNTL);
- seg_size = REG_GET_FIELD(RREG32_SOC15(GC, GET_INST(GC, 0),
- regGCMC_VM_XGMI_LFB_SIZE),
- GCMC_VM_XGMI_LFB_SIZE, PF_LFB_SIZE) << 24;
- max_region = REG_GET_FIELD(xgmi_lfb_cntl,
- GCMC_VM_XGMI_LFB_CNTL,
- PF_MAX_REGION);
-
- max_num_physical_nodes = 8;
- max_physical_node_id = 7;
-
- /* PF_MAX_REGION=0 means xgmi is disabled */
- if (max_region || adev->gmc.xgmi.connected_to_cpu) {
- adev->gmc.xgmi.num_physical_nodes = max_region + 1;
-
- if (adev->gmc.xgmi.num_physical_nodes > max_num_physical_nodes)
- return -EINVAL;
-
- adev->gmc.xgmi.physical_node_id =
- REG_GET_FIELD(xgmi_lfb_cntl,
- GCMC_VM_XGMI_LFB_CNTL,
- PF_LFB_REGION);
-
- if (adev->gmc.xgmi.physical_node_id > max_physical_node_id)
- return -EINVAL;
-
- adev->gmc.xgmi.node_segment_size = seg_size;
- }
-
- return 0;
-}
-
const struct amdgpu_gfxhub_funcs gfxhub_v12_1_funcs = {
.get_fb_location = gfxhub_v12_1_get_fb_location,
.get_mc_fb_offset = gfxhub_v12_1_get_mc_fb_offset,
@@ -856,7 +830,6 @@ const struct amdgpu_gfxhub_funcs gfxhub_v12_1_funcs = {
.gart_disable = gfxhub_v12_1_gart_disable,
.set_fault_enable_default = gfxhub_v12_1_set_fault_enable_default,
.init = gfxhub_v12_1_init,
- .get_xgmi_info = gfxhub_v12_1_get_xgmi_info,
};
static int gfxhub_v12_1_xcp_resume(void *handle, uint32_t inst_mask)
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
index 2568eeaae945..fd691b2a6e21 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
@@ -767,7 +767,7 @@ static int gmc_v10_0_sw_init(struct amdgpu_ip_block *ip_block)
adev->gmc.vram_type = AMDGPU_VRAM_TYPE_GDDR6;
adev->gmc.vram_width = 1 * 128; /* numchan * chansize */
} else {
- r = amdgpu_atomfirmware_get_vram_info(adev,
+ r = amdgpu_gmc_get_vram_info(adev,
&vram_width, &vram_type, &vram_vendor);
adev->gmc.vram_width = vram_width;
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
index 6349e239a367..e6db87b94eb1 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
@@ -751,7 +751,7 @@ static int gmc_v11_0_sw_init(struct amdgpu_ip_block *ip_block)
spin_lock_init(&adev->gmc.invalidate_lock);
- r = amdgpu_atomfirmware_get_vram_info(adev,
+ r = amdgpu_gmc_get_vram_info(adev,
&vram_width, &vram_type, &vram_vendor);
adev->gmc.vram_width = vram_width;
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c
index da4a0cf4aad0..6e184ea069ef 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c
@@ -636,6 +636,11 @@ static int gmc_v12_0_early_init(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;
+ if (adev->smuio.funcs &&
+ adev->smuio.funcs->is_host_gpu_xgmi_supported)
+ adev->gmc.xgmi.connected_to_cpu =
+ adev->smuio.funcs->is_host_gpu_xgmi_supported(adev);
+
switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(12, 1, 0):
gmc_v12_1_set_gmc_funcs(adev);
@@ -691,17 +696,23 @@ static void gmc_v12_0_vram_gtt_location(struct amdgpu_device *adev,
base = adev->mmhub.funcs->get_fb_location(adev);
- amdgpu_gmc_set_agp_default(adev, mc);
- amdgpu_gmc_vram_location(adev, &adev->gmc, base);
- amdgpu_gmc_gart_location(adev, mc, AMDGPU_GART_PLACEMENT_LOW);
- if (!amdgpu_sriov_vf(adev) && (amdgpu_agp == 1))
- amdgpu_gmc_agp_location(adev, mc);
-
+ if (amdgpu_gmc_is_pdb0_enabled(adev)) {
+ amdgpu_gmc_sysvm_location(adev, mc);
+ } else {
+ amdgpu_gmc_set_agp_default(adev, mc);
+ amdgpu_gmc_vram_location(adev, &adev->gmc, base);
+ amdgpu_gmc_gart_location(adev, mc, AMDGPU_GART_PLACEMENT_LOW);
+ if (!amdgpu_sriov_vf(adev) && (amdgpu_agp == 1))
+ amdgpu_gmc_agp_location(adev, mc);
+ }
/* base offset of vram pages */
if (amdgpu_sriov_vf(adev))
adev->vm_manager.vram_base_offset = 0;
else
adev->vm_manager.vram_base_offset = adev->mmhub.funcs->get_mc_fb_offset(adev);
+
+ adev->vm_manager.vram_base_offset +=
+ adev->gmc.xgmi.physical_node_id * adev->gmc.xgmi.node_segment_size;
}
/**
@@ -717,12 +728,17 @@ static int gmc_v12_0_mc_init(struct amdgpu_device *adev)
{
int r;
- /* size in MB on si */
- adev->gmc.mc_vram_size =
- adev->nbio.funcs->get_memsize(adev) * 1024ULL * 1024ULL;
+ if (adev->gmc.xgmi.connected_to_cpu)
+ adev->gmc.mc_vram_size =
+ adev->gmc.xgmi.node_segment_size * adev->gmc.xgmi.num_physical_nodes;
+ else
+ adev->gmc.mc_vram_size =
+ adev->nbio.funcs->get_memsize(adev) * 1024ULL * 1024ULL;
+
adev->gmc.real_vram_size = adev->gmc.mc_vram_size;
- if (!(adev->flags & AMD_IS_APU)) {
+ if (!(adev->flags & AMD_IS_APU) &&
+ !adev->gmc.xgmi.connected_to_cpu) {
r = amdgpu_device_resize_fb_bar(adev);
if (r)
return r;
@@ -732,8 +748,12 @@ static int gmc_v12_0_mc_init(struct amdgpu_device *adev)
adev->gmc.aper_size = pci_resource_len(adev->pdev, 0);
#ifdef CONFIG_X86_64
- if ((adev->flags & AMD_IS_APU) && !amdgpu_passthrough(adev)) {
- adev->gmc.aper_base = adev->mmhub.funcs->get_mc_fb_offset(adev);
+ if (((adev->flags & AMD_IS_APU) && !amdgpu_passthrough(adev)) ||
+ (adev->gmc.xgmi.connected_to_cpu)) {
+ adev->gmc.aper_base =
+ adev->mmhub.funcs->get_mc_fb_offset(adev) +
+ adev->gmc.xgmi.physical_node_id *
+ adev->gmc.xgmi.node_segment_size;
adev->gmc.aper_size = adev->gmc.real_vram_size;
}
#endif
@@ -762,6 +782,14 @@ static int gmc_v12_0_gart_init(struct amdgpu_device *adev)
return 0;
}
+ if (amdgpu_gmc_is_pdb0_enabled(adev)) {
+ adev->gmc.vmid0_page_table_depth = 1;
+ adev->gmc.vmid0_page_table_block_size = 12;
+ } else {
+ adev->gmc.vmid0_page_table_depth = 0;
+ adev->gmc.vmid0_page_table_block_size = 0;
+ }
+
/* Initialize common gart structure */
r = amdgpu_gart_init(adev);
if (r)
@@ -772,7 +800,14 @@ static int gmc_v12_0_gart_init(struct amdgpu_device *adev)
AMDGPU_PTE_EXECUTABLE |
AMDGPU_PTE_IS_PTE;
- return amdgpu_gart_table_vram_alloc(adev);
+ r = amdgpu_gart_table_vram_alloc(adev);
+ if (r)
+ return r;
+
+ if (amdgpu_gmc_is_pdb0_enabled(adev))
+ r = amdgpu_gmc_pdb0_alloc(adev);
+
+ return r;
}
static int gmc_v12_0_sw_init(struct amdgpu_ip_block *ip_block)
@@ -790,7 +825,7 @@ static int gmc_v12_0_sw_init(struct amdgpu_ip_block *ip_block)
if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(12, 1, 0)) {
gmc_v12_1_init_vram_info(adev);
} else {
- r = amdgpu_atomfirmware_get_vram_info(adev,
+ r = amdgpu_gmc_get_vram_info(adev,
&vram_width, &vram_type, &vram_vendor);
adev->gmc.vram_width = vram_width;
adev->gmc.vram_type = vram_type;
@@ -858,11 +893,15 @@ static int gmc_v12_0_sw_init(struct amdgpu_ip_block *ip_block)
if (r)
return r;
- if ((amdgpu_ip_version(adev, GC_HWIP, 0) != IP_VERSION(12, 1, 0)) &&
- !amdgpu_sriov_vf(adev)) {
+ if (!amdgpu_sriov_vf(adev)) {
/* interrupt sent to DF. */
- r = amdgpu_irq_add_id(adev, SOC21_IH_CLIENTID_DF, 0,
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(12, 0, 0))
+ r = amdgpu_irq_add_id(adev, SOC21_IH_CLIENTID_DF, 0,
+ &adev->gmc.ecc_irq);
+ else
+ r = amdgpu_irq_add_id(adev, SOC_V1_0_IH_CLIENTID_DF, 0,
&adev->gmc.ecc_irq);
+
if (r)
return r;
}
@@ -944,6 +983,7 @@ static int gmc_v12_0_sw_fini(struct amdgpu_ip_block *ip_block)
amdgpu_vm_manager_fini(adev);
gmc_v12_0_gart_fini(adev);
amdgpu_gem_force_release(adev);
+ amdgpu_bo_free_kernel(&adev->gmc.pdb0_bo, NULL, &adev->gmc.ptr_pdb0);
amdgpu_bo_fini(adev);
return 0;
@@ -963,6 +1003,9 @@ static int gmc_v12_0_gart_enable(struct amdgpu_device *adev)
int r;
bool value;
+ if (adev->gmc.xgmi.connected_to_cpu)
+ amdgpu_gmc_init_pdb0(adev);
+
if (adev->gart.bo == NULL) {
dev_err(adev->dev, "No VRAM object for PCIE GART.\n");
return -EINVAL;
@@ -984,6 +1027,7 @@ static int gmc_v12_0_gart_enable(struct amdgpu_device *adev)
drm_info(adev_to_drm(adev), "PCIE GART of %uM enabled (table at 0x%016llX).\n",
(unsigned)(adev->gmc.gart_size >> 20),
+ (adev->gmc.pdb0_bo) ? (unsigned long long)amdgpu_bo_gpu_offset(adev->gmc.pdb0_bo) :
(unsigned long long)amdgpu_bo_gpu_offset(adev->gart.bo));
return 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v12_1.c b/drivers/gpu/drm/amd/amdgpu/gmc_v12_1.c
index c49112d8300e..7ea7b9c30bca 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v12_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v12_1.c
@@ -524,20 +524,27 @@ static void gmc_v12_1_get_coherence_flags(struct amdgpu_device *adev,
bool ext_coherent = bo->flags & AMDGPU_GEM_CREATE_EXT_COHERENT;
uint32_t gc_ip_version = amdgpu_ip_version(adev, GC_HWIP, 0);
bool uncached = bo->flags & AMDGPU_GEM_CREATE_UNCACHED;
- unsigned int mtype, mtype_local;
+ unsigned int mtype, mtype_local, mtype_remote;
bool snoop = false;
bool is_local = false;
+ bool is_aid_a1;
switch (gc_ip_version) {
case IP_VERSION(12, 1, 0):
- mtype_local = MTYPE_RW;
- if (amdgpu_mtype_local == 1) {
+ is_aid_a1 = (adev->rev_id & 0x10);
+
+ mtype_local = is_aid_a1 ? MTYPE_RW : MTYPE_NC;
+ mtype_remote = is_aid_a1 ? MTYPE_NC : MTYPE_UC;
+ if (amdgpu_mtype_local == 0) {
+ DRM_INFO_ONCE("Using MTYPE_RW for local memory\n");
+ mtype_local = MTYPE_RW;
+ } else if (amdgpu_mtype_local == 1) {
DRM_INFO_ONCE("Using MTYPE_NC for local memory\n");
mtype_local = MTYPE_NC;
} else if (amdgpu_mtype_local == 2) {
- DRM_INFO_ONCE("MTYPE_CC not supported, using MTYPE_RW instead for local memory\n");
+ DRM_INFO_ONCE("MTYPE_CC not supported, using %s for local memory\n", is_aid_a1 ? "MTYPE_RW" : "MTYPE_NC");
} else {
- DRM_INFO_ONCE("Using MTYPE_RW for local memory\n");
+ DRM_INFO_ONCE("Using %s for local memory\n", is_aid_a1 ? "MTYPE_RW" : "MTYPE_NC");
}
is_local = (is_vram && adev == bo_adev);
@@ -547,10 +554,7 @@ static void gmc_v12_1_get_coherence_flags(struct amdgpu_device *adev,
} else if (ext_coherent) {
mtype = is_local ? mtype_local : MTYPE_UC;
} else {
- if (is_local)
- mtype = mtype_local;
- else
- mtype = MTYPE_NC;
+ mtype = is_local ? mtype_local : mtype_remote;
}
break;
default:
@@ -621,10 +625,17 @@ static const struct amdgpu_irq_src_funcs gmc_v12_1_irq_funcs = {
.process = gmc_v12_1_process_interrupt,
};
+static const struct amdgpu_irq_src_funcs gmc_v12_1_ecc_funcs = {
+ .process = amdgpu_umc_uniras_process_ecc_irq,
+};
+
void gmc_v12_1_set_irq_funcs(struct amdgpu_device *adev)
{
adev->gmc.vm_fault.num_types = 1;
adev->gmc.vm_fault.funcs = &gmc_v12_1_irq_funcs;
+
+ adev->gmc.ecc_irq.num_types = 1;
+ adev->gmc.ecc_irq.funcs = &gmc_v12_1_ecc_funcs;
}
void gmc_v12_1_init_vram_info(struct amdgpu_device *adev)
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
index e35ed0cc2ec6..d865059e884a 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
@@ -660,35 +660,7 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev,
gfxhub_client_ids[cid],
cid);
} else {
- switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
- case IP_VERSION(9, 0, 0):
- mmhub_cid = mmhub_client_ids_vega10[cid][rw];
- break;
- case IP_VERSION(9, 3, 0):
- mmhub_cid = mmhub_client_ids_vega12[cid][rw];
- break;
- case IP_VERSION(9, 4, 0):
- mmhub_cid = mmhub_client_ids_vega20[cid][rw];
- break;
- case IP_VERSION(9, 4, 1):
- mmhub_cid = mmhub_client_ids_arcturus[cid][rw];
- break;
- case IP_VERSION(9, 1, 0):
- case IP_VERSION(9, 2, 0):
- mmhub_cid = mmhub_client_ids_raven[cid][rw];
- break;
- case IP_VERSION(1, 5, 0):
- case IP_VERSION(2, 4, 0):
- mmhub_cid = mmhub_client_ids_renoir[cid][rw];
- break;
- case IP_VERSION(1, 8, 0):
- case IP_VERSION(9, 4, 2):
- mmhub_cid = mmhub_client_ids_aldebaran[cid][rw];
- break;
- default:
- mmhub_cid = NULL;
- break;
- }
+ mmhub_cid = amdgpu_mmhub_client_name(&adev->mmhub, cid, rw);
dev_err(adev->dev, "\t Faulty UTCL2 client ID: %s (0x%x)\n",
mmhub_cid ? mmhub_cid : "unknown", cid);
}
@@ -1428,6 +1400,52 @@ static void gmc_v9_0_set_umc_funcs(struct amdgpu_device *adev)
}
}
+static void gmc_v9_0_init_mmhub_client_info(struct amdgpu_device *adev)
+{
+ switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
+ case IP_VERSION(9, 0, 0):
+ amdgpu_mmhub_init_client_info(&adev->mmhub,
+ mmhub_client_ids_vega10,
+ ARRAY_SIZE(mmhub_client_ids_vega10));
+ break;
+ case IP_VERSION(9, 3, 0):
+ amdgpu_mmhub_init_client_info(&adev->mmhub,
+ mmhub_client_ids_vega12,
+ ARRAY_SIZE(mmhub_client_ids_vega12));
+ break;
+ case IP_VERSION(9, 4, 0):
+ amdgpu_mmhub_init_client_info(&adev->mmhub,
+ mmhub_client_ids_vega20,
+ ARRAY_SIZE(mmhub_client_ids_vega20));
+ break;
+ case IP_VERSION(9, 4, 1):
+ amdgpu_mmhub_init_client_info(&adev->mmhub,
+ mmhub_client_ids_arcturus,
+ ARRAY_SIZE(mmhub_client_ids_arcturus));
+ break;
+ case IP_VERSION(9, 1, 0):
+ case IP_VERSION(9, 2, 0):
+ amdgpu_mmhub_init_client_info(&adev->mmhub,
+ mmhub_client_ids_raven,
+ ARRAY_SIZE(mmhub_client_ids_raven));
+ break;
+ case IP_VERSION(1, 5, 0):
+ case IP_VERSION(2, 4, 0):
+ amdgpu_mmhub_init_client_info(&adev->mmhub,
+ mmhub_client_ids_renoir,
+ ARRAY_SIZE(mmhub_client_ids_renoir));
+ break;
+ case IP_VERSION(1, 8, 0):
+ case IP_VERSION(9, 4, 2):
+ amdgpu_mmhub_init_client_info(&adev->mmhub,
+ mmhub_client_ids_aldebaran,
+ ARRAY_SIZE(mmhub_client_ids_aldebaran));
+ break;
+ default:
+ break;
+ }
+}
+
static void gmc_v9_0_set_mmhub_funcs(struct amdgpu_device *adev)
{
switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
@@ -1445,6 +1463,8 @@ static void gmc_v9_0_set_mmhub_funcs(struct amdgpu_device *adev)
adev->mmhub.funcs = &mmhub_v1_0_funcs;
break;
}
+
+ gmc_v9_0_init_mmhub_client_info(adev);
}
static void gmc_v9_0_set_mmhub_ras_funcs(struct amdgpu_device *adev)
@@ -1803,24 +1823,37 @@ static void gmc_v9_0_save_registers(struct amdgpu_device *adev)
adev->gmc.sdpif_register = RREG32_SOC15(DCE, 0, mmDCHUBBUB_SDPIF_MMIO_CNTRL_0);
}
-static void gmc_v9_4_3_init_vram_info(struct amdgpu_device *adev)
+static void gmc_v9_0_init_vram_info(struct amdgpu_device *adev)
{
static const u32 regBIF_BIOS_SCRATCH_4 = 0x50;
+ int dev_var = adev->pdev->device & 0xF;
u32 vram_info;
- adev->gmc.vram_type = AMDGPU_VRAM_TYPE_HBM;
- adev->gmc.vram_width = 128 * 64;
-
- if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 5, 0))
- adev->gmc.vram_type = AMDGPU_VRAM_TYPE_HBM3E;
-
- if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 4) &&
- adev->rev_id == 0x3)
- adev->gmc.vram_type = AMDGPU_VRAM_TYPE_HBM3E;
-
- if (!(adev->flags & AMD_IS_APU) && !amdgpu_sriov_vf(adev)) {
- vram_info = RREG32(regBIF_BIOS_SCRATCH_4);
- adev->gmc.vram_vendor = vram_info & 0xF;
+ if (adev->gmc.is_app_apu) {
+ adev->gmc.vram_type = AMDGPU_VRAM_TYPE_HBM;
+ adev->gmc.vram_width = 128 * 64;
+ } else if (adev->flags & AMD_IS_APU) {
+ adev->gmc.vram_type = AMDGPU_VRAM_TYPE_DDR4;
+ adev->gmc.vram_width = 64 * 64;
+ } else if (amdgpu_is_multi_aid(adev)) {
+ adev->gmc.vram_type = AMDGPU_VRAM_TYPE_HBM;
+ adev->gmc.vram_width = 128 * 64;
+
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 5, 0))
+ adev->gmc.vram_type = AMDGPU_VRAM_TYPE_HBM3E;
+
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 4) &&
+ adev->rev_id == 0x3)
+ adev->gmc.vram_type = AMDGPU_VRAM_TYPE_HBM3E;
+
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 3) &&
+ (dev_var == 0x5))
+ adev->gmc.vram_type = AMDGPU_VRAM_TYPE_HBM3E;
+
+ if (!(adev->flags & AMD_IS_APU) && !amdgpu_sriov_vf(adev)) {
+ vram_info = RREG32(regBIF_BIOS_SCRATCH_4);
+ adev->gmc.vram_vendor = vram_info & 0xF;
+ }
}
}
@@ -1836,19 +1869,11 @@ static int gmc_v9_0_sw_init(struct amdgpu_ip_block *ip_block)
spin_lock_init(&adev->gmc.invalidate_lock);
- if (amdgpu_is_multi_aid(adev)) {
- gmc_v9_4_3_init_vram_info(adev);
- } else if (!adev->bios) {
- if (adev->flags & AMD_IS_APU) {
- adev->gmc.vram_type = AMDGPU_VRAM_TYPE_DDR4;
- adev->gmc.vram_width = 64 * 64;
- } else {
- adev->gmc.vram_type = AMDGPU_VRAM_TYPE_HBM;
- adev->gmc.vram_width = 128 * 64;
- }
+ if (!adev->bios) {
+ gmc_v9_0_init_vram_info(adev);
} else {
- r = amdgpu_atomfirmware_get_vram_info(adev,
- &vram_width, &vram_type, &vram_vendor);
+ r = amdgpu_gmc_get_vram_info(adev,
+ &vram_width, &vram_type, &vram_vendor);
if (amdgpu_sriov_vf(adev))
/* For Vega10 SR-IOV, vram_width can't be read from ATOM as RAVEN,
* and DF related registers is not readable, seems hardcord is the
@@ -1876,6 +1901,7 @@ static int gmc_v9_0_sw_init(struct amdgpu_ip_block *ip_block)
adev->gmc.vram_type = vram_type;
adev->gmc.vram_vendor = vram_vendor;
}
+
switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(9, 1, 0):
case IP_VERSION(9, 2, 2):
diff --git a/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.c b/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.c
index b3590b33cab9..485ecdec9618 100644
--- a/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.c
@@ -129,7 +129,7 @@ static int isp_genpd_add_device(struct device *dev, void *data)
if (!pdev)
return -EINVAL;
- if (!dev->type->name) {
+ if (!dev->type || !dev->type->name) {
drm_dbg(&adev->ddev, "Invalid device type to add\n");
goto exit;
}
@@ -165,7 +165,7 @@ static int isp_genpd_remove_device(struct device *dev, void *data)
if (!pdev)
return -EINVAL;
- if (!dev->type->name) {
+ if (!dev->type || !dev->type->name) {
drm_dbg(&adev->ddev, "Invalid device type to remove\n");
goto exit;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_2.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_2.c
new file mode 100644
index 000000000000..285c459379c4
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_2.c
@@ -0,0 +1,840 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+/*
+ * Copyright 2025-2026 Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "amdgpu.h"
+#include "amdgpu_jpeg.h"
+#include "amdgpu_pm.h"
+#include "soc15.h"
+#include "soc15d.h"
+#include "jpeg_v4_0_3.h"
+#include "jpeg_v5_0_2.h"
+#include "mmsch_v5_0.h"
+
+#include "vcn/vcn_5_0_0_offset.h"
+#include "vcn/vcn_5_0_0_sh_mask.h"
+#include "ivsrcid/vcn/irqsrcs_vcn_5_0.h"
+
+static void jpeg_v5_0_2_set_dec_ring_funcs(struct amdgpu_device *adev);
+static void jpeg_v5_0_2_set_irq_funcs(struct amdgpu_device *adev);
+static int jpeg_v5_0_2_set_powergating_state(struct amdgpu_ip_block *ip_block,
+ enum amd_powergating_state state);
+static void jpeg_v5_0_2_dec_ring_set_wptr(struct amdgpu_ring *ring);
+
+static int amdgpu_ih_srcid_jpeg[] = {
+ VCN_5_0__SRCID__JPEG_DECODE,
+ VCN_5_0__SRCID__JPEG1_DECODE,
+ VCN_5_0__SRCID__JPEG2_DECODE,
+ VCN_5_0__SRCID__JPEG3_DECODE,
+ VCN_5_0__SRCID__JPEG4_DECODE,
+ VCN_5_0__SRCID__JPEG5_DECODE,
+ VCN_5_0__SRCID__JPEG6_DECODE,
+ VCN_5_0__SRCID__JPEG7_DECODE,
+ VCN_5_0__SRCID__JPEG8_DECODE,
+ VCN_5_0__SRCID__JPEG9_DECODE,
+};
+
+static const struct amdgpu_hwip_reg_entry jpeg_reg_list_5_0_2[] = {
+ SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JPEG_POWER_STATUS),
+ SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JPEG_INT_STAT),
+ SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC0_UVD_JRBC_RB_RPTR),
+ SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC0_UVD_JRBC_RB_WPTR),
+ SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC0_UVD_JRBC_STATUS),
+ SOC15_REG_ENTRY_STR(JPEG, 0, regJPEG_DEC_ADDR_MODE),
+ SOC15_REG_ENTRY_STR(JPEG, 0, regJPEG_DEC_GFX10_ADDR_CONFIG),
+ SOC15_REG_ENTRY_STR(JPEG, 0, regJPEG_DEC_Y_GFX10_TILING_SURFACE),
+ SOC15_REG_ENTRY_STR(JPEG, 0, regJPEG_DEC_UV_GFX10_TILING_SURFACE),
+ SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JPEG_PITCH),
+ SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JPEG_UV_PITCH),
+ SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC1_UVD_JRBC_RB_RPTR),
+ SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC1_UVD_JRBC_RB_WPTR),
+ SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC1_UVD_JRBC_STATUS),
+ SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC2_UVD_JRBC_RB_RPTR),
+ SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC2_UVD_JRBC_RB_WPTR),
+ SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC2_UVD_JRBC_STATUS),
+ SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC3_UVD_JRBC_RB_RPTR),
+ SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC3_UVD_JRBC_RB_WPTR),
+ SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC3_UVD_JRBC_STATUS),
+ SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC4_UVD_JRBC_RB_RPTR),
+ SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC4_UVD_JRBC_RB_WPTR),
+ SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC4_UVD_JRBC_STATUS),
+ SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC5_UVD_JRBC_RB_RPTR),
+ SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC5_UVD_JRBC_RB_WPTR),
+ SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC5_UVD_JRBC_STATUS),
+ SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC6_UVD_JRBC_RB_RPTR),
+ SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC6_UVD_JRBC_RB_WPTR),
+ SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC6_UVD_JRBC_STATUS),
+ SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC7_UVD_JRBC_RB_RPTR),
+ SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC7_UVD_JRBC_RB_WPTR),
+ SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC7_UVD_JRBC_STATUS),
+ SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC8_UVD_JRBC_RB_RPTR),
+ SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC8_UVD_JRBC_RB_WPTR),
+ SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC8_UVD_JRBC_STATUS),
+ SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC9_UVD_JRBC_RB_RPTR),
+ SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC9_UVD_JRBC_RB_WPTR),
+ SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC9_UVD_JRBC_STATUS),
+};
+
+static int jpeg_v5_0_2_core_reg_offset(u32 pipe)
+{
+ if (pipe <= AMDGPU_MAX_JPEG_RINGS_4_0_3)
+ return ((0x40 * pipe) - 0xc80);
+ else
+ return ((0x40 * pipe) - 0x440);
+}
+
+/**
+ * jpeg_v5_0_2_early_init - set function pointers
+ *
+ * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
+ *
+ * Set ring and irq function pointers
+ */
+static int jpeg_v5_0_2_early_init(struct amdgpu_ip_block *ip_block)
+{
+ struct amdgpu_device *adev = ip_block->adev;
+
+ if (!adev->jpeg.num_jpeg_inst || adev->jpeg.num_jpeg_inst > AMDGPU_MAX_JPEG_INSTANCES)
+ return -ENOENT;
+
+ adev->jpeg.num_jpeg_rings = AMDGPU_MAX_JPEG_RINGS;
+ jpeg_v5_0_2_set_dec_ring_funcs(adev);
+ jpeg_v5_0_2_set_irq_funcs(adev);
+
+ return 0;
+}
+
+/**
+ * jpeg_v5_0_2_sw_init - sw init for JPEG block
+ *
+ * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
+ *
+ * Load firmware and sw initialization
+ */
+static int jpeg_v5_0_2_sw_init(struct amdgpu_ip_block *ip_block)
+{
+ struct amdgpu_device *adev = ip_block->adev;
+ struct amdgpu_ring *ring;
+ int i, j, r, jpeg_inst;
+
+ for (j = 0; j < adev->jpeg.num_jpeg_rings; ++j) {
+ /* JPEG TRAP */
+ r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN,
+ amdgpu_ih_srcid_jpeg[j], &adev->jpeg.inst->irq);
+ if (r)
+ return r;
+ }
+
+ r = amdgpu_jpeg_sw_init(adev);
+ if (r)
+ return r;
+
+ r = amdgpu_jpeg_resume(adev);
+ if (r)
+ return r;
+
+ for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
+ jpeg_inst = GET_INST(JPEG, i);
+
+ for (j = 0; j < adev->jpeg.num_jpeg_rings; ++j) {
+ ring = &adev->jpeg.inst[i].ring_dec[j];
+ ring->use_doorbell = false;
+ ring->vm_hub = AMDGPU_MMHUB0(adev->jpeg.inst[i].aid_id);
+ ring->doorbell_index =
+ (adev->doorbell_index.vcn.vcn_ring0_1 << 1) +
+ 1 + j + 11 * jpeg_inst;
+ sprintf(ring->name, "jpeg_dec_%d.%d", adev->jpeg.inst[i].aid_id, j);
+ r = amdgpu_ring_init(adev, ring, 512, &adev->jpeg.inst->irq, 0,
+ AMDGPU_RING_PRIO_DEFAULT, NULL);
+ if (r)
+ return r;
+
+ adev->jpeg.internal.jpeg_pitch[j] =
+ regUVD_JRBC0_UVD_JRBC_SCRATCH0_INTERNAL_OFFSET;
+ adev->jpeg.inst[i].external.jpeg_pitch[j] =
+ SOC15_REG_OFFSET1(JPEG, jpeg_inst, regUVD_JRBC_SCRATCH0,
+ (j ? jpeg_v5_0_2_core_reg_offset(j) : 0));
+ }
+ }
+
+ r = amdgpu_jpeg_reg_dump_init(adev, jpeg_reg_list_5_0_2, ARRAY_SIZE(jpeg_reg_list_5_0_2));
+ if (r)
+ return r;
+
+ adev->jpeg.supported_reset =
+ amdgpu_get_soft_full_reset_mask(&adev->jpeg.inst[0].ring_dec[0]);
+ adev->jpeg.supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
+ r = amdgpu_jpeg_sysfs_reset_mask_init(adev);
+
+ return r;
+}
+
+/**
+ * jpeg_v5_0_2_sw_fini - sw fini for JPEG block
+ *
+ * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
+ *
+ * JPEG suspend and free up sw allocation
+ */
+static int jpeg_v5_0_2_sw_fini(struct amdgpu_ip_block *ip_block)
+{
+ struct amdgpu_device *adev = ip_block->adev;
+ int r;
+
+ r = amdgpu_jpeg_suspend(adev);
+ if (r)
+ return r;
+
+ amdgpu_jpeg_sysfs_reset_mask_fini(adev);
+
+ r = amdgpu_jpeg_sw_fini(adev);
+
+ return r;
+}
+
+/**
+ * jpeg_v5_0_2_hw_init - start and test JPEG block
+ *
+ * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
+ *
+ */
+static int jpeg_v5_0_2_hw_init(struct amdgpu_ip_block *ip_block)
+{
+ struct amdgpu_device *adev = ip_block->adev;
+ struct amdgpu_ring *ring;
+ int i, j, r, jpeg_inst, tmp;
+
+ if (RREG32_SOC15(VCN, GET_INST(VCN, 0), regVCN_RRMT_CNTL) & 0x100)
+ adev->jpeg.caps |= AMDGPU_JPEG_CAPS(RRMT_ENABLED);
+
+ for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
+ jpeg_inst = GET_INST(JPEG, i);
+ ring = adev->jpeg.inst[i].ring_dec;
+
+ /* Remove JPEG Tile antihang mechanism */
+ tmp = RREG32_SOC15(JPEG, jpeg_inst, regUVD_JPEG_POWER_STATUS);
+ tmp &= (~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK);
+ WREG32_SOC15(JPEG, jpeg_inst, regUVD_JPEG_POWER_STATUS, tmp);
+
+ if (ring->use_doorbell)
+ adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell,
+ (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 11 * jpeg_inst,
+ adev->jpeg.inst[i].aid_id);
+
+ for (j = 0; j < adev->jpeg.num_jpeg_rings; ++j) {
+ ring = &adev->jpeg.inst[i].ring_dec[j];
+ if (ring->use_doorbell)
+ WREG32_SOC15_OFFSET(VCN, GET_INST(VCN, i), regVCN_JPEG_DB_CTRL,
+ ring->pipe,
+ ring->doorbell_index <<
+ VCN_JPEG_DB_CTRL__OFFSET__SHIFT |
+ VCN_JPEG_DB_CTRL__EN_MASK);
+ r = amdgpu_ring_test_helper(ring);
+ if (r)
+ return r;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * jpeg_v5_0_2_hw_fini - stop the hardware block
+ *
+ * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
+ *
+ * Stop the JPEG block, mark ring as not ready any more
+ */
+static int jpeg_v5_0_2_hw_fini(struct amdgpu_ip_block *ip_block)
+{
+ struct amdgpu_device *adev = ip_block->adev;
+ int ret = 0;
+
+ cancel_delayed_work_sync(&adev->jpeg.idle_work);
+
+ if (adev->jpeg.cur_state != AMD_PG_STATE_GATE)
+ ret = jpeg_v5_0_2_set_powergating_state(ip_block, AMD_PG_STATE_GATE);
+
+ return ret;
+}
+
+/**
+ * jpeg_v5_0_2_suspend - suspend JPEG block
+ *
+ * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
+ *
+ * HW fini and suspend JPEG block
+ */
+static int jpeg_v5_0_2_suspend(struct amdgpu_ip_block *ip_block)
+{
+ struct amdgpu_device *adev = ip_block->adev;
+ int r;
+
+ r = jpeg_v5_0_2_hw_fini(ip_block);
+ if (r)
+ return r;
+
+ r = amdgpu_jpeg_suspend(adev);
+
+ return r;
+}
+
+/**
+ * jpeg_v5_0_2_resume - resume JPEG block
+ *
+ * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
+ *
+ * Resume firmware and hw init JPEG block
+ */
+static int jpeg_v5_0_2_resume(struct amdgpu_ip_block *ip_block)
+{
+ struct amdgpu_device *adev = ip_block->adev;
+ int r;
+
+ r = amdgpu_jpeg_resume(adev);
+ if (r)
+ return r;
+
+ r = jpeg_v5_0_2_hw_init(ip_block);
+
+ return r;
+}
+
+static void jpeg_v5_0_2_init_inst(struct amdgpu_device *adev, int i)
+{
+ int jpeg_inst = GET_INST(JPEG, i);
+
+ /* disable anti hang mechanism */
+ WREG32_P(SOC15_REG_OFFSET(JPEG, jpeg_inst, regUVD_JPEG_POWER_STATUS), 0,
+ ~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK);
+
+ /* keep the JPEG in static PG mode */
+ WREG32_P(SOC15_REG_OFFSET(JPEG, jpeg_inst, regUVD_JPEG_POWER_STATUS), 0,
+ ~UVD_JPEG_POWER_STATUS__JPEG_PG_MODE_MASK);
+
+ /* MJPEG global tiling registers */
+ WREG32_SOC15(JPEG, 0, regJPEG_DEC_GFX10_ADDR_CONFIG,
+ adev->gfx.config.gb_addr_config);
+
+ /* enable JMI channel */
+ WREG32_P(SOC15_REG_OFFSET(JPEG, jpeg_inst, regUVD_JMI_CNTL), 0,
+ ~UVD_JMI_CNTL__SOFT_RESET_MASK);
+}
+
+static void jpeg_v5_0_2_deinit_inst(struct amdgpu_device *adev, int i)
+{
+ int jpeg_inst = GET_INST(JPEG, i);
+ /* reset JMI */
+ WREG32_P(SOC15_REG_OFFSET(JPEG, jpeg_inst, regUVD_JMI_CNTL),
+ UVD_JMI_CNTL__SOFT_RESET_MASK,
+ ~UVD_JMI_CNTL__SOFT_RESET_MASK);
+
+ /* enable anti hang mechanism */
+ WREG32_P(SOC15_REG_OFFSET(JPEG, jpeg_inst, regUVD_JPEG_POWER_STATUS),
+ UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK,
+ ~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK);
+}
+
+static void jpeg_v5_0_2_init_jrbc(struct amdgpu_ring *ring)
+{
+ struct amdgpu_device *adev = ring->adev;
+ u32 reg, data, mask;
+ int jpeg_inst = GET_INST(JPEG, ring->me);
+ int reg_offset = ring->pipe ? jpeg_v5_0_2_core_reg_offset(ring->pipe) : 0;
+
+ /* enable System Interrupt for JRBC */
+ reg = SOC15_REG_OFFSET(JPEG, jpeg_inst, regJPEG_SYS_INT_EN);
+ if (ring->pipe < AMDGPU_MAX_JPEG_RINGS_4_0_3) {
+ data = JPEG_SYS_INT_EN__DJRBC0_MASK << ring->pipe;
+ mask = ~(JPEG_SYS_INT_EN__DJRBC0_MASK << ring->pipe);
+ WREG32_P(reg, data, mask);
+ } else {
+ data = JPEG_SYS_INT_EN__DJRBC0_MASK << (ring->pipe+12);
+ mask = ~(JPEG_SYS_INT_EN__DJRBC0_MASK << (ring->pipe+12));
+ WREG32_P(reg, data, mask);
+ }
+
+ WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
+ regUVD_LMI_JRBC_RB_VMID,
+ reg_offset, 0);
+ WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
+ regUVD_JRBC_RB_CNTL,
+ reg_offset,
+ (0x00000001L | 0x00000002L));
+ WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
+ regUVD_LMI_JRBC_RB_64BIT_BAR_LOW,
+ reg_offset, lower_32_bits(ring->gpu_addr));
+ WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
+ regUVD_LMI_JRBC_RB_64BIT_BAR_HIGH,
+ reg_offset, upper_32_bits(ring->gpu_addr));
+ WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
+ regUVD_JRBC_RB_RPTR,
+ reg_offset, 0);
+ WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
+ regUVD_JRBC_RB_WPTR,
+ reg_offset, 0);
+ WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
+ regUVD_JRBC_RB_CNTL,
+ reg_offset, 0x00000002L);
+ WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
+ regUVD_JRBC_RB_SIZE,
+ reg_offset, ring->ring_size / 4);
+ ring->wptr = RREG32_SOC15_OFFSET(JPEG, jpeg_inst, regUVD_JRBC_RB_WPTR,
+ reg_offset);
+}
+
+/**
+ * jpeg_v5_0_2_start - start JPEG block
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Setup and start the JPEG block
+ */
+static int jpeg_v5_0_2_start(struct amdgpu_device *adev)
+{
+ struct amdgpu_ring *ring;
+ int i, j;
+
+ for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
+ jpeg_v5_0_2_init_inst(adev, i);
+ for (j = 0; j < adev->jpeg.num_jpeg_rings; ++j) {
+ ring = &adev->jpeg.inst[i].ring_dec[j];
+ jpeg_v5_0_2_init_jrbc(ring);
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * jpeg_v5_0_2_stop - stop JPEG block
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * stop the JPEG block
+ */
+static int jpeg_v5_0_2_stop(struct amdgpu_device *adev)
+{
+ int i;
+
+ for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i)
+ jpeg_v5_0_2_deinit_inst(adev, i);
+
+ return 0;
+}
+
+/**
+ * jpeg_v5_0_2_dec_ring_get_rptr - get read pointer
+ *
+ * @ring: amdgpu_ring pointer
+ *
+ * Returns the current hardware read pointer
+ */
+static uint64_t jpeg_v5_0_2_dec_ring_get_rptr(struct amdgpu_ring *ring)
+{
+ struct amdgpu_device *adev = ring->adev;
+
+ return RREG32_SOC15_OFFSET(JPEG, GET_INST(JPEG, ring->me), regUVD_JRBC_RB_RPTR,
+ ring->pipe ? jpeg_v5_0_2_core_reg_offset(ring->pipe) : 0);
+}
+
+/**
+ * jpeg_v5_0_2_dec_ring_get_wptr - get write pointer
+ *
+ * @ring: amdgpu_ring pointer
+ *
+ * Returns the current hardware write pointer
+ */
+static uint64_t jpeg_v5_0_2_dec_ring_get_wptr(struct amdgpu_ring *ring)
+{
+ struct amdgpu_device *adev = ring->adev;
+
+ if (ring->use_doorbell)
+ return adev->wb.wb[ring->wptr_offs];
+
+ return RREG32_SOC15_OFFSET(JPEG, GET_INST(JPEG, ring->me), regUVD_JRBC_RB_WPTR,
+ ring->pipe ? jpeg_v5_0_2_core_reg_offset(ring->pipe) : 0);
+}
+
+/**
+ * jpeg_v5_0_2_dec_ring_set_wptr - set write pointer
+ *
+ * @ring: amdgpu_ring pointer
+ *
+ * Commits the write pointer to the hardware
+ */
+static void jpeg_v5_0_2_dec_ring_set_wptr(struct amdgpu_ring *ring)
+{
+ struct amdgpu_device *adev = ring->adev;
+
+ if (ring->use_doorbell) {
+ adev->wb.wb[ring->wptr_offs] = lower_32_bits(ring->wptr);
+ WDOORBELL32(ring->doorbell_index, lower_32_bits(ring->wptr));
+ } else {
+ WREG32_SOC15_OFFSET(JPEG, GET_INST(JPEG, ring->me),
+ regUVD_JRBC_RB_WPTR,
+ (ring->pipe ? jpeg_v5_0_2_core_reg_offset(ring->pipe) : 0),
+ lower_32_bits(ring->wptr));
+ }
+}
+
+static bool jpeg_v5_0_2_is_idle(struct amdgpu_ip_block *ip_block)
+{
+ struct amdgpu_device *adev = ip_block->adev;
+ bool ret = false;
+ int i, j;
+
+ for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
+ for (j = 0; j < adev->jpeg.num_jpeg_rings; ++j) {
+ int reg_offset = (j ? jpeg_v5_0_2_core_reg_offset(j) : 0);
+
+ ret &= ((RREG32_SOC15_OFFSET(JPEG, GET_INST(JPEG, i),
+ regUVD_JRBC_STATUS, reg_offset) &
+ UVD_JRBC_STATUS__RB_JOB_DONE_MASK) ==
+ UVD_JRBC_STATUS__RB_JOB_DONE_MASK);
+ }
+ }
+
+ return ret;
+}
+
+static int jpeg_v5_0_2_wait_for_idle(struct amdgpu_ip_block *ip_block)
+{
+ struct amdgpu_device *adev = ip_block->adev;
+ int ret = 0;
+ int i, j;
+
+ for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
+ for (j = 0; j < adev->jpeg.num_jpeg_rings; ++j) {
+ int reg_offset = (j ? jpeg_v5_0_2_core_reg_offset(j) : 0);
+
+ ret &= SOC15_WAIT_ON_RREG_OFFSET(JPEG, GET_INST(JPEG, i),
+ regUVD_JRBC_STATUS, reg_offset,
+ UVD_JRBC_STATUS__RB_JOB_DONE_MASK,
+ UVD_JRBC_STATUS__RB_JOB_DONE_MASK);
+ }
+ }
+ return ret;
+}
+
+static int jpeg_v5_0_2_set_clockgating_state(struct amdgpu_ip_block *ip_block,
+ enum amd_clockgating_state state)
+{
+ struct amdgpu_device *adev = ip_block->adev;
+ bool enable = state == AMD_CG_STATE_GATE;
+
+ int i;
+
+ if (!enable)
+ return 0;
+
+ for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
+ if (!jpeg_v5_0_2_is_idle(ip_block))
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+static int jpeg_v5_0_2_set_powergating_state(struct amdgpu_ip_block *ip_block,
+ enum amd_powergating_state state)
+{
+ struct amdgpu_device *adev = ip_block->adev;
+ int ret;
+
+ if (state == adev->jpeg.cur_state)
+ return 0;
+
+ if (state == AMD_PG_STATE_GATE)
+ ret = jpeg_v5_0_2_stop(adev);
+ else
+ ret = jpeg_v5_0_2_start(adev);
+
+ if (!ret)
+ adev->jpeg.cur_state = state;
+
+ return ret;
+}
+
+static int jpeg_v5_0_2_set_interrupt_state(struct amdgpu_device *adev,
+ struct amdgpu_irq_src *source,
+ unsigned int type,
+ enum amdgpu_interrupt_state state)
+{
+ return 0;
+}
+
+static int jpeg_v5_0_2_process_interrupt(struct amdgpu_device *adev,
+ struct amdgpu_irq_src *source,
+ struct amdgpu_iv_entry *entry)
+{
+ u32 i, inst;
+
+ i = node_id_to_phys_map[entry->node_id];
+ DRM_DEV_DEBUG(adev->dev, "IH: JPEG TRAP\n");
+
+ for (inst = 0; inst < adev->jpeg.num_jpeg_inst; ++inst)
+ if (adev->jpeg.inst[inst].aid_id == i)
+ break;
+
+ if (inst >= adev->jpeg.num_jpeg_inst) {
+ dev_WARN_ONCE(adev->dev, 1,
+ "Interrupt received for unknown JPEG instance %d",
+ entry->node_id);
+ return 0;
+ }
+
+ switch (entry->src_id) {
+ case VCN_5_0__SRCID__JPEG_DECODE:
+ amdgpu_fence_process(&adev->jpeg.inst[inst].ring_dec[0]);
+ break;
+ case VCN_5_0__SRCID__JPEG1_DECODE:
+ amdgpu_fence_process(&adev->jpeg.inst[inst].ring_dec[1]);
+ break;
+ case VCN_5_0__SRCID__JPEG2_DECODE:
+ amdgpu_fence_process(&adev->jpeg.inst[inst].ring_dec[2]);
+ break;
+ case VCN_5_0__SRCID__JPEG3_DECODE:
+ amdgpu_fence_process(&adev->jpeg.inst[inst].ring_dec[3]);
+ break;
+ case VCN_5_0__SRCID__JPEG4_DECODE:
+ amdgpu_fence_process(&adev->jpeg.inst[inst].ring_dec[4]);
+ break;
+ case VCN_5_0__SRCID__JPEG5_DECODE:
+ amdgpu_fence_process(&adev->jpeg.inst[inst].ring_dec[5]);
+ break;
+ case VCN_5_0__SRCID__JPEG6_DECODE:
+ amdgpu_fence_process(&adev->jpeg.inst[inst].ring_dec[6]);
+ break;
+ case VCN_5_0__SRCID__JPEG7_DECODE:
+ amdgpu_fence_process(&adev->jpeg.inst[inst].ring_dec[7]);
+ break;
+ case VCN_5_0__SRCID__JPEG8_DECODE:
+ amdgpu_fence_process(&adev->jpeg.inst[inst].ring_dec[8]);
+ break;
+ case VCN_5_0__SRCID__JPEG9_DECODE:
+ amdgpu_fence_process(&adev->jpeg.inst[inst].ring_dec[9]);
+ break;
+ default:
+ DRM_DEV_ERROR(adev->dev, "Unhandled interrupt: %d %d\n",
+ entry->src_id, entry->src_data[0]);
+ break;
+ }
+
+ return 0;
+}
+
+static void jpeg_v5_0_2_core_stall_reset(struct amdgpu_ring *ring)
+{
+ struct amdgpu_device *adev = ring->adev;
+ int jpeg_inst = GET_INST(JPEG, ring->me);
+ int reg_offset = ring->pipe ? jpeg_v5_0_2_core_reg_offset(ring->pipe) : 0;
+
+ WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
+ regUVD_JMI0_UVD_JMI_CLIENT_STALL,
+ reg_offset, 0x1F);
+ SOC15_WAIT_ON_RREG_OFFSET(JPEG, jpeg_inst,
+ regUVD_JMI0_UVD_JMI_CLIENT_CLEAN_STATUS,
+ reg_offset, 0x1F, 0x1F);
+ WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
+ regUVD_JMI0_JPEG_LMI_DROP,
+ reg_offset, 0x1F);
+ WREG32_SOC15(JPEG, jpeg_inst, regJPEG_CORE_RST_CTRL, 1 << ring->pipe);
+ WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
+ regUVD_JMI0_UVD_JMI_CLIENT_STALL,
+ reg_offset, 0x00);
+ WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
+ regUVD_JMI0_JPEG_LMI_DROP,
+ reg_offset, 0x00);
+ WREG32_SOC15(JPEG, jpeg_inst, regJPEG_CORE_RST_CTRL, 0x00);
+}
+
+static int jpeg_v5_0_2_ring_reset(struct amdgpu_ring *ring,
+ unsigned int vmid,
+ struct amdgpu_fence *timedout_fence)
+{
+ amdgpu_ring_reset_helper_begin(ring, timedout_fence);
+ jpeg_v5_0_2_core_stall_reset(ring);
+ jpeg_v5_0_2_init_jrbc(ring);
+ return amdgpu_ring_reset_helper_end(ring, timedout_fence);
+}
+
+static const struct amd_ip_funcs jpeg_v5_0_2_ip_funcs = {
+ .name = "jpeg_v5_0_2",
+ .early_init = jpeg_v5_0_2_early_init,
+ .late_init = NULL,
+ .sw_init = jpeg_v5_0_2_sw_init,
+ .sw_fini = jpeg_v5_0_2_sw_fini,
+ .hw_init = jpeg_v5_0_2_hw_init,
+ .hw_fini = jpeg_v5_0_2_hw_fini,
+ .suspend = jpeg_v5_0_2_suspend,
+ .resume = jpeg_v5_0_2_resume,
+ .is_idle = jpeg_v5_0_2_is_idle,
+ .wait_for_idle = jpeg_v5_0_2_wait_for_idle,
+ .check_soft_reset = NULL,
+ .pre_soft_reset = NULL,
+ .soft_reset = NULL,
+ .post_soft_reset = NULL,
+ .set_clockgating_state = jpeg_v5_0_2_set_clockgating_state,
+ .set_powergating_state = jpeg_v5_0_2_set_powergating_state,
+ .dump_ip_state = amdgpu_jpeg_dump_ip_state,
+ .print_ip_state = amdgpu_jpeg_print_ip_state,
+};
+
+static const struct amdgpu_ring_funcs jpeg_v5_0_2_dec_ring_vm_funcs = {
+ .type = AMDGPU_RING_TYPE_VCN_JPEG,
+ .align_mask = 0xf,
+ .get_rptr = jpeg_v5_0_2_dec_ring_get_rptr,
+ .get_wptr = jpeg_v5_0_2_dec_ring_get_wptr,
+ .set_wptr = jpeg_v5_0_2_dec_ring_set_wptr,
+ .emit_frame_size =
+ SOC15_FLUSH_GPU_TLB_NUM_WREG * 6 +
+ SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 8 +
+ 8 + /* jpeg_v5_0_2_dec_ring_emit_vm_flush */
+ 22 + 22 + /* jpeg_v5_0_2_dec_ring_emit_fence x2 vm fence */
+ 8 + 16,
+ .emit_ib_size = 22, /* jpeg_v5_0_2_dec_ring_emit_ib */
+ .emit_ib = jpeg_v4_0_3_dec_ring_emit_ib,
+ .emit_fence = jpeg_v4_0_3_dec_ring_emit_fence,
+ .emit_vm_flush = jpeg_v4_0_3_dec_ring_emit_vm_flush,
+ .emit_hdp_flush = jpeg_v4_0_3_ring_emit_hdp_flush,
+ .test_ring = amdgpu_jpeg_dec_ring_test_ring,
+ .test_ib = amdgpu_jpeg_dec_ring_test_ib,
+ .insert_nop = jpeg_v4_0_3_dec_ring_nop,
+ .insert_start = jpeg_v4_0_3_dec_ring_insert_start,
+ .insert_end = jpeg_v4_0_3_dec_ring_insert_end,
+ .pad_ib = amdgpu_ring_generic_pad_ib,
+ .begin_use = amdgpu_jpeg_ring_begin_use,
+ .end_use = amdgpu_jpeg_ring_end_use,
+ .emit_wreg = jpeg_v4_0_3_dec_ring_emit_wreg,
+ .emit_reg_wait = jpeg_v4_0_3_dec_ring_emit_reg_wait,
+ .emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
+ .reset = jpeg_v5_0_2_ring_reset,
+};
+
+static void jpeg_v5_0_2_set_dec_ring_funcs(struct amdgpu_device *adev)
+{
+ int i, j, jpeg_inst;
+
+ for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
+ for (j = 0; j < adev->jpeg.num_jpeg_rings; ++j) {
+ adev->jpeg.inst[i].ring_dec[j].funcs = &jpeg_v5_0_2_dec_ring_vm_funcs;
+ adev->jpeg.inst[i].ring_dec[j].me = i;
+ adev->jpeg.inst[i].ring_dec[j].pipe = j;
+ }
+ jpeg_inst = GET_INST(JPEG, i);
+ adev->jpeg.inst[i].aid_id =
+ jpeg_inst / adev->jpeg.num_inst_per_aid;
+ }
+}
+
+static const struct amdgpu_irq_src_funcs jpeg_v5_0_2_irq_funcs = {
+ .set = jpeg_v5_0_2_set_interrupt_state,
+ .process = jpeg_v5_0_2_process_interrupt,
+};
+
+static void jpeg_v5_0_2_set_irq_funcs(struct amdgpu_device *adev)
+{
+ int i;
+
+ for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i)
+ adev->jpeg.inst->irq.num_types += adev->jpeg.num_jpeg_rings;
+
+ adev->jpeg.inst->irq.funcs = &jpeg_v5_0_2_irq_funcs;
+}
+
+const struct amdgpu_ip_block_version jpeg_v5_0_2_ip_block = {
+ .type = AMD_IP_BLOCK_TYPE_JPEG,
+ .major = 5,
+ .minor = 0,
+ .rev = 2,
+ .funcs = &jpeg_v5_0_2_ip_funcs,
+};
+
+#if 0
+static int jpeg_v5_0_2_aca_bank_parser(struct aca_handle *handle, struct aca_bank *bank,
+ enum aca_smu_type type, void *data)
+{
+ struct aca_bank_info info;
+ u64 misc0;
+ int ret;
+
+ ret = aca_bank_info_decode(bank, &info);
+ if (ret)
+ return ret;
+
+ misc0 = bank->regs[ACA_REG_IDX_MISC0];
+ switch (type) {
+ case ACA_SMU_TYPE_UE:
+ bank->aca_err_type = ACA_ERROR_TYPE_UE;
+ ret = aca_error_cache_log_bank_error(handle, &info, ACA_ERROR_TYPE_UE,
+ 1ULL);
+ break;
+ case ACA_SMU_TYPE_CE:
+ bank->aca_err_type = ACA_ERROR_TYPE_CE;
+ ret = aca_error_cache_log_bank_error(handle, &info, bank->aca_err_type,
+ ACA_REG__MISC0__ERRCNT(misc0));
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+/* reference to smu driver if header file */
+static int jpeg_v5_0_2_err_codes[] = {
+ 16, 17, 18, 19, 20, 21, 22, 23, /* JPEG[0-9][S|D] */
+ 24, 25, 26, 27, 28, 29, 30, 31,
+ 48, 49, 50, 51,
+};
+
+static bool jpeg_v5_0_2_aca_bank_is_valid(struct aca_handle *handle, struct aca_bank *bank,
+ enum aca_smu_type type, void *data)
+{
+ u32 instlo;
+
+ instlo = ACA_REG__IPID__INSTANCEIDLO(bank->regs[ACA_REG_IDX_IPID]);
+ instlo &= GENMASK(31, 1);
+
+ if (instlo != mmSMNAID_AID0_MCA_SMU)
+ return false;
+
+ if (aca_bank_check_error_codes(handle->adev, bank,
+ jpeg_v5_0_2_err_codes,
+ ARRAY_SIZE(jpeg_v5_0_2_err_codes)))
+ return false;
+
+ return true;
+}
+
+static const struct aca_bank_ops jpeg_v5_0_2_aca_bank_ops = {
+ .aca_bank_parser = jpeg_v5_0_2_aca_bank_parser,
+ .aca_bank_is_valid = jpeg_v5_0_2_aca_bank_is_valid,
+};
+
+static const struct aca_info jpeg_v5_0_2_aca_info = {
+ .hwip = ACA_HWIP_TYPE_SMU,
+ .mask = ACA_ERROR_UE_MASK,
+ .bank_ops = &jpeg_v5_0_2_aca_bank_ops,
+};
+#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_2.h b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_2.h
new file mode 100644
index 000000000000..c201a2c42a0d
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_2.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2025-2026 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __JPEG_V5_0_2_H__
+#define __JPEG_V5_0_2_H__
+
+extern const struct amdgpu_ip_block_version jpeg_v5_0_2_ip_block;
+
+#define regUVD_JRBC0_UVD_JRBC_SCRATCH0_INTERNAL_OFFSET 0x4094
+#define regUVD_JRBC_EXTERNAL_MCM_ADDR_INTERNAL_OFFSET 0x1bffe
+
+#define regUVD_JRBC0_UVD_JRBC_RB_WPTR 0x0640
+#define regUVD_JRBC0_UVD_JRBC_RB_WPTR_BASE_IDX 1
+#define regUVD_JRBC0_UVD_JRBC_STATUS 0x0649
+#define regUVD_JRBC0_UVD_JRBC_STATUS_BASE_IDX 1
+#define regUVD_JRBC0_UVD_JRBC_RB_RPTR 0x064a
+#define regUVD_JRBC0_UVD_JRBC_RB_RPTR_BASE_IDX 1
+#define regUVD_JRBC1_UVD_JRBC_RB_WPTR 0x0000
+#define regUVD_JRBC1_UVD_JRBC_RB_WPTR_BASE_IDX 0
+#define regUVD_JRBC1_UVD_JRBC_STATUS 0x0009
+#define regUVD_JRBC1_UVD_JRBC_STATUS_BASE_IDX 0
+#define regUVD_JRBC1_UVD_JRBC_RB_RPTR 0x000a
+#define regUVD_JRBC1_UVD_JRBC_RB_RPTR_BASE_IDX 0
+#define regUVD_JRBC2_UVD_JRBC_RB_WPTR 0x0040
+#define regUVD_JRBC2_UVD_JRBC_RB_WPTR_BASE_IDX 0
+#define regUVD_JRBC2_UVD_JRBC_STATUS 0x0049
+#define regUVD_JRBC2_UVD_JRBC_STATUS_BASE_IDX 0
+#define regUVD_JRBC2_UVD_JRBC_RB_RPTR 0x004a
+#define regUVD_JRBC2_UVD_JRBC_RB_RPTR_BASE_IDX 0
+#define regUVD_JRBC3_UVD_JRBC_RB_WPTR 0x0080
+#define regUVD_JRBC3_UVD_JRBC_RB_WPTR_BASE_IDX 0
+#define regUVD_JRBC3_UVD_JRBC_STATUS 0x0089
+#define regUVD_JRBC3_UVD_JRBC_STATUS_BASE_IDX 0
+#define regUVD_JRBC3_UVD_JRBC_RB_RPTR 0x008a
+#define regUVD_JRBC3_UVD_JRBC_RB_RPTR_BASE_IDX 0
+#define regUVD_JRBC4_UVD_JRBC_RB_WPTR 0x00c0
+#define regUVD_JRBC4_UVD_JRBC_RB_WPTR_BASE_IDX 0
+#define regUVD_JRBC4_UVD_JRBC_STATUS 0x00c9
+#define regUVD_JRBC4_UVD_JRBC_STATUS_BASE_IDX 0
+#define regUVD_JRBC4_UVD_JRBC_RB_RPTR 0x00ca
+#define regUVD_JRBC4_UVD_JRBC_RB_RPTR_BASE_IDX 0
+#define regUVD_JRBC5_UVD_JRBC_RB_WPTR 0x0100
+#define regUVD_JRBC5_UVD_JRBC_RB_WPTR_BASE_IDX 0
+#define regUVD_JRBC5_UVD_JRBC_STATUS 0x0109
+#define regUVD_JRBC5_UVD_JRBC_STATUS_BASE_IDX 0
+#define regUVD_JRBC5_UVD_JRBC_RB_RPTR 0x010a
+#define regUVD_JRBC5_UVD_JRBC_RB_RPTR_BASE_IDX 0
+#define regUVD_JRBC6_UVD_JRBC_RB_WPTR 0x0140
+#define regUVD_JRBC6_UVD_JRBC_RB_WPTR_BASE_IDX 0
+#define regUVD_JRBC6_UVD_JRBC_STATUS 0x0149
+#define regUVD_JRBC6_UVD_JRBC_STATUS_BASE_IDX 0
+#define regUVD_JRBC6_UVD_JRBC_RB_RPTR 0x014a
+#define regUVD_JRBC6_UVD_JRBC_RB_RPTR_BASE_IDX 0
+#define regUVD_JRBC7_UVD_JRBC_RB_WPTR 0x0180
+#define regUVD_JRBC7_UVD_JRBC_RB_WPTR_BASE_IDX 0
+#define regUVD_JRBC7_UVD_JRBC_STATUS 0x0189
+#define regUVD_JRBC7_UVD_JRBC_STATUS_BASE_IDX 0
+#define regUVD_JRBC7_UVD_JRBC_RB_RPTR 0x018a
+#define regUVD_JRBC7_UVD_JRBC_RB_RPTR_BASE_IDX 0
+#define regUVD_JRBC8_UVD_JRBC_RB_WPTR 0x01c0
+#define regUVD_JRBC8_UVD_JRBC_RB_WPTR_BASE_IDX 0
+#define regUVD_JRBC8_UVD_JRBC_STATUS 0x01c9
+#define regUVD_JRBC8_UVD_JRBC_STATUS_BASE_IDX 0
+#define regUVD_JRBC8_UVD_JRBC_RB_RPTR 0x01ca
+#define regUVD_JRBC8_UVD_JRBC_RB_RPTR_BASE_IDX 0
+#define regUVD_JRBC9_UVD_JRBC_RB_WPTR 0x0440
+#define regUVD_JRBC9_UVD_JRBC_RB_WPTR_BASE_IDX 1
+#define regUVD_JRBC9_UVD_JRBC_STATUS 0x0449
+#define regUVD_JRBC9_UVD_JRBC_STATUS_BASE_IDX 1
+#define regUVD_JRBC9_UVD_JRBC_RB_RPTR 0x044a
+#define regUVD_JRBC9_UVD_JRBC_RB_RPTR_BASE_IDX 1
+#define regUVD_JMI0_JPEG_LMI_DROP 0x0663
+#define regUVD_JMI0_JPEG_LMI_DROP_BASE_IDX 1
+#define regUVD_JMI0_UVD_JMI_CLIENT_STALL 0x067a
+#define regUVD_JMI0_UVD_JMI_CLIENT_STALL_BASE_IDX 1
+#define regUVD_JMI0_UVD_JMI_CLIENT_CLEAN_STATUS 0x067b
+#define regUVD_JMI0_UVD_JMI_CLIENT_CLEAN_STATUS_BASE_IDX 1
+#define regJPEG_CORE_RST_CTRL 0x072e
+#define regJPEG_CORE_RST_CTRL_BASE_IDX 1
+
+#define regVCN_RRMT_CNTL 0x0940
+#define regVCN_RRMT_CNTL_BASE_IDX 1
+
+enum amdgpu_jpeg_v5_0_2_sub_block {
+ AMDGPU_JPEG_V5_0_2_JPEG0 = 0,
+ AMDGPU_JPEG_V5_0_2_JPEG1,
+
+ AMDGPU_JPEG_V5_0_2_MAX_SUB_BLOCK,
+};
+
+#endif /* __JPEG_V5_0_2_H__ */
diff --git a/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c b/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c
index 8c74894254f7..faac21ee5739 100644
--- a/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c
+++ b/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c
@@ -324,8 +324,10 @@ static int mes_userq_mqd_create(struct amdgpu_usermode_queue *queue,
r = amdgpu_userq_input_va_validate(adev, queue, compute_mqd->eop_va,
2048);
- if (r)
+ if (r) {
+ kfree(compute_mqd);
goto free_mqd;
+ }
userq_props->eop_gpu_addr = compute_mqd->eop_va;
userq_props->hqd_pipe_priority = AMDGPU_GFX_PIPE_PRIO_NORMAL;
@@ -365,12 +367,16 @@ static int mes_userq_mqd_create(struct amdgpu_usermode_queue *queue,
r = amdgpu_userq_input_va_validate(adev, queue, mqd_gfx_v11->shadow_va,
shadow_info.shadow_size);
- if (r)
+ if (r) {
+ kfree(mqd_gfx_v11);
goto free_mqd;
+ }
r = amdgpu_userq_input_va_validate(adev, queue, mqd_gfx_v11->csa_va,
shadow_info.csa_size);
- if (r)
+ if (r) {
+ kfree(mqd_gfx_v11);
goto free_mqd;
+ }
kfree(mqd_gfx_v11);
} else if (queue->queue_type == AMDGPU_HW_IP_DMA) {
@@ -390,8 +396,10 @@ static int mes_userq_mqd_create(struct amdgpu_usermode_queue *queue,
}
r = amdgpu_userq_input_va_validate(adev, queue, mqd_sdma_v11->csa_va,
32);
- if (r)
+ if (r) {
+ kfree(mqd_sdma_v11);
goto free_mqd;
+ }
userq_props->csa_addr = mqd_sdma_v11->csa_va;
kfree(mqd_sdma_v11);
diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v12_1.c b/drivers/gpu/drm/amd/amdgpu/mes_v12_1.c
index d8e4b52bdfd5..0e9089544769 100644
--- a/drivers/gpu/drm/amd/amdgpu/mes_v12_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/mes_v12_1.c
@@ -31,6 +31,8 @@
#include "gc/gc_11_0_0_default.h"
#include "v12_structs.h"
#include "mes_v12_api_def.h"
+#include "gfx_v12_1_pkt.h"
+#include "sdma_v7_1_0_pkt_open.h"
MODULE_FIRMWARE("amdgpu/gc_12_1_0_mes.bin");
MODULE_FIRMWARE("amdgpu/gc_12_1_0_mes1.bin");
@@ -41,6 +43,7 @@ static int mes_v12_1_xcc_hw_init(struct amdgpu_ip_block *ip_block, int xcc_id);
static int mes_v12_1_hw_fini(struct amdgpu_ip_block *ip_block);
static int mes_v12_1_kiq_hw_init(struct amdgpu_device *adev, uint32_t xcc_id);
static int mes_v12_1_kiq_hw_fini(struct amdgpu_device *adev, uint32_t xcc_id);
+static int mes_v12_1_self_test(struct amdgpu_device *adev, int xcc_id);
#define MES_EOP_SIZE 2048
@@ -491,16 +494,12 @@ static int mes_v12_1_query_sched_status(struct amdgpu_mes *mes,
}
static uint32_t mes_v12_1_get_xcc_from_reg(uint32_t reg_offset)
{
- /* Check xcc reg offset range */
- uint32_t xcc = (reg_offset & XCC_MID_MASK) ? 4 : 0;
- /* Each XCC has two register ranges.
- * These are represented in reg_offset[17:16]
- */
- return ((reg_offset >> 16) & 0x3) + xcc;
+ return ((reg_offset >> 16) & 0x7);
}
static void mes_v12_1_get_rrmt(uint32_t reg, uint32_t xcc_id,
- struct RRMT_OPTION *rrmt_opt)
+ struct RRMT_OPTION *rrmt_opt,
+ uint32_t *out_reg)
{
uint32_t normalized_reg = soc_v1_0_normalize_xcc_reg_offset(reg);
@@ -509,8 +508,12 @@ static void mes_v12_1_get_rrmt(uint32_t reg, uint32_t xcc_id,
rrmt_opt->mode = (xcc_id == rrmt_opt->xcd_die_id) ?
MES_RRMT_MODE_LOCAL_XCD : MES_RRMT_MODE_REMOTE_XCD;
} else {
- rrmt_opt->mode = MES_RRMT_MODE_LOCAL_REMOTE_AID;
+ rrmt_opt->mode = MES_RRMT_MODE_REMOTE_MID;
+ if (soc_v1_0_mid1_reg_range(reg))
+ rrmt_opt->mid_die_id = 1;
}
+
+ *out_reg = soc_v1_0_normalize_reg_offset(reg);
}
static int mes_v12_1_misc_op(struct amdgpu_mes *mes,
@@ -534,65 +537,44 @@ static int mes_v12_1_misc_op(struct amdgpu_mes *mes,
switch (input->op) {
case MES_MISC_OP_READ_REG:
misc_pkt.opcode = MESAPI_MISC__READ_REG;
- misc_pkt.read_reg.reg_offset = input->read_reg.reg_offset;
misc_pkt.read_reg.buffer_addr = input->read_reg.buffer_addr;
mes_v12_1_get_rrmt(input->read_reg.reg_offset,
GET_INST(GC, input->xcc_id),
- &misc_pkt.read_reg.rrmt_opt);
- if (misc_pkt.read_reg.rrmt_opt.mode != MES_RRMT_MODE_REMOTE_MID) {
- misc_pkt.read_reg.reg_offset =
- soc_v1_0_normalize_xcc_reg_offset(misc_pkt.read_reg.reg_offset);
- }
+ &misc_pkt.read_reg.rrmt_opt,
+ &misc_pkt.read_reg.reg_offset);
break;
case MES_MISC_OP_WRITE_REG:
misc_pkt.opcode = MESAPI_MISC__WRITE_REG;
- misc_pkt.write_reg.reg_offset = input->write_reg.reg_offset;
misc_pkt.write_reg.reg_value = input->write_reg.reg_value;
mes_v12_1_get_rrmt(input->write_reg.reg_offset,
GET_INST(GC, input->xcc_id),
- &misc_pkt.write_reg.rrmt_opt);
- if (misc_pkt.write_reg.rrmt_opt.mode != MES_RRMT_MODE_REMOTE_MID) {
- misc_pkt.write_reg.reg_offset =
- soc_v1_0_normalize_xcc_reg_offset(misc_pkt.write_reg.reg_offset);
- }
+ &misc_pkt.write_reg.rrmt_opt,
+ &misc_pkt.write_reg.reg_offset);
break;
case MES_MISC_OP_WRM_REG_WAIT:
misc_pkt.opcode = MESAPI_MISC__WAIT_REG_MEM;
misc_pkt.wait_reg_mem.op = WRM_OPERATION__WAIT_REG_MEM;
misc_pkt.wait_reg_mem.reference = input->wrm_reg.ref;
misc_pkt.wait_reg_mem.mask = input->wrm_reg.mask;
- misc_pkt.wait_reg_mem.reg_offset1 = input->wrm_reg.reg0;
misc_pkt.wait_reg_mem.reg_offset2 = 0;
mes_v12_1_get_rrmt(input->wrm_reg.reg0,
GET_INST(GC, input->xcc_id),
- &misc_pkt.wait_reg_mem.rrmt_opt1);
- if (misc_pkt.wait_reg_mem.rrmt_opt1.mode != MES_RRMT_MODE_REMOTE_MID) {
- misc_pkt.wait_reg_mem.reg_offset1 =
- soc_v1_0_normalize_xcc_reg_offset(misc_pkt.wait_reg_mem.reg_offset1);
- }
+ &misc_pkt.wait_reg_mem.rrmt_opt1,
+ &misc_pkt.wait_reg_mem.reg_offset1);
break;
case MES_MISC_OP_WRM_REG_WR_WAIT:
misc_pkt.opcode = MESAPI_MISC__WAIT_REG_MEM;
misc_pkt.wait_reg_mem.op = WRM_OPERATION__WR_WAIT_WR_REG;
misc_pkt.wait_reg_mem.reference = input->wrm_reg.ref;
misc_pkt.wait_reg_mem.mask = input->wrm_reg.mask;
- misc_pkt.wait_reg_mem.reg_offset1 = input->wrm_reg.reg0;
- misc_pkt.wait_reg_mem.reg_offset2 = input->wrm_reg.reg1;
mes_v12_1_get_rrmt(input->wrm_reg.reg0,
GET_INST(GC, input->xcc_id),
- &misc_pkt.wait_reg_mem.rrmt_opt1);
+ &misc_pkt.wait_reg_mem.rrmt_opt1,
+ &misc_pkt.wait_reg_mem.reg_offset1);
mes_v12_1_get_rrmt(input->wrm_reg.reg1,
GET_INST(GC, input->xcc_id),
- &misc_pkt.wait_reg_mem.rrmt_opt2);
-
- if (misc_pkt.wait_reg_mem.rrmt_opt1.mode != MES_RRMT_MODE_REMOTE_MID) {
- misc_pkt.wait_reg_mem.reg_offset1 =
- soc_v1_0_normalize_xcc_reg_offset(misc_pkt.wait_reg_mem.reg_offset1);
- }
- if (misc_pkt.wait_reg_mem.rrmt_opt2.mode != MES_RRMT_MODE_REMOTE_MID) {
- misc_pkt.wait_reg_mem.reg_offset2 =
- soc_v1_0_normalize_xcc_reg_offset(misc_pkt.wait_reg_mem.reg_offset2);
- }
+ &misc_pkt.wait_reg_mem.rrmt_opt2,
+ &misc_pkt.wait_reg_mem.reg_offset2);
break;
case MES_MISC_OP_SET_SHADER_DEBUGGER:
pipe = AMDGPU_MES_SCHED_PIPE;
@@ -1949,10 +1931,31 @@ static int mes_v12_1_early_init(struct amdgpu_ip_block *ip_block)
return 0;
}
+static int mes_v12_1_late_init(struct amdgpu_ip_block *ip_block)
+{
+ struct amdgpu_device *adev = ip_block->adev;
+ int xcc_id, num_xcc = NUM_XCC(adev->gfx.xcc_mask);
+
+ /* TODO: remove it if issue fixed. */
+ if (adev->mes.enable_coop_mode)
+ return 0;
+
+ for (xcc_id = 0; xcc_id < num_xcc; xcc_id++) {
+ /* for COOP mode, only test master xcc. */
+ if (adev->mes.enable_coop_mode &&
+ adev->mes.master_xcc_ids[xcc_id] != xcc_id)
+ continue;
+
+ mes_v12_1_self_test(adev, xcc_id);
+ }
+
+ return 0;
+}
+
static const struct amd_ip_funcs mes_v12_1_ip_funcs = {
.name = "mes_v12_1",
.early_init = mes_v12_1_early_init,
- .late_init = NULL,
+ .late_init = mes_v12_1_late_init,
.sw_init = mes_v12_1_sw_init,
.sw_fini = mes_v12_1_sw_fini,
.hw_init = mes_v12_1_hw_init,
@@ -1968,3 +1971,312 @@ const struct amdgpu_ip_block_version mes_v12_1_ip_block = {
.rev = 0,
.funcs = &mes_v12_1_ip_funcs,
};
+
+static int mes_v12_1_alloc_test_buf(struct amdgpu_device *adev,
+ struct amdgpu_bo **bo, uint64_t *addr,
+ void **ptr, int size)
+{
+ amdgpu_bo_create_kernel(adev, size, PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT,
+ bo, addr, ptr);
+ if (!*bo) {
+ dev_err(adev->dev, "failed to allocate test buffer bo\n");
+ return -ENOMEM;
+ }
+ memset(*ptr, 0, size);
+ return 0;
+}
+
+static int mes_v12_1_map_test_bo(struct amdgpu_device *adev,
+ struct amdgpu_bo *bo, struct amdgpu_vm *vm,
+ struct amdgpu_bo_va **bo_va, u64 va, int size)
+{
+ struct amdgpu_sync sync;
+ int r;
+
+ r = amdgpu_map_static_csa(adev, vm, bo, bo_va, va, size);
+ if (r)
+ return r;
+
+ amdgpu_sync_create(&sync);
+
+ r = amdgpu_vm_bo_update(adev, *bo_va, false);
+ if (r) {
+ dev_err(adev->dev, "failed to do vm_bo_update on meta data\n");
+ goto error;
+ }
+ amdgpu_sync_fence(&sync, (*bo_va)->last_pt_update, GFP_KERNEL);
+
+ r = amdgpu_vm_update_pdes(adev, vm, false);
+ if (r) {
+ dev_err(adev->dev, "failed to update pdes on meta data\n");
+ goto error;
+ }
+ amdgpu_sync_fence(&sync, vm->last_update, GFP_KERNEL);
+ amdgpu_sync_wait(&sync, false);
+
+error:
+ amdgpu_sync_free(&sync);
+ return 0;
+}
+
+static int mes_v12_1_test_ring(struct amdgpu_device *adev, int xcc_id,
+ u32 *queue_ptr, u64 fence_gpu_addr,
+ void *fence_cpu_ptr, void *wptr_cpu_addr,
+ u64 doorbell_idx, int queue_type)
+{
+ volatile uint32_t *cpu_ptr = fence_cpu_ptr;
+ int num_xcc = NUM_XCC(adev->gfx.xcc_mask);
+ int sdma_ring_align = 0x10, compute_ring_align = 0x100;
+ uint32_t tmp, xcc_offset;
+ int r = 0, i, wptr = 0;
+
+ if (queue_type == AMDGPU_RING_TYPE_COMPUTE) {
+ if (!adev->mes.enable_coop_mode) {
+ WREG32_SOC15(GC, GET_INST(GC, xcc_id),
+ regSCRATCH_REG0, 0xCAFEDEAD);
+ } else {
+ for (i = 0; i < num_xcc; i++) {
+ if (adev->mes.master_xcc_ids[i] == xcc_id)
+ WREG32_SOC15(GC, GET_INST(GC, i),
+ regSCRATCH_REG0, 0xCAFEDEAD);
+ }
+ }
+
+ xcc_offset = SOC15_REG_OFFSET(GC, 0, regSCRATCH_REG0);
+ queue_ptr[wptr++] = PACKET3(PACKET3_SET_UCONFIG_REG, 1);
+ queue_ptr[wptr++] = xcc_offset - PACKET3_SET_UCONFIG_REG_START;
+ queue_ptr[wptr++] = 0xDEADBEEF;
+
+ for (i = wptr; i < compute_ring_align; i++)
+ queue_ptr[wptr++] = PACKET3(PACKET3_NOP, 0x3FFF);
+
+ } else if (queue_type == AMDGPU_RING_TYPE_SDMA) {
+ *cpu_ptr = 0xCAFEDEAD;
+
+ queue_ptr[wptr++] = SDMA_PKT_COPY_LINEAR_HEADER_OP(SDMA_OP_WRITE) |
+ SDMA_PKT_COPY_LINEAR_HEADER_SUB_OP(SDMA_SUBOP_WRITE_LINEAR);
+ queue_ptr[wptr++] = lower_32_bits(fence_gpu_addr);
+ queue_ptr[wptr++] = upper_32_bits(fence_gpu_addr);
+ queue_ptr[wptr++] = SDMA_PKT_WRITE_UNTILED_DW_3_COUNT(0);
+ queue_ptr[wptr++] = 0xDEADBEEF;
+
+ for (i = wptr; i < sdma_ring_align; i++)
+ queue_ptr[wptr++] = SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP);
+
+ wptr <<= 2;
+ }
+
+ atomic64_set((atomic64_t *)wptr_cpu_addr, wptr);
+ WDOORBELL64(doorbell_idx, wptr);
+
+ for (i = 0; i < adev->usec_timeout; i++) {
+ if (queue_type == AMDGPU_RING_TYPE_SDMA) {
+ tmp = le32_to_cpu(*cpu_ptr);
+ } else {
+ if (!adev->mes.enable_coop_mode) {
+ tmp = RREG32_SOC15(GC, GET_INST(GC, xcc_id),
+ regSCRATCH_REG0);
+ } else {
+ for (i = 0; i < num_xcc; i++) {
+ if (xcc_id != adev->mes.master_xcc_ids[i])
+ continue;
+
+ tmp = RREG32_SOC15(GC, GET_INST(GC, i),
+ regSCRATCH_REG0);
+ if (tmp != 0xDEADBEEF)
+ break;
+ }
+ }
+ }
+
+ if (tmp == 0xDEADBEEF)
+ break;
+
+ if (amdgpu_emu_mode == 1)
+ msleep(1);
+ else
+ udelay(1);
+ }
+
+ if (i >= adev->usec_timeout) {
+ dev_err(adev->dev, "xcc%d: mes self test (%s) failed\n", xcc_id,
+ queue_type == AMDGPU_RING_TYPE_SDMA ? "sdma" : "compute");
+
+ while (halt_if_hws_hang)
+ schedule();
+
+ r = -ETIMEDOUT;
+ } else {
+ dev_info(adev->dev, "xcc%d: mes self test (%s) pass\n", xcc_id,
+ queue_type == AMDGPU_RING_TYPE_SDMA ? "sdma" : "compute");
+ }
+
+ return r;
+}
+
+#define USER_CTX_SIZE (PAGE_SIZE * 2)
+#define USER_CTX_VA AMDGPU_VA_RESERVED_BOTTOM
+#define RING_OFFSET(addr) ((addr))
+#define EOP_OFFSET(addr) ((addr) + PAGE_SIZE)
+#define WPTR_OFFSET(addr) ((addr) + USER_CTX_SIZE - sizeof(u64))
+#define RPTR_OFFSET(addr) ((addr) + USER_CTX_SIZE - sizeof(u64) * 2)
+#define FENCE_OFFSET(addr) ((addr) + USER_CTX_SIZE - sizeof(u64) * 3)
+
+static int mes_v12_1_test_queue(struct amdgpu_device *adev, int xcc_id,
+ int pasid, struct amdgpu_vm *vm, u64 meta_gpu_addr,
+ u64 queue_gpu_addr, void *ctx_ptr, int queue_type)
+{
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB(0)];
+ struct amdgpu_mqd *mqd_mgr = &adev->mqds[queue_type];
+ struct amdgpu_mqd_prop mqd_prop = {0};
+ struct mes_add_queue_input add_queue = {0};
+ struct mes_remove_queue_input remove_queue = {0};
+ struct amdgpu_bo *mqd_bo = NULL;
+ int num_xcc = NUM_XCC(adev->gfx.xcc_mask);
+ int i, r, off, mqd_size, mqd_count = 1;
+ void *mqd_ptr = NULL;
+ u64 mqd_gpu_addr, doorbell_idx;
+
+ /* extra one page size padding for mes fw */
+ mqd_size = mqd_mgr->mqd_size + PAGE_SIZE;
+
+ if (queue_type == AMDGPU_RING_TYPE_SDMA) {
+ doorbell_idx = adev->mes.db_start_dw_offset + \
+ adev->doorbell_index.sdma_engine[0];
+ } else {
+ doorbell_idx = adev->mes.db_start_dw_offset + \
+ adev->doorbell_index.userqueue_start;
+ }
+
+ if (adev->mes.enable_coop_mode &&
+ queue_type == AMDGPU_RING_TYPE_COMPUTE) {
+ for (i = 0, mqd_count = 0; i < num_xcc; i++) {
+ if (adev->mes.master_xcc_ids[i] == xcc_id)
+ mqd_count++;
+ }
+ mqd_size *= mqd_count;
+ }
+
+ r = mes_v12_1_alloc_test_buf(adev, &mqd_bo, &mqd_gpu_addr,
+ &mqd_ptr, mqd_size * mqd_count);
+ if (r < 0)
+ return r;
+
+ mqd_prop.mqd_gpu_addr = mqd_gpu_addr;
+ mqd_prop.hqd_base_gpu_addr = RING_OFFSET(USER_CTX_VA);
+ mqd_prop.eop_gpu_addr = EOP_OFFSET(USER_CTX_VA);
+ mqd_prop.wptr_gpu_addr = WPTR_OFFSET(USER_CTX_VA);
+ mqd_prop.rptr_gpu_addr = RPTR_OFFSET(USER_CTX_VA);
+ mqd_prop.doorbell_index = doorbell_idx;
+ mqd_prop.queue_size = PAGE_SIZE;
+ mqd_prop.mqd_stride_size = mqd_size;
+ mqd_prop.use_doorbell = true;
+ mqd_prop.hqd_active = false;
+
+ mqd_mgr->init_mqd(adev, mqd_ptr, &mqd_prop);
+ if (mqd_count > 1) {
+ for (i = 1; i < mqd_count; i++) {
+ off = mqd_size * i;
+ mqd_prop.mqd_gpu_addr = mqd_gpu_addr + off;
+ mqd_mgr->init_mqd(adev, (char *)mqd_ptr + off,
+ &mqd_prop);
+ }
+ }
+
+ add_queue.xcc_id = xcc_id;
+ add_queue.process_id = pasid;
+ add_queue.page_table_base_addr = adev->vm_manager.vram_base_offset +
+ amdgpu_bo_gpu_offset(vm->root.bo) - adev->gmc.vram_start;
+ add_queue.process_va_start = 0;
+ add_queue.process_va_end = adev->vm_manager.max_pfn - 1;
+ add_queue.process_context_addr = meta_gpu_addr;
+ add_queue.gang_context_addr = meta_gpu_addr + AMDGPU_MES_PROC_CTX_SIZE;
+ add_queue.doorbell_offset = doorbell_idx;
+ add_queue.mqd_addr = mqd_gpu_addr;
+ add_queue.wptr_addr = mqd_prop.wptr_gpu_addr;
+ add_queue.wptr_mc_addr = WPTR_OFFSET(queue_gpu_addr);
+ add_queue.queue_type = queue_type;
+ add_queue.vm_cntx_cntl = hub->vm_cntx_cntl;
+
+ r = mes_v12_1_add_hw_queue(&adev->mes, &add_queue);
+ if (r)
+ goto error;
+
+ mes_v12_1_test_ring(adev, xcc_id, (u32 *)RING_OFFSET((char *)ctx_ptr),
+ FENCE_OFFSET(USER_CTX_VA),
+ FENCE_OFFSET((char *)ctx_ptr),
+ WPTR_OFFSET((char *)ctx_ptr),
+ doorbell_idx, queue_type);
+
+ remove_queue.xcc_id = xcc_id;
+ remove_queue.doorbell_offset = doorbell_idx;
+ remove_queue.gang_context_addr = add_queue.gang_context_addr;
+ r = mes_v12_1_remove_hw_queue(&adev->mes, &remove_queue);
+
+error:
+ amdgpu_bo_free_kernel(&mqd_bo, &mqd_gpu_addr, &mqd_ptr);
+ return r;
+}
+
+static int mes_v12_1_self_test(struct amdgpu_device *adev, int xcc_id)
+{
+ int queue_types[] = { AMDGPU_RING_TYPE_COMPUTE,
+ /* AMDGPU_RING_TYPE_SDMA */ };
+ struct amdgpu_bo_va *bo_va = NULL;
+ struct amdgpu_vm *vm = NULL;
+ struct amdgpu_bo *meta_bo = NULL, *ctx_bo = NULL;
+ void *meta_ptr = NULL, *ctx_ptr = NULL;
+ u64 meta_gpu_addr, ctx_gpu_addr;
+ int size, i, r, pasid;
+
+ pasid = amdgpu_pasid_alloc(16);
+ if (pasid < 0)
+ pasid = 0;
+
+ size = AMDGPU_MES_PROC_CTX_SIZE + AMDGPU_MES_GANG_CTX_SIZE;
+ r = mes_v12_1_alloc_test_buf(adev, &meta_bo, &meta_gpu_addr,
+ &meta_ptr, size);
+ if (r < 0)
+ goto err2;
+
+ r = mes_v12_1_alloc_test_buf(adev, &ctx_bo, &ctx_gpu_addr,
+ &ctx_ptr, USER_CTX_SIZE);
+ if (r < 0)
+ goto err2;
+
+ vm = kzalloc(sizeof(*vm), GFP_KERNEL);
+ if (!vm) {
+ r = -ENOMEM;
+ goto err2;
+ }
+
+ r = amdgpu_vm_init(adev, vm, -1, pasid);
+ if (r)
+ goto err1;
+
+ r = mes_v12_1_map_test_bo(adev, ctx_bo, vm, &bo_va,
+ USER_CTX_VA, USER_CTX_SIZE);
+ if (r)
+ goto err0;
+
+ for (i = 0; i < ARRAY_SIZE(queue_types); i++) {
+ memset(ctx_ptr, 0, USER_CTX_SIZE);
+
+ r = mes_v12_1_test_queue(adev, xcc_id, pasid, vm, meta_gpu_addr,
+ ctx_gpu_addr, ctx_ptr, queue_types[i]);
+ if (r)
+ break;
+ }
+
+ amdgpu_unmap_static_csa(adev, vm, ctx_bo, bo_va, USER_CTX_VA);
+err0:
+ amdgpu_vm_fini(adev, vm);
+err1:
+ kfree(vm);
+err2:
+ amdgpu_bo_free_kernel(&meta_bo, &meta_gpu_addr, &meta_ptr);
+ amdgpu_bo_free_kernel(&ctx_bo, &ctx_gpu_addr, &ctx_ptr);
+ amdgpu_pasid_free(pasid);
+ return r;
+}
+
diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c
index a0cc8e218ca1..42a09a277ec3 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c
@@ -141,7 +141,7 @@ mmhub_v2_0_print_l2_protection_fault_status(struct amdgpu_device *adev,
uint32_t status)
{
uint32_t cid, rw;
- const char *mmhub_cid = NULL;
+ const char *mmhub_cid;
cid = REG_GET_FIELD(status,
MMVM_L2_PROTECTION_FAULT_STATUS, CID);
@@ -151,22 +151,7 @@ mmhub_v2_0_print_l2_protection_fault_status(struct amdgpu_device *adev,
dev_err(adev->dev,
"MMVM_L2_PROTECTION_FAULT_STATUS:0x%08X\n",
status);
- switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
- case IP_VERSION(2, 0, 0):
- case IP_VERSION(2, 0, 2):
- mmhub_cid = mmhub_client_ids_navi1x[cid][rw];
- break;
- case IP_VERSION(2, 1, 0):
- case IP_VERSION(2, 1, 1):
- mmhub_cid = mmhub_client_ids_sienna_cichlid[cid][rw];
- break;
- case IP_VERSION(2, 1, 2):
- mmhub_cid = mmhub_client_ids_beige_goby[cid][rw];
- break;
- default:
- mmhub_cid = NULL;
- break;
- }
+ mmhub_cid = amdgpu_mmhub_client_name(&adev->mmhub, cid, rw);
dev_err(adev->dev, "\t Faulty UTCL2 client ID: %s (0x%x)\n",
mmhub_cid ? mmhub_cid : "unknown", cid);
dev_err(adev->dev, "\t MORE_FAULTS: 0x%lx\n",
@@ -518,6 +503,31 @@ static const struct amdgpu_vmhub_funcs mmhub_v2_0_vmhub_funcs = {
.get_invalidate_req = mmhub_v2_0_get_invalidate_req,
};
+static void mmhub_v2_0_init_client_info(struct amdgpu_device *adev)
+{
+ switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
+ case IP_VERSION(2, 0, 0):
+ case IP_VERSION(2, 0, 2):
+ amdgpu_mmhub_init_client_info(&adev->mmhub,
+ mmhub_client_ids_navi1x,
+ ARRAY_SIZE(mmhub_client_ids_navi1x));
+ break;
+ case IP_VERSION(2, 1, 0):
+ case IP_VERSION(2, 1, 1):
+ amdgpu_mmhub_init_client_info(&adev->mmhub,
+ mmhub_client_ids_sienna_cichlid,
+ ARRAY_SIZE(mmhub_client_ids_sienna_cichlid));
+ break;
+ case IP_VERSION(2, 1, 2):
+ amdgpu_mmhub_init_client_info(&adev->mmhub,
+ mmhub_client_ids_beige_goby,
+ ARRAY_SIZE(mmhub_client_ids_beige_goby));
+ break;
+ default:
+ break;
+ }
+}
+
static void mmhub_v2_0_init(struct amdgpu_device *adev)
{
struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
@@ -558,6 +568,8 @@ static void mmhub_v2_0_init(struct amdgpu_device *adev)
MMVM_CONTEXT1_CNTL__EXECUTE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK;
hub->vmhub_funcs = &mmhub_v2_0_vmhub_funcs;
+
+ mmhub_v2_0_init_client_info(adev);
}
static void mmhub_v2_0_update_medium_grain_clock_gating(struct amdgpu_device *adev,
diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c
index 5eb8122e2746..31c479d76c42 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c
@@ -80,7 +80,7 @@ mmhub_v2_3_print_l2_protection_fault_status(struct amdgpu_device *adev,
uint32_t status)
{
uint32_t cid, rw;
- const char *mmhub_cid = NULL;
+ const char *mmhub_cid;
cid = REG_GET_FIELD(status,
MMVM_L2_PROTECTION_FAULT_STATUS, CID);
@@ -90,16 +90,7 @@ mmhub_v2_3_print_l2_protection_fault_status(struct amdgpu_device *adev,
dev_err(adev->dev,
"MMVM_L2_PROTECTION_FAULT_STATUS:0x%08X\n",
status);
- switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
- case IP_VERSION(2, 3, 0):
- case IP_VERSION(2, 4, 0):
- case IP_VERSION(2, 4, 1):
- mmhub_cid = mmhub_client_ids_vangogh[cid][rw];
- break;
- default:
- mmhub_cid = NULL;
- break;
- }
+ mmhub_cid = amdgpu_mmhub_client_name(&adev->mmhub, cid, rw);
dev_err(adev->dev, "\t Faulty UTCL2 client ID: %s (0x%x)\n",
mmhub_cid ? mmhub_cid : "unknown", cid);
dev_err(adev->dev, "\t MORE_FAULTS: 0x%lx\n",
@@ -486,6 +477,10 @@ static void mmhub_v2_3_init(struct amdgpu_device *adev)
MMVM_CONTEXT1_CNTL__EXECUTE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK;
hub->vmhub_funcs = &mmhub_v2_3_vmhub_funcs;
+
+ amdgpu_mmhub_init_client_info(&adev->mmhub,
+ mmhub_client_ids_vangogh,
+ ARRAY_SIZE(mmhub_client_ids_vangogh));
}
static void
diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0.c
index 7d5242df58a5..3d82cfa0f1b5 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0.c
@@ -97,7 +97,7 @@ mmhub_v3_0_print_l2_protection_fault_status(struct amdgpu_device *adev,
uint32_t status)
{
uint32_t cid, rw;
- const char *mmhub_cid = NULL;
+ const char *mmhub_cid;
cid = REG_GET_FIELD(status,
MMVM_L2_PROTECTION_FAULT_STATUS, CID);
@@ -107,15 +107,7 @@ mmhub_v3_0_print_l2_protection_fault_status(struct amdgpu_device *adev,
dev_err(adev->dev,
"MMVM_L2_PROTECTION_FAULT_STATUS:0x%08X\n",
status);
- switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
- case IP_VERSION(3, 0, 0):
- case IP_VERSION(3, 0, 1):
- mmhub_cid = mmhub_client_ids_v3_0_0[cid][rw];
- break;
- default:
- mmhub_cid = NULL;
- break;
- }
+ mmhub_cid = amdgpu_mmhub_client_name(&adev->mmhub, cid, rw);
dev_err(adev->dev, "\t Faulty UTCL2 client ID: %s (0x%x)\n",
mmhub_cid ? mmhub_cid : "unknown", cid);
dev_err(adev->dev, "\t MORE_FAULTS: 0x%lx\n",
@@ -520,6 +512,10 @@ static void mmhub_v3_0_init(struct amdgpu_device *adev)
SOC15_REG_OFFSET(MMHUB, 0, regMMVM_CONTEXTS_DISABLE);
hub->vmhub_funcs = &mmhub_v3_0_vmhub_funcs;
+
+ amdgpu_mmhub_init_client_info(&adev->mmhub,
+ mmhub_client_ids_v3_0_0,
+ ARRAY_SIZE(mmhub_client_ids_v3_0_0));
}
static u64 mmhub_v3_0_get_fb_location(struct amdgpu_device *adev)
diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_1.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_1.c
index 910337dc28d1..a1b0b7b39a42 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_1.c
@@ -104,7 +104,7 @@ mmhub_v3_0_1_print_l2_protection_fault_status(struct amdgpu_device *adev,
uint32_t status)
{
uint32_t cid, rw;
- const char *mmhub_cid = NULL;
+ const char *mmhub_cid;
cid = REG_GET_FIELD(status,
MMVM_L2_PROTECTION_FAULT_STATUS, CID);
@@ -114,16 +114,7 @@ mmhub_v3_0_1_print_l2_protection_fault_status(struct amdgpu_device *adev,
dev_err(adev->dev,
"MMVM_L2_PROTECTION_FAULT_STATUS:0x%08X\n",
status);
-
- switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
- case IP_VERSION(3, 0, 1):
- mmhub_cid = mmhub_client_ids_v3_0_1[cid][rw];
- break;
- default:
- mmhub_cid = NULL;
- break;
- }
-
+ mmhub_cid = amdgpu_mmhub_client_name(&adev->mmhub, cid, rw);
dev_err(adev->dev, "\t Faulty UTCL2 client ID: %s (0x%x)\n",
mmhub_cid ? mmhub_cid : "unknown", cid);
dev_err(adev->dev, "\t MORE_FAULTS: 0x%lx\n",
@@ -503,6 +494,10 @@ static void mmhub_v3_0_1_init(struct amdgpu_device *adev)
MMVM_CONTEXT1_CNTL__EXECUTE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK;
hub->vmhub_funcs = &mmhub_v3_0_1_vmhub_funcs;
+
+ amdgpu_mmhub_init_client_info(&adev->mmhub,
+ mmhub_client_ids_v3_0_1,
+ ARRAY_SIZE(mmhub_client_ids_v3_0_1));
}
static u64 mmhub_v3_0_1_get_fb_location(struct amdgpu_device *adev)
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 f0f182f033b9..34e8dbd47c0f 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_2.c
+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_2.c
@@ -97,7 +97,7 @@ mmhub_v3_0_2_print_l2_protection_fault_status(struct amdgpu_device *adev,
uint32_t status)
{
uint32_t cid, rw;
- const char *mmhub_cid = NULL;
+ const char *mmhub_cid;
cid = REG_GET_FIELD(status,
MMVM_L2_PROTECTION_FAULT_STATUS, CID);
@@ -107,8 +107,7 @@ mmhub_v3_0_2_print_l2_protection_fault_status(struct amdgpu_device *adev,
dev_err(adev->dev,
"MMVM_L2_PROTECTION_FAULT_STATUS:0x%08X\n",
status);
-
- mmhub_cid = mmhub_client_ids_v3_0_2[cid][rw];
+ mmhub_cid = amdgpu_mmhub_client_name(&adev->mmhub, cid, rw);
dev_err(adev->dev, "\t Faulty UTCL2 client ID: %s (0x%x)\n",
mmhub_cid ? mmhub_cid : "unknown", cid);
dev_err(adev->dev, "\t MORE_FAULTS: 0x%lx\n",
@@ -509,6 +508,10 @@ static void mmhub_v3_0_2_init(struct amdgpu_device *adev)
SOC15_REG_OFFSET(MMHUB, 0, regMMVM_L2_BANK_SELECT_RESERVED_CID2);
hub->vmhub_funcs = &mmhub_v3_0_2_vmhub_funcs;
+
+ amdgpu_mmhub_init_client_info(&adev->mmhub,
+ mmhub_client_ids_v3_0_2,
+ ARRAY_SIZE(mmhub_client_ids_v3_0_2));
}
static u64 mmhub_v3_0_2_get_fb_location(struct amdgpu_device *adev)
diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v3_3.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v3_3.c
index daf1f8ad4cca..cfce7e1297d4 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v3_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v3_3.c
@@ -217,7 +217,7 @@ mmhub_v3_3_print_l2_protection_fault_status(struct amdgpu_device *adev,
uint32_t status)
{
uint32_t cid, rw;
- const char *mmhub_cid = NULL;
+ const char *mmhub_cid;
cid = REG_GET_FIELD(status,
MMVM_L2_PROTECTION_FAULT_STATUS, CID);
@@ -227,29 +227,10 @@ mmhub_v3_3_print_l2_protection_fault_status(struct amdgpu_device *adev,
dev_err(adev->dev,
"MMVM_L2_PROTECTION_FAULT_STATUS:0x%08X\n",
status);
-
- switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
- case IP_VERSION(3, 3, 0):
- case IP_VERSION(3, 3, 2):
- mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_v3_3) ?
- mmhub_client_ids_v3_3[cid][rw] :
- cid == 0x140 ? "UMSCH" : NULL;
- break;
- case IP_VERSION(3, 3, 1):
- mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_v3_3_1) ?
- mmhub_client_ids_v3_3_1[cid][rw] :
- cid == 0x140 ? "UMSCH" : NULL;
- break;
- case IP_VERSION(3, 4, 0):
- mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_v3_4) ?
- mmhub_client_ids_v3_4[cid][rw] :
- cid == 0x140 ? "UMSCH" : NULL;
- break;
- default:
- mmhub_cid = NULL;
- break;
- }
-
+ if (cid == 0x140)
+ mmhub_cid = "UMSCH";
+ else
+ mmhub_cid = amdgpu_mmhub_client_name(&adev->mmhub, cid, rw);
dev_err(adev->dev, "\t Faulty UTCL2 client ID: %s (0x%x)\n",
mmhub_cid ? mmhub_cid : "unknown", cid);
dev_err(adev->dev, "\t MORE_FAULTS: 0x%lx\n",
@@ -640,6 +621,30 @@ static const struct amdgpu_vmhub_funcs mmhub_v3_3_vmhub_funcs = {
.get_invalidate_req = mmhub_v3_3_get_invalidate_req,
};
+static void mmhub_v3_3_init_client_info(struct amdgpu_device *adev)
+{
+ switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
+ case IP_VERSION(3, 3, 0):
+ case IP_VERSION(3, 3, 2):
+ amdgpu_mmhub_init_client_info(&adev->mmhub,
+ mmhub_client_ids_v3_3,
+ ARRAY_SIZE(mmhub_client_ids_v3_3));
+ break;
+ case IP_VERSION(3, 3, 1):
+ amdgpu_mmhub_init_client_info(&adev->mmhub,
+ mmhub_client_ids_v3_3_1,
+ ARRAY_SIZE(mmhub_client_ids_v3_3_1));
+ break;
+ case IP_VERSION(3, 4, 0):
+ amdgpu_mmhub_init_client_info(&adev->mmhub,
+ mmhub_client_ids_v3_4,
+ ARRAY_SIZE(mmhub_client_ids_v3_4));
+ break;
+ default:
+ break;
+ }
+}
+
static void mmhub_v3_3_init(struct amdgpu_device *adev)
{
struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
@@ -680,6 +685,8 @@ static void mmhub_v3_3_init(struct amdgpu_device *adev)
MMVM_CONTEXT1_CNTL__EXECUTE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK;
hub->vmhub_funcs = &mmhub_v3_3_vmhub_funcs;
+
+ mmhub_v3_3_init_client_info(adev);
}
static u64 mmhub_v3_3_get_fb_location(struct amdgpu_device *adev)
diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v4_1_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v4_1_0.c
index 951998454b25..bef75c4c48d3 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v4_1_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v4_1_0.c
@@ -90,7 +90,7 @@ mmhub_v4_1_0_print_l2_protection_fault_status(struct amdgpu_device *adev,
uint32_t status)
{
uint32_t cid, rw;
- const char *mmhub_cid = NULL;
+ const char *mmhub_cid;
cid = REG_GET_FIELD(status,
MMVM_L2_PROTECTION_FAULT_STATUS_LO32, CID);
@@ -100,14 +100,7 @@ mmhub_v4_1_0_print_l2_protection_fault_status(struct amdgpu_device *adev,
dev_err(adev->dev,
"MMVM_L2_PROTECTION_FAULT_STATUS_LO32:0x%08X\n",
status);
- switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
- case IP_VERSION(4, 1, 0):
- mmhub_cid = mmhub_client_ids_v4_1_0[cid][rw];
- break;
- default:
- mmhub_cid = NULL;
- break;
- }
+ mmhub_cid = amdgpu_mmhub_client_name(&adev->mmhub, cid, rw);
dev_err(adev->dev, "\t Faulty UTCL2 client ID: %s (0x%x)\n",
mmhub_cid ? mmhub_cid : "unknown", cid);
dev_err(adev->dev, "\t MORE_FAULTS: 0x%lx\n",
@@ -514,6 +507,10 @@ static void mmhub_v4_1_0_init(struct amdgpu_device *adev)
SOC15_REG_OFFSET(MMHUB, 0, regMMVM_CONTEXTS_DISABLE);
hub->vmhub_funcs = &mmhub_v4_1_0_vmhub_funcs;
+
+ amdgpu_mmhub_init_client_info(&adev->mmhub,
+ mmhub_client_ids_v4_1_0,
+ ARRAY_SIZE(mmhub_client_ids_v4_1_0));
}
static u64 mmhub_v4_1_0_get_fb_location(struct amdgpu_device *adev)
diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v4_2_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v4_2_0.c
index a72770e3d0e9..29f7ed466858 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v4_2_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v4_2_0.c
@@ -72,6 +72,45 @@ static const char *mmhub_client_ids_v4_2_0[][2] = {
[23][1] = "VCN1",
};
+static int mmhub_v4_2_0_get_xgmi_info(struct amdgpu_device *adev)
+{
+ u32 max_num_physical_nodes;
+ u32 max_physical_node_id;
+ u32 xgmi_lfb_cntl;
+ u32 max_region;
+ u64 seg_size;
+
+ /* limit this callback to A + A configuration only */
+ if (!adev->gmc.xgmi.connected_to_cpu)
+ return 0;
+
+ xgmi_lfb_cntl = RREG32_SOC15(MMHUB, GET_INST(MMHUB, 0),
+ regMMMC_VM_XGMI_LFB_CNTL);
+ seg_size = REG_GET_FIELD(
+ RREG32_SOC15(MMHUB, GET_INST(MMHUB, 0), regMMMC_VM_XGMI_LFB_SIZE),
+ MMMC_VM_XGMI_LFB_SIZE, PF_LFB_SIZE) << 24;
+ max_region =
+ REG_GET_FIELD(xgmi_lfb_cntl, MMMC_VM_XGMI_LFB_CNTL, PF_MAX_REGION);
+
+ max_num_physical_nodes = 4;
+ max_physical_node_id = 3;
+
+ adev->gmc.xgmi.num_physical_nodes = max_region + 1;
+
+ if (adev->gmc.xgmi.num_physical_nodes > max_num_physical_nodes)
+ return -EINVAL;
+
+ adev->gmc.xgmi.physical_node_id =
+ REG_GET_FIELD(xgmi_lfb_cntl, MMMC_VM_XGMI_LFB_CNTL, PF_LFB_REGION);
+
+ if (adev->gmc.xgmi.physical_node_id > max_physical_node_id)
+ return -EINVAL;
+
+ adev->gmc.xgmi.node_segment_size = seg_size;
+
+ return 0;
+}
+
static u64 mmhub_v4_2_0_get_fb_location(struct amdgpu_device *adev)
{
u64 base;
@@ -131,7 +170,7 @@ static void mmhub_v4_2_0_setup_vm_pt_regs(struct amdgpu_device *adev,
static void mmhub_v4_2_0_mid_init_gart_aperture_regs(struct amdgpu_device *adev,
uint32_t mid_mask)
{
- uint64_t pt_base = amdgpu_gmc_pd_addr(adev->gart.bo);
+ uint64_t pt_base;
int i;
if (adev->gmc.pdb0_bo)
@@ -152,10 +191,10 @@ static void mmhub_v4_2_0_mid_init_gart_aperture_regs(struct amdgpu_device *adev,
WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
regMMVM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32,
- (u32)(adev->gmc.fb_end >> 12));
+ (u32)(adev->gmc.gart_end >> 12));
WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
regMMVM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32,
- (u32)(adev->gmc.fb_end >> 44));
+ (u32)(adev->gmc.gart_end >> 44));
} else {
WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
regMMVM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32,
@@ -190,41 +229,74 @@ static void mmhub_v4_2_0_mid_init_system_aperture_regs(struct amdgpu_device *ade
return;
for_each_inst(i, mid_mask) {
- /* Program the AGP BAR */
- WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
- regMMMC_VM_AGP_BASE_LO32, 0);
- WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
- regMMMC_VM_AGP_BASE_HI32, 0);
- WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
- regMMMC_VM_AGP_BOT_LO32,
- lower_32_bits(adev->gmc.agp_start >> 24));
- WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
- regMMMC_VM_AGP_BOT_HI32,
- upper_32_bits(adev->gmc.agp_start >> 24));
- WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
- regMMMC_VM_AGP_TOP_LO32,
- lower_32_bits(adev->gmc.agp_end >> 24));
- WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
- regMMMC_VM_AGP_TOP_HI32,
- upper_32_bits(adev->gmc.agp_end >> 24));
+ if (adev->gmc.pdb0_bo) {
+ /* Disable agp and system aperture
+ * when vmid0 page table is enabled */
+ WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
+ regMMMC_VM_FB_LOCATION_TOP_LO32, 0);
+ WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
+ regMMMC_VM_FB_LOCATION_TOP_HI32, 0);
+ WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
+ regMMMC_VM_FB_LOCATION_BASE_LO32,
+ 0xFFFFFFFF);
+ WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
+ regMMMC_VM_FB_LOCATION_BASE_HI32, 1);
+ WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
+ regMMMC_VM_AGP_TOP_LO32, 0);
+ WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
+ regMMMC_VM_AGP_TOP_HI32, 0);
+ WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
+ regMMMC_VM_AGP_BOT_LO32,
+ 0xFFFFFFFF);
+ WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
+ regMMMC_VM_AGP_BOT_HI32, 1);
+ WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
+ regMMMC_VM_SYSTEM_APERTURE_LOW_ADDR_LO32,
+ 0xFFFFFFFF);
+ WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
+ regMMMC_VM_SYSTEM_APERTURE_LOW_ADDR_HI32,
+ 0x7F);
+ WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
+ regMMMC_VM_SYSTEM_APERTURE_HIGH_ADDR_LO32, 0);
+ WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
+ regMMMC_VM_SYSTEM_APERTURE_HIGH_ADDR_HI32, 0);
+ } else {
+ /* Program the AGP BAR */
+ WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
+ regMMMC_VM_AGP_BASE_LO32, 0);
+ WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
+ regMMMC_VM_AGP_BASE_HI32, 0);
+ WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
+ regMMMC_VM_AGP_BOT_LO32,
+ lower_32_bits(adev->gmc.agp_start >> 24));
+ WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
+ regMMMC_VM_AGP_BOT_HI32,
+ upper_32_bits(adev->gmc.agp_start >> 24));
+ WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
+ regMMMC_VM_AGP_TOP_LO32,
+ lower_32_bits(adev->gmc.agp_end >> 24));
+ WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
+ regMMMC_VM_AGP_TOP_HI32,
+ upper_32_bits(adev->gmc.agp_end >> 24));
- /* Program the system aperture low logical page number. */
- WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
- regMMMC_VM_SYSTEM_APERTURE_LOW_ADDR_LO32,
- lower_32_bits(min(adev->gmc.fb_start,
- adev->gmc.agp_start) >> 18));
- WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
- regMMMC_VM_SYSTEM_APERTURE_LOW_ADDR_HI32,
- upper_32_bits(min(adev->gmc.fb_start,
- adev->gmc.agp_start) >> 18));
- WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
- regMMMC_VM_SYSTEM_APERTURE_HIGH_ADDR_LO32,
- lower_32_bits(max(adev->gmc.fb_end,
- adev->gmc.agp_end) >> 18));
- WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
- regMMMC_VM_SYSTEM_APERTURE_HIGH_ADDR_HI32,
- upper_32_bits(max(adev->gmc.fb_end,
- adev->gmc.agp_end) >> 18));
+ /* Program the system aperture low logical page number. */
+ WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
+ regMMMC_VM_SYSTEM_APERTURE_LOW_ADDR_LO32,
+ lower_32_bits(min(adev->gmc.fb_start,
+ adev->gmc.agp_start) >> 18));
+ WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
+ regMMMC_VM_SYSTEM_APERTURE_LOW_ADDR_HI32,
+ upper_32_bits(min(adev->gmc.fb_start,
+ adev->gmc.agp_start) >> 18));
+ WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
+ regMMMC_VM_SYSTEM_APERTURE_HIGH_ADDR_LO32,
+ lower_32_bits(max(adev->gmc.fb_end,
+ adev->gmc.agp_end) >> 18));
+ WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
+ regMMMC_VM_SYSTEM_APERTURE_HIGH_ADDR_HI32,
+ upper_32_bits(max(adev->gmc.fb_end,
+ adev->gmc.agp_end) >> 18));
+ }
/* Set default page address. */
value = amdgpu_gmc_vram_mc2pa(adev, adev->mem_scratch.gpu_addr);
@@ -252,38 +324,6 @@ static void mmhub_v4_2_0_mid_init_system_aperture_regs(struct amdgpu_device *ade
WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
regMMVM_L2_PROTECTION_FAULT_CNTL2, tmp);
}
-
- /* In the case squeezing vram into GART aperture, we don't use
- * FB aperture and AGP aperture. Disable them.
- */
- if (adev->gmc.pdb0_bo) {
- WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
- regMMMC_VM_FB_LOCATION_TOP_LO32, 0);
- WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
- regMMMC_VM_FB_LOCATION_TOP_HI32, 0);
- WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
- regMMMC_VM_FB_LOCATION_BASE_LO32, 0xFFFFFFFF);
- WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
- regMMMC_VM_FB_LOCATION_BASE_HI32, 1);
- WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
- regMMMC_VM_AGP_TOP_LO32, 0);
- WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
- regMMMC_VM_AGP_TOP_HI32, 0);
- WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
- regMMMC_VM_AGP_BOT_LO32, 0xFFFFFFFF);
- WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
- regMMMC_VM_AGP_BOT_HI32, 1);
- WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
- regMMMC_VM_SYSTEM_APERTURE_LOW_ADDR_LO32,
- 0xFFFFFFFF);
- WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
- regMMMC_VM_SYSTEM_APERTURE_LOW_ADDR_HI32,
- 0x7F);
- WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
- regMMMC_VM_SYSTEM_APERTURE_HIGH_ADDR_LO32, 0);
- WREG32_SOC15(MMHUB, GET_INST(MMHUB, i),
- regMMMC_VM_SYSTEM_APERTURE_HIGH_ADDR_HI32, 0);
- }
}
static void mmhub_v4_2_0_mid_init_tlb_regs(struct amdgpu_device *adev,
@@ -676,7 +716,7 @@ mmhub_v4_2_0_print_l2_protection_fault_status(struct amdgpu_device *adev,
uint32_t status)
{
uint32_t cid, rw;
- const char *mmhub_cid = NULL;
+ const char *mmhub_cid;
cid = REG_GET_FIELD(status,
MMVM_L2_PROTECTION_FAULT_STATUS_LO32, CID);
@@ -686,14 +726,7 @@ mmhub_v4_2_0_print_l2_protection_fault_status(struct amdgpu_device *adev,
dev_err(adev->dev,
"MMVM_L2_PROTECTION_FAULT_STATUS_LO32:0x%08X\n",
status);
- switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
- case IP_VERSION(4, 2, 0):
- mmhub_cid = mmhub_client_ids_v4_2_0[cid][rw];
- break;
- default:
- mmhub_cid = NULL;
- break;
- }
+ mmhub_cid = amdgpu_mmhub_client_name(&adev->mmhub, cid, rw);
dev_err(adev->dev, "\t Faulty UTCL2 client ID: %s (0x%x)\n",
mmhub_cid ? mmhub_cid : "unknown", cid);
dev_err(adev->dev, "\t MORE_FAULTS: 0x%lx\n",
@@ -784,6 +817,10 @@ static void mmhub_v4_2_0_init(struct amdgpu_device *adev)
mid_mask = adev->aid_mask;
mmhub_v4_2_0_mid_init(adev, mid_mask);
+
+ amdgpu_mmhub_init_client_info(&adev->mmhub,
+ mmhub_client_ids_v4_2_0,
+ ARRAY_SIZE(mmhub_client_ids_v4_2_0));
}
static void
@@ -883,6 +920,7 @@ const struct amdgpu_mmhub_funcs mmhub_v4_2_0_funcs = {
.set_fault_enable_default = mmhub_v4_2_0_set_fault_enable_default,
.set_clockgating = mmhub_v4_2_0_set_clockgating,
.get_clockgating = mmhub_v4_2_0_get_clockgating,
+ .get_xgmi_info = mmhub_v4_2_0_get_xgmi_info,
};
static int mmhub_v4_2_0_xcp_resume(void *handle, uint32_t inst_mask)
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
index 9aa988982304..fb7aaf5ae05c 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
@@ -170,7 +170,8 @@ static int psp_v11_0_wait_for_bootloader(struct psp_context *psp)
int retry_loop;
/* For a reset done at the end of S3, only wait for TOS to be unloaded */
- if (adev->in_s3 && !(adev->flags & AMD_IS_APU) && amdgpu_in_reset(adev))
+ if ((adev->in_s4 || adev->in_s3) && !(adev->flags & AMD_IS_APU) &&
+ amdgpu_in_reset(adev))
return psp_v11_wait_for_tos_unload(psp);
for (retry_loop = 0; retry_loop < 20; retry_loop++) {
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v7_1.c b/drivers/gpu/drm/amd/amdgpu/sdma_v7_1.c
index 03bf1f86098f..f20e0fc3fc74 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v7_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v7_1.c
@@ -1129,12 +1129,21 @@ static void sdma_v7_1_vm_set_pte_pde(struct amdgpu_ib *ib,
/* for physically contiguous pages (vram) */
u32 header = SDMA_PKT_COPY_LINEAR_HEADER_OP(SDMA_OP_PTEPDE);
- if (amdgpu_mtype_local)
- header |= SDMA_PKT_PTEPDE_COPY_HEADER_MTYPE(0x3);
- else
- header |= (SDMA_PKT_PTEPDE_COPY_HEADER_MTYPE(0x2) |
- SDMA_PKT_PTEPDE_COPY_HEADER_SNOOP(0x1) |
- SDMA_PKT_PTEPDE_COPY_HEADER_SCOPE(0x3));
+ /* TODO:
+ * When VM_L2_CNTL5.WALKER_FETCH_PDE_MTYPE_ENABLE is enabled, change below MTYPE
+ * to RW for AID A1 and UC for AID A0. NC needs additional GCR flush and need not
+ * be supported. Also, honour amdgpu_mtype_local override. RW would additionally
+ * require setting SCOPE bits in the header.
+ *
+ * header |= (SDMA_PKT_PTEPDE_COPY_HEADER_MTYPE(0x2:RW) |
+ * SDMA_PKT_PTEPDE_COPY_HEADER_SNOOP(0x1) |
+ * SDMA_PKT_PTEPDE_COPY_HEADER_SCOPE(0x3:SYS_SCOPE));
+ */
+
+ /* VM_L2_CNTL5.WALKER_FETCH_PDE_MTYPE_ENABLE is 0 which defaults to UC. So,
+ * use MTYPE_UC (0x3). For ref. MTYPE_RW=0x2 MTYPE_NC=0x0
+ */
+ header |= SDMA_PKT_PTEPDE_COPY_HEADER_MTYPE(0x3) | SDMA_PKT_PTEPDE_COPY_HEADER_SNOOP(0x1);
ib->ptr[ib->length_dw++] = header;
ib->ptr[ib->length_dw++] = lower_32_bits(pe); /* dst addr */
diff --git a/drivers/gpu/drm/amd/amdgpu/soc_v1_0.c b/drivers/gpu/drm/amd/amdgpu/soc_v1_0.c
index 0c7759b82fa6..709b1669b07b 100644
--- a/drivers/gpu/drm/amd/amdgpu/soc_v1_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/soc_v1_0.c
@@ -41,6 +41,44 @@
#define NORMALIZE_XCC_REG_OFFSET(offset) \
(offset & 0xFFFF)
+#define MID1_REG_RANGE_0_LOW 0x40000
+#define MID1_REG_RANGE_0_HIGH 0x80000
+#define NORMALIZE_MID_REG_OFFSET(offset) \
+ (offset & 0x3FFFF)
+
+static const struct amdgpu_video_codecs vcn_5_0_2_video_codecs_encode_vcn0 = {
+ .codec_count = 0,
+ .codec_array = NULL,
+};
+
+static const struct amdgpu_video_codec_info vcn_5_0_2_video_codecs_decode_array_vcn0[] = {
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 186)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 16384, 16384, 0)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 8192, 4352, 0)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_AV1, 8192, 4352, 0)},
+};
+
+static const struct amdgpu_video_codecs vcn_5_0_2_video_codecs_decode_vcn0 = {
+ .codec_count = ARRAY_SIZE(vcn_5_0_2_video_codecs_decode_array_vcn0),
+ .codec_array = vcn_5_0_2_video_codecs_decode_array_vcn0,
+};
+
+static int soc_v1_0_query_video_codecs(struct amdgpu_device *adev, bool encode,
+ const struct amdgpu_video_codecs **codecs)
+{
+ switch (amdgpu_ip_version(adev, UVD_HWIP, 0)) {
+ case IP_VERSION(5, 0, 2):
+ if (encode)
+ *codecs = &vcn_5_0_2_video_codecs_encode_vcn0;
+ else
+ *codecs = &vcn_5_0_2_video_codecs_decode_vcn0;
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
/* Initialized doorbells for amdgpu including multimedia
* KFD can use all the rest in 2M doorbell bar */
static void soc_v1_0_doorbell_index_init(struct amdgpu_device *adev)
@@ -257,6 +295,7 @@ static const struct amdgpu_asic_funcs soc_v1_0_asic_funcs = {
.encode_ext_smn_addressing = &soc_v1_0_encode_ext_smn_addressing,
.reset = soc_v1_0_asic_reset,
.reset_method = &soc_v1_0_asic_reset_method,
+ .query_video_codecs = &soc_v1_0_query_video_codecs,
};
static int soc_v1_0_common_early_init(struct amdgpu_ip_block *ip_block)
@@ -283,7 +322,7 @@ static int soc_v1_0_common_early_init(struct amdgpu_ip_block *ip_block)
case IP_VERSION(12, 1, 0):
adev->cg_flags = AMD_CG_SUPPORT_GFX_CGCG |
AMD_CG_SUPPORT_GFX_CGLS;
- adev->pg_flags = 0;
+ adev->pg_flags = AMD_PG_SUPPORT_VCN_DPG;
adev->external_rev_id = adev->rev_id + 0x50;
break;
default:
@@ -870,3 +909,31 @@ uint32_t soc_v1_0_normalize_xcc_reg_offset(uint32_t reg)
else
return reg;
}
+
+bool soc_v1_0_mid1_reg_range(uint32_t reg)
+{
+ uint32_t normalized_reg = soc_v1_0_normalize_xcc_reg_offset(reg);
+
+ if (soc_v1_0_normalize_xcc_reg_range(normalized_reg))
+ return false;
+
+ if ((reg >= MID1_REG_RANGE_0_LOW) && (reg < MID1_REG_RANGE_0_HIGH))
+ return true;
+ else
+ return false;
+}
+
+uint32_t soc_v1_0_normalize_reg_offset(uint32_t reg)
+{
+ uint32_t normalized_reg = soc_v1_0_normalize_xcc_reg_offset(reg);
+
+ if (soc_v1_0_normalize_xcc_reg_range(normalized_reg))
+ return soc_v1_0_normalize_xcc_reg_offset(reg);
+
+ /* check if the reg offset is inside MID1. */
+ if (soc_v1_0_mid1_reg_range(reg))
+ return NORMALIZE_MID_REG_OFFSET(reg);
+
+ return reg;
+}
+
diff --git a/drivers/gpu/drm/amd/amdgpu/soc_v1_0.h b/drivers/gpu/drm/amd/amdgpu/soc_v1_0.h
index 146996101aa0..16c220fcc4e9 100644
--- a/drivers/gpu/drm/amd/amdgpu/soc_v1_0.h
+++ b/drivers/gpu/drm/amd/amdgpu/soc_v1_0.h
@@ -31,7 +31,9 @@ void soc_v1_0_grbm_select(struct amdgpu_device *adev,
int xcc_id);
int soc_v1_0_init_soc_config(struct amdgpu_device *adev);
bool soc_v1_0_normalize_xcc_reg_range(uint32_t reg);
+bool soc_v1_0_mid1_reg_range(uint32_t reg);
uint32_t soc_v1_0_normalize_xcc_reg_offset(uint32_t reg);
+uint32_t soc_v1_0_normalize_reg_offset(uint32_t reg);
u64 soc_v1_0_encode_ext_smn_addressing(int ext_id);
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v12_0.c b/drivers/gpu/drm/amd/amdgpu/umc_v12_0.c
index 1f80045775f5..db505ab32fa0 100644
--- a/drivers/gpu/drm/amd/amdgpu/umc_v12_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/umc_v12_0.c
@@ -183,50 +183,97 @@ static void umc_v12_0_get_retire_flip_bits(struct amdgpu_device *adev)
if (adev->gmc.gmc_funcs->query_mem_partition_mode)
nps = adev->gmc.gmc_funcs->query_mem_partition_mode(adev);
- /* default setting */
- flip_bits->flip_bits_in_pa[0] = UMC_V12_0_PA_C2_BIT;
- flip_bits->flip_bits_in_pa[1] = UMC_V12_0_PA_C3_BIT;
- flip_bits->flip_bits_in_pa[2] = UMC_V12_0_PA_C4_BIT;
- flip_bits->flip_bits_in_pa[3] = UMC_V12_0_PA_R13_BIT;
- flip_bits->flip_row_bit = 13;
- flip_bits->bit_num = 4;
- flip_bits->r13_in_pa = UMC_V12_0_PA_R13_BIT;
-
- if (nps == AMDGPU_NPS2_PARTITION_MODE) {
+ if (adev->gmc.num_umc == 16) {
+ /* default setting */
+ flip_bits->flip_bits_in_pa[0] = UMC_V12_0_PA_C2_BIT;
+ flip_bits->flip_bits_in_pa[1] = UMC_V12_0_PA_C3_BIT;
+ flip_bits->flip_bits_in_pa[2] = UMC_V12_0_PA_C4_BIT;
+ flip_bits->flip_bits_in_pa[3] = UMC_V12_0_PA_R13_BIT;
+ flip_bits->flip_row_bit = 13;
+ flip_bits->bit_num = 4;
+ flip_bits->r13_in_pa = UMC_V12_0_PA_R13_BIT;
+
+ if (nps == AMDGPU_NPS2_PARTITION_MODE) {
+ flip_bits->flip_bits_in_pa[0] = UMC_V12_0_PA_CH5_BIT;
+ flip_bits->flip_bits_in_pa[1] = UMC_V12_0_PA_C2_BIT;
+ flip_bits->flip_bits_in_pa[2] = UMC_V12_0_PA_B1_BIT;
+ flip_bits->r13_in_pa = UMC_V12_0_PA_R12_BIT;
+ } else if (nps == AMDGPU_NPS4_PARTITION_MODE) {
+ flip_bits->flip_bits_in_pa[0] = UMC_V12_0_PA_CH4_BIT;
+ flip_bits->flip_bits_in_pa[1] = UMC_V12_0_PA_CH5_BIT;
+ flip_bits->flip_bits_in_pa[2] = UMC_V12_0_PA_B0_BIT;
+ flip_bits->r13_in_pa = UMC_V12_0_PA_R11_BIT;
+ }
+
+ switch (vram_type) {
+ case AMDGPU_VRAM_TYPE_HBM:
+ /* other nps modes are taken as nps1 */
+ if (nps == AMDGPU_NPS2_PARTITION_MODE)
+ flip_bits->flip_bits_in_pa[3] = UMC_V12_0_PA_R12_BIT;
+ else if (nps == AMDGPU_NPS4_PARTITION_MODE)
+ flip_bits->flip_bits_in_pa[3] = UMC_V12_0_PA_R11_BIT;
+
+ break;
+ case AMDGPU_VRAM_TYPE_HBM3E:
+ flip_bits->flip_bits_in_pa[3] = UMC_V12_0_PA_R12_BIT;
+ flip_bits->flip_row_bit = 12;
+
+ if (nps == AMDGPU_NPS2_PARTITION_MODE)
+ flip_bits->flip_bits_in_pa[3] = UMC_V12_0_PA_R11_BIT;
+ else if (nps == AMDGPU_NPS4_PARTITION_MODE)
+ flip_bits->flip_bits_in_pa[3] = UMC_V12_0_PA_R10_BIT;
+
+ break;
+ default:
+ dev_warn(adev->dev,
+ "Unknown HBM type, set RAS retire flip bits to the value in NPS1 mode.\n");
+ break;
+ }
+ } else if (adev->gmc.num_umc == 8) {
+ /* default setting */
flip_bits->flip_bits_in_pa[0] = UMC_V12_0_PA_CH5_BIT;
flip_bits->flip_bits_in_pa[1] = UMC_V12_0_PA_C2_BIT;
flip_bits->flip_bits_in_pa[2] = UMC_V12_0_PA_B1_BIT;
+ flip_bits->flip_bits_in_pa[3] = UMC_V12_0_PA_R11_BIT;
+ flip_bits->flip_row_bit = 12;
+ flip_bits->bit_num = 4;
flip_bits->r13_in_pa = UMC_V12_0_PA_R12_BIT;
- } else if (nps == AMDGPU_NPS4_PARTITION_MODE) {
- flip_bits->flip_bits_in_pa[0] = UMC_V12_0_PA_CH4_BIT;
- flip_bits->flip_bits_in_pa[1] = UMC_V12_0_PA_CH5_BIT;
- flip_bits->flip_bits_in_pa[2] = UMC_V12_0_PA_B0_BIT;
- flip_bits->r13_in_pa = UMC_V12_0_PA_R11_BIT;
- }
- switch (vram_type) {
- case AMDGPU_VRAM_TYPE_HBM:
- /* other nps modes are taken as nps1 */
- if (nps == AMDGPU_NPS2_PARTITION_MODE)
+ if (nps == AMDGPU_NPS2_PARTITION_MODE) {
+ flip_bits->flip_bits_in_pa[0] = UMC_V12_0_PA_CH4_BIT;
+ flip_bits->flip_bits_in_pa[1] = UMC_V12_0_PA_CH5_BIT;
+ flip_bits->flip_bits_in_pa[2] = UMC_V12_0_PA_B0_BIT;
+ flip_bits->r13_in_pa = UMC_V12_0_PA_R11_BIT;
+ }
+
+ switch (vram_type) {
+ case AMDGPU_VRAM_TYPE_HBM:
flip_bits->flip_bits_in_pa[3] = UMC_V12_0_PA_R12_BIT;
- else if (nps == AMDGPU_NPS4_PARTITION_MODE)
- flip_bits->flip_bits_in_pa[3] = UMC_V12_0_PA_R11_BIT;
- break;
- case AMDGPU_VRAM_TYPE_HBM3E:
- flip_bits->flip_bits_in_pa[3] = UMC_V12_0_PA_R12_BIT;
- flip_bits->flip_row_bit = 12;
+ /* other nps modes are taken as nps1 */
+ if (nps == AMDGPU_NPS2_PARTITION_MODE)
+ flip_bits->flip_bits_in_pa[3] = UMC_V12_0_PA_R11_BIT;
- if (nps == AMDGPU_NPS2_PARTITION_MODE)
+ break;
+ case AMDGPU_VRAM_TYPE_HBM3E:
flip_bits->flip_bits_in_pa[3] = UMC_V12_0_PA_R11_BIT;
- else if (nps == AMDGPU_NPS4_PARTITION_MODE)
- flip_bits->flip_bits_in_pa[3] = UMC_V12_0_PA_R10_BIT;
+ flip_bits->flip_row_bit = 12;
- break;
- default:
+ if (nps == AMDGPU_NPS2_PARTITION_MODE)
+ flip_bits->flip_bits_in_pa[3] = UMC_V12_0_PA_R10_BIT;
+
+ break;
+ default:
+ dev_warn(adev->dev,
+ "Unknown HBM type, set RAS retire flip bits to the value in NPS1 mode.\n");
+ break;
+ }
+ } else {
dev_warn(adev->dev,
- "Unknown HBM type, set RAS retire flip bits to the value in NPS1 mode.\n");
- break;
+ "Unsupported UMC number(%d), failed to set RAS flip bits.\n",
+ adev->gmc.num_umc);
+
+ return;
}
adev->umc.retire_unit = 0x1 << flip_bits->bit_num;
diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c
index 73ce3d211ed6..8a9ba2276275 100644
--- a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c
+++ b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c
@@ -93,6 +93,11 @@ static void uvd_v4_2_ring_set_wptr(struct amdgpu_ring *ring)
static int uvd_v4_2_early_init(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;
+
+ /* UVD doesn't work without DPM, it needs DPM to ungate it. */
+ if (!amdgpu_dpm)
+ return -ENOENT;
+
adev->uvd.num_uvd_inst = 1;
uvd_v4_2_set_ring_funcs(adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
index e78526a4e521..ff3013b97abd 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
@@ -134,6 +134,21 @@ static int vcn_v4_0_3_early_init(struct amdgpu_ip_block *ip_block)
return 0;
}
+static bool vcn_v4_0_3_is_psp_fw_reset_supported(struct amdgpu_device *adev)
+{
+ uint32_t fw_ver = adev->psp.sos.fw_version;
+ uint32_t pgm = (fw_ver >> 8) & 0xFF;
+
+ /*
+ * FWDEV-159155: PSP SOS FW must be >= 0x0036015f for program 0x01
+ * before enabling VCN per-queue reset.
+ */
+ if (pgm == 1)
+ return fw_ver >= 0x0036015f;
+
+ return true;
+}
+
static int vcn_v4_0_3_late_init(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;
@@ -141,7 +156,9 @@ static int vcn_v4_0_3_late_init(struct amdgpu_ip_block *ip_block)
adev->vcn.supported_reset =
amdgpu_get_soft_full_reset_mask(&adev->vcn.inst[0].ring_enc[0]);
- if (amdgpu_dpm_reset_vcn_is_supported(adev) && !amdgpu_sriov_vf(adev))
+ if (amdgpu_dpm_reset_vcn_is_supported(adev) &&
+ vcn_v4_0_3_is_psp_fw_reset_supported(adev) &&
+ !amdgpu_sriov_vf(adev))
adev->vcn.supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
return 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_2.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_2.c
new file mode 100644
index 000000000000..c3d3cc023058
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_2.c
@@ -0,0 +1,1219 @@
+/*
+ * Copyright 2025-2026 Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include <linux/firmware.h>
+#include "amdgpu.h"
+#include "amdgpu_vcn.h"
+#include "amdgpu_pm.h"
+#include "soc15.h"
+#include "soc15d.h"
+#include "soc15_hw_ip.h"
+#include "vcn_v2_0.h"
+#include "vcn_v4_0_3.h"
+
+#include "vcn/vcn_5_0_0_offset.h"
+#include "vcn/vcn_5_0_0_sh_mask.h"
+#include "ivsrcid/vcn/irqsrcs_vcn_5_0.h"
+#include "vcn_v5_0_0.h"
+#include "vcn_v5_0_1.h"
+#include "vcn_v5_0_2.h"
+
+#include <drm/drm_drv.h>
+
+static void vcn_v5_0_2_set_unified_ring_funcs(struct amdgpu_device *adev);
+static void vcn_v5_0_2_set_irq_funcs(struct amdgpu_device *adev);
+static int vcn_v5_0_2_set_pg_state(struct amdgpu_vcn_inst *vinst,
+ enum amd_powergating_state state);
+static void vcn_v5_0_2_unified_ring_set_wptr(struct amdgpu_ring *ring);
+
+/**
+ * vcn_v5_0_2_early_init - set function pointers and load microcode
+ *
+ * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
+ *
+ * Set ring and irq function pointers
+ * Load microcode from filesystem
+ */
+static int vcn_v5_0_2_early_init(struct amdgpu_ip_block *ip_block)
+{
+ struct amdgpu_device *adev = ip_block->adev;
+ int i, r;
+
+ for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
+ /* re-use enc ring as unified ring */
+ adev->vcn.inst[i].num_enc_rings = 1;
+
+ vcn_v5_0_2_set_unified_ring_funcs(adev);
+ vcn_v5_0_2_set_irq_funcs(adev);
+
+ for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+ adev->vcn.inst[i].set_pg_state = vcn_v5_0_2_set_pg_state;
+
+ r = amdgpu_vcn_early_init(adev, i);
+ if (r)
+ return r;
+ }
+
+ return 0;
+}
+
+static void vcn_v5_0_2_fw_shared_init(struct amdgpu_device *adev, int inst_idx)
+{
+ struct amdgpu_vcn5_fw_shared *fw_shared;
+
+ fw_shared = adev->vcn.inst[inst_idx].fw_shared.cpu_addr;
+
+ if (fw_shared->sq.is_enabled)
+ return;
+ fw_shared->present_flag_0 =
+ cpu_to_le32(AMDGPU_FW_SHARED_FLAG_0_UNIFIED_QUEUE);
+ fw_shared->sq.is_enabled = 1;
+
+ if (amdgpu_vcnfw_log)
+ amdgpu_vcn_fwlog_init(&adev->vcn.inst[inst_idx]);
+}
+
+/**
+ * vcn_v5_0_2_sw_init - sw init for VCN block
+ *
+ * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
+ *
+ * Load firmware and sw initialization
+ */
+static int vcn_v5_0_2_sw_init(struct amdgpu_ip_block *ip_block)
+{
+ struct amdgpu_device *adev = ip_block->adev;
+ struct amdgpu_ring *ring;
+ int i, r, vcn_inst;
+
+ /* VCN UNIFIED TRAP */
+ r = amdgpu_irq_add_id(adev, SOC_V1_0_IH_CLIENTID_VCN,
+ VCN_5_0__SRCID__UVD_ENC_GENERAL_PURPOSE, &adev->vcn.inst->irq);
+ if (r)
+ return r;
+
+ for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+ vcn_inst = GET_INST(VCN, i);
+
+ r = amdgpu_vcn_sw_init(adev, i);
+ if (r)
+ return r;
+
+ amdgpu_vcn_setup_ucode(adev, i);
+
+ r = amdgpu_vcn_resume(adev, i);
+ if (r)
+ return r;
+
+ ring = &adev->vcn.inst[i].ring_enc[0];
+ ring->use_doorbell = true;
+
+ ring->doorbell_index =
+ (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 32 * vcn_inst;
+
+ ring->vm_hub = AMDGPU_MMHUB0(adev->vcn.inst[i].aid_id);
+ sprintf(ring->name, "vcn_unified_%d", adev->vcn.inst[i].aid_id);
+
+ r = amdgpu_ring_init(adev, ring, 512, &adev->vcn.inst[i].irq, 0,
+ AMDGPU_RING_PRIO_DEFAULT, &adev->vcn.inst[i].sched_score);
+ if (r)
+ return r;
+
+ vcn_v5_0_2_fw_shared_init(adev, i);
+ }
+
+ /* TODO: Add queue reset mask when FW fully supports it */
+ adev->vcn.supported_reset =
+ amdgpu_get_soft_full_reset_mask(&adev->vcn.inst[0].ring_enc[0]);
+
+ return amdgpu_vcn_sysfs_reset_mask_init(adev);
+}
+
+/**
+ * vcn_v5_0_2_sw_fini - sw fini for VCN block
+ *
+ * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
+ *
+ * VCN suspend and free up sw allocation
+ */
+static int vcn_v5_0_2_sw_fini(struct amdgpu_ip_block *ip_block)
+{
+ struct amdgpu_device *adev = ip_block->adev;
+ int i, r, idx;
+
+ if (drm_dev_enter(adev_to_drm(adev), &idx)) {
+ for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+ struct amdgpu_vcn5_fw_shared *fw_shared;
+
+ fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
+ fw_shared->present_flag_0 = 0;
+ fw_shared->sq.is_enabled = 0;
+ }
+
+ drm_dev_exit(idx);
+ }
+
+ for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+ r = amdgpu_vcn_suspend(adev, i);
+ if (r)
+ return r;
+ }
+
+ for (i = 0; i < adev->vcn.num_vcn_inst; i++)
+ amdgpu_vcn_sw_fini(adev, i);
+
+ amdgpu_vcn_sysfs_reset_mask_fini(adev);
+
+ kfree(adev->vcn.ip_dump); //TODO check
+
+ return 0;
+}
+
+/**
+ * vcn_v5_0_2_hw_init - start and test VCN block
+ *
+ * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
+ *
+ * Initialize the hardware, boot up the VCPU and do some testing
+ */
+static int vcn_v5_0_2_hw_init(struct amdgpu_ip_block *ip_block)
+{
+ struct amdgpu_device *adev = ip_block->adev;
+ struct amdgpu_ring *ring;
+ int i, r, vcn_inst;
+ uint32_t tmp;
+
+ if (RREG32_SOC15(VCN, GET_INST(VCN, 0), regVCN_RRMT_CNTL) & 0x200)
+ adev->vcn.caps |= AMDGPU_VCN_CAPS(RRMT_ENABLED);
+ for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+ vcn_inst = GET_INST(VCN, i);
+ ring = &adev->vcn.inst[i].ring_enc[0];
+
+ /* Remove Video Tiles antihang mechanism */
+ tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_POWER_STATUS);
+ tmp &= (~UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
+ WREG32_SOC15(VCN, vcn_inst, regUVD_POWER_STATUS, tmp);
+
+ if (ring->use_doorbell)
+ adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell,
+ ((adev->doorbell_index.vcn.vcn_ring0_1 << 1) +
+ 11 * vcn_inst),
+ adev->vcn.inst[i].aid_id);
+
+ /* Re-init fw_shared, if required */
+ vcn_v5_0_2_fw_shared_init(adev, i);
+
+ r = amdgpu_ring_test_helper(ring);
+ if (r)
+ return r;
+ }
+
+ return 0;
+}
+
+/**
+ * vcn_v5_0_2_hw_fini - stop the hardware block
+ *
+ * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
+ *
+ * Stop the VCN block, mark ring as not ready any more
+ */
+static int vcn_v5_0_2_hw_fini(struct amdgpu_ip_block *ip_block)
+{
+ struct amdgpu_device *adev = ip_block->adev;
+ int i;
+
+ for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+ struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
+
+ cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
+ if (vinst->cur_state != AMD_PG_STATE_GATE)
+ vinst->set_pg_state(vinst, AMD_PG_STATE_GATE);
+ }
+
+ return 0;
+}
+
+/**
+ * vcn_v5_0_2_suspend - suspend VCN block
+ *
+ * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
+ *
+ * HW fini and suspend VCN block
+ */
+static int vcn_v5_0_2_suspend(struct amdgpu_ip_block *ip_block)
+{
+ struct amdgpu_device *adev = ip_block->adev;
+ int r, i;
+
+ r = vcn_v5_0_2_hw_fini(ip_block);
+ if (r)
+ return r;
+
+ for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+ r = amdgpu_vcn_suspend(ip_block->adev, i);
+ if (r)
+ return r;
+ }
+
+ return r;
+}
+
+/**
+ * vcn_v5_0_2_resume - resume VCN block
+ *
+ * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
+ *
+ * Resume firmware and hw init VCN block
+ */
+static int vcn_v5_0_2_resume(struct amdgpu_ip_block *ip_block)
+{
+ struct amdgpu_device *adev = ip_block->adev;
+ int r, i;
+
+ for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+ struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
+
+ if (amdgpu_in_reset(adev))
+ vinst->cur_state = AMD_PG_STATE_GATE;
+
+ r = amdgpu_vcn_resume(ip_block->adev, i);
+ if (r)
+ return r;
+ }
+
+ r = vcn_v5_0_2_hw_init(ip_block);
+
+ return r;
+}
+
+/**
+ * vcn_v5_0_2_mc_resume - memory controller programming
+ *
+ * @vinst: VCN instance
+ *
+ * Let the VCN memory controller know it's offsets
+ */
+static void vcn_v5_0_2_mc_resume(struct amdgpu_vcn_inst *vinst)
+{
+ struct amdgpu_device *adev = vinst->adev;
+ int inst = vinst->inst;
+ uint32_t offset, size, vcn_inst;
+ const struct common_firmware_header *hdr;
+
+ hdr = (const struct common_firmware_header *)adev->vcn.inst[inst].fw->data;
+ size = AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8);
+
+ vcn_inst = GET_INST(VCN, inst);
+ /* cache window 0: fw */
+ if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
+ WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW,
+ (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + inst].tmr_mc_addr_lo));
+ WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH,
+ (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + inst].tmr_mc_addr_hi));
+ WREG32_SOC15(VCN, vcn_inst, regUVD_VCPU_CACHE_OFFSET0, 0);
+ offset = 0;
+ } else {
+ WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW,
+ lower_32_bits(adev->vcn.inst[inst].gpu_addr));
+ WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH,
+ upper_32_bits(adev->vcn.inst[inst].gpu_addr));
+ offset = size;
+ WREG32_SOC15(VCN, vcn_inst, regUVD_VCPU_CACHE_OFFSET0,
+ AMDGPU_UVD_FIRMWARE_OFFSET >> 3);
+ }
+ WREG32_SOC15(VCN, vcn_inst, regUVD_VCPU_CACHE_SIZE0, size);
+
+ /* cache window 1: stack */
+ WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW,
+ lower_32_bits(adev->vcn.inst[inst].gpu_addr + offset));
+ WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH,
+ upper_32_bits(adev->vcn.inst[inst].gpu_addr + offset));
+ WREG32_SOC15(VCN, vcn_inst, regUVD_VCPU_CACHE_OFFSET1, 0);
+ WREG32_SOC15(VCN, vcn_inst, regUVD_VCPU_CACHE_SIZE1, AMDGPU_VCN_STACK_SIZE);
+
+ /* cache window 2: context */
+ WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_VCPU_CACHE2_64BIT_BAR_LOW,
+ lower_32_bits(adev->vcn.inst[inst].gpu_addr + offset + AMDGPU_VCN_STACK_SIZE));
+ WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_VCPU_CACHE2_64BIT_BAR_HIGH,
+ upper_32_bits(adev->vcn.inst[inst].gpu_addr + offset + AMDGPU_VCN_STACK_SIZE));
+ WREG32_SOC15(VCN, vcn_inst, regUVD_VCPU_CACHE_OFFSET2, 0);
+ WREG32_SOC15(VCN, vcn_inst, regUVD_VCPU_CACHE_SIZE2, AMDGPU_VCN_CONTEXT_SIZE);
+
+ /* non-cache window */
+ WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_VCPU_NC0_64BIT_BAR_LOW,
+ lower_32_bits(adev->vcn.inst[inst].fw_shared.gpu_addr));
+ WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_VCPU_NC0_64BIT_BAR_HIGH,
+ upper_32_bits(adev->vcn.inst[inst].fw_shared.gpu_addr));
+ WREG32_SOC15(VCN, vcn_inst, regUVD_VCPU_NONCACHE_OFFSET0, 0);
+ WREG32_SOC15(VCN, vcn_inst, regUVD_VCPU_NONCACHE_SIZE0,
+ AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn5_fw_shared)));
+}
+
+/**
+ * vcn_v5_0_2_mc_resume_dpg_mode - memory controller programming for dpg mode
+ *
+ * @vinst: VCN instance
+ * @indirect: indirectly write sram
+ *
+ * Let the VCN memory controller know it's offsets with dpg mode
+ */
+static void vcn_v5_0_2_mc_resume_dpg_mode(struct amdgpu_vcn_inst *vinst,
+ bool indirect)
+{
+ struct amdgpu_device *adev = vinst->adev;
+ int inst_idx = vinst->inst;
+ uint32_t offset, size;
+ const struct common_firmware_header *hdr;
+
+ hdr = (const struct common_firmware_header *)adev->vcn.inst[inst_idx].fw->data;
+ size = AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8);
+
+ /* cache window 0: fw */
+ if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
+ if (!indirect) {
+ WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW),
+ (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN +
+ inst_idx].tmr_mc_addr_lo), 0, indirect);
+ WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH),
+ (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN +
+ inst_idx].tmr_mc_addr_hi), 0, indirect);
+ WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_VCPU_CACHE_OFFSET0), 0, 0, indirect);
+ } else {
+ WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW), 0, 0, indirect);
+ WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH), 0, 0, indirect);
+ WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_VCPU_CACHE_OFFSET0), 0, 0, indirect);
+ }
+ offset = 0;
+ } else {
+ WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW),
+ lower_32_bits(adev->vcn.inst[inst_idx].gpu_addr), 0, indirect);
+ WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH),
+ upper_32_bits(adev->vcn.inst[inst_idx].gpu_addr), 0, indirect);
+ offset = size;
+ WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_VCPU_CACHE_OFFSET0),
+ AMDGPU_UVD_FIRMWARE_OFFSET >> 3, 0, indirect);
+ }
+
+ if (!indirect)
+ WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_VCPU_CACHE_SIZE0), size, 0, indirect);
+ else
+ WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_VCPU_CACHE_SIZE0), 0, 0, indirect);
+
+ /* cache window 1: stack */
+ if (!indirect) {
+ WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW),
+ lower_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset), 0, indirect);
+ WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH),
+ upper_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset), 0, indirect);
+ WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_VCPU_CACHE_OFFSET1), 0, 0, indirect);
+ } else {
+ WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW), 0, 0, indirect);
+ WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH), 0, 0, indirect);
+ WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_VCPU_CACHE_OFFSET1), 0, 0, indirect);
+ }
+ WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_VCPU_CACHE_SIZE1), AMDGPU_VCN_STACK_SIZE, 0, indirect);
+
+ /* cache window 2: context */
+ WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_LMI_VCPU_CACHE2_64BIT_BAR_LOW),
+ lower_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset +
+ AMDGPU_VCN_STACK_SIZE), 0, indirect);
+ WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_LMI_VCPU_CACHE2_64BIT_BAR_HIGH),
+ upper_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset +
+ AMDGPU_VCN_STACK_SIZE), 0, indirect);
+ WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_VCPU_CACHE_OFFSET2), 0, 0, indirect);
+ WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_VCPU_CACHE_SIZE2), AMDGPU_VCN_CONTEXT_SIZE, 0, indirect);
+
+ /* non-cache window */
+ WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_LMI_VCPU_NC0_64BIT_BAR_LOW),
+ lower_32_bits(adev->vcn.inst[inst_idx].fw_shared.gpu_addr), 0, indirect);
+ WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_LMI_VCPU_NC0_64BIT_BAR_HIGH),
+ upper_32_bits(adev->vcn.inst[inst_idx].fw_shared.gpu_addr), 0, indirect);
+ WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_VCPU_NONCACHE_OFFSET0), 0, 0, indirect);
+ WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_VCPU_NONCACHE_SIZE0),
+ AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn5_fw_shared)), 0, indirect);
+
+ /* VCN global tiling registers */
+ WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_GFX10_ADDR_CONFIG), adev->gfx.config.gb_addr_config, 0, indirect);
+}
+
+/**
+ * vcn_v5_0_2_disable_clock_gating - disable VCN clock gating
+ *
+ * @vinst: VCN instance
+ *
+ * Disable clock gating for VCN block
+ */
+static void vcn_v5_0_2_disable_clock_gating(struct amdgpu_vcn_inst *vinst)
+{
+}
+
+/**
+ * vcn_v5_0_2_enable_clock_gating - enable VCN clock gating
+ *
+ * @vinst: VCN instance
+ *
+ * Enable clock gating for VCN block
+ */
+static void vcn_v5_0_2_enable_clock_gating(struct amdgpu_vcn_inst *vinst)
+{
+}
+
+/**
+ * vcn_v5_0_2_pause_dpg_mode - VCN pause with dpg mode
+ *
+ * @vinst: VCN instance
+ * @new_state: pause state
+ *
+ * Pause dpg mode for VCN block
+ */
+static int vcn_v5_0_2_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
+ struct dpg_pause_state *new_state)
+{
+ struct amdgpu_device *adev = vinst->adev;
+ uint32_t reg_data = 0;
+ int vcn_inst;
+
+ vcn_inst = GET_INST(VCN, vinst->inst);
+
+ /* pause/unpause if state is changed */
+ if (vinst->pause_state.fw_based != new_state->fw_based) {
+ DRM_DEV_DEBUG(adev->dev, "dpg pause state changed %d -> %d %s\n",
+ vinst->pause_state.fw_based, new_state->fw_based,
+ new_state->fw_based ? "VCN_DPG_STATE__PAUSE" : "VCN_DPG_STATE__UNPAUSE");
+ reg_data = RREG32_SOC15(VCN, vcn_inst, regUVD_DPG_PAUSE) &
+ (~UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK);
+
+ if (new_state->fw_based == VCN_DPG_STATE__PAUSE) {
+ /* pause DPG */
+ reg_data |= UVD_DPG_PAUSE__NJ_PAUSE_DPG_REQ_MASK;
+ WREG32_SOC15(VCN, vcn_inst, regUVD_DPG_PAUSE, reg_data);
+
+ /* wait for ACK */
+ SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_DPG_PAUSE,
+ UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK,
+ UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK);
+ } else {
+ /* unpause DPG, no need to wait */
+ reg_data &= ~UVD_DPG_PAUSE__NJ_PAUSE_DPG_REQ_MASK;
+ WREG32_SOC15(VCN, vcn_inst, regUVD_DPG_PAUSE, reg_data);
+ }
+ vinst->pause_state.fw_based = new_state->fw_based;
+ }
+
+ return 0;
+}
+
+/**
+ * vcn_v5_0_2_start_dpg_mode - VCN start with dpg mode
+ *
+ * @vinst: VCN instance
+ * @indirect: indirectly write sram
+ *
+ * Start VCN block with dpg mode
+ */
+static int vcn_v5_0_2_start_dpg_mode(struct amdgpu_vcn_inst *vinst,
+ bool indirect)
+{
+ struct amdgpu_device *adev = vinst->adev;
+ int inst_idx = vinst->inst;
+ struct amdgpu_vcn5_fw_shared *fw_shared =
+ adev->vcn.inst[inst_idx].fw_shared.cpu_addr;
+ struct amdgpu_ring *ring;
+ struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__PAUSE};
+ int vcn_inst, ret;
+ uint32_t tmp;
+
+ vcn_inst = GET_INST(VCN, inst_idx);
+
+ /* disable register anti-hang mechanism */
+ WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_POWER_STATUS), 1,
+ ~UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
+
+ /* enable dynamic power gating mode */
+ tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_POWER_STATUS);
+ tmp |= UVD_POWER_STATUS__UVD_PG_MODE_MASK;
+ WREG32_SOC15(VCN, vcn_inst, regUVD_POWER_STATUS, tmp);
+
+ if (indirect) {
+ adev->vcn.inst[inst_idx].dpg_sram_curr_addr =
+ (uint32_t *)adev->vcn.inst[inst_idx].dpg_sram_cpu_addr;
+ /* Use dummy register 0xDEADBEEF passing AID selection to PSP FW */
+ WREG32_SOC24_DPG_MODE(inst_idx, 0xDEADBEEF,
+ adev->vcn.inst[inst_idx].aid_id, 0, true);
+ }
+
+ /* enable VCPU clock */
+ tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT);
+ tmp |= UVD_VCPU_CNTL__CLK_EN_MASK | UVD_VCPU_CNTL__BLK_RST_MASK;
+ WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_VCPU_CNTL), tmp, 0, indirect);
+
+ /* disable master interrupt */
+ WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_MASTINT_EN), 0, 0, indirect);
+
+ /* setup regUVD_LMI_CTRL */
+ tmp = (UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK |
+ UVD_LMI_CTRL__REQ_MODE_MASK |
+ UVD_LMI_CTRL__CRC_RESET_MASK |
+ UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
+ UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
+ UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK |
+ (8 << UVD_LMI_CTRL__WRITE_CLEAN_TIMER__SHIFT) |
+ 0x00100000L);
+ WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_LMI_CTRL), tmp, 0, indirect);
+
+ vcn_v5_0_2_mc_resume_dpg_mode(vinst, indirect);
+
+ tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT);
+ tmp |= UVD_VCPU_CNTL__CLK_EN_MASK;
+ WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_VCPU_CNTL), tmp, 0, indirect);
+
+ /* enable LMI MC and UMC channels */
+ tmp = 0x1f << UVD_LMI_CTRL2__RE_OFLD_MIF_WR_REQ_NUM__SHIFT;
+ WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_LMI_CTRL2), tmp, 0, indirect);
+
+ /* enable master interrupt */
+ WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_MASTINT_EN),
+ UVD_MASTINT_EN__VCPU_EN_MASK, 0, indirect);
+
+ if (indirect) {
+ ret = amdgpu_vcn_psp_update_sram(adev, inst_idx, AMDGPU_UCODE_ID_VCN0_RAM);
+ if (ret) {
+ dev_err(adev->dev, "vcn sram load failed %d\n", ret);
+ return ret;
+ }
+ }
+
+ /* resetting ring, fw should not check RB ring */
+ fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET;
+
+ /* Pause dpg */
+ vcn_v5_0_2_pause_dpg_mode(vinst, &state);
+
+ ring = &adev->vcn.inst[inst_idx].ring_enc[0];
+
+ WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_LO, lower_32_bits(ring->gpu_addr));
+ WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
+ WREG32_SOC15(VCN, vcn_inst, regUVD_RB_SIZE, ring->ring_size / sizeof(uint32_t));
+
+ tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE);
+ tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK);
+ WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp);
+ WREG32_SOC15(VCN, vcn_inst, regUVD_RB_RPTR, 0);
+ WREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR, 0);
+
+ ring->wptr = RREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR);
+
+ tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE);
+ tmp |= VCN_RB_ENABLE__RB1_EN_MASK;
+ WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp);
+ /* resetting done, fw can check RB ring */
+ fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF);
+
+ WREG32_SOC15(VCN, vcn_inst, regVCN_RB1_DB_CTRL,
+ ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT |
+ VCN_RB1_DB_CTRL__EN_MASK);
+ /* Read DB_CTRL to flush the write DB_CTRL command. */
+ RREG32_SOC15(VCN, vcn_inst, regVCN_RB1_DB_CTRL);
+
+ return 0;
+}
+
+/**
+ * vcn_v5_0_2_start - VCN start
+ *
+ * @vinst: VCN instance
+ *
+ * Start VCN block
+ */
+static int vcn_v5_0_2_start(struct amdgpu_vcn_inst *vinst)
+{
+ struct amdgpu_device *adev = vinst->adev;
+ int i = vinst->inst;
+ struct amdgpu_vcn5_fw_shared *fw_shared;
+ struct amdgpu_ring *ring;
+ uint32_t tmp;
+ int j, k, r, vcn_inst;
+
+ fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
+
+ if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
+ return vcn_v5_0_2_start_dpg_mode(vinst, adev->vcn.inst[i].indirect_sram);
+
+ vcn_inst = GET_INST(VCN, i);
+
+ /* set VCN status busy */
+ tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_STATUS) | UVD_STATUS__UVD_BUSY;
+ WREG32_SOC15(VCN, vcn_inst, regUVD_STATUS, tmp);
+
+ /* enable VCPU clock */
+ WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL),
+ UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK);
+
+ /* disable master interrupt */
+ WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_MASTINT_EN), 0,
+ ~UVD_MASTINT_EN__VCPU_EN_MASK);
+
+ /* enable LMI MC and UMC channels */
+ WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_LMI_CTRL2), 0,
+ ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);
+
+ tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET);
+ tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
+ tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
+ WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp);
+
+ /* setup regUVD_LMI_CTRL */
+ tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL);
+ WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL, tmp |
+ UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK |
+ UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
+ UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
+ UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);
+
+ vcn_v5_0_2_mc_resume(vinst);
+
+ /* VCN global tiling registers */
+ WREG32_SOC15(VCN, vcn_inst, regUVD_GFX10_ADDR_CONFIG,
+ adev->gfx.config.gb_addr_config);
+
+ /* unblock VCPU register access */
+ WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_RB_ARB_CTRL), 0,
+ ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
+
+ /* release VCPU reset to boot */
+ WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0,
+ ~UVD_VCPU_CNTL__BLK_RST_MASK);
+
+ for (j = 0; j < 10; ++j) {
+ uint32_t status;
+
+ for (k = 0; k < 100; ++k) {
+ status = RREG32_SOC15(VCN, vcn_inst, regUVD_STATUS);
+ if (status & 2)
+ break;
+ mdelay(1000);
+ if (amdgpu_emu_mode == 1)
+ msleep(520);
+ }
+
+ if (amdgpu_emu_mode == 1) {
+ r = -1;
+ if (status & 2) {
+ r = 0;
+ break;
+ }
+ } else {
+ r = 0;
+ if (status & 2)
+ break;
+
+ dev_err(adev->dev,
+ "VCN[%d] is not responding, trying to reset the VCPU!!!\n", i);
+ WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL),
+ UVD_VCPU_CNTL__BLK_RST_MASK,
+ ~UVD_VCPU_CNTL__BLK_RST_MASK);
+ mdelay(10);
+ WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0,
+ ~UVD_VCPU_CNTL__BLK_RST_MASK);
+
+ mdelay(10);
+ r = -1;
+ }
+ }
+
+ if (r) {
+ dev_err(adev->dev, "VCN[%d] is not responding, giving up!!!\n", i);
+ return r;
+ }
+
+ /* enable master interrupt */
+ WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_MASTINT_EN),
+ UVD_MASTINT_EN__VCPU_EN_MASK,
+ ~UVD_MASTINT_EN__VCPU_EN_MASK);
+
+ /* clear the busy bit of VCN_STATUS */
+ WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_STATUS), 0,
+ ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT));
+
+ ring = &adev->vcn.inst[i].ring_enc[0];
+
+ WREG32_SOC15(VCN, vcn_inst, regVCN_RB1_DB_CTRL,
+ ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT |
+ VCN_RB1_DB_CTRL__EN_MASK);
+
+ /* Read DB_CTRL to flush the write DB_CTRL command. */
+ RREG32_SOC15(VCN, vcn_inst, regVCN_RB1_DB_CTRL);
+
+ WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_LO, ring->gpu_addr);
+ WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
+ WREG32_SOC15(VCN, vcn_inst, regUVD_RB_SIZE, ring->ring_size / 4);
+
+ tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE);
+ tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK);
+ WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp);
+ fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET;
+ WREG32_SOC15(VCN, vcn_inst, regUVD_RB_RPTR, 0);
+ WREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR, 0);
+
+ tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_RB_RPTR);
+ WREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR, tmp);
+ ring->wptr = RREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR);
+
+ tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE);
+ tmp |= VCN_RB_ENABLE__RB1_EN_MASK;
+ WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp);
+ fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF);
+
+ return 0;
+}
+
+/**
+ * vcn_v5_0_2_stop_dpg_mode - VCN stop with dpg mode
+ *
+ * @vinst: VCN instance
+ *
+ * Stop VCN block with dpg mode
+ */
+static void vcn_v5_0_2_stop_dpg_mode(struct amdgpu_vcn_inst *vinst)
+{
+ struct amdgpu_device *adev = vinst->adev;
+ int inst_idx = vinst->inst;
+ uint32_t tmp;
+ int vcn_inst;
+ struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__UNPAUSE};
+
+ vcn_inst = GET_INST(VCN, inst_idx);
+
+ /* Unpause dpg */
+ vcn_v5_0_2_pause_dpg_mode(vinst, &state);
+
+ /* Wait for power status to be 1 */
+ SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_POWER_STATUS, 1,
+ UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
+
+ /* wait for read ptr to be equal to write ptr */
+ tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR);
+ SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_RB_RPTR, tmp, 0xFFFFFFFF);
+
+ /* disable dynamic power gating mode */
+ WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_POWER_STATUS), 0,
+ ~UVD_POWER_STATUS__UVD_PG_MODE_MASK);
+}
+
+/**
+ * vcn_v5_0_2_stop - VCN stop
+ *
+ * @vinst: VCN instance
+ *
+ * Stop VCN block
+ */
+static int vcn_v5_0_2_stop(struct amdgpu_vcn_inst *vinst)
+{
+ struct amdgpu_device *adev = vinst->adev;
+ int i = vinst->inst;
+ struct amdgpu_vcn5_fw_shared *fw_shared;
+ uint32_t tmp;
+ int r = 0, vcn_inst;
+
+ vcn_inst = GET_INST(VCN, i);
+
+ fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
+ fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;
+
+ if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
+ vcn_v5_0_2_stop_dpg_mode(vinst);
+ return 0;
+ }
+
+ /* wait for vcn idle */
+ r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_STATUS, UVD_STATUS__IDLE, 0x7);
+ if (r)
+ return r;
+
+ tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK |
+ UVD_LMI_STATUS__READ_CLEAN_MASK |
+ UVD_LMI_STATUS__WRITE_CLEAN_MASK |
+ UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK;
+ r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_LMI_STATUS, tmp, tmp);
+ if (r)
+ return r;
+
+ /* disable LMI UMC channel */
+ tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL2);
+ tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK;
+ WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL2, tmp);
+ tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK |
+ UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK;
+ r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_LMI_STATUS, tmp, tmp);
+ if (r)
+ return r;
+
+ /* block VCPU register access */
+ WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_RB_ARB_CTRL),
+ UVD_RB_ARB_CTRL__VCPU_DIS_MASK,
+ ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
+
+ /* reset VCPU */
+ WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL),
+ UVD_VCPU_CNTL__BLK_RST_MASK,
+ ~UVD_VCPU_CNTL__BLK_RST_MASK);
+
+ /* disable VCPU clock */
+ WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0,
+ ~(UVD_VCPU_CNTL__CLK_EN_MASK));
+
+ /* apply soft reset */
+ tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET);
+ tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
+ WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp);
+ tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET);
+ tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
+ WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp);
+
+ /* clear status */
+ WREG32_SOC15(VCN, vcn_inst, regUVD_STATUS, 0);
+
+ return 0;
+}
+
+/**
+ * vcn_v5_0_2_unified_ring_get_rptr - get unified read pointer
+ *
+ * @ring: amdgpu_ring pointer
+ *
+ * Returns the current hardware unified read pointer
+ */
+static uint64_t vcn_v5_0_2_unified_ring_get_rptr(struct amdgpu_ring *ring)
+{
+ struct amdgpu_device *adev = ring->adev;
+
+ if (ring != &adev->vcn.inst[ring->me].ring_enc[0])
+ DRM_ERROR("wrong ring id is identified in %s", __func__);
+
+ return RREG32_SOC15(VCN, GET_INST(VCN, ring->me), regUVD_RB_RPTR);
+}
+
+/**
+ * vcn_v5_0_2_unified_ring_get_wptr - get unified write pointer
+ *
+ * @ring: amdgpu_ring pointer
+ *
+ * Returns the current hardware unified write pointer
+ */
+static uint64_t vcn_v5_0_2_unified_ring_get_wptr(struct amdgpu_ring *ring)
+{
+ struct amdgpu_device *adev = ring->adev;
+
+ if (ring != &adev->vcn.inst[ring->me].ring_enc[0])
+ DRM_ERROR("wrong ring id is identified in %s", __func__);
+
+ if (ring->use_doorbell)
+ return *ring->wptr_cpu_addr;
+ else
+ return RREG32_SOC15(VCN, GET_INST(VCN, ring->me), regUVD_RB_WPTR);
+}
+
+/**
+ * vcn_v5_0_2_unified_ring_set_wptr - set enc write pointer
+ *
+ * @ring: amdgpu_ring pointer
+ *
+ * Commits the enc write pointer to the hardware
+ */
+static void vcn_v5_0_2_unified_ring_set_wptr(struct amdgpu_ring *ring)
+{
+ struct amdgpu_device *adev = ring->adev;
+
+ if (ring != &adev->vcn.inst[ring->me].ring_enc[0])
+ DRM_ERROR("wrong ring id is identified in %s", __func__);
+
+ if (ring->use_doorbell) {
+ *ring->wptr_cpu_addr = lower_32_bits(ring->wptr);
+ WDOORBELL32(ring->doorbell_index, lower_32_bits(ring->wptr));
+ } else {
+ WREG32_SOC15(VCN, GET_INST(VCN, ring->me), regUVD_RB_WPTR,
+ lower_32_bits(ring->wptr));
+ }
+}
+
+static const struct amdgpu_ring_funcs vcn_v5_0_2_unified_ring_vm_funcs = {
+ .type = AMDGPU_RING_TYPE_VCN_ENC,
+ .align_mask = 0x3f,
+ .nop = VCN_ENC_CMD_NO_OP,
+ .get_rptr = vcn_v5_0_2_unified_ring_get_rptr,
+ .get_wptr = vcn_v5_0_2_unified_ring_get_wptr,
+ .set_wptr = vcn_v5_0_2_unified_ring_set_wptr,
+ .emit_frame_size = SOC15_FLUSH_GPU_TLB_NUM_WREG * 3 +
+ SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 4 +
+ 4 + /* vcn_v2_0_enc_ring_emit_vm_flush */
+ 5 +
+ 5 + /* vcn_v2_0_enc_ring_emit_fence x2 vm fence */
+ 1, /* vcn_v2_0_enc_ring_insert_end */
+ .emit_ib_size = 5, /* vcn_v2_0_enc_ring_emit_ib */
+ .emit_ib = vcn_v2_0_enc_ring_emit_ib,
+ .emit_fence = vcn_v2_0_enc_ring_emit_fence,
+ .emit_vm_flush = vcn_v4_0_3_enc_ring_emit_vm_flush,
+ .emit_hdp_flush = vcn_v4_0_3_ring_emit_hdp_flush,
+ .test_ring = amdgpu_vcn_enc_ring_test_ring,
+ .test_ib = amdgpu_vcn_unified_ring_test_ib,
+ .insert_nop = amdgpu_ring_insert_nop,
+ .insert_end = vcn_v2_0_enc_ring_insert_end,
+ .pad_ib = amdgpu_ring_generic_pad_ib,
+ .begin_use = amdgpu_vcn_ring_begin_use,
+ .end_use = amdgpu_vcn_ring_end_use,
+ .emit_wreg = vcn_v4_0_3_enc_ring_emit_wreg,
+ .emit_reg_wait = vcn_v4_0_3_enc_ring_emit_reg_wait,
+ .emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
+};
+
+/**
+ * vcn_v5_0_2_set_unified_ring_funcs - set unified ring functions
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Set unified ring functions
+ */
+static void vcn_v5_0_2_set_unified_ring_funcs(struct amdgpu_device *adev)
+{
+ int i, vcn_inst;
+
+ for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+ adev->vcn.inst[i].ring_enc[0].funcs = &vcn_v5_0_2_unified_ring_vm_funcs;
+ adev->vcn.inst[i].ring_enc[0].me = i;
+ vcn_inst = GET_INST(VCN, i);
+ adev->vcn.inst[i].aid_id = vcn_inst / adev->vcn.num_inst_per_aid;
+ }
+}
+
+/**
+ * vcn_v5_0_2_is_idle - check VCN block is idle
+ *
+ * @ip_block: Pointer to the amdgpu_ip_block structure
+ *
+ * Check whether VCN block is idle
+ */
+static bool vcn_v5_0_2_is_idle(struct amdgpu_ip_block *ip_block)
+{
+ struct amdgpu_device *adev = ip_block->adev;
+ int i, ret = 1;
+
+ for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
+ ret &= (RREG32_SOC15(VCN, GET_INST(VCN, i), regUVD_STATUS) == UVD_STATUS__IDLE);
+
+ return ret;
+}
+
+/**
+ * vcn_v5_0_2_wait_for_idle - wait for VCN block idle
+ *
+ * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
+ *
+ * Wait for VCN block idle
+ */
+static int vcn_v5_0_2_wait_for_idle(struct amdgpu_ip_block *ip_block)
+{
+ struct amdgpu_device *adev = ip_block->adev;
+ int i, ret = 0;
+
+ for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+ ret = SOC15_WAIT_ON_RREG(VCN, GET_INST(VCN, i), regUVD_STATUS, UVD_STATUS__IDLE,
+ UVD_STATUS__IDLE);
+ if (ret)
+ return ret;
+ }
+
+ return ret;
+}
+
+/**
+ * vcn_v5_0_2_set_clockgating_state - set VCN block clockgating state
+ *
+ * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
+ * @state: clock gating state
+ *
+ * Set VCN block clockgating state
+ */
+static int vcn_v5_0_2_set_clockgating_state(struct amdgpu_ip_block *ip_block,
+ enum amd_clockgating_state state)
+{
+ struct amdgpu_device *adev = ip_block->adev;
+ bool enable = state == AMD_CG_STATE_GATE;
+ int i;
+
+ for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+ struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
+
+ if (enable) {
+ if (RREG32_SOC15(VCN, GET_INST(VCN, i), regUVD_STATUS) != UVD_STATUS__IDLE)
+ return -EBUSY;
+ vcn_v5_0_2_enable_clock_gating(vinst);
+ } else {
+ vcn_v5_0_2_disable_clock_gating(vinst);
+ }
+ }
+
+ return 0;
+}
+
+static int vcn_v5_0_2_set_pg_state(struct amdgpu_vcn_inst *vinst,
+ enum amd_powergating_state state)
+{
+ int ret = 0;
+
+ if (state == vinst->cur_state)
+ return 0;
+
+ if (state == AMD_PG_STATE_GATE)
+ ret = vcn_v5_0_2_stop(vinst);
+ else
+ ret = vcn_v5_0_2_start(vinst);
+
+ if (!ret)
+ vinst->cur_state = state;
+
+ return ret;
+}
+
+/**
+ * vcn_v5_0_2_process_interrupt - process VCN block interrupt
+ *
+ * @adev: amdgpu_device pointer
+ * @source: interrupt sources
+ * @entry: interrupt entry from clients and sources
+ *
+ * Process VCN block interrupt
+ */
+static int vcn_v5_0_2_process_interrupt(struct amdgpu_device *adev, struct amdgpu_irq_src *source,
+ struct amdgpu_iv_entry *entry)
+{
+ uint32_t i, inst;
+
+ i = node_id_to_phys_map[entry->node_id];
+
+ DRM_DEV_DEBUG(adev->dev, "IH: VCN TRAP\n");
+
+ for (inst = 0; inst < adev->vcn.num_vcn_inst; ++inst)
+ if (adev->vcn.inst[inst].aid_id == i)
+ break;
+
+ if (inst >= adev->vcn.num_vcn_inst) {
+ dev_WARN_ONCE(adev->dev, 1,
+ "Interrupt received for unknown VCN instance %d",
+ entry->node_id);
+ return 0;
+ }
+
+ switch (entry->src_id) {
+ case VCN_5_0__SRCID__UVD_ENC_GENERAL_PURPOSE:
+ amdgpu_fence_process(&adev->vcn.inst[inst].ring_enc[0]);
+ break;
+ default:
+ DRM_DEV_ERROR(adev->dev, "Unhandled interrupt: %d %d\n",
+ entry->src_id, entry->src_data[0]);
+ break;
+ }
+
+ return 0;
+}
+
+static const struct amdgpu_irq_src_funcs vcn_v5_0_2_irq_funcs = {
+ .process = vcn_v5_0_2_process_interrupt,
+};
+
+/**
+ * vcn_v5_0_2_set_irq_funcs - set VCN block interrupt irq functions
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Set VCN block interrupt irq functions
+ */
+static void vcn_v5_0_2_set_irq_funcs(struct amdgpu_device *adev)
+{
+ int i;
+
+ for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
+ adev->vcn.inst->irq.num_types++;
+ adev->vcn.inst->irq.funcs = &vcn_v5_0_2_irq_funcs;
+}
+
+static const struct amd_ip_funcs vcn_v5_0_2_ip_funcs = {
+ .name = "vcn_v5_0_2",
+ .early_init = vcn_v5_0_2_early_init,
+ .late_init = NULL,
+ .sw_init = vcn_v5_0_2_sw_init,
+ .sw_fini = vcn_v5_0_2_sw_fini,
+ .hw_init = vcn_v5_0_2_hw_init,
+ .hw_fini = vcn_v5_0_2_hw_fini,
+ .suspend = vcn_v5_0_2_suspend,
+ .resume = vcn_v5_0_2_resume,
+ .is_idle = vcn_v5_0_2_is_idle,
+ .wait_for_idle = vcn_v5_0_2_wait_for_idle,
+ .check_soft_reset = NULL,
+ .pre_soft_reset = NULL,
+ .soft_reset = NULL,
+ .post_soft_reset = NULL,
+ .set_clockgating_state = vcn_v5_0_2_set_clockgating_state,
+ .set_powergating_state = vcn_set_powergating_state,
+};
+
+const struct amdgpu_ip_block_version vcn_v5_0_2_ip_block = {
+ .type = AMD_IP_BLOCK_TYPE_VCN,
+ .major = 5,
+ .minor = 0,
+ .rev = 2,
+ .funcs = &vcn_v5_0_2_ip_funcs,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_2.h b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_2.h
new file mode 100644
index 000000000000..461bdda91eb6
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_2.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2025-2026 Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __VCN_v5_0_2_H__
+#define __VCN_v5_0_2_H__
+
+extern const struct amdgpu_ip_block_version vcn_v5_0_2_ip_block;
+
+#endif /* __VCN_v5_0_2_H__ */
diff --git a/drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c b/drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c
index 73acbe0b7c21..b799c70f5742 100644
--- a/drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c
+++ b/drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c
@@ -97,11 +97,11 @@ static void cik_event_interrupt_wq(struct kfd_node *dev,
return;
if (ihre->source_id == CIK_INTSRC_CP_END_OF_PIPE)
- kfd_signal_event_interrupt(pasid, context_id, 28);
+ kfd_signal_event_interrupt(pasid, context_id, 28, true);
else if (ihre->source_id == CIK_INTSRC_SDMA_TRAP)
- kfd_signal_event_interrupt(pasid, context_id, 28);
+ kfd_signal_event_interrupt(pasid, context_id, 28, true);
else if (ihre->source_id == CIK_INTSRC_SQ_INTERRUPT_MSG)
- kfd_signal_event_interrupt(pasid, context_id & 0xff, 8);
+ kfd_signal_event_interrupt(pasid, context_id & 0xff, 8, true);
else if (ihre->source_id == CIK_INTSRC_CP_BAD_OPCODE)
kfd_signal_hw_exception_event(pasid);
else if (ihre->source_id == CIK_INTSRC_GFX_PAGE_INV_FAULT ||
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
index 09dabb3b3297..462a32abf720 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
@@ -3170,11 +3170,11 @@ static int kfd_ioctl_create_process(struct file *filep, struct kfd_process *p, v
struct kfd_process *process;
int ret;
- /* Each FD owns only one kfd_process */
- if (p->context_id != KFD_CONTEXT_ID_PRIMARY)
+ if (!filep->private_data || !p)
return -EINVAL;
- if (!filep->private_data || !p)
+ /* Each FD owns only one kfd_process */
+ if (p->context_id != KFD_CONTEXT_ID_PRIMARY)
return -EINVAL;
mutex_lock(&kfd_processes_mutex);
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_events.c b/drivers/gpu/drm/amd/amdkfd/kfd_events.c
index bafc7b699dcc..44150a71ffd5 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_events.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_events.c
@@ -142,6 +142,7 @@ static struct kfd_event *lookup_event_by_id(struct kfd_process *p, uint32_t id)
* @p: Pointer to struct kfd_process
* @id: ID to look up
* @bits: Number of valid bits in @id
+ * @signal_mailbox_updated: flag indicates if FW updates signal mailbox entry
*
* Finds the first signaled event with a matching partial ID. If no
* matching signaled event is found, returns NULL. In that case the
@@ -155,7 +156,8 @@ static struct kfd_event *lookup_event_by_id(struct kfd_process *p, uint32_t id)
* driver.
*/
static struct kfd_event *lookup_signaled_event_by_partial_id(
- struct kfd_process *p, uint32_t id, uint32_t bits)
+ struct kfd_process *p, uint32_t id, uint32_t bits,
+ bool signal_mailbox_updated)
{
struct kfd_event *ev;
@@ -166,7 +168,8 @@ static struct kfd_event *lookup_signaled_event_by_partial_id(
* and we only need a single lookup.
*/
if (bits > 31 || (1U << bits) >= KFD_SIGNAL_EVENT_LIMIT) {
- if (page_slots(p->signal_page)[id] == UNSIGNALED_EVENT_SLOT)
+ if (signal_mailbox_updated &&
+ page_slots(p->signal_page)[id] == UNSIGNALED_EVENT_SLOT)
return NULL;
return idr_find(&p->event_idr, id);
@@ -724,7 +727,7 @@ static void set_event_from_interrupt(struct kfd_process *p,
}
void kfd_signal_event_interrupt(u32 pasid, uint32_t partial_id,
- uint32_t valid_id_bits)
+ uint32_t valid_id_bits, bool signal_mailbox_updated)
{
struct kfd_event *ev = NULL;
@@ -742,7 +745,8 @@ void kfd_signal_event_interrupt(u32 pasid, uint32_t partial_id,
if (valid_id_bits)
ev = lookup_signaled_event_by_partial_id(p, partial_id,
- valid_id_bits);
+ valid_id_bits,
+ signal_mailbox_updated);
if (ev) {
set_event_from_interrupt(p, ev);
} else if (p->signal_page) {
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_events.h b/drivers/gpu/drm/amd/amdkfd/kfd_events.h
index 52ccfd397c2b..1dc21c13833b 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_events.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_events.h
@@ -85,6 +85,7 @@ struct kfd_event {
#define KFD_EVENT_TYPE_MEMORY 8
extern void kfd_signal_event_interrupt(u32 pasid, uint32_t partial_id,
- uint32_t valid_id_bits);
+ uint32_t valid_id_bits,
+ bool signal_mailbox_updated);
#endif
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v10.c b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v10.c
index 3e1ad8974797..19406ab92c5b 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v10.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v10.c
@@ -211,7 +211,7 @@ static void event_interrupt_wq_v10(struct kfd_node *dev,
client_id == SOC15_IH_CLIENTID_SE2SH ||
client_id == SOC15_IH_CLIENTID_SE3SH) {
if (source_id == SOC15_INTSRC_CP_END_OF_PIPE)
- kfd_signal_event_interrupt(pasid, context_id0, 32);
+ kfd_signal_event_interrupt(pasid, context_id0, 32, true);
else if (source_id == SOC15_INTSRC_SQ_INTERRUPT_MSG) {
encoding = REG_GET_FIELD(context_id1,
SQ_INTERRUPT_WORD_WAVE_CTXID1, ENCODING);
@@ -324,7 +324,7 @@ static void event_interrupt_wq_v10(struct kfd_node *dev,
default:
break;
}
- kfd_signal_event_interrupt(pasid, context_id0 & 0x7fffff, 23);
+ kfd_signal_event_interrupt(pasid, context_id0 & 0x7fffff, 23, true);
} else if (source_id == SOC15_INTSRC_CP_BAD_OPCODE &&
KFD_DBG_EC_TYPE_IS_PACKET(KFD_DEBUG_CP_BAD_OP_ECODE(context_id0))) {
kfd_set_dbg_ev_from_interrupt(dev, pasid,
@@ -344,7 +344,7 @@ static void event_interrupt_wq_v10(struct kfd_node *dev,
client_id == SOC15_IH_CLIENTID_SDMA6 ||
client_id == SOC15_IH_CLIENTID_SDMA7) {
if (source_id == SOC15_INTSRC_SDMA_TRAP) {
- kfd_signal_event_interrupt(pasid, context_id0 & 0xfffffff, 28);
+ kfd_signal_event_interrupt(pasid, context_id0 & 0xfffffff, 28, true);
}
} else if (client_id == SOC15_IH_CLIENTID_VMC ||
client_id == SOC15_IH_CLIENTID_VMC1 ||
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v11.c b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v11.c
index 2788a52714d1..12d81abed748 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v11.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v11.c
@@ -353,7 +353,7 @@ static void event_interrupt_wq_v11(struct kfd_node *dev,
/* CP */
if (source_id == SOC15_INTSRC_CP_END_OF_PIPE)
- kfd_signal_event_interrupt(pasid, context_id0, 32);
+ kfd_signal_event_interrupt(pasid, context_id0, 32, true);
else if (source_id == SOC15_INTSRC_CP_BAD_OPCODE &&
KFD_DBG_EC_TYPE_IS_PACKET(KFD_CTXID0_CP_BAD_OP_ECODE(context_id0))) {
u32 doorbell_id = KFD_CTXID0_DOORBELL_ID(context_id0);
@@ -366,7 +366,7 @@ static void event_interrupt_wq_v11(struct kfd_node *dev,
/* SDMA */
else if (source_id == SOC21_INTSRC_SDMA_TRAP)
- kfd_signal_event_interrupt(pasid, context_id0 & 0xfffffff, 28);
+ kfd_signal_event_interrupt(pasid, context_id0 & 0xfffffff, 28, true);
else if (source_id == SOC21_INTSRC_SDMA_ECC) {
event_interrupt_poison_consumption_v11(dev, pasid, source_id);
return;
@@ -404,7 +404,7 @@ static void event_interrupt_wq_v11(struct kfd_node *dev,
default:
break;
}
- kfd_signal_event_interrupt(pasid, context_id0 & 0xffffff, 24);
+ kfd_signal_event_interrupt(pasid, context_id0 & 0xffffff, 24, true);
}
} else if (KFD_IRQ_IS_FENCE(client_id, source_id)) {
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v12_1.c b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v12_1.c
index 230e57dbcec5..0da7e1db55c9 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v12_1.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v12_1.c
@@ -28,6 +28,7 @@
#include "ivsrcid/vmc/irqsrcs_vmc_1_0.h"
#include "kfd_smi_events.h"
#include "kfd_debug.h"
+#include "amdgpu_ras_mgr.h"
/*
* GFX12.1 SQ Interrupts
@@ -143,9 +144,10 @@ enum SQ_INTERRUPT_ERROR_TYPE {
#define KFD_CTXID0_DOORBELL_ID(ctxid0) ((ctxid0) & \
KFD_CTXID0_DOORBELL_ID_MASK)
-static void print_sq_intr_info_auto(uint32_t context_id0, uint32_t context_id1)
+static void print_sq_intr_info_auto(struct kfd_node *dev, uint32_t context_id0, uint32_t context_id1)
{
- pr_debug_ratelimited(
+ dev_dbg_ratelimited(
+ dev->adev->dev,
"sq_intr: auto, ttrace %d, wlt %d, ttrace_buf0_full %d, ttrace_buf1_full %d ttrace_utc_err %d\n",
REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_AUTO_CTXID0, THREAD_TRACE),
REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_AUTO_CTXID0, WLT),
@@ -154,9 +156,10 @@ static void print_sq_intr_info_auto(uint32_t context_id0, uint32_t context_id1)
REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_AUTO_CTXID0, THREAD_TRACE_UTC_ERROR));
}
-static void print_sq_intr_info_inst(uint32_t context_id0, uint32_t context_id1)
+static void print_sq_intr_info_inst(struct kfd_node *dev, uint32_t context_id0, uint32_t context_id1)
{
- pr_debug_ratelimited(
+ dev_dbg_ratelimited(
+ dev->adev->dev,
"sq_intr: inst, data 0x%08x, sh %d, priv %d, wave_id %d, simd_id %d, wgp_id %d\n",
REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_WAVE_CTXID0, DATA),
REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_WAVE_CTXID0, SA_ID),
@@ -166,9 +169,10 @@ static void print_sq_intr_info_inst(uint32_t context_id0, uint32_t context_id1)
REG_GET_FIELD(context_id1, SQ_INTERRUPT_WORD_WAVE_CTXID1, WGP_ID));
}
-static void print_sq_intr_info_error(uint32_t context_id0, uint32_t context_id1)
+static void print_sq_intr_info_error(struct kfd_node *dev, uint32_t context_id0, uint32_t context_id1)
{
- pr_debug_ratelimited(
+ dev_warn_ratelimited(
+ dev->adev->dev,
"sq_intr: error, detail 0x%08x, type %d, sh %d, priv %d, wave_id %d, simd_id %d, wgp_id %d\n",
REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_ERROR_CTXID0, DETAIL),
REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_ERROR_CTXID0, TYPE),
@@ -185,6 +189,7 @@ static void event_interrupt_poison_consumption_v12_1(struct kfd_node *node,
enum amdgpu_ras_block block = 0;
int ret = -EINVAL;
uint32_t reset = 0;
+ u64 event_id = RAS_EVENT_INVALID_ID;
struct kfd_process *p = kfd_lookup_process_by_pasid(pasid, NULL);
if (!p)
@@ -220,7 +225,15 @@ static void event_interrupt_poison_consumption_v12_1(struct kfd_node *node,
* resetting queue passes, do page retirement without gpu reset
* resetting queue fails, fallback to gpu reset solution
*/
- amdgpu_amdkfd_ras_poison_consumption_handler(node->adev, block, reset);
+ if (amdgpu_uniras_enabled(node->adev))
+ event_id = amdgpu_ras_mgr_gen_ras_event_seqno(node->adev,
+ RAS_SEQNO_TYPE_POISON_CONSUMPTION);
+
+ RAS_EVENT_LOG(node->adev, event_id,
+ "poison is consumed by source %d, kick off gpu reset flow\n", source_id);
+
+ amdgpu_amdkfd_ras_pasid_poison_consumption_handler(node->adev,
+ block, pasid, NULL, NULL, reset);
}
static bool event_interrupt_isr_v12_1(struct kfd_node *node,
@@ -236,7 +249,8 @@ static bool event_interrupt_isr_v12_1(struct kfd_node *node,
vmid = SOC15_VMID_FROM_IH_ENTRY(ih_ring_entry);
if (!kfd_irq_is_from_node(node, node_id, vmid)) {
- pr_debug("Interrupt not for Node, node_id: %d, vmid: %d\n", node_id, vmid);
+ dev_dbg_ratelimited(node->adev->dev,
+ "Interrupt not for Node, node_id: %d, vmid: %d\n", node_id, vmid);
return false;
}
@@ -256,9 +270,9 @@ static bool event_interrupt_isr_v12_1(struct kfd_node *node,
(context_id0 & AMDGPU_FENCE_MES_QUEUE_FLAG))
return false;
- pr_debug("client id 0x%x, source id %d, vmid %d, pasid 0x%x. raw data:\n",
+ dev_dbg(node->adev->dev, "client id 0x%x, source id %d, vmid %d, pasid 0x%x. raw data:\n",
client_id, source_id, vmid, pasid);
- pr_debug("%8X, %8X, %8X, %8X, %8X, %8X, %8X, %8X.\n",
+ dev_dbg(node->adev->dev, "%8X, %8X, %8X, %8X, %8X, %8X, %8X, %8X.\n",
data[0], data[1], data[2], data[3],
data[4], data[5], data[6], data[7]);
@@ -326,7 +340,7 @@ static void event_interrupt_wq_v12_1(struct kfd_node *node,
/* CP */
if (source_id == SOC15_INTSRC_CP_END_OF_PIPE)
- kfd_signal_event_interrupt(pasid, context_id0, 32);
+ kfd_signal_event_interrupt(pasid, context_id0, 32, false);
else if (source_id == SOC15_INTSRC_CP_BAD_OPCODE &&
KFD_DBG_EC_TYPE_IS_PACKET(KFD_CTXID0_CP_BAD_OP_ECODE(context_id0))) {
u32 doorbell_id = KFD_CTXID0_DOORBELL_ID(context_id0);
@@ -339,7 +353,7 @@ static void event_interrupt_wq_v12_1(struct kfd_node *node,
/* SDMA */
else if (source_id == SOC21_INTSRC_SDMA_TRAP)
- kfd_signal_event_interrupt(pasid, context_id0 & 0xfffffff, 28);
+ kfd_signal_event_interrupt(pasid, context_id0 & 0xfffffff, 28, true);
else if (source_id == SOC21_INTSRC_SDMA_ECC) {
event_interrupt_poison_consumption_v12_1(node, pasid, source_id);
return;
@@ -351,10 +365,10 @@ static void event_interrupt_wq_v12_1(struct kfd_node *node,
SQ_INTERRUPT_WORD_WAVE_CTXID1, ENCODING);
switch (sq_int_enc) {
case SQ_INTERRUPT_WORD_ENCODING_AUTO:
- print_sq_intr_info_auto(context_id0, context_id1);
+ print_sq_intr_info_auto(node, context_id0, context_id1);
break;
case SQ_INTERRUPT_WORD_ENCODING_INST:
- print_sq_intr_info_inst(context_id0, context_id1);
+ print_sq_intr_info_inst(node, context_id0, context_id1);
sq_int_priv = REG_GET_FIELD(context_id0,
SQ_INTERRUPT_WORD_WAVE_CTXID0, PRIV);
if (sq_int_priv && (kfd_set_dbg_ev_from_interrupt(node, pasid,
@@ -364,7 +378,7 @@ static void event_interrupt_wq_v12_1(struct kfd_node *node,
return;
break;
case SQ_INTERRUPT_WORD_ENCODING_ERROR:
- print_sq_intr_info_error(context_id0, context_id1);
+ print_sq_intr_info_error(node, context_id0, context_id1);
sq_int_errtype = REG_GET_FIELD(context_id0,
SQ_INTERRUPT_WORD_ERROR_CTXID0, TYPE);
if (sq_int_errtype != SQ_INTERRUPT_ERROR_TYPE_ILLEGAL_INST &&
@@ -377,7 +391,7 @@ static void event_interrupt_wq_v12_1(struct kfd_node *node,
default:
break;
}
- kfd_signal_event_interrupt(pasid, context_id0 & 0xffffff, 24);
+ kfd_signal_event_interrupt(pasid, context_id0 & 0xffffff, 24, true);
}
} else if (KFD_IRQ_IS_FENCE(client_id, source_id)) {
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c
index d76fb61869c7..1688d8e595f2 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c
@@ -379,7 +379,7 @@ static void event_interrupt_wq_v9(struct kfd_node *dev,
client_id == SOC15_IH_CLIENTID_SE2SH ||
client_id == SOC15_IH_CLIENTID_SE3SH) {
if (source_id == SOC15_INTSRC_CP_END_OF_PIPE)
- kfd_signal_event_interrupt(pasid, context_id0, 32);
+ kfd_signal_event_interrupt(pasid, context_id0, 32, true);
else if (source_id == SOC15_INTSRC_SQ_INTERRUPT_MSG) {
sq_int_data = KFD_CONTEXT_ID_GET_SQ_INT_DATA(context_id0, context_id1);
encoding = REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_WAVE_CTXID, ENCODING);
@@ -513,7 +513,7 @@ static void event_interrupt_wq_v9(struct kfd_node *dev,
default:
break;
}
- kfd_signal_event_interrupt(pasid, sq_int_data, 24);
+ kfd_signal_event_interrupt(pasid, sq_int_data, 24, true);
} else if (source_id == SOC15_INTSRC_CP_BAD_OPCODE &&
KFD_DBG_EC_TYPE_IS_PACKET(KFD_DEBUG_CP_BAD_OP_ECODE(context_id0))) {
kfd_set_dbg_ev_from_interrupt(dev, pasid,
@@ -530,7 +530,7 @@ static void event_interrupt_wq_v9(struct kfd_node *dev,
client_id == SOC15_IH_CLIENTID_SDMA6 ||
client_id == SOC15_IH_CLIENTID_SDMA7) {
if (source_id == SOC15_INTSRC_SDMA_TRAP) {
- kfd_signal_event_interrupt(pasid, context_id0 & 0xfffffff, 28);
+ kfd_signal_event_interrupt(pasid, context_id0 & 0xfffffff, 28, true);
} else if (source_id == SOC15_INTSRC_SDMA_ECC) {
event_interrupt_poison_consumption_v9(dev, pasid, client_id);
return;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
index 10bc81ce37cb..964efa325908 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
@@ -136,7 +136,7 @@ svm_migrate_copy_memory_gart(struct amdgpu_device *adev, dma_addr_t *sys,
u64 size;
int r;
- entity = &adev->mman.move_entity;
+ entity = &adev->mman.move_entities[0];
mutex_lock(&entity->lock);
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c
index 979ae94ac966..e8f97de9d6e4 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c
@@ -42,9 +42,16 @@ static uint64_t mqd_stride_v9(struct mqd_manager *mm,
struct queue_properties *q)
{
if (mm->dev->kfd->cwsr_enabled &&
- q->type == KFD_QUEUE_TYPE_COMPUTE)
- return ALIGN(q->ctl_stack_size, PAGE_SIZE) +
- ALIGN(sizeof(struct v9_mqd), PAGE_SIZE);
+ q->type == KFD_QUEUE_TYPE_COMPUTE) {
+
+ /* On gfxv9, the MQD resides in the first 4K page,
+ * followed by the control stack. Align both to
+ * AMDGPU_GPU_PAGE_SIZE to maintain the required 4K boundary.
+ */
+
+ return ALIGN(ALIGN(q->ctl_stack_size, AMDGPU_GPU_PAGE_SIZE) +
+ ALIGN(sizeof(struct v9_mqd), AMDGPU_GPU_PAGE_SIZE), PAGE_SIZE);
+ }
return mm->mqd_size;
}
@@ -150,8 +157,8 @@ static struct kfd_mem_obj *allocate_mqd(struct mqd_manager *mm,
if (!mqd_mem_obj)
return NULL;
retval = amdgpu_amdkfd_alloc_kernel_mem(node->adev,
- (ALIGN(q->ctl_stack_size, PAGE_SIZE) +
- ALIGN(sizeof(struct v9_mqd), PAGE_SIZE)) *
+ (ALIGN(ALIGN(q->ctl_stack_size, AMDGPU_GPU_PAGE_SIZE) +
+ ALIGN(sizeof(struct v9_mqd), AMDGPU_GPU_PAGE_SIZE), PAGE_SIZE)) *
NUM_XCC(node->xcc_mask),
mqd_on_vram(node->adev) ? AMDGPU_GEM_DOMAIN_VRAM :
AMDGPU_GEM_DOMAIN_GTT,
@@ -359,7 +366,7 @@ static int get_wave_state(struct mqd_manager *mm, void *mqd,
struct kfd_context_save_area_header header;
/* Control stack is located one page after MQD. */
- void *mqd_ctl_stack = (void *)((uintptr_t)mqd + PAGE_SIZE);
+ void *mqd_ctl_stack = (void *)((uintptr_t)mqd + AMDGPU_GPU_PAGE_SIZE);
m = get_mqd(mqd);
@@ -399,7 +406,7 @@ static void checkpoint_mqd(struct mqd_manager *mm, void *mqd, void *mqd_dst, voi
{
struct v9_mqd *m;
/* Control stack is located one page after MQD. */
- void *ctl_stack = (void *)((uintptr_t)mqd + PAGE_SIZE);
+ void *ctl_stack = (void *)((uintptr_t)mqd + AMDGPU_GPU_PAGE_SIZE);
m = get_mqd(mqd);
@@ -445,7 +452,7 @@ static void restore_mqd(struct mqd_manager *mm, void **mqd,
*gart_addr = addr;
/* Control stack is located one page after MQD. */
- ctl_stack = (void *)((uintptr_t)*mqd + PAGE_SIZE);
+ ctl_stack = (void *)((uintptr_t)*mqd + AMDGPU_GPU_PAGE_SIZE);
memcpy(ctl_stack, ctl_stack_src, ctl_stack_size);
m->cp_hqd_pq_doorbell_control =
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
index e5b56412931b..fa025bea9b4f 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
@@ -102,8 +102,8 @@
* The first chunk is the TBA used for the CWSR ISA code. The second
* chunk is used as TMA for user-mode trap handler setup in daisy-chain mode.
*/
-#define KFD_CWSR_TBA_TMA_SIZE (PAGE_SIZE * 2)
-#define KFD_CWSR_TMA_OFFSET (PAGE_SIZE + 2048)
+#define KFD_CWSR_TBA_TMA_SIZE (AMDGPU_GPU_PAGE_SIZE * 2)
+#define KFD_CWSR_TMA_OFFSET (AMDGPU_GPU_PAGE_SIZE + 2048)
#define KFD_MAX_NUM_OF_QUEUES_PER_DEVICE \
(KFD_MAX_NUM_OF_PROCESSES * \
@@ -1525,7 +1525,7 @@ int kfd_wait_on_events(struct kfd_process *p,
bool all, uint32_t *user_timeout_ms,
uint32_t *wait_result);
void kfd_signal_event_interrupt(u32 pasid, uint32_t partial_id,
- uint32_t valid_id_bits);
+ uint32_t valid_id_bits, bool signal_mailbox_updated);
void kfd_signal_hw_exception_event(u32 pasid);
int kfd_set_event(struct kfd_process *p, uint32_t event_id);
int kfd_reset_event(struct kfd_process *p, uint32_t event_id);
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
index a031166f270c..bcd21204aa50 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
@@ -679,7 +679,7 @@ static void kfd_procfs_add_sysfs_files(struct kfd_process *p)
void kfd_procfs_del_queue(struct queue *q)
{
- if (!q)
+ if (!q || !q->process->kobj)
return;
kobject_del(&q->kobj);
@@ -858,6 +858,7 @@ int kfd_create_process_sysfs(struct kfd_process *process)
if (ret) {
pr_warn("Creating procfs pid directory failed");
kobject_put(process->kobj);
+ process->kobj = NULL;
return ret;
}
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
index cc2621ae12f9..44e39ce222b7 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
@@ -590,7 +590,8 @@ int pqm_update_queue_properties(struct process_queue_manager *pqm,
return err;
if (kfd_queue_buffer_get(vm, (void *)p->queue_address, &p->ring_bo,
- p->queue_size)) {
+ p->queue_size +
+ pqn->q->properties.metadata_queue_size)) {
pr_debug("ring buf 0x%llx size 0x%llx not mapped on GPU\n",
p->queue_address, p->queue_size);
amdgpu_bo_unreserve(vm->root.bo);
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_queue.c b/drivers/gpu/drm/amd/amdkfd/kfd_queue.c
index bbe869ceae3f..28354a4e5dd5 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_queue.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_queue.c
@@ -249,10 +249,10 @@ int kfd_queue_acquire_buffers(struct kfd_process_device *pdd, struct queue_prope
topo_dev->node_props.gfx_target_version < 90000)
/* metadata_queue_size not supported on GFX7/GFX8 */
expected_queue_size =
- properties->queue_size / 2;
+ PAGE_ALIGN(properties->queue_size / 2);
else
expected_queue_size =
- properties->queue_size + properties->metadata_queue_size;
+ PAGE_ALIGN(properties->queue_size + properties->metadata_queue_size);
vm = drm_priv_to_vm(pdd->drm_priv);
err = amdgpu_bo_reserve(vm->root.bo, false);
@@ -492,10 +492,11 @@ void kfd_queue_ctx_save_restore_size(struct kfd_topology_device *dev)
cu_num = props->simd_count / props->simd_per_cu / NUM_XCC(dev->gpu->xcc_mask);
wave_num = get_num_waves(props, gfxv, cu_num);
- wg_data_size = ALIGN(cu_num * WG_CONTEXT_DATA_SIZE_PER_CU(gfxv, props), PAGE_SIZE);
+ wg_data_size = ALIGN(cu_num * WG_CONTEXT_DATA_SIZE_PER_CU(gfxv, props),
+ AMDGPU_GPU_PAGE_SIZE);
ctl_stack_size = wave_num * CNTL_STACK_BYTES_PER_WAVE(gfxv) + 8;
ctl_stack_size = ALIGN(SIZEOF_HSA_USER_CONTEXT_SAVE_AREA_HEADER + ctl_stack_size,
- PAGE_SIZE);
+ AMDGPU_GPU_PAGE_SIZE);
if ((gfxv / 10000 * 10000) == 100000) {
/* HW design limits control stack size to 0x7000.
@@ -507,7 +508,7 @@ void kfd_queue_ctx_save_restore_size(struct kfd_topology_device *dev)
props->ctl_stack_size = ctl_stack_size;
props->debug_memory_size = ALIGN(wave_num * DEBUGGER_BYTES_PER_WAVE, DEBUGGER_BYTES_ALIGN);
- props->cwsr_size = ctl_stack_size + wg_data_size;
+ props->cwsr_size = ALIGN(ctl_stack_size + wg_data_size, PAGE_SIZE);
if (gfxv == 80002) /* GFX_VERSION_TONGA */
props->eop_buffer_size = 0x8000;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index 080242f9981b..b120fdb0ef77 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -628,9 +628,8 @@ svm_range_vram_node_new(struct kfd_node *node, struct svm_range *prange,
}
}
- r = dma_resv_reserve_fences(bo->tbo.base.resv, 1);
+ r = dma_resv_reserve_fences(bo->tbo.base.resv, TTM_NUM_MOVE_FENCES);
if (r) {
- pr_debug("failed %d to reserve bo\n", r);
amdgpu_bo_unreserve(bo);
goto reserve_bo_failed;
}
@@ -1219,7 +1218,8 @@ svm_range_get_pte_flags(struct kfd_node *node, struct amdgpu_vm *vm,
bool snoop = (domain != SVM_RANGE_VRAM_DOMAIN);
bool coherent = flags & (KFD_IOCTL_SVM_FLAG_COHERENT | KFD_IOCTL_SVM_FLAG_EXT_COHERENT);
bool ext_coherent = flags & KFD_IOCTL_SVM_FLAG_EXT_COHERENT;
- unsigned int mtype_local;
+ unsigned int mtype_local, mtype_remote;
+ bool is_aid_a1, is_local;
if (domain == SVM_RANGE_VRAM_DOMAIN)
bo_node = prange->svm_bo->node;
@@ -1307,20 +1307,23 @@ svm_range_get_pte_flags(struct kfd_node *node, struct amdgpu_vm *vm,
mapping_flags |= AMDGPU_VM_MTYPE_NC;
break;
case IP_VERSION(12, 1, 0):
+ is_aid_a1 = (node->adev->rev_id & 0x10);
+ is_local = (domain == SVM_RANGE_VRAM_DOMAIN) &&
+ (bo_node->adev == node->adev);
+
+ mtype_local = amdgpu_mtype_local == 0 ? AMDGPU_VM_MTYPE_RW :
+ amdgpu_mtype_local == 1 ? AMDGPU_VM_MTYPE_NC :
+ is_aid_a1 ? AMDGPU_VM_MTYPE_RW : AMDGPU_VM_MTYPE_NC;
+ mtype_remote = is_aid_a1 ? AMDGPU_VM_MTYPE_NC : AMDGPU_VM_MTYPE_UC;
snoop = true;
- if (domain == SVM_RANGE_VRAM_DOMAIN) {
- mtype_local = amdgpu_mtype_local == 1 ? AMDGPU_VM_MTYPE_NC :
- AMDGPU_VM_MTYPE_RW;
- /* local HBM */
- if (bo_node->adev == node->adev)
- mapping_flags |= mtype_local;
- /* Remote GPU memory */
- else
- mapping_flags |= ext_coherent ? AMDGPU_VM_MTYPE_UC :
- AMDGPU_VM_MTYPE_NC;
- /* system memory accessed by the dGPU */
+
+ if (is_local) /* local HBM */ {
+ mapping_flags |= mtype_local;
+ } else if (ext_coherent) {
+ mapping_flags |= AMDGPU_VM_MTYPE_UC;
} else {
- mapping_flags |= ext_coherent ? AMDGPU_VM_MTYPE_UC : AMDGPU_VM_MTYPE_NC;
+ /* system memory or remote VRAM */
+ mapping_flags |= mtype_remote;
}
break;
default:
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile b/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile
index 8e949fe77312..89350aa9ca7e 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile
@@ -40,7 +40,8 @@ AMDGPUDM = \
amdgpu_dm_replay.o \
amdgpu_dm_quirks.o \
amdgpu_dm_wb.o \
- amdgpu_dm_colorop.o
+ amdgpu_dm_colorop.o \
+ amdgpu_dm_ism.o
ifdef CONFIG_DRM_AMD_DC_FP
AMDGPUDM += dc_fpu.o
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 65b256a7b6c4..21635e80349a 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -2290,6 +2290,11 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev)
&adev->dm.dmub_bo_gpu_addr,
&adev->dm.dmub_bo_cpu_addr);
+ if (adev->dm.boot_time_crc_info.bo_ptr)
+ amdgpu_bo_free_kernel(&adev->dm.boot_time_crc_info.bo_ptr,
+ &adev->dm.boot_time_crc_info.gpu_addr,
+ &adev->dm.boot_time_crc_info.cpu_addr);
+
if (adev->dm.hpd_rx_offload_wq && adev->dm.dc) {
for (i = 0; i < adev->dm.dc->caps.max_links; i++) {
if (adev->dm.hpd_rx_offload_wq[i].wq) {
@@ -2577,7 +2582,7 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev)
fw_meta_info_params.fw_inst_const = adev->dm.dmub_fw->data +
le32_to_cpu(hdr->header.ucode_array_offset_bytes) +
PSP_HEADER_BYTES_256;
- fw_meta_info_params.fw_bss_data = region_params.bss_data_size ? adev->dm.dmub_fw->data +
+ fw_meta_info_params.fw_bss_data = fw_meta_info_params.bss_data_size ? adev->dm.dmub_fw->data +
le32_to_cpu(hdr->header.ucode_array_offset_bytes) +
le32_to_cpu(hdr->inst_const_bytes) : NULL;
fw_meta_info_params.custom_psp_footer_size = 0;
@@ -2738,6 +2743,54 @@ static int detect_mst_link_for_all_connectors(struct drm_device *dev)
return ret;
}
+static void amdgpu_dm_boot_time_crc_init(struct amdgpu_device *adev)
+{
+ struct dm_boot_time_crc_info *bootcrc_info = NULL;
+ struct dmub_srv *dmub = NULL;
+ union dmub_fw_boot_options option = {0};
+ int ret = 0;
+ const uint32_t fb_size = 3 * 1024 * 1024; /* 3MB for DCC pattern */
+
+ if (!adev || !adev->dm.dc || !adev->dm.dc->ctx ||
+ !adev->dm.dc->ctx->dmub_srv) {
+ return;
+ }
+
+ dmub = adev->dm.dc->ctx->dmub_srv->dmub;
+ bootcrc_info = &adev->dm.boot_time_crc_info;
+
+ if (!dmub || !dmub->hw_funcs.get_fw_boot_option) {
+ drm_dbg(adev_to_drm(adev), "failed to init boot time crc buffer\n");
+ return;
+ }
+
+ option = dmub->hw_funcs.get_fw_boot_option(dmub);
+
+ /* Return if boot time CRC is not enabled */
+ if (option.bits.bootcrc_en_at_S0i3 == 0)
+ return;
+
+ /* Create a buffer for boot time CRC */
+ ret = amdgpu_bo_create_kernel(adev, fb_size, PAGE_SIZE,
+ AMDGPU_GEM_DOMAIN_VRAM | AMDGPU_GEM_DOMAIN_GTT,
+ &bootcrc_info->bo_ptr,
+ &bootcrc_info->gpu_addr,
+ &bootcrc_info->cpu_addr);
+
+ if (ret) {
+ drm_dbg(adev_to_drm(adev), "failed to create boot time crc buffer\n");
+ } else {
+ bootcrc_info->size = fb_size;
+
+ drm_dbg(adev_to_drm(adev), "boot time crc buffer created addr 0x%llx, size %u\n",
+ bootcrc_info->gpu_addr, bootcrc_info->size);
+
+ /* Send the buffer info to DMUB */
+ dc_dmub_srv_boot_time_crc_init(adev->dm.dc,
+ bootcrc_info->gpu_addr, bootcrc_info->size);
+ }
+}
+
static int dm_late_init(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;
@@ -2749,6 +2802,11 @@ static int dm_late_init(struct amdgpu_ip_block *ip_block)
dmcu = adev->dm.dc->res_pool->dmcu;
+ /* Init the boot time CRC (skip in resume) */
+ if ((adev->in_suspend == 0) &&
+ (amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(3, 6, 0)))
+ amdgpu_dm_boot_time_crc_init(adev);
+
for (i = 0; i < 16; i++)
linear_lut[i] = 0xFFFF * i / 15;
@@ -3225,6 +3283,7 @@ static int dm_suspend(struct amdgpu_ip_block *ip_block)
mutex_lock(&dm->dc_lock);
+ amdgpu_dm_ism_disable(dm);
dc_allow_idle_optimizations(adev->dm.dc, false);
dm->cached_dc_state = dc_state_create_copy(dm->dc->current_state);
@@ -3258,6 +3317,9 @@ static int dm_suspend(struct amdgpu_ip_block *ip_block)
amdgpu_dm_irq_suspend(adev);
+ scoped_guard(mutex, &dm->dc_lock)
+ amdgpu_dm_ism_disable(dm);
+
hpd_rx_irq_work_suspend(dm);
dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D3);
@@ -3548,6 +3610,7 @@ static int dm_resume(struct amdgpu_ip_block *ip_block)
dc_resume(dm->dc);
+ amdgpu_dm_ism_enable(dm);
amdgpu_dm_irq_resume_early(adev);
for (i = 0; i < dc_state->stream_count; i++) {
@@ -3608,6 +3671,9 @@ static int dm_resume(struct amdgpu_ip_block *ip_block)
/* program HPD filter */
dc_resume(dm->dc);
+ scoped_guard(mutex, &dm->dc_lock)
+ amdgpu_dm_ism_enable(dm);
+
/*
* early enable HPD Rx IRQ, should be done before set mode as short
* pulse interrupts are used for MST
@@ -3936,8 +4002,9 @@ void amdgpu_dm_update_connector_after_detect(
aconnector->dc_sink = sink;
dc_sink_retain(aconnector->dc_sink);
+ drm_edid_free(aconnector->drm_edid);
+ aconnector->drm_edid = NULL;
if (sink->dc_edid.length == 0) {
- aconnector->drm_edid = NULL;
hdmi_cec_unset_edid(aconnector);
if (aconnector->dc_link->aux_mode) {
drm_dp_cec_unset_edid(&aconnector->dm_dp_aux.aux);
@@ -4846,14 +4913,37 @@ static void dm_atomic_destroy_state(struct drm_private_obj *obj,
kfree(dm_state);
}
+static struct drm_private_state *
+dm_atomic_create_state(struct drm_private_obj *obj)
+{
+ struct amdgpu_device *adev = drm_to_adev(obj->dev);
+ struct dm_atomic_state *dm_state;
+ struct dc_state *context;
+
+ dm_state = kzalloc_obj(*dm_state);
+ if (!dm_state)
+ return ERR_PTR(-ENOMEM);
+
+ context = dc_state_create_current_copy(adev->dm.dc);
+ if (!context) {
+ kfree(dm_state);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ __drm_atomic_helper_private_obj_create_state(obj, &dm_state->base);
+ dm_state->context = context;
+
+ return &dm_state->base;
+}
+
static struct drm_private_state_funcs dm_atomic_state_funcs = {
+ .atomic_create_state = dm_atomic_create_state,
.atomic_duplicate_state = dm_atomic_duplicate_state,
.atomic_destroy_state = dm_atomic_destroy_state,
};
static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev)
{
- struct dm_atomic_state *state;
int r;
adev->mode_info.mode_config_initialized = true;
@@ -4873,42 +4963,22 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev)
/* indicates support for immediate flip */
adev_to_drm(adev)->mode_config.async_page_flip = true;
- state = kzalloc_obj(*state);
- if (!state)
- return -ENOMEM;
-
- state->context = dc_state_create_current_copy(adev->dm.dc);
- if (!state->context) {
- kfree(state);
- return -ENOMEM;
- }
-
drm_atomic_private_obj_init(adev_to_drm(adev),
&adev->dm.atomic_obj,
- &state->base,
&dm_atomic_state_funcs);
r = amdgpu_display_modeset_create_props(adev);
- if (r) {
- dc_state_release(state->context);
- kfree(state);
+ if (r)
return r;
- }
#ifdef AMD_PRIVATE_COLOR
- if (amdgpu_dm_create_color_properties(adev)) {
- dc_state_release(state->context);
- kfree(state);
+ if (amdgpu_dm_create_color_properties(adev))
return -ENOMEM;
- }
#endif
r = amdgpu_dm_audio_init(adev);
- if (r) {
- dc_state_release(state->context);
- kfree(state);
+ if (r)
return r;
- }
return 0;
}
@@ -5359,7 +5429,7 @@ static void setup_backlight_device(struct amdgpu_display_manager *dm,
caps = &dm->backlight_caps[aconnector->bl_idx];
/* Only offer ABM property when non-OLED and user didn't turn off by module parameter */
- if (!caps->ext_caps->bits.oled && amdgpu_dm_abm_level < 0)
+ if (caps->ext_caps && !caps->ext_caps->bits.oled && amdgpu_dm_abm_level < 0)
drm_object_attach_property(&aconnector->base.base,
dm->adev->mode_info.abm_level_property,
ABM_SYSFS_CONTROL);
@@ -5519,6 +5589,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
case IP_VERSION(3, 5, 0):
case IP_VERSION(3, 5, 1):
case IP_VERSION(3, 6, 0):
+ case IP_VERSION(4, 2, 0):
replay_feature_enabled = true;
break;
@@ -6659,11 +6730,11 @@ static void fill_stream_properties_from_drm_display_mode(
&& aconnector
&& aconnector->force_yuv420_output)
timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420;
- else if ((connector->display_info.color_formats & DRM_COLOR_FORMAT_YCBCR422)
+ else if ((connector->display_info.color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422))
&& aconnector
&& aconnector->force_yuv422_output)
timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR422;
- else if ((connector->display_info.color_formats & DRM_COLOR_FORMAT_YCBCR444)
+ else if ((connector->display_info.color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444))
&& stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR444;
else
@@ -9271,31 +9342,7 @@ static void manage_dm_interrupts(struct amdgpu_device *adev,
if (acrtc_state) {
timing = &acrtc_state->stream->timing;
- /*
- * Depending on when the HW latching event of double-buffered
- * registers happen relative to the PSR SDP deadline, and how
- * bad the Panel clock has drifted since the last ALPM off
- * event, there can be up to 3 frames of delay between sending
- * the PSR exit cmd to DMUB fw, and when the panel starts
- * displaying live frames.
- *
- * We can set:
- *
- * 20/100 * offdelay_ms = 3_frames_ms
- * => offdelay_ms = 5 * 3_frames_ms
- *
- * This ensures that `3_frames_ms` will only be experienced as a
- * 20% delay on top how long the display has been static, and
- * thus make the delay less perceivable.
- */
- if (acrtc_state->stream->link->psr_settings.psr_version <
- DC_PSR_VERSION_UNSUPPORTED) {
- offdelay = DIV64_U64_ROUND_UP((u64)5 * 3 * 10 *
- timing->v_total *
- timing->h_total,
- timing->pix_clk_100hz);
- config.offdelay_ms = offdelay ?: 30;
- } else if (amdgpu_ip_version(adev, DCE_HWIP, 0) <
+ if (amdgpu_ip_version(adev, DCE_HWIP, 0) <
IP_VERSION(3, 5, 0) ||
!(adev->flags & AMD_IS_APU)) {
/*
@@ -9840,7 +9887,8 @@ static void amdgpu_dm_enable_self_refresh(struct amdgpu_crtc *acrtc_attach,
* a vblank event disable request to enable PSR/RP. PSR SU/RP
* can be enabled immediately once OS demonstrates an
* adequate number of fast atomic commits to notify KMD
- * of update events. See `vblank_control_worker()`.
+ * of update events.
+ * See `amdgpu_dm_crtc_vblank_control_worker()`.
*/
if (!vrr_active &&
acrtc_attach->dm_irq_params.allow_sr_entry &&
@@ -10008,8 +10056,9 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
/*
* If the dirty regions changed, PSR-SU need to be disabled temporarily
* and enabled it again after dirty regions are stable to avoid video glitch.
- * PSR-SU will be enabled in vblank_control_worker() if user pause the video
- * during the PSR-SU was disabled.
+ * PSR-SU will be enabled in
+ * amdgpu_dm_crtc_vblank_control_worker() if user
+ * pause the video during the PSR-SU was disabled.
*/
if (acrtc_state->stream->link->psr_settings.psr_version >= DC_PSR_VERSION_SU_1 &&
acrtc_attach->dm_irq_params.allow_sr_entry &&
@@ -12471,6 +12520,11 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
if (dc_resource_is_dsc_encoding_supported(dc)) {
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
+ dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
+ dm_new_crtc_state->mode_changed_independent_from_dsc = new_crtc_state->mode_changed;
+ }
+
+ for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
if (drm_atomic_crtc_needs_modeset(new_crtc_state)) {
ret = add_affected_mst_dsc_crtcs(state, crtc);
if (ret) {
@@ -13067,7 +13121,7 @@ static void parse_edid_displayid_vrr(struct drm_connector *connector,
u16 min_vfreq;
u16 max_vfreq;
- if (edid == NULL || edid->extensions == 0)
+ if (!edid || !edid->extensions)
return;
/* Find DisplayID extension */
@@ -13077,7 +13131,7 @@ static void parse_edid_displayid_vrr(struct drm_connector *connector,
break;
}
- if (edid_ext == NULL)
+ if (i == edid->extensions)
return;
while (j < EDID_LENGTH) {
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 800813671748..d1a14e0c12bd 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -123,6 +123,20 @@ struct dm_compressor_info {
uint64_t gpu_addr;
};
+/**
+ * struct dm_boot_time_crc_info - Buffer info used by boot time CRC
+ * @cpu_addr: MMIO cpu addr
+ * @bo_ptr: Pointer to the buffer object
+ * @gpu_addr: MMIO gpu addr
+ * @size: Size of the buffer
+ */
+struct dm_boot_time_crc_info {
+ void *cpu_addr;
+ struct amdgpu_bo *bo_ptr;
+ uint64_t gpu_addr;
+ uint32_t size;
+};
+
typedef void (*dmub_notify_interrupt_callback_t)(struct amdgpu_device *adev, struct dmub_notification *notify);
/**
@@ -698,6 +712,13 @@ struct amdgpu_display_manager {
struct completion replied;
char reply_data[0x40]; // Cannot include dmub_cmd here
} fused_io[8];
+
+ /**
+ * @dm_boot_time_crc_info:
+ *
+ * Buffer info for the boot time crc.
+ */
+ struct dm_boot_time_crc_info boot_time_crc_info;
};
enum dsc_clock_force_state {
@@ -984,6 +1005,7 @@ struct dm_crtc_state {
bool freesync_vrr_info_changed;
+ bool mode_changed_independent_from_dsc;
bool dsc_force_changed;
bool vrr_supported;
struct mod_freesync_config freesync_config;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
index 3e05e48a8792..7ee051cb3c05 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
@@ -37,19 +37,19 @@ const u64 amdgpu_dm_supported_degam_tfs =
BIT(DRM_COLOROP_1D_CURVE_SRGB_EOTF) |
BIT(DRM_COLOROP_1D_CURVE_PQ_125_EOTF) |
BIT(DRM_COLOROP_1D_CURVE_BT2020_INV_OETF) |
- BIT(DRM_COLOROP_1D_CURVE_GAMMA22_INV);
+ BIT(DRM_COLOROP_1D_CURVE_GAMMA22);
const u64 amdgpu_dm_supported_shaper_tfs =
BIT(DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF) |
BIT(DRM_COLOROP_1D_CURVE_PQ_125_INV_EOTF) |
BIT(DRM_COLOROP_1D_CURVE_BT2020_OETF) |
- BIT(DRM_COLOROP_1D_CURVE_GAMMA22);
+ BIT(DRM_COLOROP_1D_CURVE_GAMMA22_INV);
const u64 amdgpu_dm_supported_blnd_tfs =
BIT(DRM_COLOROP_1D_CURVE_SRGB_EOTF) |
BIT(DRM_COLOROP_1D_CURVE_PQ_125_EOTF) |
BIT(DRM_COLOROP_1D_CURVE_BT2020_INV_OETF) |
- BIT(DRM_COLOROP_1D_CURVE_GAMMA22_INV);
+ BIT(DRM_COLOROP_1D_CURVE_GAMMA22);
#define MAX_COLOR_PIPELINE_OPS 10
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
index b96fbc03c371..62573173e2ac 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
@@ -812,7 +812,6 @@ void amdgpu_dm_crtc_handle_crc_window_irq(struct drm_crtc *crtc)
unsigned long flags1;
bool forward_roi_change = false;
bool notify_ta = false;
- bool all_crc_ready = true;
struct dc_stream_state *stream_state;
int i;
@@ -936,9 +935,6 @@ void amdgpu_dm_crtc_handle_crc_window_irq(struct drm_crtc *crtc)
continue;
}
- if (!crtc_ctx->crc_info.crc[i].crc_ready)
- all_crc_ready = false;
-
if (reset_crc_frame_count[i] || crtc_ctx->crc_info.crc[i].frame_count == UINT_MAX)
/* Reset the reference frame count after user update the ROI
* or it reaches the maximum value.
@@ -948,9 +944,6 @@ void amdgpu_dm_crtc_handle_crc_window_irq(struct drm_crtc *crtc)
crtc_ctx->crc_info.crc[i].frame_count += 1;
}
spin_unlock_irqrestore(&crtc_ctx->crc_info.lock, flags1);
-
- if (all_crc_ready)
- complete_all(&crtc_ctx->crc_info.completion);
}
void amdgpu_dm_crtc_secure_display_create_contexts(struct amdgpu_device *adev)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h
index 95bdb8699d7f..8538513ea879 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h
@@ -70,7 +70,6 @@ struct crc_data {
struct crc_info {
struct crc_data crc[MAX_CRC_WINDOW_NUM];
- struct completion completion;
spinlock_t lock;
};
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
index 304437c2284d..c3c588294665 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
@@ -124,37 +124,37 @@ bool amdgpu_dm_crtc_vrr_active(const struct dm_crtc_state *dm_state)
* - Enable condition same as above
* - Disable when vblank counter is enabled
*/
-static void amdgpu_dm_crtc_set_panel_sr_feature(
- struct vblank_control_work *vblank_work,
+void amdgpu_dm_crtc_set_panel_sr_feature(
+ struct amdgpu_display_manager *dm,
+ struct amdgpu_crtc *acrtc,
+ struct dc_stream_state *stream,
bool vblank_enabled, bool allow_sr_entry)
{
- struct dc_link *link = vblank_work->stream->link;
+ struct dc_link *link = stream->link;
bool is_sr_active = (link->replay_settings.replay_allow_active ||
link->psr_settings.psr_allow_active);
bool is_crc_window_active = false;
- bool vrr_active = amdgpu_dm_crtc_vrr_active_irq(vblank_work->acrtc);
+ bool vrr_active = amdgpu_dm_crtc_vrr_active_irq(acrtc);
#ifdef CONFIG_DRM_AMD_SECURE_DISPLAY
is_crc_window_active =
- amdgpu_dm_crc_window_is_activated(&vblank_work->acrtc->base);
+ amdgpu_dm_crc_window_is_activated(&acrtc->base);
#endif
if (link->replay_settings.replay_feature_enabled && !vrr_active &&
allow_sr_entry && !is_sr_active && !is_crc_window_active) {
- amdgpu_dm_replay_enable(vblank_work->stream, true);
+ amdgpu_dm_replay_enable(stream, true);
} else if (vblank_enabled) {
if (link->psr_settings.psr_version < DC_PSR_VERSION_SU_1 && is_sr_active)
- amdgpu_dm_psr_disable(vblank_work->stream, false);
+ amdgpu_dm_psr_disable(stream, false);
} else if (link->psr_settings.psr_feature_enabled && !vrr_active &&
allow_sr_entry && !is_sr_active && !is_crc_window_active) {
struct amdgpu_dm_connector *aconn =
- (struct amdgpu_dm_connector *) vblank_work->stream->dm_stream_context;
+ (struct amdgpu_dm_connector *) stream->dm_stream_context;
if (!aconn->disallow_edp_enter_psr) {
- struct amdgpu_display_manager *dm = vblank_work->dm;
-
- amdgpu_dm_psr_enable(vblank_work->stream);
+ amdgpu_dm_psr_enable(stream);
if (dm->idle_workqueue &&
(dm->dc->config.disable_ips == DMUB_IPS_ENABLE) &&
dm->dc->idle_optimizations_allowed &&
@@ -251,33 +251,15 @@ static void amdgpu_dm_crtc_vblank_control_worker(struct work_struct *work)
mutex_lock(&dm->dc_lock);
- if (vblank_work->enable)
+ if (vblank_work->enable) {
dm->active_vblank_irq_count++;
- else if (dm->active_vblank_irq_count)
- dm->active_vblank_irq_count--;
-
- if (dm->active_vblank_irq_count > 0)
- dc_allow_idle_optimizations(dm->dc, false);
-
- /*
- * Control PSR based on vblank requirements from OS
- *
- * If panel supports PSR SU, there's no need to disable PSR when OS is
- * submitting fast atomic commits (we infer this by whether the OS
- * requests vblank events). Fast atomic commits will simply trigger a
- * full-frame-update (FFU); a specific case of selective-update (SU)
- * where the SU region is the full hactive*vactive region. See
- * fill_dc_dirty_rects().
- */
- if (vblank_work->stream && vblank_work->stream->link && vblank_work->acrtc) {
- amdgpu_dm_crtc_set_panel_sr_feature(
- vblank_work, vblank_work->enable,
- vblank_work->acrtc->dm_irq_params.allow_sr_entry);
- }
-
- if (dm->active_vblank_irq_count == 0) {
- dc_post_update_surfaces_to_stream(dm->dc);
- dc_allow_idle_optimizations(dm->dc, true);
+ amdgpu_dm_ism_commit_event(&vblank_work->acrtc->ism,
+ DM_ISM_EVENT_EXIT_IDLE_REQUESTED);
+ } else {
+ if (dm->active_vblank_irq_count > 0)
+ dm->active_vblank_irq_count--;
+ amdgpu_dm_ism_commit_event(&vblank_work->acrtc->ism,
+ DM_ISM_EVENT_ENTER_IDLE_REQUESTED);
}
mutex_unlock(&dm->dc_lock);
@@ -476,6 +458,9 @@ static struct drm_crtc_state *amdgpu_dm_crtc_duplicate_state(struct drm_crtc *cr
static void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc)
{
+ struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
+
+ amdgpu_dm_ism_fini(&acrtc->ism);
drm_crtc_cleanup(crtc);
kfree(crtc);
}
@@ -719,6 +704,35 @@ static const struct drm_crtc_helper_funcs amdgpu_dm_crtc_helper_funcs = {
.get_scanout_position = amdgpu_crtc_get_scanout_position,
};
+/*
+ * This hysteresis filter as configured will:
+ *
+ * * Search through the latest 8[filter_history_size] entries in history,
+ * skipping entries that are older than [filter_old_history_threshold] frames
+ * (0 means ignore age)
+ * * Searches for short-idle-periods that lasted shorter than
+ * 4[filter_num_frames] frames-times
+ * * If there is at least 1[filter_entry_count] short-idle-period, then a delay
+ * of 4[activation_num_delay_frames] will applied before allowing idle
+ * optimizations again.
+ * * An additional delay of 11[sso_num_frames] is applied before enabling
+ * panel-specific optimizations.
+ *
+ * The values were determined empirically on another OS, optimizing for Z8
+ * residency on APUs when running a productivity + web browsing test.
+ *
+ * TODO: Run similar tests to determine if these values are also optimal for
+ * Linux, and if each APU generation benefits differently.
+ */
+static struct amdgpu_dm_ism_config default_ism_config = {
+ .filter_num_frames = 4,
+ .filter_history_size = 8,
+ .filter_entry_count = 1,
+ .activation_num_delay_frames = 4,
+ .filter_old_history_threshold = 0,
+ .sso_num_frames = 11,
+};
+
int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm,
struct drm_plane *plane,
uint32_t crtc_index)
@@ -749,6 +763,8 @@ int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm,
if (res)
goto fail;
+ amdgpu_dm_ism_init(&acrtc->ism, &default_ism_config);
+
drm_crtc_helper_add(&acrtc->base, &amdgpu_dm_crtc_helper_funcs);
/* Create (reset) the plane state */
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h
index c1212947a77b..3a8094013a5d 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h
@@ -27,6 +27,12 @@
#ifndef __AMDGPU_DM_CRTC_H__
#define __AMDGPU_DM_CRTC_H__
+void amdgpu_dm_crtc_set_panel_sr_feature(
+ struct amdgpu_display_manager *dm,
+ struct amdgpu_crtc *acrtc,
+ struct dc_stream_state *stream,
+ bool vblank_enabled, bool allow_sr_entry);
+
void amdgpu_dm_crtc_handle_vblank(struct amdgpu_crtc *acrtc);
bool amdgpu_dm_crtc_modeset_required(struct drm_crtc_state *crtc_state,
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
index 24bc2a86904b..2409ac72b166 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
@@ -3305,6 +3305,52 @@ static int disallow_edp_enter_psr_set(void *data, u64 val)
return 0;
}
+/* check if kernel disallow eDP enter replay state
+ * cat /sys/kernel/debug/dri/0/eDP-X/disallow_edp_enter_replay
+ * 0: allow edp enter replay; 1: disallow
+ */
+static int disallow_edp_enter_replay_get(void *data, u64 *val)
+{
+ struct amdgpu_dm_connector *aconnector = data;
+
+ *val = (u64) aconnector->disallow_edp_enter_replay;
+ return 0;
+}
+
+/* set kernel disallow eDP enter replay state
+ * echo 0x0 /sys/kernel/debug/dri/0/eDP-X/disallow_edp_enter_replay
+ * 0: allow edp enter replay; 1: disallow
+ *
+ * usage: test app read crc from PSR eDP rx.
+ *
+ * during kernel boot up, kernel write dpcd 0x37b to
+ * notify eDP rx replay enable.
+ * rx fw will start checking crc for rx internal logic.
+ * crc read count within dpcd 0x246 is not updated and
+ * value is 0. when eDP tx driver wants to read rx crc
+ * from dpcd 0x246, 0x270, read count 0 lead tx driver
+ * timeout.
+ *
+ * to avoid this, we add this debugfs to let test app to disbable
+ * rx replay. then test app can read non-zero crc read count.
+ *
+ * expected app sequence is as below:
+ * 1. disable eDP PHY and notify eDP rx with dpcd 0x600 = 2.
+ * 2. echo 0x1 /sys/kernel/debug/dri/0/eDP-X/disallow_edp_enter_replay
+ * 3. enable eDP PHY and notify eDP rx with dpcd 0x600 = 1 but
+ * without programming dpcd 0x37b.
+ * 4. read crc from rx dpcd 0x270, 0x246, etc.
+ * 5. echo 0x0 /sys/kernel/debug/dri/0/eDP-X/disallow_edp_enter_replay.
+ * this will let eDP back to normal with replay setup dpcd 0x37b.
+ */
+static int disallow_edp_enter_replay_set(void *data, u64 val)
+{
+ struct amdgpu_dm_connector *aconnector = data;
+
+ aconnector->disallow_edp_enter_replay = val ? true : false;
+ return 0;
+}
+
static int dmub_trace_mask_set(void *data, u64 val)
{
struct amdgpu_device *adev = data;
@@ -3433,6 +3479,10 @@ DEFINE_DEBUGFS_ATTRIBUTE(disallow_edp_enter_psr_fops,
disallow_edp_enter_psr_get,
disallow_edp_enter_psr_set, "%llu\n");
+DEFINE_DEBUGFS_ATTRIBUTE(disallow_edp_enter_replay_fops,
+ disallow_edp_enter_replay_get,
+ disallow_edp_enter_replay_set, "%llu\n");
+
DEFINE_DEBUGFS_ATTRIBUTE(ips_residency_cntl_fops, ips_residency_cntl_get,
ips_residency_cntl_set, "%llu\n");
DEFINE_SHOW_ATTRIBUTE(current_backlight);
@@ -3635,6 +3685,8 @@ void connector_debugfs_init(struct amdgpu_dm_connector *connector)
&allow_edp_hotplug_detection_fops);
debugfs_create_file("disallow_edp_enter_psr", 0644, dir, connector,
&disallow_edp_enter_psr_fops);
+ debugfs_create_file("disallow_edp_enter_replay", 0644, dir, connector,
+ &disallow_edp_enter_replay_fops);
}
for (i = 0; i < ARRAY_SIZE(connector_debugfs_entries); i++) {
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.c
new file mode 100644
index 000000000000..65a5cfe1e106
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.c
@@ -0,0 +1,598 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright 2026 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include <linux/types.h>
+#include <drm/drm_vblank.h>
+
+#include "dc.h"
+#include "amdgpu.h"
+#include "amdgpu_dm_ism.h"
+#include "amdgpu_dm_crtc.h"
+#include "amdgpu_dm_trace.h"
+
+/**
+ * dm_ism_next_state - Get next state based on current state and event
+ *
+ * This function defines the idle state management FSM. Invalid transitions
+ * are ignored and will not progress the FSM.
+ */
+static bool dm_ism_next_state(enum amdgpu_dm_ism_state current_state,
+ enum amdgpu_dm_ism_event event,
+ enum amdgpu_dm_ism_state *next_state)
+{
+ switch (STATE_EVENT(current_state, event)) {
+ case STATE_EVENT(DM_ISM_STATE_FULL_POWER_RUNNING,
+ DM_ISM_EVENT_ENTER_IDLE_REQUESTED):
+ *next_state = DM_ISM_STATE_HYSTERESIS_WAITING;
+ break;
+ case STATE_EVENT(DM_ISM_STATE_FULL_POWER_RUNNING,
+ DM_ISM_EVENT_BEGIN_CURSOR_UPDATE):
+ *next_state = DM_ISM_STATE_FULL_POWER_BUSY;
+ break;
+
+ case STATE_EVENT(DM_ISM_STATE_FULL_POWER_BUSY,
+ DM_ISM_EVENT_ENTER_IDLE_REQUESTED):
+ *next_state = DM_ISM_STATE_HYSTERESIS_BUSY;
+ break;
+ case STATE_EVENT(DM_ISM_STATE_FULL_POWER_BUSY,
+ DM_ISM_EVENT_END_CURSOR_UPDATE):
+ *next_state = DM_ISM_STATE_FULL_POWER_RUNNING;
+ break;
+
+ case STATE_EVENT(DM_ISM_STATE_HYSTERESIS_WAITING,
+ DM_ISM_EVENT_EXIT_IDLE_REQUESTED):
+ *next_state = DM_ISM_STATE_TIMER_ABORTED;
+ break;
+ case STATE_EVENT(DM_ISM_STATE_HYSTERESIS_WAITING,
+ DM_ISM_EVENT_BEGIN_CURSOR_UPDATE):
+ *next_state = DM_ISM_STATE_HYSTERESIS_BUSY;
+ break;
+ case STATE_EVENT(DM_ISM_STATE_HYSTERESIS_WAITING,
+ DM_ISM_EVENT_TIMER_ELAPSED):
+ *next_state = DM_ISM_STATE_OPTIMIZED_IDLE;
+ break;
+ case STATE_EVENT(DM_ISM_STATE_HYSTERESIS_WAITING,
+ DM_ISM_EVENT_IMMEDIATE):
+ *next_state = DM_ISM_STATE_OPTIMIZED_IDLE;
+ break;
+
+ case STATE_EVENT(DM_ISM_STATE_HYSTERESIS_BUSY,
+ DM_ISM_EVENT_EXIT_IDLE_REQUESTED):
+ *next_state = DM_ISM_STATE_FULL_POWER_BUSY;
+ break;
+ case STATE_EVENT(DM_ISM_STATE_HYSTERESIS_BUSY,
+ DM_ISM_EVENT_END_CURSOR_UPDATE):
+ *next_state = DM_ISM_STATE_HYSTERESIS_WAITING;
+ break;
+
+ case STATE_EVENT(DM_ISM_STATE_OPTIMIZED_IDLE,
+ DM_ISM_EVENT_EXIT_IDLE_REQUESTED):
+ *next_state = DM_ISM_STATE_FULL_POWER_RUNNING;
+ break;
+ case STATE_EVENT(DM_ISM_STATE_OPTIMIZED_IDLE,
+ DM_ISM_EVENT_BEGIN_CURSOR_UPDATE):
+ *next_state = DM_ISM_STATE_HYSTERESIS_BUSY;
+ break;
+ case STATE_EVENT(DM_ISM_STATE_OPTIMIZED_IDLE,
+ DM_ISM_EVENT_SSO_TIMER_ELAPSED):
+ case STATE_EVENT(DM_ISM_STATE_OPTIMIZED_IDLE,
+ DM_ISM_EVENT_IMMEDIATE):
+ *next_state = DM_ISM_STATE_OPTIMIZED_IDLE_SSO;
+ break;
+
+ case STATE_EVENT(DM_ISM_STATE_OPTIMIZED_IDLE_SSO,
+ DM_ISM_EVENT_EXIT_IDLE_REQUESTED):
+ *next_state = DM_ISM_STATE_FULL_POWER_RUNNING;
+ break;
+ case STATE_EVENT(DM_ISM_STATE_OPTIMIZED_IDLE_SSO,
+ DM_ISM_EVENT_BEGIN_CURSOR_UPDATE):
+ *next_state = DM_ISM_STATE_HYSTERESIS_BUSY;
+ break;
+
+ case STATE_EVENT(DM_ISM_STATE_TIMER_ABORTED,
+ DM_ISM_EVENT_IMMEDIATE):
+ *next_state = DM_ISM_STATE_FULL_POWER_RUNNING;
+ break;
+
+ default:
+ return false;
+ }
+ return true;
+}
+
+static uint64_t dm_ism_get_sso_delay(const struct amdgpu_dm_ism *ism,
+ const struct dc_stream_state *stream)
+{
+ const struct amdgpu_dm_ism_config *config = &ism->config;
+ uint32_t v_total, h_total;
+ uint64_t one_frame_ns, sso_delay_ns;
+
+ if (!stream)
+ return 0;
+
+ if (!config->sso_num_frames)
+ return 0;
+
+ v_total = stream->timing.v_total;
+ h_total = stream->timing.h_total;
+
+ one_frame_ns = div64_u64(v_total * h_total * 10000000ull,
+ stream->timing.pix_clk_100hz);
+ sso_delay_ns = config->sso_num_frames * one_frame_ns;
+
+ return sso_delay_ns;
+}
+
+/**
+ * dm_ism_get_idle_allow_delay - Calculate hysteresis-based idle allow delay
+ */
+static uint64_t dm_ism_get_idle_allow_delay(const struct amdgpu_dm_ism *ism,
+ const struct dc_stream_state *stream)
+{
+ const struct amdgpu_dm_ism_config *config = &ism->config;
+ uint32_t v_total, h_total;
+ uint64_t one_frame_ns, short_idle_ns, old_hist_ns;
+ uint32_t history_size;
+ int pos;
+ uint32_t short_idle_count = 0;
+ uint64_t ret_ns = 0;
+
+ if (!stream)
+ return 0;
+
+ if (!config->filter_num_frames)
+ return 0;
+ if (!config->filter_entry_count)
+ return 0;
+ if (!config->activation_num_delay_frames)
+ return 0;
+
+ v_total = stream->timing.v_total;
+ h_total = stream->timing.h_total;
+
+ one_frame_ns = div64_u64(v_total * h_total * 10000000ull,
+ stream->timing.pix_clk_100hz);
+
+ short_idle_ns = config->filter_num_frames * one_frame_ns;
+ old_hist_ns = config->filter_old_history_threshold * one_frame_ns;
+
+ /*
+ * Look back into the recent history and count how many times we entered
+ * idle power state for a short duration of time
+ */
+ history_size = min(
+ max(config->filter_history_size, config->filter_entry_count),
+ AMDGPU_DM_IDLE_HIST_LEN);
+ pos = ism->next_record_idx;
+
+ for (int k = 0; k < history_size; k++) {
+ if (pos <= 0 || pos > AMDGPU_DM_IDLE_HIST_LEN)
+ pos = AMDGPU_DM_IDLE_HIST_LEN;
+ pos -= 1;
+
+ if (ism->records[pos].duration_ns <= short_idle_ns)
+ short_idle_count += 1;
+
+ if (short_idle_count >= config->filter_entry_count)
+ break;
+
+ if (old_hist_ns > 0 &&
+ ism->last_idle_timestamp_ns - ism->records[pos].timestamp_ns > old_hist_ns)
+ break;
+ }
+
+ if (short_idle_count >= config->filter_entry_count)
+ ret_ns = config->activation_num_delay_frames * one_frame_ns;
+
+ return ret_ns;
+}
+
+/**
+ * dm_ism_insert_record - Insert a record into the circular history buffer
+ */
+static void dm_ism_insert_record(struct amdgpu_dm_ism *ism)
+{
+ struct amdgpu_dm_ism_record *record;
+
+ if (ism->next_record_idx < 0 ||
+ ism->next_record_idx >= AMDGPU_DM_IDLE_HIST_LEN)
+ ism->next_record_idx = 0;
+
+ record = &ism->records[ism->next_record_idx];
+ ism->next_record_idx += 1;
+
+ record->timestamp_ns = ktime_get_ns();
+ record->duration_ns =
+ record->timestamp_ns - ism->last_idle_timestamp_ns;
+}
+
+
+static void dm_ism_set_last_idle_ts(struct amdgpu_dm_ism *ism)
+{
+ ism->last_idle_timestamp_ns = ktime_get_ns();
+}
+
+
+static bool dm_ism_trigger_event(struct amdgpu_dm_ism *ism,
+ enum amdgpu_dm_ism_event event)
+{
+ enum amdgpu_dm_ism_state next_state;
+
+ bool gotNextState = dm_ism_next_state(ism->current_state, event,
+ &next_state);
+
+ if (gotNextState) {
+ ism->previous_state = ism->current_state;
+ ism->current_state = next_state;
+ }
+
+ return gotNextState;
+}
+
+
+static void dm_ism_commit_idle_optimization_state(struct amdgpu_dm_ism *ism,
+ struct dc_stream_state *stream,
+ bool vblank_enabled,
+ bool allow_panel_sso)
+{
+ struct amdgpu_crtc *acrtc = ism_to_amdgpu_crtc(ism);
+ struct amdgpu_device *adev = drm_to_adev(acrtc->base.dev);
+ struct amdgpu_display_manager *dm = &adev->dm;
+ int r;
+
+ trace_amdgpu_dm_ism_commit(dm->active_vblank_irq_count,
+ vblank_enabled,
+ allow_panel_sso);
+
+ /*
+ * If there is an active vblank requestor, or if SSO is being engaged,
+ * then disallow idle optimizations.
+ */
+ if (vblank_enabled || allow_panel_sso)
+ dc_allow_idle_optimizations(dm->dc, false);
+
+ /*
+ * Control PSR based on vblank requirements from OS
+ *
+ * If panel supports PSR SU/Replay, there's no need to exit self-refresh
+ * when OS is submitting fast atomic commits, as they can allow
+ * self-refresh during vblank periods.
+ */
+ if (stream && stream->link) {
+ /*
+ * If allow_panel_sso is true when disabling vblank, allow
+ * deeper panel sleep states such as PSR1 and Replay static
+ * screen optimization.
+ */
+ if (!vblank_enabled && allow_panel_sso) {
+ amdgpu_dm_crtc_set_panel_sr_feature(
+ dm, acrtc, stream, false,
+ acrtc->dm_irq_params.allow_sr_entry);
+ } else if (vblank_enabled) {
+ /* Make sure to exit SSO on vblank enable */
+ amdgpu_dm_crtc_set_panel_sr_feature(
+ dm, acrtc, stream, true,
+ acrtc->dm_irq_params.allow_sr_entry);
+ }
+ /*
+ * Else, vblank_enabled == false and allow_panel_sso == false;
+ * do nothing here.
+ */
+ }
+
+ /*
+ * Check for any active drm vblank requestors on other CRTCs
+ * (dm->active_vblank_irq_count) before allowing HW-wide idle
+ * optimizations.
+ *
+ * There's no need to have a "balanced" check when disallowing idle
+ * optimizations at the start of this func -- we should disallow
+ * whenever there's *an* active CRTC.
+ */
+ if (!vblank_enabled && dm->active_vblank_irq_count == 0) {
+ dc_post_update_surfaces_to_stream(dm->dc);
+
+ r = amdgpu_dpm_pause_power_profile(adev, true);
+ if (r)
+ dev_warn(adev->dev, "failed to set default power profile mode\n");
+
+ dc_allow_idle_optimizations(dm->dc, true);
+
+ r = amdgpu_dpm_pause_power_profile(adev, false);
+ if (r)
+ dev_warn(adev->dev, "failed to restore the power profile mode\n");
+ }
+}
+
+
+static enum amdgpu_dm_ism_event dm_ism_dispatch_power_state(
+ struct amdgpu_dm_ism *ism,
+ struct dm_crtc_state *acrtc_state,
+ enum amdgpu_dm_ism_event event)
+{
+ enum amdgpu_dm_ism_event ret = event;
+ const struct amdgpu_dm_ism_config *config = &ism->config;
+ uint64_t delay_ns, sso_delay_ns;
+
+ switch (ism->previous_state) {
+ case DM_ISM_STATE_HYSTERESIS_WAITING:
+ /*
+ * Stop the timer if it was set, and we're not running from the
+ * idle allow worker.
+ */
+ if (ism->current_state != DM_ISM_STATE_OPTIMIZED_IDLE &&
+ ism->current_state != DM_ISM_STATE_OPTIMIZED_IDLE_SSO)
+ cancel_delayed_work(&ism->delayed_work);
+ break;
+ case DM_ISM_STATE_OPTIMIZED_IDLE:
+ if (ism->current_state == DM_ISM_STATE_OPTIMIZED_IDLE_SSO)
+ break;
+ /* If idle disallow, cancel SSO work and insert record */
+ cancel_delayed_work(&ism->sso_delayed_work);
+ dm_ism_insert_record(ism);
+ dm_ism_commit_idle_optimization_state(ism, acrtc_state->stream,
+ true, false);
+ break;
+ case DM_ISM_STATE_OPTIMIZED_IDLE_SSO:
+ /* Disable idle optimization */
+ dm_ism_insert_record(ism);
+ dm_ism_commit_idle_optimization_state(ism, acrtc_state->stream,
+ true, false);
+ break;
+ default:
+ break;
+ }
+
+ switch (ism->current_state) {
+ case DM_ISM_STATE_HYSTERESIS_WAITING:
+ dm_ism_set_last_idle_ts(ism);
+
+ /* CRTC can be disabled; allow immediate idle */
+ if (!acrtc_state->stream) {
+ ret = DM_ISM_EVENT_IMMEDIATE;
+ break;
+ }
+
+ delay_ns = dm_ism_get_idle_allow_delay(ism,
+ acrtc_state->stream);
+ if (delay_ns == 0) {
+ ret = DM_ISM_EVENT_IMMEDIATE;
+ break;
+ }
+
+ /* Schedule worker */
+ mod_delayed_work(system_unbound_wq, &ism->delayed_work,
+ nsecs_to_jiffies(delay_ns));
+
+ break;
+ case DM_ISM_STATE_OPTIMIZED_IDLE:
+ sso_delay_ns = dm_ism_get_sso_delay(ism, acrtc_state->stream);
+ if (sso_delay_ns == 0)
+ ret = DM_ISM_EVENT_IMMEDIATE;
+ else if (config->sso_num_frames < config->filter_num_frames) {
+ /*
+ * If sso_num_frames is less than hysteresis frames, it
+ * indicates that allowing idle here, then disallowing
+ * idle after sso_num_frames has expired, will likely
+ * have a negative power impact. Skip idle allow here,
+ * and let the sso_delayed_work handle it.
+ */
+ mod_delayed_work(system_unbound_wq,
+ &ism->sso_delayed_work,
+ nsecs_to_jiffies(sso_delay_ns));
+ } else {
+ /* Enable idle optimization without SSO */
+ dm_ism_commit_idle_optimization_state(
+ ism, acrtc_state->stream, false, false);
+ mod_delayed_work(system_unbound_wq,
+ &ism->sso_delayed_work,
+ nsecs_to_jiffies(sso_delay_ns));
+ }
+ break;
+ case DM_ISM_STATE_OPTIMIZED_IDLE_SSO:
+ /* Enable static screen optimizations. */
+ dm_ism_commit_idle_optimization_state(ism, acrtc_state->stream,
+ false, true);
+ break;
+ case DM_ISM_STATE_TIMER_ABORTED:
+ dm_ism_insert_record(ism);
+ dm_ism_commit_idle_optimization_state(ism, acrtc_state->stream,
+ true, false);
+ ret = DM_ISM_EVENT_IMMEDIATE;
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+static char *dm_ism_events_str[DM_ISM_NUM_EVENTS] = {
+ [DM_ISM_EVENT_IMMEDIATE] = "IMMEDIATE",
+ [DM_ISM_EVENT_ENTER_IDLE_REQUESTED] = "ENTER_IDLE_REQUESTED",
+ [DM_ISM_EVENT_EXIT_IDLE_REQUESTED] = "EXIT_IDLE_REQUESTED",
+ [DM_ISM_EVENT_BEGIN_CURSOR_UPDATE] = "BEGIN_CURSOR_UPDATE",
+ [DM_ISM_EVENT_END_CURSOR_UPDATE] = "END_CURSOR_UPDATE",
+ [DM_ISM_EVENT_TIMER_ELAPSED] = "TIMER_ELAPSED",
+ [DM_ISM_EVENT_SSO_TIMER_ELAPSED] = "SSO_TIMER_ELAPSED",
+};
+
+static char *dm_ism_states_str[DM_ISM_NUM_STATES] = {
+ [DM_ISM_STATE_FULL_POWER_RUNNING] = "FULL_POWER_RUNNING",
+ [DM_ISM_STATE_FULL_POWER_BUSY] = "FULL_POWER_BUSY",
+ [DM_ISM_STATE_HYSTERESIS_WAITING] = "HYSTERESIS_WAITING",
+ [DM_ISM_STATE_HYSTERESIS_BUSY] = "HYSTERESIS_BUSY",
+ [DM_ISM_STATE_OPTIMIZED_IDLE] = "OPTIMIZED_IDLE",
+ [DM_ISM_STATE_OPTIMIZED_IDLE_SSO] = "OPTIMIZED_IDLE_SSO",
+ [DM_ISM_STATE_TIMER_ABORTED] = "TIMER_ABORTED",
+};
+
+
+void amdgpu_dm_ism_commit_event(struct amdgpu_dm_ism *ism,
+ enum amdgpu_dm_ism_event event)
+{
+ enum amdgpu_dm_ism_event next_event = event;
+ struct amdgpu_crtc *acrtc = ism_to_amdgpu_crtc(ism);
+ struct amdgpu_device *adev = drm_to_adev(acrtc->base.dev);
+ struct amdgpu_display_manager *dm = &adev->dm;
+ struct dm_crtc_state *acrtc_state = to_dm_crtc_state(acrtc->base.state);
+
+ /* ISM transitions must be called with mutex acquired */
+ ASSERT(mutex_is_locked(&dm->dc_lock));
+
+ if (!acrtc_state) {
+ trace_amdgpu_dm_ism_event(acrtc->crtc_id, "NO_STATE",
+ "NO_STATE", "N/A");
+ return;
+ }
+
+ do {
+ bool transition = dm_ism_trigger_event(ism, event);
+
+ next_event = DM_ISM_NUM_EVENTS;
+ if (transition) {
+ trace_amdgpu_dm_ism_event(
+ acrtc->crtc_id,
+ dm_ism_states_str[ism->previous_state],
+ dm_ism_states_str[ism->current_state],
+ dm_ism_events_str[event]);
+ next_event = dm_ism_dispatch_power_state(
+ ism, acrtc_state, next_event);
+ } else {
+ trace_amdgpu_dm_ism_event(
+ acrtc->crtc_id,
+ dm_ism_states_str[ism->current_state],
+ dm_ism_states_str[ism->current_state],
+ dm_ism_events_str[event]);
+ }
+
+ event = next_event;
+
+ } while (next_event < DM_ISM_NUM_EVENTS);
+}
+
+
+static void dm_ism_delayed_work_func(struct work_struct *work)
+{
+ struct amdgpu_dm_ism *ism =
+ container_of(work, struct amdgpu_dm_ism, delayed_work.work);
+ struct amdgpu_crtc *acrtc = ism_to_amdgpu_crtc(ism);
+ struct amdgpu_device *adev = drm_to_adev(acrtc->base.dev);
+ struct amdgpu_display_manager *dm = &adev->dm;
+
+ guard(mutex)(&dm->dc_lock);
+
+ amdgpu_dm_ism_commit_event(ism, DM_ISM_EVENT_TIMER_ELAPSED);
+}
+
+static void dm_ism_sso_delayed_work_func(struct work_struct *work)
+{
+ struct amdgpu_dm_ism *ism =
+ container_of(work, struct amdgpu_dm_ism, sso_delayed_work.work);
+ struct amdgpu_crtc *acrtc = ism_to_amdgpu_crtc(ism);
+ struct amdgpu_device *adev = drm_to_adev(acrtc->base.dev);
+ struct amdgpu_display_manager *dm = &adev->dm;
+
+ guard(mutex)(&dm->dc_lock);
+
+ amdgpu_dm_ism_commit_event(ism, DM_ISM_EVENT_SSO_TIMER_ELAPSED);
+}
+
+/**
+ * amdgpu_dm_ism_disable - Disable the ISM
+ *
+ * @dm: The amdgpu display manager
+ *
+ * Disable the idle state manager by disabling any ISM work, canceling pending
+ * work, and waiting for in-progress work to finish. After disabling, the system
+ * is left in DM_ISM_STATE_FULL_POWER_RUNNING state.
+ */
+void amdgpu_dm_ism_disable(struct amdgpu_display_manager *dm)
+{
+ struct drm_crtc *crtc;
+ struct amdgpu_crtc *acrtc;
+ struct amdgpu_dm_ism *ism;
+
+ drm_for_each_crtc(crtc, dm->ddev) {
+ acrtc = to_amdgpu_crtc(crtc);
+ ism = &acrtc->ism;
+
+ /* Cancel and disable any pending work */
+ disable_delayed_work_sync(&ism->delayed_work);
+ disable_delayed_work_sync(&ism->sso_delayed_work);
+
+ /*
+ * When disabled, leave in FULL_POWER_RUNNING state.
+ * EXIT_IDLE will not queue any work
+ */
+ amdgpu_dm_ism_commit_event(ism,
+ DM_ISM_EVENT_EXIT_IDLE_REQUESTED);
+ }
+}
+
+/**
+ * amdgpu_dm_ism_enable - enable the ISM
+ *
+ * @dm: The amdgpu display manager
+ *
+ * Re-enable the idle state manager by enabling work that was disabled by
+ * amdgpu_dm_ism_disable.
+ */
+void amdgpu_dm_ism_enable(struct amdgpu_display_manager *dm)
+{
+ struct drm_crtc *crtc;
+ struct amdgpu_crtc *acrtc;
+ struct amdgpu_dm_ism *ism;
+
+ drm_for_each_crtc(crtc, dm->ddev) {
+ acrtc = to_amdgpu_crtc(crtc);
+ ism = &acrtc->ism;
+
+ enable_delayed_work(&ism->delayed_work);
+ enable_delayed_work(&ism->sso_delayed_work);
+ }
+}
+
+void amdgpu_dm_ism_init(struct amdgpu_dm_ism *ism,
+ struct amdgpu_dm_ism_config *config)
+{
+ ism->config = *config;
+
+ ism->current_state = DM_ISM_STATE_FULL_POWER_RUNNING;
+ ism->previous_state = DM_ISM_STATE_FULL_POWER_RUNNING;
+ ism->next_record_idx = 0;
+ ism->last_idle_timestamp_ns = 0;
+
+ INIT_DELAYED_WORK(&ism->delayed_work, dm_ism_delayed_work_func);
+ INIT_DELAYED_WORK(&ism->sso_delayed_work, dm_ism_sso_delayed_work_func);
+}
+
+
+void amdgpu_dm_ism_fini(struct amdgpu_dm_ism *ism)
+{
+ cancel_delayed_work_sync(&ism->sso_delayed_work);
+ cancel_delayed_work_sync(&ism->delayed_work);
+}
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.h
new file mode 100644
index 000000000000..fde0ddc8d4e4
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.h
@@ -0,0 +1,151 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2026 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __AMDGPU_DM_ISM_H__
+#define __AMDGPU_DM_ISM_H__
+
+#include <linux/workqueue.h>
+
+struct amdgpu_crtc;
+struct amdgpu_display_manager;
+
+#define AMDGPU_DM_IDLE_HIST_LEN 16
+
+enum amdgpu_dm_ism_state {
+ DM_ISM_STATE_FULL_POWER_RUNNING,
+ DM_ISM_STATE_FULL_POWER_BUSY,
+ DM_ISM_STATE_HYSTERESIS_WAITING,
+ DM_ISM_STATE_HYSTERESIS_BUSY,
+ DM_ISM_STATE_OPTIMIZED_IDLE,
+ DM_ISM_STATE_OPTIMIZED_IDLE_SSO,
+ DM_ISM_STATE_TIMER_ABORTED,
+ DM_ISM_NUM_STATES,
+};
+
+enum amdgpu_dm_ism_event {
+ DM_ISM_EVENT_IMMEDIATE,
+ DM_ISM_EVENT_ENTER_IDLE_REQUESTED,
+ DM_ISM_EVENT_EXIT_IDLE_REQUESTED,
+ DM_ISM_EVENT_BEGIN_CURSOR_UPDATE,
+ DM_ISM_EVENT_END_CURSOR_UPDATE,
+ DM_ISM_EVENT_TIMER_ELAPSED,
+ DM_ISM_EVENT_SSO_TIMER_ELAPSED,
+ DM_ISM_NUM_EVENTS,
+};
+
+#define STATE_EVENT(state, event) (((state) << 8) | (event))
+
+struct amdgpu_dm_ism_config {
+
+ /**
+ * @filter_num_frames: Idle periods shorter than this number of frames
+ * will be considered a "short idle period" for filtering.
+ *
+ * 0 indicates no filtering (i.e. no idle allow delay will be applied)
+ */
+ unsigned int filter_num_frames;
+
+ /**
+ * @filter_history_size: Number of recent idle periods to consider when
+ * counting the number of short idle periods.
+ */
+ unsigned int filter_history_size;
+
+ /**
+ * @filter_entry_count: When the number of short idle periods within
+ * recent &filter_history_size reaches this count, the idle allow delay
+ * will be applied.
+ *
+ * 0 indicates no filtering (i.e. no idle allow delay will be applied)
+ */
+ unsigned int filter_entry_count;
+
+ /**
+ * @activation_num_delay_frames: Defines the number of frames to wait
+ * for the idle allow delay.
+ *
+ * 0 indicates no filtering (i.e. no idle allow delay will be applied)
+ */
+ unsigned int activation_num_delay_frames;
+
+ /**
+ * @filter_old_history_threshold: A time-based restriction on top of
+ * &filter_history_size. Idle periods older than this threshold (in
+ * number of frames) will be ignored when counting the number of short
+ * idle periods.
+ *
+ * 0 indicates no time-based restriction, i.e. history is limited only
+ * by &filter_history_size.
+ */
+ unsigned int filter_old_history_threshold;
+
+ /**
+ * @sso_num_frames: Number of frames to delay before enabling static
+ * screen optimizations, such as PSR1 and Replay low HZ idle mode.
+ *
+ * 0 indicates immediate SSO enable upon allowing idle.
+ */
+ unsigned int sso_num_frames;
+};
+
+struct amdgpu_dm_ism_record {
+ /**
+ * @timestamp_ns: When idle was allowed
+ */
+ unsigned long long timestamp_ns;
+
+ /**
+ * @duration_ns: How long idle was allowed
+ */
+ unsigned long long duration_ns;
+};
+
+struct amdgpu_dm_ism {
+ struct amdgpu_dm_ism_config config;
+ unsigned long long last_idle_timestamp_ns;
+
+ enum amdgpu_dm_ism_state current_state;
+ enum amdgpu_dm_ism_state previous_state;
+
+ struct amdgpu_dm_ism_record records[AMDGPU_DM_IDLE_HIST_LEN];
+ int next_record_idx;
+
+ struct delayed_work delayed_work;
+ struct delayed_work sso_delayed_work;
+};
+
+#define ism_to_amdgpu_crtc(ism_ptr) \
+ container_of(ism_ptr, struct amdgpu_crtc, ism)
+
+void amdgpu_dm_ism_init(struct amdgpu_dm_ism *ism,
+ struct amdgpu_dm_ism_config *config);
+void amdgpu_dm_ism_fini(struct amdgpu_dm_ism *ism);
+void amdgpu_dm_ism_commit_event(struct amdgpu_dm_ism *ism,
+ enum amdgpu_dm_ism_event event);
+void amdgpu_dm_ism_disable(struct amdgpu_display_manager *dm);
+void amdgpu_dm_ism_enable(struct amdgpu_display_manager *dm);
+
+#endif
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 7be50e8c0636..5d8c4c7020b1 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
@@ -1744,9 +1744,11 @@ int pre_validate_dsc(struct drm_atomic_state *state,
int ind = find_crtc_index_in_state_by_stream(state, stream);
if (ind >= 0) {
+ struct dm_crtc_state *dm_new_crtc_state = to_dm_crtc_state(state->crtcs[ind].new_state);
+
DRM_INFO_ONCE("%s:%d MST_DSC no mode changed for stream 0x%p\n",
__func__, __LINE__, stream);
- state->crtcs[ind].new_state->mode_changed = 0;
+ dm_new_crtc_state->base.mode_changed = dm_new_crtc_state->mode_changed_independent_from_dsc;
}
}
}
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
index d8c69fc94abb..81e43534ec59 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
@@ -62,9 +62,6 @@ static const uint32_t rgb_formats[] = {
DRM_FORMAT_XBGR8888,
DRM_FORMAT_ABGR8888,
DRM_FORMAT_RGB565,
- DRM_FORMAT_NV21,
- DRM_FORMAT_NV12,
- DRM_FORMAT_P010
};
static const uint32_t overlay_formats[] = {
@@ -707,21 +704,21 @@ static void amdgpu_dm_plane_add_gfx12_modifiers(struct amdgpu_device *adev,
uint8_t max_comp_block[] = {2, 1, 0};
uint64_t max_comp_block_mod[ARRAY_SIZE(max_comp_block)] = {0};
uint8_t i = 0, j = 0;
- uint64_t gfx12_modifiers[] = {mod_256k, mod_64k, mod_4k, mod_256b, DRM_FORMAT_MOD_LINEAR};
+ /* Note, linear (no DCC) gets added to the modifier list for all chips by the caller. */
+ uint64_t gfx12_modifiers[] = {mod_256k, mod_64k, mod_4k, mod_256b};
for (i = 0; i < ARRAY_SIZE(max_comp_block); i++)
max_comp_block_mod[i] = AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, max_comp_block[i]);
/* With DCC: Best choice should be kept first. Hence, add all 256k modifiers of different
* max compressed blocks first and then move on to the next smaller sized layouts.
- * Do not add the linear modifier here, and hence the condition of size-1 for the loop
*/
- for (j = 0; j < ARRAY_SIZE(gfx12_modifiers) - 1; j++)
+ for (j = 0; j < ARRAY_SIZE(gfx12_modifiers); j++)
for (i = 0; i < ARRAY_SIZE(max_comp_block); i++)
amdgpu_dm_plane_add_modifier(mods, size, capacity,
ver | dcc | max_comp_block_mod[i] | gfx12_modifiers[j]);
- /* Without DCC. Add all modifiers including linear at the end */
+ /* Without DCC. */
for (i = 0; i < ARRAY_SIZE(gfx12_modifiers); i++)
amdgpu_dm_plane_add_modifier(mods, size, capacity, gfx12_modifiers[i]);
@@ -957,11 +954,9 @@ static int amdgpu_dm_plane_helper_prepare_fb(struct drm_plane *plane,
return r;
}
- r = dma_resv_reserve_fences(rbo->tbo.base.resv, 1);
- if (r) {
- drm_err(adev_to_drm(adev), "reserving fence slot failed (%d)\n", r);
+ r = dma_resv_reserve_fences(rbo->tbo.base.resv, TTM_NUM_MOVE_FENCES);
+ if (r)
goto error_unlock;
- }
if (plane->type != DRM_PLANE_TYPE_CURSOR)
domain = amdgpu_display_supported_domains(adev, rbo->flags);
@@ -1377,8 +1372,16 @@ void amdgpu_dm_plane_handle_cursor_update(struct drm_plane *plane,
/* turn off cursor */
if (crtc_state && crtc_state->stream) {
mutex_lock(&adev->dm.dc_lock);
+ amdgpu_dm_ism_commit_event(
+ &amdgpu_crtc->ism,
+ DM_ISM_EVENT_BEGIN_CURSOR_UPDATE);
+
dc_stream_program_cursor_position(crtc_state->stream,
&position);
+
+ amdgpu_dm_ism_commit_event(
+ &amdgpu_crtc->ism,
+ DM_ISM_EVENT_END_CURSOR_UPDATE);
mutex_unlock(&adev->dm.dc_lock);
}
return;
@@ -1408,6 +1411,10 @@ void amdgpu_dm_plane_handle_cursor_update(struct drm_plane *plane,
if (crtc_state->stream) {
mutex_lock(&adev->dm.dc_lock);
+ amdgpu_dm_ism_commit_event(
+ &amdgpu_crtc->ism,
+ DM_ISM_EVENT_BEGIN_CURSOR_UPDATE);
+
if (!dc_stream_program_cursor_attributes(crtc_state->stream,
&attributes))
DRM_ERROR("DC failed to set cursor attributes\n");
@@ -1415,6 +1422,10 @@ void amdgpu_dm_plane_handle_cursor_update(struct drm_plane *plane,
if (!dc_stream_program_cursor_position(crtc_state->stream,
&position))
DRM_ERROR("DC failed to set cursor position\n");
+
+ amdgpu_dm_ism_commit_event(
+ &amdgpu_crtc->ism,
+ DM_ISM_EVENT_END_CURSOR_UPDATE);
mutex_unlock(&adev->dm.dc_lock);
}
}
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
index aa56fd6d56c3..e0fab8878d19 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
@@ -753,6 +753,69 @@ TRACE_EVENT(amdgpu_dm_brightness,
)
);
+TRACE_EVENT(amdgpu_dm_ism_commit,
+ TP_PROTO(
+ int active_vblank_irq_count,
+ bool vblank_enabled,
+ bool allow_panel_sso
+ ),
+ TP_ARGS(
+ active_vblank_irq_count,
+ vblank_enabled,
+ allow_panel_sso
+ ),
+ TP_STRUCT__entry(
+ __field(int, active_vblank_irq_count)
+ __field(bool, vblank_enabled)
+ __field(bool, allow_panel_sso)
+ ),
+ TP_fast_assign(
+ __entry->active_vblank_irq_count = active_vblank_irq_count;
+ __entry->vblank_enabled = vblank_enabled;
+ __entry->allow_panel_sso = allow_panel_sso;
+ ),
+ TP_printk(
+ "active_vblank_irq_count=%d vblank_enabled=%d allow_panel_sso=%d",
+ __entry->active_vblank_irq_count,
+ __entry->vblank_enabled,
+ __entry->allow_panel_sso
+ )
+);
+
+TRACE_EVENT(amdgpu_dm_ism_event,
+ TP_PROTO(
+ int crtc_id,
+ const char *prev_state,
+ const char *curr_state,
+ const char *event
+ ),
+ TP_ARGS(
+ crtc_id,
+ prev_state,
+ curr_state,
+ event
+ ),
+ TP_STRUCT__entry(
+ __field(int, crtc_id)
+ __string(prev_state, prev_state)
+ __string(curr_state, curr_state)
+ __string(event, event)
+ ),
+ TP_fast_assign(
+ __entry->crtc_id = crtc_id;
+ __assign_str(prev_state);
+ __assign_str(curr_state);
+ __assign_str(event);
+ ),
+ TP_printk(
+ "[CRTC %d] %s -> %s on event %s",
+ __entry->crtc_id,
+ __get_str(prev_state),
+ __get_str(curr_state),
+ __get_str(event))
+);
+
+
#endif /* _AMDGPU_DM_TRACE_H_ */
#undef TRACE_INCLUDE_PATH
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c
index d9527c05fc87..110f0173eee6 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c
@@ -106,11 +106,9 @@ static int amdgpu_dm_wb_prepare_job(struct drm_writeback_connector *wb_connector
return r;
}
- r = dma_resv_reserve_fences(rbo->tbo.base.resv, 1);
- if (r) {
- drm_err(adev_to_drm(adev), "reserving fence slot failed (%d)\n", r);
+ r = dma_resv_reserve_fences(rbo->tbo.base.resv, TTM_NUM_MOVE_FENCES);
+ if (r)
goto error_unlock;
- }
domain = amdgpu_display_supported_domains(adev, rbo->flags);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
index e46f8ce41d87..8ba9b4f56f87 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
@@ -53,12 +53,31 @@ inline void dc_assert_fp_enabled(void)
{
int depth;
- depth = __this_cpu_read(fpu_recursion_depth);
+ depth = this_cpu_read(fpu_recursion_depth);
ASSERT(depth >= 1);
}
/**
+ * dc_assert_fp_enabled - Check if FPU protection is enabled
+ *
+ * This function tells if the code is already under FPU protection or not. A
+ * function that works as an API for a set of FPU operations can use this
+ * function for checking if the caller invoked it after DC_FP_START(). For
+ * example, take a look at dcn20_fpu.c file.
+ *
+ * Similar to dc_assert_fp_enabled, but does not assert, returns status instead.
+ */
+inline bool dc_is_fp_enabled(void)
+{
+ int depth;
+
+ depth = this_cpu_read(fpu_recursion_depth);
+
+ return (depth >= 1);
+}
+
+/**
* dc_fpu_begin - Enables FPU protection
* @function_name: A string containing the function name for debug purposes
* (usually __func__)
@@ -77,7 +96,7 @@ void dc_fpu_begin(const char *function_name, const int line)
WARN_ON_ONCE(!in_task());
preempt_disable();
- depth = __this_cpu_inc_return(fpu_recursion_depth);
+ depth = this_cpu_inc_return(fpu_recursion_depth);
if (depth == 1) {
BUG_ON(!kernel_fpu_available());
kernel_fpu_begin();
@@ -100,7 +119,7 @@ void dc_fpu_end(const char *function_name, const int line)
{
int depth;
- depth = __this_cpu_dec_return(fpu_recursion_depth);
+ depth = this_cpu_dec_return(fpu_recursion_depth);
if (depth == 0) {
kernel_fpu_end();
} else {
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.h b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.h
index 4e921632bc4e..5e95419d3798 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.h
@@ -28,15 +28,30 @@
#define __DC_FPU_H__
void dc_assert_fp_enabled(void);
+bool dc_is_fp_enabled(void);
void dc_fpu_begin(const char *function_name, const int line);
void dc_fpu_end(const char *function_name, const int line);
#ifndef _LINUX_FPU_COMPILATION_UNIT
#define DC_FP_START() dc_fpu_begin(__func__, __LINE__)
#define DC_FP_END() dc_fpu_end(__func__, __LINE__)
+#ifdef CONFIG_DRM_AMD_DC_FP
+#define DC_RUN_WITH_PREEMPTION_ENABLED(code) \
+ do { \
+ bool dc_fp_enabled = dc_is_fp_enabled(); \
+ if (dc_fp_enabled) \
+ DC_FP_END(); \
+ code; \
+ if (dc_fp_enabled) \
+ DC_FP_START(); \
+ } while (0)
+#else
+#define DC_RUN_WITH_PREEMPTION_ENABLED(code) code
+#endif // !CONFIG_DRM_AMD_DC_FP
#else
#define DC_FP_START() BUILD_BUG()
#define DC_FP_END() BUILD_BUG()
-#endif
+#define DC_RUN_WITH_PREEMPTION_ENABLED(code) code
+#endif // !_LINUX_FPU_COMPILATION_UNIT
#endif /* __DC_FPU_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/basics/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/basics/dce_calcs.c
index 8c54c02a0e26..f37a43f4172e 100644
--- a/drivers/gpu/drm/amd/display/dc/basics/dce_calcs.c
+++ b/drivers/gpu/drm/amd/display/dc/basics/dce_calcs.c
@@ -2010,10 +2010,10 @@ static void calculate_bandwidth(
}
/*output link bit per pixel supported*/
for (k = 0; k <= maximum_number_of_surfaces - 1; k++) {
- data->output_bpphdmi[k] = bw_def_na;
- data->output_bppdp4_lane_hbr[k] = bw_def_na;
- data->output_bppdp4_lane_hbr2[k] = bw_def_na;
- data->output_bppdp4_lane_hbr3[k] = bw_def_na;
+ data->output_bpphdmi[k] = (uint32_t)bw_def_na;
+ data->output_bppdp4_lane_hbr[k] = (uint32_t)bw_def_na;
+ data->output_bppdp4_lane_hbr2[k] = (uint32_t)bw_def_na;
+ data->output_bppdp4_lane_hbr3[k] = (uint32_t)bw_def_na;
if (data->enable[k]) {
data->output_bpphdmi[k] = bw_fixed_to_int(bw_mul(bw_div(bw_min2(bw_int_to_fixed(600), data->max_phyclk), data->pixel_rate[k]), bw_int_to_fixed(24)));
if (bw_meq(data->max_phyclk, bw_int_to_fixed(270))) {
diff --git a/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c b/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c
index 6073cadde76c..fa10f85df3db 100644
--- a/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c
+++ b/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c
@@ -503,6 +503,7 @@ struct fixed31_32 dc_fixpt_from_int_dy(unsigned int int_value,
unsigned int integer_bits,
unsigned int fractional_bits)
{
+ (void)integer_bits;
struct fixed31_32 fixpt_value = dc_fixpt_from_int(int_value);
fixpt_value.value |= (long long)frac_value << (FIXED31_32_BITS_PER_FRACTIONAL_PART - fractional_bits);
diff --git a/drivers/gpu/drm/amd/display/dc/basics/vector.c b/drivers/gpu/drm/amd/display/dc/basics/vector.c
index a8b750ff8573..e8736c134b8d 100644
--- a/drivers/gpu/drm/amd/display/dc/basics/vector.c
+++ b/drivers/gpu/drm/amd/display/dc/basics/vector.c
@@ -56,6 +56,7 @@ static bool dal_vector_presized_costruct(struct vector *vector,
void *initial_value,
uint32_t struct_size)
{
+ (void)ctx;
uint32_t i;
vector->container = NULL;
diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
index f947f82013c6..dd362071a6c9 100644
--- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
+++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
@@ -1963,7 +1963,7 @@ static enum bp_result get_gpio_i2c_info(struct bios_parser *bp,
count = (le16_to_cpu(header->sHeader.usStructureSize)
- sizeof(ATOM_COMMON_TABLE_HEADER))
/ sizeof(ATOM_GPIO_I2C_ASSIGMENT);
- if (count < record->sucI2cId.bfI2C_LineMux)
+ if (count <= record->sucI2cId.bfI2C_LineMux)
return BP_RESULT_BADBIOSTABLE;
/* get the GPIO_I2C_INFO */
@@ -2696,6 +2696,7 @@ static enum bp_result update_slot_layout_info(struct dc_bios *dcb,
struct slot_layout_info *slot_layout_info,
unsigned int record_offset)
{
+ (void)i;
unsigned int j;
struct bios_parser *bp;
ATOM_BRACKET_LAYOUT_RECORD *record;
diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
index 94fddf22f5a9..a1c08e1cc411 100644
--- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
+++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
@@ -205,6 +205,7 @@ static enum bp_result bios_parser_get_src_obj(struct dc_bios *dcb,
struct graphics_object_id object_id, uint32_t index,
struct graphics_object_id *src_object_id)
{
+ (void)index;
struct bios_parser *bp = BP_FROM_DCB(dcb);
unsigned int i;
enum bp_result bp_result = BP_RESULT_BADINPUT;
@@ -765,6 +766,7 @@ static enum bp_result bios_parser_get_device_tag(
uint32_t device_tag_index,
struct connector_device_tag_info *info)
{
+ (void)device_tag_index;
struct bios_parser *bp = BP_FROM_DCB(dcb);
struct atom_display_object_path_v2 *object;
@@ -809,6 +811,7 @@ static enum bp_result get_ss_info_v4_1(
uint32_t index,
struct spread_spectrum_info *ss_info)
{
+ (void)index;
enum bp_result result = BP_RESULT_OK;
struct atom_display_controller_info_v4_1 *disp_cntl_tbl = NULL;
struct atom_smu_info_v3_3 *smu_info = NULL;
@@ -897,6 +900,7 @@ static enum bp_result get_ss_info_v4_2(
uint32_t index,
struct spread_spectrum_info *ss_info)
{
+ (void)index;
enum bp_result result = BP_RESULT_OK;
struct atom_display_controller_info_v4_2 *disp_cntl_tbl = NULL;
struct atom_smu_info_v3_1 *smu_info = NULL;
@@ -977,6 +981,7 @@ static enum bp_result get_ss_info_v4_5(
uint32_t index,
struct spread_spectrum_info *ss_info)
{
+ (void)index;
enum bp_result result = BP_RESULT_OK;
struct atom_display_controller_info_v4_5 *disp_cntl_tbl = NULL;
@@ -1604,6 +1609,8 @@ static uint32_t bios_parser_get_ss_entry_number(
struct dc_bios *dcb,
enum as_signal_type signal)
{
+ (void)dcb;
+ (void)signal;
/* TODO: DAL2 atomfirmware implementation does not need this.
* why DAL3 need this?
*/
@@ -3536,6 +3543,8 @@ static uint16_t bios_parser_pack_data_tables(
struct dc_bios *dcb,
void *dst)
{
+ (void)dcb;
+ (void)dst;
// TODO: There is data bytes alignment issue, disable it for now.
return 0;
}
diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c
index f2b1720a6a66..17ef515c6c69 100644
--- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c
+++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c
@@ -783,6 +783,8 @@ static enum bp_result external_encoder_control_v3(
struct bios_parser *bp,
struct bp_external_encoder_control *cntl)
{
+ (void)bp;
+ (void)cntl;
/* TODO */
return BP_RESULT_OK;
}
diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c b/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c
index 3099128223df..cec61c9d7263 100644
--- a/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c
+++ b/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c
@@ -94,6 +94,7 @@ static uint8_t hpd_sel_to_atom(enum hpd_source_id id)
static uint8_t dig_encoder_sel_to_atom(enum engine_id id)
{
+ (void)id;
/* On any ASIC after DCE80, we manually program the DIG_FE
* selection (see connect_dig_be_to_fe function of the link
* encoder), so translation should always return 0 (no FE).
diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c
index 349f0e5d5856..478465fba224 100644
--- a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c
+++ b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c
@@ -93,6 +93,7 @@ static uint8_t hpd_sel_to_atom(enum hpd_source_id id)
static uint8_t dig_encoder_sel_to_atom(enum engine_id id)
{
+ (void)id;
/* On any ASIC after DCE80, we manually program the DIG_FE
* selection (see connect_dig_be_to_fe function of the link
* encoder), so translation should always return 0 (no FE).
diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c
index 1a5fefcde8af..6b8a87f2c49e 100644
--- a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c
+++ b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c
@@ -91,6 +91,7 @@ static uint8_t hpd_sel_to_atom(enum hpd_source_id id)
static uint8_t dig_encoder_sel_to_atom(enum engine_id id)
{
+ (void)id;
/* On any ASIC after DCE80, we manually program the DIG_FE
* selection (see connect_dig_be_to_fe function of the link
* encoder), so translation should always return 0 (no FE).
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c
index e91636d033c7..880bce368238 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c
@@ -78,6 +78,7 @@ int clk_mgr_helper_get_active_plane_cnt(
struct dc *dc,
struct dc_state *context)
{
+ (void)dc;
int i, total_plane_count;
total_plane_count = 0;
@@ -97,7 +98,7 @@ void clk_mgr_exit_optimized_pwr_state(const struct dc *dc, struct clk_mgr *clk_m
{
struct dc_link *edp_links[MAX_NUM_EDP];
struct dc_link *edp_link = NULL;
- int edp_num;
+ unsigned int edp_num;
unsigned int panel_inst;
dc_get_edp_links(dc, edp_links, &edp_num);
@@ -123,7 +124,7 @@ void clk_mgr_optimize_pwr_state(const struct dc *dc, struct clk_mgr *clk_mgr)
{
struct dc_link *edp_links[MAX_NUM_EDP];
struct dc_link *edp_link = NULL;
- int edp_num;
+ unsigned int edp_num;
unsigned int panel_inst;
dc_get_edp_links(dc, edp_links, &edp_num);
@@ -244,6 +245,10 @@ struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *p
BREAK_TO_DEBUGGER();
return NULL;
}
+ if (ctx->dce_version == DCN_VERSION_2_01) {
+ dcn201_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg);
+ return &clk_mgr->base;
+ }
if (ASICREV_IS_SIENNA_CICHLID_P(asic_id.hw_internal_rev)) {
dcn3_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg);
return &clk_mgr->base;
@@ -256,10 +261,6 @@ struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *p
dcn3_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg);
return &clk_mgr->base;
}
- if (ctx->dce_version == DCN_VERSION_2_01) {
- dcn201_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg);
- return &clk_mgr->base;
- }
dcn20_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg);
return &clk_mgr->base;
}
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c
index d50b9440210e..cd4c45516616 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c
@@ -92,7 +92,7 @@ static int determine_sclk_from_bounding_box(
uint32_t dce110_get_min_vblank_time_us(const struct dc_state *context)
{
uint8_t j;
- uint32_t min_vertical_blank_time = -1;
+ uint32_t min_vertical_blank_time = (uint32_t)-1;
for (j = 0; j < context->stream_count; j++) {
struct dc_stream_state *stream = context->streams[j];
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
index e18097f82091..09e83097a623 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
@@ -740,7 +740,8 @@ void rn_clk_mgr_construct(
if (clk_mgr->base.dentist_vco_freq_khz == 0)
clk_mgr->base.dentist_vco_freq_khz = 3600000;
- if (ctx->dc_bios->integrated_info->memory_type == LpDdr4MemType) {
+ if (ctx->dc_bios->integrated_info &&
+ ctx->dc_bios->integrated_info->memory_type == LpDdr4MemType) {
if (clk_mgr->periodic_retraining_disabled) {
rn_bw_params.wm_table = lpddr4_wm_table_with_disabled_ppt;
} else {
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c
index b48522480dfd..dcec9d0f8c34 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c
@@ -421,10 +421,8 @@ static void dcn3_get_memclk_states_from_smu(struct clk_mgr *clk_mgr_base)
clk_mgr_base->bw_params->dc_mode_softmax_memclk = dcn30_smu_get_dc_mode_max_dpm_freq(clk_mgr, PPCLK_UCLK);
/* Refresh bounding box */
- DC_FP_START();
clk_mgr_base->ctx->dc->res_pool->funcs->update_bw_bounding_box(
clk_mgr->base.ctx->dc, clk_mgr_base->bw_params);
- DC_FP_END();
}
static bool dcn3_is_smu_present(struct clk_mgr *clk_mgr_base)
@@ -523,6 +521,7 @@ void dcn3_clk_mgr_construct(
struct pp_smu_funcs *pp_smu,
struct dccg *dccg)
{
+ (void)pp_smu;
struct clk_state_registers_and_bypass s = { 0 };
clk_mgr->base.ctx = ctx;
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c
index 7aee02d56292..57ba7bc4d16e 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c
@@ -733,11 +733,12 @@ void vg_clk_mgr_construct(
if (clk_mgr->base.base.dentist_vco_freq_khz == 0)
clk_mgr->base.base.dentist_vco_freq_khz = 3600000;
- if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) {
+ if (ctx->dc_bios->integrated_info &&
+ ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType)
vg_bw_params.wm_table = lpddr5_wm_table;
- } else {
+ else
vg_bw_params.wm_table = ddr4_wm_table;
- }
+
/* Saved clocks configured at boot for debug purposes */
vg_dump_clk_registers(&clk_mgr->base.base.boot_snapshot, &clk_mgr->base.base, &log_info);
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c
index 051052bd10c9..89fc482947ef 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c
@@ -329,6 +329,9 @@ bool dcn31_are_clock_states_equal(struct dc_clocks *a,
static void dcn31_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
struct clk_mgr *clk_mgr_base, struct clk_log_info *log_info)
{
+ (void)regs_and_bypass;
+ (void)clk_mgr_base;
+ (void)log_info;
return;
}
@@ -725,11 +728,12 @@ void dcn31_clk_mgr_construct(
/* TODO: Check we get what we expect during bringup */
clk_mgr->base.base.dentist_vco_freq_khz = get_vco_frequency_from_reg(&clk_mgr->base);
- if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) {
+ if (ctx->dc_bios->integrated_info &&
+ ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType)
dcn31_bw_params.wm_table = lpddr5_wm_table;
- } else {
+ else
dcn31_bw_params.wm_table = ddr5_wm_table;
- }
+
/* Saved clocks configured at boot for debug purposes */
dcn31_dump_clk_registers(&clk_mgr->base.base.boot_snapshot,
&clk_mgr->base.base, &log_info);
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 0cb37827a62b..b08a70a2f571 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
@@ -395,6 +395,9 @@ bool dcn314_are_clock_states_equal(struct dc_clocks *a,
static void dcn314_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
struct clk_mgr *clk_mgr_base, struct clk_log_info *log_info)
{
+ (void)regs_and_bypass;
+ (void)clk_mgr_base;
+ (void)log_info;
return;
}
@@ -842,7 +845,8 @@ void dcn314_clk_mgr_construct(
/* TODO: Check we get what we expect during bringup */
clk_mgr->base.base.dentist_vco_freq_khz = get_vco_frequency_from_reg(&clk_mgr->base);
- if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType)
+ if (ctx->dc_bios->integrated_info &&
+ ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType)
dcn314_bw_params.wm_table = lpddr5_wm_table;
else
dcn314_bw_params.wm_table = ddr5_wm_table;
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 c49268db85f6..3a651c1a866d 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
@@ -247,6 +247,9 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base,
static void dcn315_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
struct clk_mgr *clk_mgr_base, struct clk_log_info *log_info)
{
+ (void)regs_and_bypass;
+ (void)clk_mgr_base;
+ (void)log_info;
return;
}
@@ -652,11 +655,12 @@ void dcn315_clk_mgr_construct(
if (clk_mgr->base.smu_ver > 0)
clk_mgr->base.smu_present = true;
- if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) {
+ if (ctx->dc_bios->integrated_info &&
+ ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType)
dcn315_bw_params.wm_table = lpddr5_wm_table;
- } else {
+ else
dcn315_bw_params.wm_table = ddr5_wm_table;
- }
+
/* Saved clocks configured at boot for debug purposes */
dcn315_dump_clk_registers(&clk_mgr->base.base.boot_snapshot,
&clk_mgr->base.base, &log_info);
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c
index 1769b1f26e75..e9d492d8c8d4 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c
@@ -255,6 +255,9 @@ static void dcn316_update_clocks(struct clk_mgr *clk_mgr_base,
static void dcn316_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
struct clk_mgr *clk_mgr_base, struct clk_log_info *log_info)
{
+ (void)regs_and_bypass;
+ (void)clk_mgr_base;
+ (void)log_info;
return;
}
@@ -636,11 +639,12 @@ void dcn316_clk_mgr_construct(
clk_mgr->base.base.dentist_vco_freq_khz = 2500000; /* 2400MHz */
- if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) {
+ if (ctx->dc_bios->integrated_info &&
+ ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType)
dcn316_bw_params.wm_table = lpddr5_wm_table;
- } else {
+ else
dcn316_bw_params.wm_table = ddr4_wm_table;
- }
+
/* Saved clocks configured at boot for debug purposes */
dcn316_dump_clk_registers(&clk_mgr->base.base.boot_snapshot,
&clk_mgr->base.base, &log_info);
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
index 2856b0337e87..fda6cade30a8 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
@@ -872,6 +872,7 @@ static uint32_t dcn32_get_vco_frequency_from_reg(struct clk_mgr_internal *clk_mg
static void dcn32_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
struct clk_mgr *clk_mgr_base, struct clk_log_info *log_info)
{
+ (void)log_info;
struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
uint32_t dprefclk_did = 0;
uint32_t dcfclk_did = 0;
@@ -1059,11 +1060,9 @@ static void dcn32_get_memclk_states_from_smu(struct clk_mgr *clk_mgr_base)
if (!clk_mgr->dpm_present)
dcn32_patch_dpm_table(clk_mgr_base->bw_params);
- DC_FP_START();
/* Refresh bounding box */
clk_mgr_base->ctx->dc->res_pool->funcs->update_bw_bounding_box(
clk_mgr->base.ctx->dc, clk_mgr_base->bw_params);
- DC_FP_END();
}
static bool dcn32_are_clock_states_equal(struct dc_clocks *a,
@@ -1147,6 +1146,7 @@ void dcn32_clk_mgr_construct(
struct pp_smu_funcs *pp_smu,
struct dccg *dccg)
{
+ (void)pp_smu;
struct clk_log_info log_info = {0};
clk_mgr->base.ctx = ctx;
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c
index 6fc524752613..2798088842f4 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c
@@ -1464,11 +1464,12 @@ void dcn35_clk_mgr_construct(
/* TODO: Check we get what we expect during bringup */
clk_mgr->base.base.dentist_vco_freq_khz = get_vco_frequency_from_reg(&clk_mgr->base);
- if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) {
+ if (ctx->dc_bios->integrated_info &&
+ ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType)
dcn35_bw_params.wm_table = lpddr5_wm_table;
- } else {
+ else
dcn35_bw_params.wm_table = ddr5_wm_table;
- }
+
/* Saved clocks configured at boot for debug purposes */
dcn35_save_clk_registers(&clk_mgr->base.base.boot_snapshot, clk_mgr);
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c
index 03464f21d119..82c1a55a2271 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c
@@ -333,6 +333,7 @@ bool dcn401_is_dc_mode_present(struct clk_mgr *clk_mgr_base)
static void dcn401_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
struct clk_mgr *clk_mgr_base, struct clk_log_info *log_info)
{
+ (void)log_info;
struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
uint32_t dprefclk_did = 0;
uint32_t dcfclk_did = 0;
@@ -525,6 +526,7 @@ static void dcn401_update_clocks_update_dtb_dto(struct clk_mgr_internal *clk_mgr
struct dc_state *context,
int ref_dtbclk_khz)
{
+ (void)ref_dtbclk_khz;
int i;
struct dccg *dccg = clk_mgr->dccg;
struct pipe_ctx *otg_master;
@@ -614,6 +616,7 @@ static void dcn401_update_clocks_update_dentist(
struct clk_mgr_internal *clk_mgr,
struct dc_state *context)
{
+ (void)context;
uint32_t new_disp_divider = 0;
uint32_t new_dispclk_wdivider = 0;
uint32_t dentist_dispclk_wdivider_readback = 0;
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.c
index 97c9f0ce13e4..ec888aed207d 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.c
@@ -43,8 +43,6 @@
#define DC_LOGGER_INIT(logger) \
struct dal_logger *dc_logger = logger
-#define DCN42_CLKIP_REFCLK 48000
-
#undef FN
#define FN(reg_name, field_name) \
clk_mgr->clk_mgr_shift->field_name, clk_mgr->clk_mgr_mask->field_name
@@ -160,6 +158,9 @@ void dcn42_update_clocks_update_dtb_dto(struct clk_mgr_internal *clk_mgr,
struct dc_state *context,
int ref_dtbclk_khz)
{
+ (void)clk_mgr;
+ (void)context;
+ (void)ref_dtbclk_khz;
/* DCN42 does not implement set_dtbclk_dto function, so this is a no-op */
}
@@ -255,6 +256,10 @@ void dcn42_update_clocks(struct clk_mgr *clk_mgr_base,
dcn42_smu_set_zstate_support(clk_mgr, DCN_ZSTATE_SUPPORT_DISALLOW);
clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
}
+ /* Only attempt to enable dtbclk if currently disabled AND new state requests it.
+ * For dcn42b (no dtbclk hardware), init_clk_states sets dtbclk_en=false and
+ * new_clocks->dtbclk_en should always be false, so this block never executes.
+ */
if (!clk_mgr_base->clks.dtbclk_en && new_clocks->dtbclk_en) {
int actual_dtbclk = 0;
@@ -291,6 +296,11 @@ void dcn42_update_clocks(struct clk_mgr *clk_mgr_base,
if (should_set_clock(safe_to_lower,
new_clocks->dcfclk_deep_sleep_khz, clk_mgr_base->clks.dcfclk_deep_sleep_khz)) {
clk_mgr_base->clks.dcfclk_deep_sleep_khz = new_clocks->dcfclk_deep_sleep_khz;
+
+ /* Clamp the requested clock to PMFW based on DCN limit. */
+ if (dc->debug.min_deep_sleep_dcfclk_khz > 0 && clk_mgr_base->clks.dcfclk_deep_sleep_khz < dc->debug.min_deep_sleep_dcfclk_khz)
+ clk_mgr_base->clks.dcfclk_deep_sleep_khz = dc->debug.min_deep_sleep_dcfclk_khz;
+
dcn42_smu_set_min_deep_sleep_dcfclk(clk_mgr, clk_mgr_base->clks.dcfclk_deep_sleep_khz);
}
@@ -321,7 +331,7 @@ void dcn42_update_clocks(struct clk_mgr *clk_mgr_base,
}
/* clock limits are received with MHz precision, divide by 1000 to prevent setting clocks at every call */
- if (!dc->debug.disable_dtb_ref_clk_switch &&
+ if (!dc->debug.disable_dtb_ref_clk_switch && new_clocks->dtbclk_en &&
should_set_clock(safe_to_lower, new_clocks->ref_dtbclk_khz / 1000,
clk_mgr_base->clks.ref_dtbclk_khz / 1000)) {
dcn42_update_clocks_update_dtb_dto(clk_mgr, context, new_clocks->ref_dtbclk_khz);
@@ -469,6 +479,9 @@ static void dcn42_dump_clk_registers(struct clk_state_registers_and_bypass *regs
DC_LOG_SMU("CLK1_CLK1_CURRENT_CNT,%d,dppclk\n",
internal.CLK8_CLK1_CURRENT_CNT);
+ DC_LOG_SMU("CLK1_CLK4_CURRENT_CNT,%d,dtbclk\n",
+ internal.CLK8_CLK4_CURRENT_CNT);
+
DC_LOG_SMU("CLK1_CLK3_BYPASS_CNTL,%d,dcfclk_bypass\n",
internal.CLK8_CLK3_BYPASS_CNTL);
@@ -511,7 +524,7 @@ static void init_clk_states(struct clk_mgr *clk_mgr)
clk_mgr->clks.zstate_support = DCN_ZSTATE_SUPPORT_UNKNOWN;
}
-static void dcn42_get_dpm_table_from_smu(struct clk_mgr_internal *clk_mgr,
+void dcn42_get_dpm_table_from_smu(struct clk_mgr_internal *clk_mgr,
struct dcn42_smu_dpm_clks *smu_dpm_clks)
{
DpmClocks_t_dcn42 *table = smu_dpm_clks->dpm_clks;
@@ -569,7 +582,6 @@ void dcn42_init_clocks(struct clk_mgr *clk_mgr_base)
{
struct clk_mgr_internal *clk_mgr_int = TO_CLK_MGR_INTERNAL(clk_mgr_base);
struct clk_mgr_dcn42 *clk_mgr = TO_CLK_MGR_DCN42(clk_mgr_int);
- struct dcn42_smu_dpm_clks smu_dpm_clks = { 0 };
DC_LOGGER_INIT(clk_mgr_base->ctx->logger);
(void)dc_logger;
@@ -587,131 +599,7 @@ void dcn42_init_clocks(struct clk_mgr *clk_mgr_base)
dcn42_dump_clk_registers(&clk_mgr_base->boot_snapshot, clk_mgr);
clk_mgr_base->clks.ref_dtbclk_khz = clk_mgr_base->boot_snapshot.dtbclk * 10;
- if (clk_mgr_base->boot_snapshot.dtbclk > 59000) {
- /*dtbclk enabled based on*/
- clk_mgr_base->clks.dtbclk_en = true;
- }
-
- if (clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_dcfclk_levels != 0) {
- /*skip to get clock table and notify pmfw watermark range again*/
- DC_LOG_SMU("skip to get dpm_clks from pmfw from resume and acr\n");
- return;
- }
-
- smu_dpm_clks.dpm_clks = (DpmClocks_t_dcn42 *)dm_helpers_allocate_gpu_mem(
- clk_mgr_base->ctx,
- DC_MEM_ALLOC_TYPE_GART,
- sizeof(DpmClocks_t_dcn42),
- &smu_dpm_clks.mc_address.quad_part);
-
- ASSERT(smu_dpm_clks.dpm_clks);
- if (clk_mgr_base->ctx->dc->debug.pstate_enabled && clk_mgr_int->smu_present && smu_dpm_clks.mc_address.quad_part != 0) {
- int i;
- DpmClocks_t_dcn42 *dpm_clks = smu_dpm_clks.dpm_clks;
-
- dcn42_get_dpm_table_from_smu(clk_mgr_int, &smu_dpm_clks);
- DC_LOG_SMU("NumDcfClkLevelsEnabled: %d\n"
- "NumDispClkLevelsEnabled: %d\n"
- "NumSocClkLevelsEnabled: %d\n"
- "VcnClkLevelsEnabled: %d\n"
- "FClkLevelsEnabled: %d\n"
- "NumMemPstatesEnabled: %d\n"
- "MinGfxClk: %d\n"
- "MaxGfxClk: %d\n",
- dpm_clks->NumDcfClkLevelsEnabled,
- dpm_clks->NumDispClkLevelsEnabled,
- dpm_clks->NumSocClkLevelsEnabled,
- dpm_clks->VcnClkLevelsEnabled,
- dpm_clks->NumFclkLevelsEnabled,
- dpm_clks->NumMemPstatesEnabled,
- dpm_clks->MinGfxClk,
- dpm_clks->MaxGfxClk);
-
- for (i = 0; i < NUM_DCFCLK_DPM_LEVELS; i++) {
- DC_LOG_SMU("dpm_clks->DcfClocks[%d] = %d\n",
- i,
- dpm_clks->DcfClocks[i]);
- }
- for (i = 0; i < NUM_DISPCLK_DPM_LEVELS; i++) {
- DC_LOG_SMU("dpm_clks->DispClocks[%d] = %d\n",
- i, dpm_clks->DispClocks[i]);
- }
- for (i = 0; i < NUM_SOCCLK_DPM_LEVELS; i++) {
- DC_LOG_SMU("dpm_clks->SocClocks[%d] = %d\n",
- i, dpm_clks->SocClocks[i]);
- }
- for (i = 0; i < NUM_FCLK_DPM_LEVELS; i++) {
- DC_LOG_SMU("dpm_clks->FclkClocks_Freq[%d] = %d\n",
- i, dpm_clks->FclkClocks_Freq[i]);
- DC_LOG_SMU("dpm_clks->FclkClocks_Voltage[%d] = %d\n",
- i, dpm_clks->FclkClocks_Voltage[i]);
- }
- for (i = 0; i < NUM_SOCCLK_DPM_LEVELS; i++)
- DC_LOG_SMU("dpm_clks->SocVoltage[%d] = %d\n",
- i, dpm_clks->SocVoltage[i]);
-
- for (i = 0; i < NUM_MEM_PSTATE_LEVELS; i++) {
- DC_LOG_SMU("dpm_clks.MemPstateTable[%d].UClk = %d\n"
- "dpm_clks->MemPstateTable[%d].MemClk= %d\n"
- "dpm_clks->MemPstateTable[%d].Voltage = %d\n",
- i, dpm_clks->MemPstateTable[i].UClk,
- i, dpm_clks->MemPstateTable[i].MemClk,
- i, dpm_clks->MemPstateTable[i].Voltage);
- }
-
- if (clk_mgr_base->ctx->dc_bios->integrated_info && clk_mgr_base->ctx->dc->config.use_default_clock_table == false) {
- /* DCFCLK */
- dcn42_init_single_clock(&clk_mgr_base->bw_params->clk_table.entries[0].dcfclk_mhz,
- dpm_clks->DcfClocks,
- dpm_clks->NumDcfClkLevelsEnabled);
- clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_dcfclk_levels = dpm_clks->NumDcfClkLevelsEnabled;
-
- /* SOCCLK */
- dcn42_init_single_clock(&clk_mgr_base->bw_params->clk_table.entries[0].socclk_mhz,
- dpm_clks->SocClocks,
- dpm_clks->NumSocClkLevelsEnabled);
- clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_socclk_levels = dpm_clks->NumSocClkLevelsEnabled;
-
- /* DISPCLK */
- dcn42_init_single_clock(&clk_mgr_base->bw_params->clk_table.entries[0].dispclk_mhz,
- dpm_clks->DispClocks,
- dpm_clks->NumDispClkLevelsEnabled);
- clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_dispclk_levels = dpm_clks->NumDispClkLevelsEnabled;
-
- /* DPPCLK */
- dcn42_init_single_clock(&clk_mgr_base->bw_params->clk_table.entries[0].dppclk_mhz,
- dpm_clks->DppClocks,
- dpm_clks->NumDispClkLevelsEnabled);
- clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_dppclk_levels = dpm_clks->NumDispClkLevelsEnabled;
-
- /* FCLK */
- dcn42_init_single_clock(&clk_mgr_base->bw_params->clk_table.entries[0].fclk_mhz,
- dpm_clks->FclkClocks_Freq,
- NUM_FCLK_DPM_LEVELS);
- clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_fclk_levels = dpm_clks->NumFclkLevelsEnabled;
- clk_mgr_base->bw_params->clk_table.num_entries = dpm_clks->NumFclkLevelsEnabled;
-
- /* Memory Pstate table is in reverse order*/
- ASSERT(dpm_clks->NumMemPstatesEnabled <= NUM_MEM_PSTATE_LEVELS);
- if (dpm_clks->NumMemPstatesEnabled > NUM_MEM_PSTATE_LEVELS)
- dpm_clks->NumMemPstatesEnabled = NUM_MEM_PSTATE_LEVELS;
- for (i = 0; i < dpm_clks->NumMemPstatesEnabled; i++) {
- clk_mgr_base->bw_params->clk_table.entries[dpm_clks->NumMemPstatesEnabled - 1 - i].memclk_mhz = dpm_clks->MemPstateTable[i].UClk;
- clk_mgr_base->bw_params->clk_table.entries[dpm_clks->NumMemPstatesEnabled - 1 - i].wck_ratio = dcn42_convert_wck_ratio(dpm_clks->MemPstateTable[i].WckRatio) ;
- }
- clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_memclk_levels = dpm_clks->NumMemPstatesEnabled;
-
- /* DTBCLK*/
- clk_mgr_base->bw_params->clk_table.entries[0].dtbclk_mhz = clk_mgr_base->clks.ref_dtbclk_khz / 1000;
- clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_dtbclk_levels = 1;
- /* Refresh bounding box */
- clk_mgr_base->ctx->dc->res_pool->funcs->update_bw_bounding_box(
- clk_mgr_base->ctx->dc, clk_mgr_base->bw_params);
- }
- }
- if (smu_dpm_clks.dpm_clks && smu_dpm_clks.mc_address.quad_part != 0)
- dm_helpers_free_gpu_mem(clk_mgr_base->ctx, DC_MEM_ALLOC_TYPE_GART,
- smu_dpm_clks.dpm_clks);
+ clk_mgr_base->clks.dtbclk_en = clk_mgr_base->boot_snapshot.dtbclk > 59000;
}
static struct clk_bw_params dcn42_bw_params = {
@@ -950,6 +838,7 @@ void dcn42_set_low_power_state(struct clk_mgr *clk_mgr_base)
void dcn42_exit_low_power_state(struct clk_mgr *clk_mgr_base)
{
+ (void)clk_mgr_base;
}
@@ -959,7 +848,7 @@ static void dcn42_init_clocks_fpga(struct clk_mgr *clk_mgr)
}
-static void dcn42_update_clocks_fpga(struct clk_mgr *clk_mgr,
+void dcn42_update_clocks_fpga(struct clk_mgr *clk_mgr,
struct dc_state *context,
bool safe_to_lower)
{
@@ -1012,13 +901,13 @@ static void dcn42_update_clocks_fpga(struct clk_mgr *clk_mgr,
// Both fclk and ref_dppclk run on the same scemi clock.
clk_mgr_int->dccg->ref_dppclk = clk_mgr->clks.fclk_khz;
- /* TODO: set dtbclk in correct place */
- clk_mgr->clks.dtbclk_en = true;
-
dm_set_dcn_clocks(clk_mgr->ctx, &clk_mgr->clks);
+ if (clk_mgr->clks.dtbclk_en) {
+ dcn42_update_clocks_update_dtb_dto(clk_mgr_int, context, clk_mgr->clks.ref_dtbclk_khz);
+ } else {
+ clk_mgr->clks.ref_dtbclk_khz = 0;
+ }
dcn42_update_clocks_update_dpp_dto(clk_mgr_int, context, safe_to_lower);
-
- dcn42_update_clocks_update_dtb_dto(clk_mgr_int, context, clk_mgr->clks.ref_dtbclk_khz);
}
unsigned int dcn42_get_max_clock_khz(struct clk_mgr *clk_mgr_base, enum clk_type clk_type)
@@ -1050,8 +939,9 @@ unsigned int dcn42_get_max_clock_khz(struct clk_mgr *clk_mgr_base, enum clk_type
return 0;
}
-static int dcn42_get_dispclk_from_dentist(struct clk_mgr *clk_mgr_base)
+int dcn42_get_dispclk_from_dentist(struct clk_mgr *clk_mgr_base)
{
+ (void)clk_mgr_base;
struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
uint32_t dispclk_wdivider;
int disp_divider;
@@ -1071,6 +961,127 @@ bool dcn42_is_smu_present(struct clk_mgr *clk_mgr_base)
return clk_mgr->smu_present;
}
+void dcn42_get_smu_clocks(struct clk_mgr_internal *clk_mgr_int)
+{
+ struct clk_mgr *clk_mgr_base = &clk_mgr_int->base;
+ struct dcn42_smu_dpm_clks smu_dpm_clks = { 0 };
+
+ DC_LOGGER_INIT(clk_mgr_base->ctx->logger);
+ (void)dc_logger;
+
+ smu_dpm_clks.dpm_clks = (DpmClocks_t_dcn42 *)dm_helpers_allocate_gpu_mem(
+ clk_mgr_base->ctx,
+ DC_MEM_ALLOC_TYPE_GART,
+ sizeof(DpmClocks_t_dcn42),
+ &smu_dpm_clks.mc_address.quad_part);
+
+ ASSERT(smu_dpm_clks.dpm_clks);
+ if (clk_mgr_base->ctx->dc->debug.pstate_enabled && smu_dpm_clks.mc_address.quad_part != 0) {
+ int i;
+ DpmClocks_t_dcn42 *dpm_clks = smu_dpm_clks.dpm_clks;
+
+ dcn42_get_dpm_table_from_smu(clk_mgr_int, &smu_dpm_clks);
+ DC_LOG_SMU("NumDcfClkLevelsEnabled: %d\n"
+ "NumDispClkLevelsEnabled: %d\n"
+ "NumSocClkLevelsEnabled: %d\n"
+ "VcnClkLevelsEnabled: %d\n"
+ "FClkLevelsEnabled: %d\n"
+ "NumMemPstatesEnabled: %d\n"
+ "MinGfxClk: %d\n"
+ "MaxGfxClk: %d\n",
+ dpm_clks->NumDcfClkLevelsEnabled,
+ dpm_clks->NumDispClkLevelsEnabled,
+ dpm_clks->NumSocClkLevelsEnabled,
+ dpm_clks->VcnClkLevelsEnabled,
+ dpm_clks->NumFclkLevelsEnabled,
+ dpm_clks->NumMemPstatesEnabled,
+ dpm_clks->MinGfxClk,
+ dpm_clks->MaxGfxClk);
+
+ for (i = 0; i < NUM_DCFCLK_DPM_LEVELS; i++) {
+ DC_LOG_SMU("dpm_clks->DcfClocks[%d] = %d\n",
+ i,
+ dpm_clks->DcfClocks[i]);
+ }
+ for (i = 0; i < NUM_DISPCLK_DPM_LEVELS; i++) {
+ DC_LOG_SMU("dpm_clks->DispClocks[%d] = %d\n",
+ i, dpm_clks->DispClocks[i]);
+ }
+ for (i = 0; i < NUM_SOCCLK_DPM_LEVELS; i++) {
+ DC_LOG_SMU("dpm_clks->SocClocks[%d] = %d\n",
+ i, dpm_clks->SocClocks[i]);
+ }
+ for (i = 0; i < NUM_FCLK_DPM_LEVELS; i++) {
+ DC_LOG_SMU("dpm_clks->FclkClocks_Freq[%d] = %d\n",
+ i, dpm_clks->FclkClocks_Freq[i]);
+ DC_LOG_SMU("dpm_clks->FclkClocks_Voltage[%d] = %d\n",
+ i, dpm_clks->FclkClocks_Voltage[i]);
+ }
+ for (i = 0; i < NUM_SOCCLK_DPM_LEVELS; i++)
+ DC_LOG_SMU("dpm_clks->SocVoltage[%d] = %d\n",
+ i, dpm_clks->SocVoltage[i]);
+
+ for (i = 0; i < NUM_MEM_PSTATE_LEVELS; i++) {
+ DC_LOG_SMU("dpm_clks.MemPstateTable[%d].UClk = %d\n"
+ "dpm_clks->MemPstateTable[%d].MemClk= %d\n"
+ "dpm_clks->MemPstateTable[%d].Voltage = %d\n",
+ i, dpm_clks->MemPstateTable[i].UClk,
+ i, dpm_clks->MemPstateTable[i].MemClk,
+ i, dpm_clks->MemPstateTable[i].Voltage);
+ }
+
+ if (clk_mgr_base->ctx->dc_bios->integrated_info && clk_mgr_base->ctx->dc->config.use_default_clock_table == false) {
+ /* DCFCLK */
+ dcn42_init_single_clock(&clk_mgr_base->bw_params->clk_table.entries[0].dcfclk_mhz,
+ dpm_clks->DcfClocks,
+ dpm_clks->NumDcfClkLevelsEnabled);
+ clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_dcfclk_levels = dpm_clks->NumDcfClkLevelsEnabled;
+
+ /* SOCCLK */
+ dcn42_init_single_clock(&clk_mgr_base->bw_params->clk_table.entries[0].socclk_mhz,
+ dpm_clks->SocClocks,
+ dpm_clks->NumSocClkLevelsEnabled);
+ clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_socclk_levels = dpm_clks->NumSocClkLevelsEnabled;
+
+ /* DISPCLK */
+ dcn42_init_single_clock(&clk_mgr_base->bw_params->clk_table.entries[0].dispclk_mhz,
+ dpm_clks->DispClocks,
+ dpm_clks->NumDispClkLevelsEnabled);
+ clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_dispclk_levels = dpm_clks->NumDispClkLevelsEnabled;
+
+ /* DPPCLK */
+ dcn42_init_single_clock(&clk_mgr_base->bw_params->clk_table.entries[0].dppclk_mhz,
+ dpm_clks->DppClocks,
+ dpm_clks->NumDispClkLevelsEnabled);
+ clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_dppclk_levels = dpm_clks->NumDispClkLevelsEnabled;
+
+ /* FCLK */
+ dcn42_init_single_clock(&clk_mgr_base->bw_params->clk_table.entries[0].fclk_mhz,
+ dpm_clks->FclkClocks_Freq,
+ NUM_FCLK_DPM_LEVELS);
+ clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_fclk_levels = dpm_clks->NumFclkLevelsEnabled;
+ clk_mgr_base->bw_params->clk_table.num_entries = dpm_clks->NumFclkLevelsEnabled;
+
+ /* Memory Pstate table is in reverse order*/
+ ASSERT(dpm_clks->NumMemPstatesEnabled <= NUM_MEM_PSTATE_LEVELS);
+ if (dpm_clks->NumMemPstatesEnabled > NUM_MEM_PSTATE_LEVELS)
+ dpm_clks->NumMemPstatesEnabled = NUM_MEM_PSTATE_LEVELS;
+ for (i = 0; i < dpm_clks->NumMemPstatesEnabled; i++) {
+ clk_mgr_base->bw_params->clk_table.entries[dpm_clks->NumMemPstatesEnabled - 1 - i].memclk_mhz = dpm_clks->MemPstateTable[i].MemClk;
+ clk_mgr_base->bw_params->clk_table.entries[dpm_clks->NumMemPstatesEnabled - 1 - i].wck_ratio = dcn42_convert_wck_ratio(dpm_clks->MemPstateTable[i].WckRatio) ;
+ }
+ clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_memclk_levels = dpm_clks->NumMemPstatesEnabled;
+
+ /* DTBCLK*/
+ clk_mgr_base->bw_params->clk_table.entries[0].dtbclk_mhz = 600; /* Fixed on platform */
+ clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_dtbclk_levels = 1;
+ }
+ }
+ if (smu_dpm_clks.dpm_clks && smu_dpm_clks.mc_address.quad_part != 0)
+ dm_helpers_free_gpu_mem(clk_mgr_base->ctx, DC_MEM_ALLOC_TYPE_GART,
+ smu_dpm_clks.dpm_clks);
+}
+
static struct clk_mgr_funcs dcn42_funcs = {
.get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
.get_dtb_ref_clk_frequency = dcn31_get_dtb_ref_freq_khz,
@@ -1139,6 +1150,11 @@ void dcn42_clk_mgr_construct(
dcn42_bw_params.num_channels = ctx->dc_bios->integrated_info->ma_channel_number ? ctx->dc_bios->integrated_info->ma_channel_number : 1;
clk_mgr->base.base.dprefclk_khz = dcn42_smu_get_dprefclk(&clk_mgr->base);
clk_mgr->base.base.clks.ref_dtbclk_khz = dcn42_smu_get_dtbclk(&clk_mgr->base);
+
+ clk_mgr->base.base.bw_params = &dcn42_bw_params;
+
+ if (clk_mgr->base.smu_present)
+ dcn42_get_smu_clocks(&clk_mgr->base);
}
/* in case we don't get a value from the BIOS, use default */
if (clk_mgr->base.base.dentist_vco_freq_khz == 0)
@@ -1153,6 +1169,8 @@ void dcn42_clk_mgr_construct(
dcn42_read_ss_info_from_lut(&clk_mgr->base);
clk_mgr->base.base.bw_params = &dcn42_bw_params;
+ if (clk_mgr->base.smu_present)
+ dcn42_get_smu_clocks(&clk_mgr->base);
}
void dcn42_clk_mgr_destroy(struct clk_mgr_internal *clk_mgr_int)
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.h
index 5ad027a9edaf..9568ca06f00f 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.h
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.h
@@ -27,6 +27,7 @@
#include "clk_mgr_internal.h"
#define NUM_CLOCK_SOURCES 5
+#define DCN42_CLKIP_REFCLK 48000
struct dcn42_watermarks;
@@ -71,9 +72,15 @@ void dcn42_set_low_power_state(struct clk_mgr *clk_mgr_base);
void dcn42_exit_low_power_state(struct clk_mgr *clk_mgr_base);
unsigned int dcn42_get_max_clock_khz(struct clk_mgr *clk_mgr_base, enum clk_type clk_type);
bool dcn42_is_smu_present(struct clk_mgr *clk_mgr_base);
+bool dcn42_has_active_display(struct dc *dc, const struct dc_state *context);
int dcn42_get_active_display_cnt_wa(struct dc *dc, struct dc_state *context, int *all_active_disps);
+bool dcn42_has_active_display(struct dc *dc, const struct dc_state *context);
void dcn42_update_clocks_update_dpp_dto(struct clk_mgr_internal *clk_mgr, struct dc_state *context, bool safe_to_lower);
void dcn42_update_clocks_update_dtb_dto(struct clk_mgr_internal *clk_mgr, struct dc_state *context, int ref_dtbclk_khz);
bool dcn42_is_spll_ssc_enabled(struct clk_mgr *clk_mgr_base);
-bool dcn42_has_active_display(struct dc *dc, const struct dc_state *context);
+struct dcn42_smu_dpm_clks; /* Forward declaration for pointer parameter below */
+void dcn42_get_dpm_table_from_smu(struct clk_mgr_internal *clk_mgr, struct dcn42_smu_dpm_clks *smu_dpm_clks);
+void dcn42_get_smu_clocks(struct clk_mgr_internal *clk_mgr_int);
+void dcn42_update_clocks_fpga(struct clk_mgr *clk_mgr, struct dc_state *context, bool safe_to_lower);
+int dcn42_get_dispclk_from_dentist(struct clk_mgr *clk_mgr_base);
#endif //__DCN42_CLK_MGR_H__
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 31589f22aae0..419f894c87b0 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -1096,11 +1096,8 @@ static bool dc_construct(struct dc *dc,
#ifdef CONFIG_DRM_AMD_DC_FP
dc->clk_mgr->force_smu_not_present = init_params->force_smu_not_present;
- if (dc->res_pool->funcs->update_bw_bounding_box) {
- DC_FP_START();
+ if (dc->res_pool->funcs->update_bw_bounding_box)
dc->res_pool->funcs->update_bw_bounding_box(dc, dc->clk_mgr->bw_params);
- DC_FP_END();
- }
dc->soc_and_ip_translator = dc_create_soc_and_ip_translator(dc_ctx->dce_version);
if (!dc->soc_and_ip_translator)
goto fail;
@@ -1137,6 +1134,8 @@ static void disable_all_writeback_pipes_for_stream(
struct dc_stream_state *stream,
struct dc_state *context)
{
+ (void)dc;
+ (void)context;
int i;
for (i = 0; i < stream->num_wb_info; i++)
@@ -1148,6 +1147,8 @@ static void apply_ctx_interdependent_lock(struct dc *dc,
struct dc_stream_state *stream,
bool lock)
{
+ (void)dc;
+ (void)context;
int i;
/* Checks if interdependent update function pointer is NULL or not, takes care of DCE110 case */
@@ -1563,8 +1564,7 @@ static void detect_edp_presence(struct dc *dc)
struct dc_link *edp_links[MAX_NUM_EDP];
struct dc_link *edp_link = NULL;
enum dc_connection_type type;
- int i;
- int edp_num;
+ unsigned int i, edp_num;
dc_get_edp_links(dc, edp_links, &edp_num);
if (!edp_num)
@@ -1923,10 +1923,77 @@ bool dc_validate_boot_timing(const struct dc *dc,
return false;
}
- /* block DSC for now, as VBIOS does not currently support DSC timings */
if (crtc_timing->flags.DSC) {
- DC_LOG_DEBUG("boot timing validation failed due to DSC\n");
- return false;
+ struct display_stream_compressor *dsc = NULL;
+ struct dcn_dsc_state dsc_state = {0};
+
+ /* Find DSC associated with this timing generator */
+ if (tg_inst < dc->res_pool->res_cap->num_dsc) {
+ dsc = dc->res_pool->dscs[tg_inst];
+ }
+
+ if (!dsc || !dsc->funcs->dsc_read_state) {
+ DC_LOG_DEBUG("boot timing validation failed due to no DSC resource or read function\n");
+ return false;
+ }
+
+ /* Read current DSC hardware state */
+ dsc->funcs->dsc_read_state(dsc, &dsc_state);
+
+ /* Check if DSC is actually enabled in hardware */
+ if (dsc_state.dsc_clock_en == 0) {
+ DC_LOG_DEBUG("boot timing validation failed due to DSC not enabled in hardware\n");
+ return false;
+ }
+
+ uint32_t num_slices_h = 0;
+ uint32_t num_slices_v = 0;
+
+ if (dsc_state.dsc_slice_width > 0) {
+ num_slices_h = (crtc_timing->h_addressable + dsc_state.dsc_slice_width - 1) / dsc_state.dsc_slice_width;
+ }
+
+ if (dsc_state.dsc_slice_height > 0) {
+ num_slices_v = (crtc_timing->v_addressable + dsc_state.dsc_slice_height - 1) / dsc_state.dsc_slice_height;
+ }
+
+ if (crtc_timing->dsc_cfg.num_slices_h != num_slices_h) {
+ DC_LOG_DEBUG("boot timing validation failed due to num_slices_h mismatch\n");
+ return false;
+ }
+
+ if (crtc_timing->dsc_cfg.num_slices_v != num_slices_v) {
+ DC_LOG_DEBUG("boot timing validation failed due to num_slices_v mismatch\n");
+ return false;
+ }
+
+ if (crtc_timing->dsc_cfg.bits_per_pixel != dsc_state.dsc_bits_per_pixel) {
+ DC_LOG_DEBUG("boot timing validation failed due to bits_per_pixel mismatch\n");
+ return false;
+ }
+
+ if (crtc_timing->dsc_cfg.block_pred_enable != dsc_state.dsc_block_pred_enable) {
+ DC_LOG_DEBUG("boot timing validation failed due to block_pred_enable mismatch\n");
+ return false;
+ }
+
+ if (crtc_timing->dsc_cfg.linebuf_depth != dsc_state.dsc_line_buf_depth) {
+ DC_LOG_DEBUG("boot timing validation failed due to linebuf_depth mismatch\n");
+ return false;
+ }
+
+ if (crtc_timing->dsc_cfg.version_minor != dsc_state.dsc_version_minor) {
+ DC_LOG_DEBUG("boot timing validation failed due to version_minor mismatch\n");
+ return false;
+ }
+
+ if (crtc_timing->dsc_cfg.ycbcr422_simple != dsc_state.dsc_simple_422) {
+ DC_LOG_DEBUG("boot timing validation failed due to pixel encoding mismatch\n");
+ return false;
+ }
+
+ // Skip checks for is_frl, is_dp, and rc_buffer_size which are not programmed by vbios
+ // or not necessary for seamless boot validation.
}
if (dc_is_dp_signal(link->connector_signal)) {
@@ -2617,6 +2684,16 @@ void dc_post_update_surfaces_to_stream(struct dc *dc)
dc->optimized_required = false;
}
+void dc_get_default_tiling_info(const struct dc *dc, struct dc_tiling_info *tiling_info)
+{
+ if (!dc || !tiling_info)
+ return;
+ if (dc->res_pool && dc->res_pool->funcs && dc->res_pool->funcs->get_default_tiling_info) {
+ dc->res_pool->funcs->get_default_tiling_info(tiling_info);
+ return;
+ }
+}
+
bool dc_set_generic_gpio_for_stereo(bool enable,
struct gpio_service *gpio_service)
{
@@ -2759,28 +2836,12 @@ static struct surface_update_descriptor get_plane_info_update_type(const struct
if (memcmp(tiling, &u->surface->tiling_info, sizeof(*tiling)) != 0) {
update_flags->bits.swizzle_change = 1;
- elevate_update_type(&update_type, UPDATE_TYPE_MED, LOCK_DESCRIPTOR_STREAM);
- switch (tiling->gfxversion) {
- case DcGfxVersion9:
- case DcGfxVersion10:
- case DcGfxVersion11:
- if (tiling->gfx9.swizzle != DC_SW_LINEAR) {
- update_flags->bits.bandwidth_change = 1;
- elevate_update_type(&update_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
- }
- break;
- case DcGfxAddr3:
- if (tiling->gfx_addr3.swizzle != DC_ADDR3_SW_LINEAR) {
- update_flags->bits.bandwidth_change = 1;
- elevate_update_type(&update_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
- }
- break;
- case DcGfxVersion7:
- case DcGfxVersion8:
- case DcGfxVersionUnknown:
- default:
- break;
+ if (tiling->flags.avoid_full_update_on_tiling_change) {
+ elevate_update_type(&update_type, UPDATE_TYPE_MED, LOCK_DESCRIPTOR_STREAM);
+ } else {
+ update_flags->bits.bandwidth_change = 1;
+ elevate_update_type(&update_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
}
}
@@ -2950,6 +3011,7 @@ static struct surface_update_descriptor det_surface_update(
*/
static void force_immediate_gsl_plane_flip(struct dc *dc, struct dc_surface_update *updates, int surface_count)
{
+ (void)dc;
bool has_flip_immediate_plane = false;
int i;
@@ -3228,6 +3290,7 @@ static void copy_stream_update_to_stream(struct dc *dc,
struct dc_stream_state *stream,
struct dc_stream_update *update)
{
+ (void)context;
struct dc_context *dc_ctx = dc->ctx;
if (update == NULL || stream == NULL)
@@ -3503,6 +3566,7 @@ static void restore_minimal_pipe_split_policy(struct dc *dc,
* @surface_count: surface update count
* @stream: Corresponding stream to be updated
* @stream_update: stream update
+ * @update_descriptor: describes what plane and stream changes to apply
* @new_update_type: [out] determined update type by the function
* @new_context: [out] new context allocated and validated if update type is
* FULL, reference to current context if update type is less than FULL.
@@ -3831,6 +3895,7 @@ static void commit_planes_do_stream_update(struct dc *dc,
static bool dc_dmub_should_send_dirty_rect_cmd(struct dc *dc, struct dc_stream_state *stream)
{
+ (void)dc;
if ((stream->link->psr_settings.psr_version == DC_PSR_VERSION_SU_1
|| stream->link->psr_settings.psr_version == DC_PSR_VERSION_1)
&& stream->ctx->dce_version >= DCN_VERSION_3_1)
@@ -4631,6 +4696,7 @@ static bool could_mpcc_tree_change_for_active_pipes(struct dc *dc,
int surface_count,
bool *is_plane_addition)
{
+ (void)srf_updates;
struct dc_stream_status *cur_stream_status = stream_get_status(dc->current_state, stream);
bool force_minimal_pipe_splitting = false;
@@ -5055,7 +5121,9 @@ void populate_fast_updates(struct dc_fast_update *fast_update,
fast_update[i].input_csc_color_matrix = srf_updates[i].input_csc_color_matrix;
fast_update[i].coeff_reduction_factor = srf_updates[i].coeff_reduction_factor;
fast_update[i].cursor_csc_color_matrix = srf_updates[i].cursor_csc_color_matrix;
+#if defined(CONFIG_DRM_AMD_DC_DCN4_2)
fast_update[i].cm_hist_control = srf_updates[i].cm_hist_control;
+#endif
}
}
@@ -5073,7 +5141,9 @@ static bool fast_updates_exist(const struct dc_fast_update *fast_update, int sur
fast_update[i].gamut_remap_matrix ||
fast_update[i].input_csc_color_matrix ||
fast_update[i].cursor_csc_color_matrix ||
+#if defined(CONFIG_DRM_AMD_DC_DCN4_2)
fast_update[i].cm_hist_control ||
+#endif
fast_update[i].coeff_reduction_factor)
return true;
}
@@ -5094,7 +5164,9 @@ bool fast_nonaddr_updates_exist(struct dc_fast_update *fast_update, int surface_
fast_update[i].gamma ||
fast_update[i].gamut_remap_matrix ||
fast_update[i].coeff_reduction_factor ||
+#if defined(CONFIG_DRM_AMD_DC_DCN4_2)
fast_update[i].cm_hist_control ||
+#endif
fast_update[i].cursor_csc_color_matrix)
return true;
}
@@ -5109,6 +5181,7 @@ static bool full_update_required_weak(
const struct dc_stream_update *stream_update,
const struct dc_stream_state *stream)
{
+ (void)stream_update;
const struct dc_state *context = dc->current_state;
if (srf_updates)
for (int i = 0; i < surface_count; i++)
@@ -5478,6 +5551,7 @@ void dc_commit_updates_for_stream(struct dc *dc,
struct dc_stream_update *stream_update,
struct dc_state *state)
{
+ (void)state;
bool ret = false;
dc_exit_ips_for_hw_access(dc);
@@ -5787,6 +5861,7 @@ void dc_lock_memory_clock_frequency(struct dc *dc)
static void blank_and_force_memclk(struct dc *dc, bool apply, unsigned int memclk_mhz)
{
+ (void)apply;
struct dc_state *context = dc->current_state;
struct hubp *hubp;
struct pipe_ctx *pipe;
@@ -6331,8 +6406,7 @@ void dc_disable_accelerated_mode(struct dc *dc)
*/
void dc_notify_vsync_int_state(struct dc *dc, struct dc_stream_state *stream, bool enable)
{
- int i;
- int edp_num;
+ unsigned int i, edp_num;
struct pipe_ctx *pipe = NULL;
struct dc_link *link = stream->sink->link;
struct dc_link *edp_links[MAX_NUM_EDP];
@@ -6386,8 +6460,7 @@ bool dc_abm_save_restore(
struct dc_stream_state *stream,
struct abm_save_restore *pData)
{
- int i;
- int edp_num;
+ unsigned int i, edp_num;
struct pipe_ctx *pipe = NULL;
struct dc_link *link = stream->sink->link;
struct dc_link *edp_links[MAX_NUM_EDP];
@@ -6463,6 +6536,7 @@ void dc_query_current_properties(struct dc *dc, struct dc_current_properties *pr
void dc_set_edp_power(const struct dc *dc, struct dc_link *edp_link,
bool powerOn)
{
+ (void)dc;
if (edp_link->connector_signal != SIGNAL_TYPE_EDP)
return;
@@ -6589,6 +6663,7 @@ void dc_get_underflow_debug_data_for_otg(struct dc *dc, int primary_otg_inst,
void dc_get_power_feature_status(struct dc *dc, int primary_otg_inst,
struct power_features *out_data)
{
+ (void)primary_otg_inst;
out_data->uclk_p_state = dc->current_state->clk_mgr->clks.p_state_change_support;
out_data->fams = dc->current_state->bw_ctx.bw.dcn.clk.fw_based_mclk_switching;
}
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
index 5b3695e72e19..db86e346307c 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
@@ -249,6 +249,7 @@ void color_space_to_black_color(
enum dc_color_space colorspace,
struct tg_color *black_color)
{
+ (void)dc;
switch (colorspace) {
case COLOR_SPACE_YCBCR601:
case COLOR_SPACE_YCBCR709:
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c
index 7bb4504889be..f4e99ca7918f 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c
@@ -46,7 +46,7 @@ struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_index)
void dc_get_edp_links(const struct dc *dc,
struct dc_link **edp_links,
- int *edp_num)
+ unsigned int *edp_num)
{
int i;
@@ -68,7 +68,7 @@ bool dc_get_edp_link_panel_inst(const struct dc *dc,
unsigned int *inst_out)
{
struct dc_link *edp_links[MAX_NUM_EDP];
- int edp_num, i;
+ unsigned int edp_num, i;
*inst_out = 0;
if (link->connector_signal != SIGNAL_TYPE_EDP)
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
index 8271b12c1a66..66597a1f5b78 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -749,10 +749,10 @@ struct clock_source *resource_find_used_clk_src_for_sharing(
return NULL;
}
-static enum pixel_format convert_pixel_format_to_dalsurface(
+static enum dc_pixel_format convert_pixel_format_to_dalsurface(
enum surface_pixel_format surface_pixel_format)
{
- enum pixel_format dal_pixel_format = PIXEL_FORMAT_UNKNOWN;
+ enum dc_pixel_format dal_pixel_format = PIXEL_FORMAT_UNKNOWN;
switch (surface_pixel_format) {
case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS:
@@ -1748,6 +1748,7 @@ enum dc_status resource_build_scaling_params_for_context(
const struct dc *dc,
struct dc_state *context)
{
+ (void)dc;
int i;
for (i = 0; i < MAX_PIPES; i++) {
@@ -1825,6 +1826,7 @@ int resource_find_free_pipe_used_as_sec_opp_head_by_cur_otg_master(
struct resource_context *new_res_ctx,
const struct pipe_ctx *cur_otg_master)
{
+ (void)cur_res_ctx;
const struct pipe_ctx *cur_sec_opp_head = cur_otg_master->next_odm_pipe;
struct pipe_ctx *new_pipe;
int free_pipe_idx = FREE_PIPE_INDEX_NOT_FOUND;
@@ -1846,6 +1848,7 @@ int resource_find_free_pipe_used_in_cur_mpc_blending_tree(
struct resource_context *new_res_ctx,
const struct pipe_ctx *cur_opp_head)
{
+ (void)cur_res_ctx;
const struct pipe_ctx *cur_sec_dpp = cur_opp_head->bottom_pipe;
struct pipe_ctx *new_pipe;
int free_pipe_idx = FREE_PIPE_INDEX_NOT_FOUND;
@@ -2941,6 +2944,7 @@ enum dc_status resource_add_otg_master_for_stream_output(struct dc_state *new_ct
const struct resource_pool *pool,
struct dc_stream_state *stream)
{
+ (void)pool;
struct dc *dc = stream->ctx->dc;
return dc->res_pool->funcs->add_stream_to_ctx(dc, new_ctx, stream);
@@ -3023,6 +3027,7 @@ static bool add_plane_to_opp_head_pipes(struct pipe_ctx *otg_master_pipe,
struct dc_plane_state *plane_state,
struct dc_state *context)
{
+ (void)context;
struct pipe_ctx *opp_head_pipe = otg_master_pipe;
while (opp_head_pipe) {
@@ -3615,6 +3620,7 @@ static struct hpo_dp_stream_encoder *find_first_free_match_hpo_dp_stream_enc_for
const struct resource_pool *pool,
struct dc_stream_state *stream)
{
+ (void)stream;
int i;
for (i = 0; i < pool->hpo_dp_stream_enc_count; i++) {
@@ -3634,6 +3640,7 @@ static struct audio *find_first_free_audio(
enum engine_id id,
enum dce_version dc_version)
{
+ (void)dc_version;
int i, available_audio_count;
if (id == ENGINE_ID_UNKNOWN)
@@ -5240,7 +5247,7 @@ unsigned int resource_pixel_format_to_bpp(enum surface_pixel_format format)
return 64;
default:
ASSERT_CRITICAL(false);
- return -1;
+ return UINT_MAX;
}
}
static unsigned int get_max_audio_sample_rate(struct audio_mode *modes)
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_state.c b/drivers/gpu/drm/amd/display/dc/core/dc_state.c
index a40e5c44143f..40f7aa732258 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_state.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_state.c
@@ -205,19 +205,33 @@ struct dc_state *dc_state_create(struct dc *dc, struct dc_state_create_params *p
state->power_source = params ? params->power_source : DC_POWER_SOURCE_AC;
#ifdef CONFIG_DRM_AMD_DC_FP
+ bool status;
+
if (dc->debug.using_dml2) {
- if (!dml2_create(dc, &dc->dml2_options, &state->bw_ctx.dml2)) {
+ DC_FP_START();
+ status = dml2_create(dc, &dc->dml2_options, &state->bw_ctx.dml2);
+ DC_FP_END();
+
+ if (!status) {
dc_state_release(state);
return NULL;
}
- if (dc->caps.dcmode_power_limits_present && !dml2_create(dc, &dc->dml2_dc_power_options, &state->bw_ctx.dml2_dc_power_source)) {
- dc_state_release(state);
- return NULL;
+ if (dc->caps.dcmode_power_limits_present) {
+ bool status;
+
+ DC_FP_START();
+ status = dml2_create(dc, &dc->dml2_dc_power_options, &state->bw_ctx.dml2_dc_power_source);
+ DC_FP_END();
+
+ if (!status) {
+ dc_state_release(state);
+ return NULL;
+ }
}
- }
-#endif
+ }
+#endif // CONFIG_DRM_AMD_DC_FP
kref_init(&state->refcount);
return state;
@@ -235,14 +249,20 @@ void dc_state_copy(struct dc_state *dst_state, struct dc_state *src_state)
#ifdef CONFIG_DRM_AMD_DC_FP
dst_state->bw_ctx.dml2 = dst_dml2;
- if (src_state->bw_ctx.dml2)
+ if (src_state->bw_ctx.dml2) {
+ DC_FP_START();
dml2_copy(dst_state->bw_ctx.dml2, src_state->bw_ctx.dml2);
+ DC_FP_END();
+ }
dst_state->bw_ctx.dml2_dc_power_source = dst_dml2_dc_power_source;
- if (src_state->bw_ctx.dml2_dc_power_source)
- dml2_copy(dst_state->bw_ctx.dml2_dc_power_source, src_state->bw_ctx.dml2_dc_power_source);
-#endif
+ if (src_state->bw_ctx.dml2_dc_power_source) {
+ DC_FP_START();
+ dml2_copy(dst_state->bw_ctx.dml2_dc_power_source, src_state->bw_ctx.dml2_dc_power_source);
+ DC_FP_END();
+ }
+#endif // CONFIG_DRM_AMD_DC_FP
/* context refcount should not be overridden */
dst_state->refcount = refcount;
}
@@ -258,22 +278,35 @@ struct dc_state *dc_state_create_copy(struct dc_state *src_state)
dc_state_copy_internal(new_state, src_state);
#ifdef CONFIG_DRM_AMD_DC_FP
+ bool status;
+
new_state->bw_ctx.dml2 = NULL;
new_state->bw_ctx.dml2_dc_power_source = NULL;
- if (src_state->bw_ctx.dml2 &&
- !dml2_create_copy(&new_state->bw_ctx.dml2, src_state->bw_ctx.dml2)) {
- dc_state_release(new_state);
- return NULL;
- }
+ if (src_state->bw_ctx.dml2) {
+ DC_FP_START();
+ status = dml2_create_copy(&new_state->bw_ctx.dml2, src_state->bw_ctx.dml2);
+ DC_FP_END();
- if (src_state->bw_ctx.dml2_dc_power_source &&
- !dml2_create_copy(&new_state->bw_ctx.dml2_dc_power_source, src_state->bw_ctx.dml2_dc_power_source)) {
- dc_state_release(new_state);
- return NULL;
+ if (!status) {
+ dc_state_release(new_state);
+ return NULL;
+ }
}
-#endif
+
+ if (src_state->bw_ctx.dml2_dc_power_source) {
+ DC_FP_START();
+ status = dml2_create_copy(&new_state->bw_ctx.dml2_dc_power_source,
+ src_state->bw_ctx.dml2_dc_power_source);
+ DC_FP_END();
+
+ if (!status) {
+ dc_state_release(new_state);
+ return NULL;
+ }
+ }
+#endif // CONFIG_DRM_AMD_DC_FP
kref_init(&new_state->refcount);
return new_state;
@@ -351,11 +384,13 @@ static void dc_state_free(struct kref *kref)
dc_state_destruct(state);
#ifdef CONFIG_DRM_AMD_DC_FP
+ DC_FP_START();
dml2_destroy(state->bw_ctx.dml2);
state->bw_ctx.dml2 = 0;
dml2_destroy(state->bw_ctx.dml2_dc_power_source);
state->bw_ctx.dml2_dc_power_source = 0;
+ DC_FP_END();
#endif
kvfree(state);
@@ -374,6 +409,7 @@ enum dc_status dc_state_add_stream(
struct dc_state *state,
struct dc_stream_state *stream)
{
+ (void)dc;
enum dc_status res;
DC_LOGGER_INIT(dc->ctx->logger);
@@ -749,6 +785,7 @@ struct dc_plane_state *dc_state_create_phantom_plane(const struct dc *dc,
struct dc_state *state,
struct dc_plane_state *main_plane)
{
+ (void)main_plane;
struct dc_plane_state *phantom_plane = dc_create_plane_state(dc);
DC_LOGGER_INIT(dc->ctx->logger);
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
index 908f79b02102..e16de323f39c 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
@@ -33,7 +33,6 @@
#include "dc_dmub_srv.h"
#include "dc_state_priv.h"
#include "dc_stream_priv.h"
-#include "dce/dmub_hw_lock_mgr.h"
#define DC_LOGGER dc->ctx->logger
#ifndef MIN
@@ -43,6 +42,13 @@
#define MAX(x, y) ((x > y) ? x : y)
#endif
+#include "dc_fpu.h"
+
+#if !defined(DC_RUN_WITH_PREEMPTION_ENABLED)
+#define DC_RUN_WITH_PREEMPTION_ENABLED(code) code
+#endif // !DC_RUN_WITH_PREEMPTION_ENABLED
+
+
/*******************************************************************************
* Private functions
******************************************************************************/
@@ -171,12 +177,14 @@ struct dc_stream_state *dc_create_stream_for_sink(
if (sink == NULL)
goto fail;
- stream = kzalloc_obj(struct dc_stream_state, GFP_ATOMIC);
+ DC_RUN_WITH_PREEMPTION_ENABLED(stream = kzalloc_obj(struct dc_stream_state, GFP_ATOMIC));
if (stream == NULL)
goto fail;
- stream->update_scratch = kzalloc((int32_t) dc_update_scratch_space_size(), GFP_ATOMIC);
+ DC_RUN_WITH_PREEMPTION_ENABLED(stream->update_scratch =
+ kzalloc((int32_t) dc_update_scratch_space_size(),
+ GFP_ATOMIC));
if (stream->update_scratch == NULL)
goto fail;
@@ -259,7 +267,6 @@ void program_cursor_attributes(
struct resource_context *res_ctx;
struct pipe_ctx *pipe_to_program = NULL;
bool enable_cursor_offload = dc_dmub_srv_is_cursor_offload_enabled(dc);
- bool unlock_dmub = false;
if (!stream)
return;
@@ -278,12 +285,6 @@ void program_cursor_attributes(
if (enable_cursor_offload && dc->hwss.begin_cursor_offload_update) {
dc->hwss.begin_cursor_offload_update(dc, pipe_ctx);
} else {
- if (dc->hwss.dmub_hw_control_lock && pipe_ctx->stream &&
- should_use_dmub_inbox0_lock_for_link(dc, pipe_ctx->stream->link)) {
- dc->hwss.dmub_hw_control_lock(dc, dc->current_state, true);
- unlock_dmub = true;
- }
-
dc->hwss.cursor_lock(dc, pipe_to_program, true);
if (pipe_to_program->next_odm_pipe)
dc->hwss.cursor_lock(dc, pipe_to_program->next_odm_pipe, true);
@@ -306,9 +307,6 @@ void program_cursor_attributes(
dc->hwss.cursor_lock(dc, pipe_to_program, false);
if (pipe_to_program->next_odm_pipe)
dc->hwss.cursor_lock(dc, pipe_to_program->next_odm_pipe, false);
-
- if (unlock_dmub)
- dc->hwss.dmub_hw_control_lock(dc, dc->current_state, false);
}
}
}
@@ -416,7 +414,6 @@ void program_cursor_position(
struct resource_context *res_ctx;
struct pipe_ctx *pipe_to_program = NULL;
bool enable_cursor_offload = dc_dmub_srv_is_cursor_offload_enabled(dc);
- bool unlock_dmub = false;
if (!stream)
return;
@@ -436,16 +433,10 @@ void program_cursor_position(
if (!pipe_to_program) {
pipe_to_program = pipe_ctx;
- if (enable_cursor_offload && dc->hwss.begin_cursor_offload_update) {
+ if (enable_cursor_offload && dc->hwss.begin_cursor_offload_update)
dc->hwss.begin_cursor_offload_update(dc, pipe_ctx);
- } else {
- if (dc->hwss.dmub_hw_control_lock && pipe_ctx->stream &&
- should_use_dmub_inbox0_lock_for_link(dc, pipe_ctx->stream->link)) {
- dc->hwss.dmub_hw_control_lock(dc, dc->current_state, true);
- unlock_dmub = true;
- }
+ else
dc->hwss.cursor_lock(dc, pipe_to_program, true);
- }
}
dc->hwss.set_cursor_position(pipe_ctx);
@@ -457,14 +448,10 @@ void program_cursor_position(
}
if (pipe_to_program) {
- if (enable_cursor_offload && dc->hwss.commit_cursor_offload_update) {
+ if (enable_cursor_offload && dc->hwss.commit_cursor_offload_update)
dc->hwss.commit_cursor_offload_update(dc, pipe_to_program);
- } else {
+ else
dc->hwss.cursor_lock(dc, pipe_to_program, false);
-
- if (unlock_dmub)
- dc->hwss.dmub_hw_control_lock(dc, dc->current_state, false);
- }
}
}
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c
index 5f12dcca7f71..a59b176d8e55 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c
@@ -57,6 +57,7 @@ void dc_plane_construct(struct dc_context *ctx, struct dc_plane_state *plane_sta
void dc_plane_destruct(struct dc_plane_state *plane_state)
{
+ (void)plane_state;
// no more pointers to free within dc_plane_state
}
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index c7a09724f569..55ec281db3b7 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -63,7 +63,7 @@ struct dcn_dsc_reg_state;
struct dcn_optc_reg_state;
struct dcn_dccg_reg_state;
-#define DC_VER "3.2.373"
+#define DC_VER "3.2.376"
/**
* MAX_SURFACES - representative of the upper bound of surfaces that can be piped to a single CRTC
@@ -520,7 +520,7 @@ struct dc_config {
union allow_lttpr_non_transparent_mode allow_lttpr_non_transparent_mode;
bool multi_mon_pp_mclk_switch;
bool disable_dmcu;
- bool enable_4to1MPC;
+ bool allow_4to1MPC;
bool enable_windowed_mpo_odm;
bool forceHBR2CP2520; // Used for switching between test patterns TPS4 and CP2520
uint32_t allow_edp_hotplug_detection;
@@ -1215,6 +1215,7 @@ struct dc_debug_options {
bool enable_dmu_recovery;
unsigned int force_vmin_threshold;
bool enable_otg_frame_sync_pwa;
+ unsigned int min_deep_sleep_dcfclk_khz;
};
@@ -1888,7 +1889,9 @@ struct dc_fast_update {
struct dc_transfer_func *out_transfer_func;
struct dc_csc_transform *output_csc_transform;
const struct dc_csc_transform *cursor_csc_color_matrix;
+#if defined(CONFIG_DRM_AMD_DC_DCN4_2)
struct cm_hist_control *cm_hist_control;
+#endif
};
struct dc_surface_update {
@@ -1970,6 +1973,15 @@ void dc_plane_cm_retain(struct dc_plane_cm *cm);
void dc_post_update_surfaces_to_stream(
struct dc *dc);
+/*
+ * dc_get_default_tiling_info() - Retrieve an ASIC-appropriate default tiling
+ * description for (typically) linear surfaces.
+ *
+ * This is used by OS/DM paths that need a valid, fully-initialized tiling
+ * description without hardcoding gfx-version specifics in the caller.
+ */
+void dc_get_default_tiling_info(const struct dc *dc, struct dc_tiling_info *tiling_info);
+
/**
* struct dc_validation_set - Struct to store surface/stream associations for validation
*/
@@ -2068,7 +2080,7 @@ bool dc_get_edp_link_panel_inst(const struct dc *dc,
/* Return an array of link pointers to edp links. */
void dc_get_edp_links(const struct dc *dc,
struct dc_link **edp_links,
- int *edp_num);
+ unsigned int *edp_num);
void dc_set_edp_power(const struct dc *dc, struct dc_link *edp_link,
bool powerOn);
diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
index b15360bcdacf..79c8b4cab053 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
+++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
@@ -958,7 +958,10 @@ void dc_dmub_srv_log_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv)
{
uint32_t i;
- if (!dc_dmub_srv || !dc_dmub_srv->dmub) {
+ if (!dc_dmub_srv)
+ return;
+
+ if (!dc_dmub_srv->dmub) {
DC_LOG_ERROR("%s: invalid parameters.", __func__);
return;
}
@@ -1082,6 +1085,7 @@ static void dc_build_cursor_attribute_update_payload1(
struct dmub_cursor_attributes_cfg *pl_A, const uint8_t p_idx,
const struct hubp *hubp, const struct dpp *dpp)
{
+ (void)p_idx;
/* Hubp */
pl_A->aHubp.SURFACE_ADDR_HIGH = hubp->att.SURFACE_ADDR_HIGH;
pl_A->aHubp.SURFACE_ADDR = hubp->att.SURFACE_ADDR;
@@ -1163,7 +1167,10 @@ void dc_dmub_srv_enable_dpia_trace(const struct dc *dc)
{
struct dc_dmub_srv *dc_dmub_srv = dc->ctx->dmub_srv;
- if (!dc_dmub_srv || !dc_dmub_srv->dmub) {
+ if (!dc_dmub_srv)
+ return;
+
+ if (!dc_dmub_srv->dmub) {
DC_LOG_ERROR("%s: invalid parameters.", __func__);
return;
}
@@ -2349,6 +2356,33 @@ bool dc_dmub_srv_is_cursor_offload_enabled(const struct dc *dc)
return dc->ctx->dmub_srv && dc->ctx->dmub_srv->cursor_offload_enabled;
}
+void dc_dmub_srv_boot_time_crc_init(const struct dc *dc, uint64_t gpu_addr, uint32_t size)
+{
+ struct dc_dmub_srv *dc_dmub_srv;
+ struct dc_context *dc_ctx;
+ union dmub_rb_cmd cmd = {0};
+ bool result = false;
+
+ if (!dc || !dc->ctx || !dc->ctx->dmub_srv || size == 0)
+ return;
+
+ dc_dmub_srv = dc->ctx->dmub_srv;
+ dc_ctx = dc_dmub_srv->ctx;
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.boot_time_crc_init.header.type = DMUB_CMD__BOOT_TIME_CRC;
+ cmd.boot_time_crc_init.header.sub_type = DMUB_CMD__BOOT_TIME_CRC_INIT_MEM;
+ cmd.boot_time_crc_init.header.payload_bytes =
+ sizeof(struct dmub_rb_cmd_boot_time_crc_init);
+ cmd.boot_time_crc_init.data.buffer_addr.quad_part = gpu_addr;
+ cmd.boot_time_crc_init.data.buffer_size = size;
+
+ result = dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT);
+
+ if (!result)
+ DC_ERROR("Boot time crc init failed in DMUB");
+}
+
void dc_dmub_srv_release_hw(const struct dc *dc)
{
struct dc_dmub_srv *dc_dmub_srv = dc->ctx->dmub_srv;
diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h
index 72e0a41f39f0..6579cf9cce3c 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h
@@ -362,6 +362,15 @@ void dc_dmub_srv_program_cursor_now(struct dc *dc, const struct pipe_ctx *pipe);
bool dc_dmub_srv_is_cursor_offload_enabled(const struct dc *dc);
/**
+ * dc_dmub_srv_boot_time_crc_init() - Initializes DMUB boot time CRC.
+ *
+ * @dc - pointer to DC object
+ * @gpu_addr - address for the boot time CRC buffer
+ * @size - size of the boot time CRC buffer
+ */
+void dc_dmub_srv_boot_time_crc_init(const struct dc *dc, uint64_t gpu_addr, uint32_t size);
+
+/**
* dc_dmub_srv_release_hw() - Notifies DMUB service that HW access is no longer required.
*
* @dc - pointer to DC object
diff --git a/drivers/gpu/drm/amd/display/dc/dc_helper.c b/drivers/gpu/drm/amd/display/dc/dc_helper.c
index 04b8b798dfff..77299767096f 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_helper.c
+++ b/drivers/gpu/drm/amd/display/dc/dc_helper.c
@@ -108,6 +108,7 @@ static void set_reg_field_values(struct dc_reg_value_masks *field_value_mask,
uint8_t shift1, uint32_t mask1, uint32_t field_value1,
va_list ap)
{
+ (void)addr;
uint32_t shift, mask, field_value;
int i = 1;
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 9bf853edc46f..c2ca08d26e37 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
@@ -218,7 +218,7 @@ enum surface_pixel_format {
/* Pixel format */
-enum pixel_format {
+enum dc_pixel_format {
/*graph*/
PIXEL_FORMAT_UNINITIALIZED,
PIXEL_FORMAT_INDEX8,
@@ -445,6 +445,10 @@ enum dc_gfxversion {
enum swizzle_mode_addr3_values swizzle;
} gfx_addr3;/*gfx with addr3 and above*/
};
+
+ struct {
+ bool avoid_full_update_on_tiling_change;
+ } flags;
};
/* Rotation angle */
diff --git a/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c b/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c
index ba7bf23f2b2f..52ed8deebf63 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c
+++ b/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c
@@ -63,7 +63,8 @@ static void populate_inits_from_splinits(struct scl_inits *inits,
inits->h_c = dc_fixpt_from_int_dy(spl_inits->h_filter_init_int_c, spl_inits->h_filter_init_frac_c >> 5, 0, 19);
inits->v_c = dc_fixpt_from_int_dy(spl_inits->v_filter_init_int_c, spl_inits->v_filter_init_frac_c >> 5, 0, 19);
}
-static void populate_splformat_from_format(enum spl_pixel_format *spl_pixel_format, const enum pixel_format pixel_format)
+static void populate_splformat_from_format(enum spl_pixel_format *spl_pixel_format,
+ const enum dc_pixel_format pixel_format)
{
if (pixel_format < PIXEL_FORMAT_INVALID)
*spl_pixel_format = (enum spl_pixel_format)pixel_format;
diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h
index e224077c8902..fd8ec1660312 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_types.h
@@ -1144,10 +1144,12 @@ union replay_low_refresh_rate_enable_options {
union replay_optimization {
struct {
- //BIT[0-3]: Replay Teams Optimization
+ //BIT[0-1]: Replay Teams Optimization
unsigned int TEAMS_OPTIMIZATION_VER_1 :1;
unsigned int TEAMS_OPTIMIZATION_VER_2 :1;
- unsigned int RESERVED_2_3 :2;
+ //BIT[2]: Replay Live Capture with CVT
+ unsigned int LIVE_CAPTURE_WITH_CVT :1;
+ unsigned int RESERVED_3 :1;
} bits;
unsigned int raw;
@@ -1196,6 +1198,8 @@ struct replay_config {
bool frame_skip_supported;
/* Replay Received Frame Skipping Error HPD. */
bool received_frame_skipping_error_hpd;
+ /* Live capture with CVT is activated */
+ bool live_capture_with_cvt_activated;
};
/* Replay feature flags*/
diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn31/dcn31_dccg.c b/drivers/gpu/drm/amd/display/dc/dccg/dcn31/dcn31_dccg.c
index 7f58acfe1177..a72bf413fad6 100644
--- a/drivers/gpu/drm/amd/display/dc/dccg/dcn31/dcn31_dccg.c
+++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn31/dcn31_dccg.c
@@ -165,6 +165,7 @@ void dccg31_set_dpstreamclk(
int otg_inst,
int dp_hpo_inst)
{
+ (void)dp_hpo_inst;
if (src == REFCLK)
dccg31_disable_dpstreamclk(dccg, otg_inst);
else
@@ -644,6 +645,7 @@ void dccg31_get_dccg_ref_freq(struct dccg *dccg,
unsigned int xtalin_freq_inKhz,
unsigned int *dccg_ref_freq_inKhz)
{
+ (void)dccg;
/*
* Assume refclk is sourced from xtalin
* expect 24MHz
diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn32/dcn32_dccg.c b/drivers/gpu/drm/amd/display/dc/dccg/dcn32/dcn32_dccg.c
index e817cd7c2b6a..18b9c5ceed43 100644
--- a/drivers/gpu/drm/amd/display/dc/dccg/dcn32/dcn32_dccg.c
+++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn32/dcn32_dccg.c
@@ -265,6 +265,7 @@ static void dccg32_get_dccg_ref_freq(struct dccg *dccg,
unsigned int xtalin_freq_inKhz,
unsigned int *dccg_ref_freq_inKhz)
{
+ (void)dccg;
/*
* Assume refclk is sourced from xtalin
* expect 100MHz
diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c b/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c
index 0b7908fbb115..efac64165ccd 100644
--- a/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c
+++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c
@@ -558,6 +558,7 @@ static void dccg35_set_symclk32_se_src_new(
static int
dccg35_is_symclk32_se_src_functional_le_new(struct dccg *dccg, int symclk_32_se_inst, int symclk_32_le_inst)
{
+ (void)symclk_32_se_inst;
uint32_t en;
uint32_t src_sel;
@@ -2373,6 +2374,7 @@ static void dccg35_disable_symclk_se_cb(
uint32_t stream_enc_inst,
uint32_t link_enc_inst)
{
+ (void)link_enc_inst;
dccg35_disable_symclk_fe_new(dccg, stream_enc_inst);
/* DMU PHY sequence switches SYMCLK_BE (link_enc_inst) to ref clock once PHY is turned off */
diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c b/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c
index 4b9a14c679d3..97605a416031 100644
--- a/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c
+++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c
@@ -161,6 +161,7 @@ void dccg401_set_pixel_rate_div(
enum pixel_rate_div tmds_div,
enum pixel_rate_div unused)
{
+ (void)unused;
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
uint32_t cur_tmds_div = PIXEL_RATE_DIV_NA;
uint32_t dp_dto_int;
@@ -353,6 +354,7 @@ void dccg401_get_dccg_ref_freq(struct dccg *dccg,
unsigned int xtalin_freq_inKhz,
unsigned int *dccg_ref_freq_inKhz)
{
+ (void)dccg;
/*
* Assume refclk is sourced from xtalin
* expect 100MHz
@@ -526,10 +528,6 @@ static void dccg401_enable_dpstreamclk(struct dccg *dccg, int otg_inst, int dp_h
BREAK_TO_DEBUGGER();
return;
}
- if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream)
- REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
- DPSTREAMCLK_GATE_DISABLE, 1,
- DPSTREAMCLK_ROOT_GATE_DISABLE, 1);
}
void dccg401_disable_dpstreamclk(struct dccg *dccg, int dp_hpo_inst)
@@ -725,6 +723,7 @@ void dccg401_init(struct dccg *dccg)
void dccg401_set_dto_dscclk(struct dccg *dccg, uint32_t inst, uint32_t num_slices_h)
{
+ (void)num_slices_h;
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
switch (inst) {
@@ -842,6 +841,7 @@ void dccg401_enable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst, uint3
void dccg401_disable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst, uint32_t link_enc_inst)
{
+ (void)link_enc_inst;
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
switch (stream_enc_inst) {
diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.c b/drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.c
index 19dfc3fe5c3a..b813310763e5 100644
--- a/drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.c
+++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.c
@@ -186,6 +186,7 @@ void dccg42_set_pixel_rate_div(
enum pixel_rate_div tmds_div,
enum pixel_rate_div unused)
{
+ (void)unused;
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
uint32_t cur_tmds_div = PIXEL_RATE_DIV_NA;
uint32_t dp_dto_int;
diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.h b/drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.h
index d9831b0f8235..2076565b1caa 100644
--- a/drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.h
+++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.h
@@ -122,6 +122,7 @@
DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYBSYMCLK_ROOT_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYCSYMCLK_ROOT_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYDSYMCLK_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GLOBAL_FGCG_REP_CNTL, DCCG_GLOBAL_FGCG_REP_DIS, mask_sh),\
DCCG_SFII(OTG, PIXEL_RATE_CNTL, DP_DTO, ENABLE, 0, mask_sh),\
DCCG_SFII(OTG, PIXEL_RATE_CNTL, DP_DTO, ENABLE, 1, mask_sh),\
DCCG_SFII(OTG, PIXEL_RATE_CNTL, DP_DTO, ENABLE, 2, mask_sh),\
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c
index 41169b42534c..469b4b8f88a3 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c
@@ -57,6 +57,7 @@
static bool dce_abm_set_pipe(struct abm *abm, uint32_t controller_id, uint32_t panel_inst)
{
+ (void)panel_inst;
struct dce_abm *abm_dce = TO_DCE_ABM(abm);
uint32_t rampingBoundary = 0xFFFF;
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c
index 0807d20985c7..77df61bfaf27 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c
@@ -350,6 +350,7 @@ static uint32_t calculate_required_audio_bw_in_symbols(
uint32_t av_stream_map_lane_count,
uint32_t audio_sdp_overhead)
{
+ (void)channel_count;
/* DP spec recommends between 1.05 to 1.1 safety margin to prevent sample under-run */
struct fixed31_32 audio_sdp_margin = dc_fixpt_from_fraction(110, 100);
struct fixed31_32 horizontal_line_freq_khz = dc_fixpt_from_fraction(
@@ -1027,6 +1028,7 @@ static void get_azalia_clock_info_hdmi(
uint32_t actual_pixel_clock_100Hz,
struct azalia_clock_info *azalia_clock_info)
{
+ (void)crtc_pixel_clock_100hz;
/* audio_dto_phase= 24 * 10,000;
* 24MHz in [100Hz] units */
azalia_clock_info->audio_dto_phase =
@@ -1043,6 +1045,7 @@ static void get_azalia_clock_info_dp(
const struct audio_pll_info *pll_info,
struct azalia_clock_info *azalia_clock_info)
{
+ (void)requested_pixel_clock_100Hz;
/* Reported dpDtoSourceClockInkhz value for
* DCE8 already adjusted for SS, do not need any
* adjustment here anymore
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
index 5722be965422..34e54fdb9d13 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
@@ -539,6 +539,7 @@ static void dce112_get_pix_clk_dividers_helper (
struct pll_settings *pll_settings,
struct pixel_clk_params *pix_clk_params)
{
+ (void)clk_src;
uint32_t actual_pixel_clock_100hz;
actual_pixel_clock_100hz = pix_clk_params->requested_pix_clk_100hz;
@@ -610,7 +611,7 @@ static uint32_t dce112_get_pix_clk_dividers(
|| pix_clk_params->requested_pix_clk_100hz == 0) {
DC_LOG_ERROR(
"%s: Invalid parameters!!\n", __func__);
- return -1;
+ return (uint32_t)-1;
}
memset(pll_settings, 0, sizeof(*pll_settings));
@@ -621,7 +622,7 @@ static uint32_t dce112_get_pix_clk_dividers(
pll_settings->calculated_pix_clk_100hz = clk_src->ext_clk_khz * 10;
pll_settings->actual_pix_clk_100hz =
pix_clk_params->requested_pix_clk_100hz;
- return -1;
+ return (uint32_t)-1;
}
dce112_get_pix_clk_dividers_helper(clk_src,
@@ -847,6 +848,7 @@ static bool dce110_program_pix_clk(
enum dp_link_encoding encoding,
struct pll_settings *pll_settings)
{
+ (void)encoding;
struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);
struct bp_pixel_clock_parameters bp_pc_params = {0};
@@ -921,6 +923,7 @@ static bool dce112_program_pix_clk(
enum dp_link_encoding encoding,
struct pll_settings *pll_settings)
{
+ (void)encoding;
struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);
struct bp_pixel_clock_parameters bp_pc_params = {0};
@@ -1070,6 +1073,7 @@ static bool dcn401_program_pix_clk(
enum dp_link_encoding encoding,
struct pll_settings *pll_settings)
{
+ (void)encoding;
struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);
unsigned int inst = pix_clk_params->controller_id - CONTROLLER_ID_D0;
const struct pixel_rate_range_table_entry *e =
@@ -1376,7 +1380,7 @@ static uint32_t dcn3_get_pix_clk_dividers(
|| pix_clk_params->requested_pix_clk_100hz == 0) {
DC_LOG_ERROR(
"%s: Invalid parameters!!\n", __func__);
- return -1;
+ return UINT_MAX;
}
memset(pll_settings, 0, sizeof(*pll_settings));
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c
index e871b72e43ef..25ebd8a52ae4 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c
@@ -71,6 +71,7 @@ static const uint32_t abm_gain_stepsize = 0x0060;
static bool dce_dmcu_init(struct dmcu *dmcu)
{
+ (void)dmcu;
// Do nothing
return true;
}
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c.c b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c.c
index f5cd2392fc5f..f5261e8d7678 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c.c
@@ -31,6 +31,7 @@ bool dce_i2c_oem_device_present(
size_t slave_address
)
{
+ (void)pool;
struct dc *dc = ddc->ctx->dc;
struct dc_bios *dcb = dc->ctx->dc_bios;
struct graphics_object_id id = {0};
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.c b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.c
index 365dd2e37aea..fe239a96121e 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.c
@@ -69,6 +69,7 @@ static enum i2c_channel_operation_result get_channel_status(
struct dce_i2c_hw *dce_i2c_hw,
uint8_t *returned_bytes)
{
+ (void)returned_bytes;
uint32_t i2c_sw_status = 0;
uint32_t value =
REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status);
@@ -631,6 +632,7 @@ bool dce_i2c_submit_command_hw(
struct i2c_command *cmd,
struct dce_i2c_hw *dce_i2c_hw)
{
+ (void)ddc;
uint8_t index_of_payload = 0;
bool result;
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_sw.c b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_sw.c
index 2d73b94c515c..52e05b9185f1 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_sw.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_sw.c
@@ -67,6 +67,7 @@ static void release_engine_dce_sw(
struct resource_pool *pool,
struct dce_i2c_sw *dce_i2c_sw)
{
+ (void)pool;
dal_ddc_close(dce_i2c_sw->ddc);
dce_i2c_sw->ddc = NULL;
}
@@ -76,6 +77,7 @@ static bool wait_for_scl_high_sw(
struct ddc *ddc,
uint16_t clock_delay_div_4)
{
+ (void)ctx;
uint32_t scl_retry = 0;
uint32_t scl_retry_max = I2C_SW_TIMEOUT_DELAY / clock_delay_div_4;
@@ -469,6 +471,7 @@ bool dce_i2c_submit_command_sw(
struct i2c_command *cmd,
struct dce_i2c_sw *dce_i2c_sw)
{
+ (void)ddc;
uint8_t index_of_payload = 0;
bool result;
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c
index 34bff9aef66c..ee55ec21d270 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c
@@ -43,6 +43,7 @@ static void dce_ipp_cursor_set_position(
const struct dc_cursor_position *position,
const struct dc_cursor_mi_param *param)
{
+ (void)param;
struct dce_ipp *ipp_dce = TO_DCE_IPP(ipp);
/* lock cursor registers */
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c
index 2ba3d3a3aac5..5f40ae9e3120 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c
@@ -122,6 +122,33 @@ static const struct link_encoder_funcs dce110_lnk_enc_funcs = {
.program_hpd_filter = dce110_program_hpd_filter,
};
+static const struct link_encoder_funcs dce110_lnk_enc_funcs_no_hpd = {
+ .validate_output_with_stream =
+ dce110_link_encoder_validate_output_with_stream,
+ .hw_init = dce110_link_encoder_hw_init,
+ .setup = dce110_link_encoder_setup,
+ .enable_tmds_output = dce110_link_encoder_enable_tmds_output,
+ .enable_dp_output = dce110_link_encoder_enable_dp_output,
+ .enable_dp_mst_output = dce110_link_encoder_enable_dp_mst_output,
+ .enable_lvds_output = dce110_link_encoder_enable_lvds_output,
+ .enable_analog_output = dce110_link_encoder_enable_analog_output,
+ .disable_output = dce110_link_encoder_disable_output,
+ .dp_set_lane_settings = dce110_link_encoder_dp_set_lane_settings,
+ .dp_set_phy_pattern = dce110_link_encoder_dp_set_phy_pattern,
+ .update_mst_stream_allocation_table =
+ dce110_link_encoder_update_mst_stream_allocation_table,
+ .psr_program_dp_dphy_fast_training =
+ dce110_psr_program_dp_dphy_fast_training,
+ .psr_program_secondary_packet = dce110_psr_program_secondary_packet,
+ .connect_dig_be_to_fe = dce110_link_encoder_connect_dig_be_to_fe,
+ .is_dig_enabled = dce110_is_dig_enabled,
+ .destroy = dce110_link_encoder_destroy,
+ .get_max_link_cap = dce110_link_encoder_get_max_link_cap,
+ .get_dig_frontend = dce110_get_dig_frontend,
+ .get_hpd_state = dce110_get_hpd_state,
+ .program_hpd_filter = dce110_program_hpd_filter,
+};
+
static enum bp_result link_transmitter_control(
struct dce110_link_encoder *enc110,
struct bp_transmitter_control *cntl)
@@ -820,6 +847,7 @@ bool dce110_link_encoder_validate_dp_output(
const struct dce110_link_encoder *enc110,
const struct dc_crtc_timing *crtc_timing)
{
+ (void)enc110;
if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
return false;
@@ -865,7 +893,10 @@ void dce110_link_encoder_construct(
const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs;
enum bp_result result = BP_RESULT_OK;
- enc110->base.funcs = &dce110_lnk_enc_funcs;
+ if (hpd_regs)
+ enc110->base.funcs = &dce110_lnk_enc_funcs;
+ else
+ enc110->base.funcs = &dce110_lnk_enc_funcs_no_hpd;
enc110->base.ctx = init_data->ctx;
enc110->base.id = init_data->encoder;
enc110->base.analog_id = init_data->analog_encoder;
@@ -1855,6 +1886,33 @@ static const struct link_encoder_funcs dce60_lnk_enc_funcs = {
.program_hpd_filter = dce110_program_hpd_filter,
};
+static const struct link_encoder_funcs dce60_lnk_enc_funcs_no_hpd = {
+ .validate_output_with_stream =
+ dce110_link_encoder_validate_output_with_stream,
+ .hw_init = dce110_link_encoder_hw_init,
+ .setup = dce110_link_encoder_setup,
+ .enable_tmds_output = dce110_link_encoder_enable_tmds_output,
+ .enable_dp_output = dce60_link_encoder_enable_dp_output,
+ .enable_dp_mst_output = dce60_link_encoder_enable_dp_mst_output,
+ .enable_lvds_output = dce110_link_encoder_enable_lvds_output,
+ .enable_analog_output = dce110_link_encoder_enable_analog_output,
+ .disable_output = dce110_link_encoder_disable_output,
+ .dp_set_lane_settings = dce110_link_encoder_dp_set_lane_settings,
+ .dp_set_phy_pattern = dce60_link_encoder_dp_set_phy_pattern,
+ .update_mst_stream_allocation_table =
+ dce110_link_encoder_update_mst_stream_allocation_table,
+ .psr_program_dp_dphy_fast_training =
+ dce110_psr_program_dp_dphy_fast_training,
+ .psr_program_secondary_packet = dce110_psr_program_secondary_packet,
+ .connect_dig_be_to_fe = dce110_link_encoder_connect_dig_be_to_fe,
+ .is_dig_enabled = dce110_is_dig_enabled,
+ .destroy = dce110_link_encoder_destroy,
+ .get_max_link_cap = dce110_link_encoder_get_max_link_cap,
+ .get_dig_frontend = dce110_get_dig_frontend,
+ .get_hpd_state = dce110_get_hpd_state,
+ .program_hpd_filter = dce110_program_hpd_filter,
+};
+
void dce60_link_encoder_construct(
struct dce110_link_encoder *enc110,
const struct encoder_init_data *init_data,
@@ -1867,7 +1925,10 @@ void dce60_link_encoder_construct(
const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs;
enum bp_result result = BP_RESULT_OK;
- enc110->base.funcs = &dce60_lnk_enc_funcs;
+ if (hpd_regs)
+ enc110->base.funcs = &dce60_lnk_enc_funcs;
+ else
+ enc110->base.funcs = &dce60_lnk_enc_funcs_no_hpd;
enc110->base.ctx = init_data->ctx;
enc110->base.id = init_data->encoder;
enc110->base.analog_id = init_data->analog_encoder;
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c
index 1c2009e38aa1..168c2d0a5eaa 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c
@@ -317,6 +317,7 @@ static void dce_mi_program_display_marks(
struct dce_watermarks urgent,
uint32_t total_dest_line_time_ns)
{
+ (void)stutter_enter;
struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1;
@@ -370,6 +371,7 @@ static void dce112_mi_program_display_marks(struct mem_input *mi,
struct dce_watermarks urgent,
uint32_t total_dest_line_time_ns)
{
+ (void)stutter_entry;
struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1;
@@ -656,6 +658,8 @@ static void dce_mi_program_surface_config(
struct dc_plane_dcc_param *dcc,
bool horizontal_mirror)
{
+ (void)dcc;
+ (void)horizontal_mirror;
struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
REG_UPDATE(GRPH_ENABLE, GRPH_ENABLE, 1);
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c
index f342da5a5e50..61d478cfca6d 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c
@@ -600,6 +600,7 @@ void dce110_opp_set_dyn_expansion(
enum dc_color_depth color_dpth,
enum signal_type signal)
{
+ (void)color_sp;
struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c
index 87c19f17c799..ed407e779c12 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c
@@ -271,6 +271,8 @@ static void dce110_stream_encoder_dp_set_stream_attribute(
bool use_vsc_sdp_for_colorimetry,
uint32_t enable_sdp_splitting)
{
+ (void)use_vsc_sdp_for_colorimetry;
+ (void)enable_sdp_splitting;
uint32_t h_active_start;
uint32_t v_active_start;
uint32_t misc0 = 0;
@@ -901,6 +903,7 @@ static void dce110_stream_encoder_dp_blank(
struct dc_link *link,
struct stream_encoder *enc)
{
+ (void)link;
struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
uint32_t reg1 = 0;
uint32_t max_retries = DP_BLANK_MAX_RETRY * 10;
@@ -951,6 +954,7 @@ static void dce110_stream_encoder_dp_unblank(
struct stream_encoder *enc,
const struct encoder_unblank_param *param)
{
+ (void)link;
struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
if (param->link_settings.link_rate != LINK_RATE_UNKNOWN) {
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c
index 1ab5ae9b5ea5..c1448ae47366 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c
@@ -282,6 +282,7 @@ static void calculate_inits(
const struct scaler_data *data,
struct scl_ratios_inits *inits)
{
+ (void)xfm_dce;
struct fixed31_32 h_init;
struct fixed31_32 v_init;
@@ -1240,6 +1241,7 @@ static void program_color_matrix(
const struct out_csc_color_matrix *tbl_entry,
enum grph_color_adjust_option options)
{
+ (void)options;
{
REG_SET_2(OUTPUT_CSC_C11_C12, 0,
OUTPUT_CSC_C11, tbl_entry->regval[0],
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c
index b686d89b79b2..93550c5e4d02 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c
@@ -41,8 +41,7 @@ static unsigned int abm_feature_support(struct abm *abm, unsigned int panel_inst
{
struct dc_context *dc = abm->ctx;
struct dc_link *edp_links[MAX_NUM_EDP];
- int i;
- int edp_num;
+ unsigned int i, edp_num;
unsigned int ret = ABM_FEATURE_NO_SUPPORT;
dc_get_edp_links(dc->dc, edp_links, &edp_num);
@@ -174,6 +173,7 @@ static bool dmub_abm_set_backlight_level_pwm_ex(struct abm *abm,
unsigned int controller_id,
unsigned int panel_inst)
{
+ (void)controller_id;
bool ret = false;
unsigned int feature_support;
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_abm_lcd.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_abm_lcd.c
index a641ae04450c..806b5709c9e7 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_abm_lcd.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_abm_lcd.c
@@ -188,6 +188,7 @@ void dmub_abm_init_config(struct abm *abm,
bool dmub_abm_set_pause(struct abm *abm, bool pause, unsigned int panel_inst, unsigned int stream_inst)
{
+ (void)stream_inst;
union dmub_rb_cmd cmd;
struct dc_context *dc = abm->ctx;
uint8_t panel_mask = 0x01 << panel_inst;
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c
index d0ffa99f1fe0..52673e2f504c 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c
@@ -82,7 +82,7 @@ bool dmub_hw_lock_mgr_does_link_require_lock(const struct dc *dc, const struct d
if (link->psr_settings.psr_version == DC_PSR_VERSION_1) {
struct dc_link *edp_links[MAX_NUM_EDP];
- int edp_num;
+ unsigned int edp_num;
dc_get_edp_links(dc, edp_links, &edp_num);
if (edp_num == 1)
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c
index 28a218149b8b..0af1b8e0a49e 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c
@@ -216,6 +216,7 @@ static void dmub_replay_set_coasting_vtotal(struct dmub_replay *dmub,
uint8_t panel_inst,
uint16_t frame_skip_number)
{
+ (void)panel_inst;
union dmub_rb_cmd cmd;
struct dc_context *dc = dmub->ctx;
struct dmub_rb_cmd_replay_set_coasting_vtotal *pCmd = NULL;
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c
index 2c43c2422638..b265a72eeb70 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c
@@ -40,6 +40,7 @@ static void set_flip_control(
struct dce_mem_input *mem_input110,
bool immediate)
{
+ (void)immediate;
uint32_t value = 0;
value = dm_read_reg(
@@ -165,6 +166,7 @@ static void program_tiling(
const struct dc_tiling_info *info,
const enum surface_pixel_format pixel_format)
{
+ (void)pixel_format;
uint32_t value = 0;
set_reg_field_value(value, info->gfx8.num_banks,
@@ -642,6 +644,8 @@ static void dce_mem_input_v_program_surface_config(
struct dc_plane_dcc_param *dcc,
bool horizotal_mirror)
{
+ (void)dcc;
+ (void)horizotal_mirror;
struct dce_mem_input *mem_input110 = TO_DCE_MEM_INPUT(mem_input);
enable(mem_input110);
@@ -927,6 +931,7 @@ static void dce_mem_input_v_program_display_marks(
struct dce_watermarks urgent,
uint32_t total_dest_line_time_ns)
{
+ (void)stutter_enter;
program_urgency_watermark_l(
mem_input->ctx,
urgent,
@@ -970,6 +975,9 @@ static void dce110_allocate_mem_input_v(
uint32_t pix_clk_khz,/* for current stream */
uint32_t total_stream_num)
{
+ (void)h_total;
+ (void)v_total;
+ (void)total_stream_num;
uint32_t addr;
uint32_t value;
uint32_t pix_dur;
@@ -1009,6 +1017,8 @@ static void dce110_free_mem_input_v(
struct mem_input *mi,
uint32_t total_stream_num)
{
+ (void)mi;
+ (void)total_stream_num;
}
static const struct mem_input_funcs dce110_mem_input_v_funcs = {
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c
index e096d2b95ef9..cf63fac82832 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c
@@ -110,6 +110,7 @@ static void program_color_matrix_v(
const struct out_csc_color_matrix *tbl_entry,
enum grph_color_adjust_option options)
{
+ (void)options;
struct dc_context *ctx = xfm_dce->base.ctx;
uint32_t cntl_value = dm_read_reg(ctx, mmCOL_MAN_OUTPUT_CSC_CONTROL);
bool use_set_a = (get_reg_field_value(cntl_value,
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c
index 9b65b77e8823..a4e76db46c9c 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c
@@ -551,5 +551,7 @@ void dce110_opp_set_regamma_mode_v(
struct transform *xfm,
enum opp_regamma mode)
{
+ (void)xfm;
+ (void)mode;
// TODO: need to implement the function
}
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c
index 61b0807693fb..b015b27cd1c6 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c
@@ -66,6 +66,7 @@ static void dce110_timing_generator_apply_front_porch_workaround(
struct timing_generator *tg,
struct dc_crtc_timing *timing)
{
+ (void)tg;
if (timing->flags.INTERLACE == 1) {
if (timing->v_front_porch < 2)
timing->v_front_porch = 2;
@@ -1115,6 +1116,7 @@ bool dce110_timing_generator_validate_timing(
const struct dc_crtc_timing *timing,
enum signal_type signal)
{
+ (void)signal;
uint32_t h_blank;
uint32_t h_back_porch, hsync_offset, h_sync_start;
@@ -1490,6 +1492,7 @@ void dce110_timing_generator_enable_reset_trigger(
struct timing_generator *tg,
int source_tg_inst)
{
+ (void)source_tg_inst;
uint32_t value;
uint32_t rising_edge = 0;
uint32_t falling_edge = 0;
@@ -1959,6 +1962,12 @@ void dce110_tg_program_timing(struct timing_generator *tg,
const enum signal_type signal,
bool use_vbios)
{
+ (void)vready_offset;
+ (void)vstartup_start;
+ (void)vupdate_offset;
+ (void)vupdate_width;
+ (void)pstate_keepout;
+ (void)signal;
if (use_vbios)
dce110_timing_generator_program_timing_generator(tg, timing);
else
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c
index 9837dec837ff..ba22c93acd81 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c
@@ -442,6 +442,12 @@ static void dce110_timing_generator_v_program_timing(struct timing_generator *tg
const enum signal_type signal,
bool use_vbios)
{
+ (void)vready_offset;
+ (void)vstartup_start;
+ (void)vupdate_offset;
+ (void)vupdate_width;
+ (void)pstate_keepout;
+ (void)signal;
if (use_vbios)
dce110_timing_generator_program_timing_generator(tg, timing);
else
@@ -621,6 +627,7 @@ static void dce110_timing_generator_v_setup_global_swap_lock(
struct timing_generator *tg,
const struct dcp_gsl_params *gsl_params)
{
+ (void)gsl_params;
DC_LOG_ERROR("Timing Sync not supported on underlay pipe\n");
return;
}
@@ -629,6 +636,7 @@ static void dce110_timing_generator_v_enable_reset_trigger(
struct timing_generator *tg,
int source_tg_inst)
{
+ (void)source_tg_inst;
DC_LOG_ERROR("Timing Sync not supported on underlay pipe\n");
return;
}
@@ -650,6 +658,7 @@ static void dce110_timing_generator_v_tear_down_global_swap_lock(
static void dce110_timing_generator_v_disable_vga(
struct timing_generator *tg)
{
+ (void)tg;
return;
}
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c
index 28d3b2663cd3..6be18665b1f7 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c
@@ -371,6 +371,9 @@ static void calculate_inits(
struct rect *luma_viewport,
struct rect *chroma_viewport)
{
+ (void)xfm_dce;
+ (void)luma_viewport;
+ (void)chroma_viewport;
inits->h_int_scale_ratio_luma =
dc_fixpt_u2d19(data->ratios.horz) << 5;
inits->v_int_scale_ratio_luma =
@@ -619,6 +622,8 @@ static void dce110_xfmv_set_gamut_remap(
struct transform *xfm,
const struct xfm_grph_csc_adjustment *adjust)
{
+ (void)xfm;
+ (void)adjust;
/* DO NOTHING*/
}
@@ -627,6 +632,7 @@ static void dce110_xfmv_set_pixel_storage_depth(
enum lb_pixel_depth depth,
const struct bit_depth_reduction_params *bit_depth_params)
{
+ (void)bit_depth_params;
struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
int pixel_depth = 0;
int expan_mode = 0;
diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c
index 187f45a7f5e1..fe97d3946cab 100644
--- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c
+++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c
@@ -284,6 +284,7 @@ static uint32_t align_to_chunks_number_per_line(
struct dce112_compressor *cp110,
uint32_t pixels)
{
+ (void)cp110;
return 256 * ((pixels + 255) / 256);
}
diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c
index 31c4f44ceaac..70410ef0c291 100644
--- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c
+++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c
@@ -304,6 +304,7 @@ static void dce120_timing_generator_enable_reset_trigger(
struct timing_generator *tg,
int source)
{
+ (void)source;
enum trigger_source_select trig_src_select = TRIGGER_SOURCE_SELECT_LOGIC_ZERO;
struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
uint32_t rising_edge = 0;
@@ -701,6 +702,12 @@ static void dce120_tg_program_timing(struct timing_generator *tg,
const enum signal_type signal,
bool use_vbios)
{
+ (void)vready_offset;
+ (void)vstartup_start;
+ (void)vupdate_offset;
+ (void)vupdate_width;
+ (void)pstate_keepout;
+ (void)signal;
if (use_vbios)
dce110_timing_generator_program_timing_generator(tg, timing);
else
diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c
index 88e7a1fc9a30..53c03364f5d4 100644
--- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c
+++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c
@@ -115,6 +115,12 @@ static void dce80_timing_generator_program_timing(struct timing_generator *tg,
const enum signal_type signal,
bool use_vbios)
{
+ (void)vready_offset;
+ (void)vstartup_start;
+ (void)vupdate_offset;
+ (void)vupdate_width;
+ (void)pstate_keepout;
+ (void)signal;
if (!use_vbios)
program_pix_dur(tg, timing->pix_clk_100hz);
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c
index dcd2cdfe91eb..c702a30563f9 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c
@@ -381,10 +381,10 @@ bool cm_helper_translate_curve_to_hw_format(struct dc_context *ctx,
}
for (i = region_end - region_start; i < MAX_REGIONS_NUMBER ; i++)
- seg_distr[i] = -1;
+ seg_distr[i] = (uint32_t)-1;
for (k = 0; k < MAX_REGIONS_NUMBER; k++) {
- if (seg_distr[k] != -1)
+ if (seg_distr[k] != (uint32_t)-1)
hw_points += (1 << seg_distr[k]);
}
@@ -565,7 +565,7 @@ bool cm_helper_translate_curve_to_degamma_hw_format(
for (i = region_end - region_start; i < MAX_REGIONS_NUMBER ; i++)
- seg_distr[i] = -1;
+ seg_distr[i] = (uint32_t)-1;
/* 12 segments
* segments are from 2^-12 to 0
*/
@@ -573,7 +573,7 @@ bool cm_helper_translate_curve_to_degamma_hw_format(
seg_distr[i] = 4;
for (k = 0; k < MAX_REGIONS_NUMBER; k++) {
- if (seg_distr[k] != -1)
+ if (seg_distr[k] != (uint32_t)-1)
hw_points += (1 << seg_distr[k]);
}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c
index 365a3215f6d5..e9efbb49586e 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c
@@ -44,6 +44,7 @@
static bool dwb1_get_caps(struct dwbc *dwbc, struct dwb_caps *caps)
{
+ (void)dwbc;
if (caps) {
caps->adapter_id = 0; /* we only support 1 adapter currently */
caps->hw_version = DCN_VERSION_1_0;
@@ -63,6 +64,7 @@ static bool dwb1_get_caps(struct dwbc *dwbc, struct dwb_caps *caps)
static bool dwb1_enable(struct dwbc *dwbc, struct dc_dwb_params *params)
{
+ (void)params;
struct dcn10_dwbc *dwbc10 = TO_DCN10_DWBC(dwbc);
/* disable first. */
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dwb_scl.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dwb_scl.c
index a0d437f0ce2b..f73c5f42ea68 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dwb_scl.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dwb_scl.c
@@ -746,7 +746,7 @@ bool dwb_program_horz_scalar(struct dcn20_dwbc *dwbc20,
src_width, dest_width);
if (dc_fixpt_floor(tmp_h_ratio_luma) == 8)
- h_ratio_luma = -1;
+ h_ratio_luma = (uint32_t)-1;
else
h_ratio_luma = dc_fixpt_u3d19(tmp_h_ratio_luma) << 5;
@@ -824,7 +824,7 @@ bool dwb_program_vert_scalar(struct dcn20_dwbc *dwbc20,
src_height, dest_height);
if (dc_fixpt_floor(tmp_v_ratio_luma) == 8)
- v_ratio_luma = -1;
+ v_ratio_luma = (uint32_t)-1;
else
v_ratio_luma = dc_fixpt_u3d19(tmp_v_ratio_luma) << 5;
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c
index 227aa8672d17..9dbccf58dde5 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c
@@ -159,10 +159,10 @@ bool cm3_helper_translate_curve_to_hw_format(struct dc_context *ctx,
}
for (i = region_end - region_start; i < MAX_REGIONS_NUMBER ; i++)
- seg_distr[i] = -1;
+ seg_distr[i] = (uint32_t)-1;
for (k = 0; k < MAX_REGIONS_NUMBER; k++) {
- if (seg_distr[k] != -1)
+ if (seg_distr[k] != (uint32_t)-1)
hw_points += (1 << seg_distr[k]);
}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.c
index 05aac3e444b4..4c7e4fe3c680 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.c
@@ -77,6 +77,7 @@ static void apg31_se_audio_setup(
unsigned int az_inst,
struct audio_info *audio_info)
{
+ (void)az_inst;
struct dcn31_apg *apg31 = DCN31_APG_FROM_APG(apg);
ASSERT(audio_info);
diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c
index d928b4dcf6b8..d913f065ecca 100644
--- a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c
@@ -249,6 +249,7 @@ void enc1_stream_encoder_dp_set_stream_attribute(
bool use_vsc_sdp_for_colorimetry,
uint32_t enable_sdp_splitting)
{
+ (void)enable_sdp_splitting;
uint32_t h_active_start;
uint32_t v_active_start;
uint32_t misc0 = 0;
@@ -783,6 +784,7 @@ void enc1_stream_encoder_send_immediate_sdp_message(
const uint8_t *custom_sdp_message,
unsigned int sdp_message_size)
{
+ (void)sdp_message_size;
struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
uint32_t value = 0;
diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn314/dcn314_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn314/dcn314_dio_stream_encoder.c
index 3e85e9c3d2cb..d1fd5462dca5 100644
--- a/drivers/gpu/drm/amd/display/dc/dio/dcn314/dcn314_dio_stream_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn314/dcn314_dio_stream_encoder.c
@@ -394,6 +394,8 @@ void enc314_dp_set_dsc_config(struct stream_encoder *enc,
uint32_t dsc_bytes_per_pixel,
uint32_t dsc_slice_width)
{
+ (void)dsc_bytes_per_pixel;
+ (void)dsc_slice_width;
struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
REG_UPDATE(DP_DSC_CNTL, DP_DSC_MODE, dsc_mode == OPTC_DSC_DISABLED ? 0 : 1);
diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_stream_encoder.c
index 3523d1cdc1a3..edafa3808455 100644
--- a/drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_stream_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_stream_encoder.c
@@ -356,6 +356,8 @@ static void enc32_dp_set_dsc_config(struct stream_encoder *enc,
uint32_t dsc_bytes_per_pixel,
uint32_t dsc_slice_width)
{
+ (void)dsc_bytes_per_pixel;
+ (void)dsc_slice_width;
struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
REG_UPDATE(DP_DSC_CNTL, DP_DSC_MODE, dsc_mode == OPTC_DSC_DISABLED ? 0 : 1);
diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_stream_encoder.c
index fd5d1dbf9dc6..de24dcd27e6c 100644
--- a/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_stream_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_stream_encoder.c
@@ -369,6 +369,7 @@ static void enc35_stream_encoder_map_to_link(
uint32_t stream_enc_inst,
uint32_t link_enc_inst)
{
+ (void)stream_enc_inst;
struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
ASSERT(stream_enc_inst < 5 && link_enc_inst < 5);
diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c
index 99aab70ef3e1..2d33ed0c062d 100644
--- a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c
@@ -57,6 +57,8 @@ static void enc401_dp_set_odm_combine(
struct stream_encoder *enc,
bool odm_combine)
{
+ (void)enc;
+ (void)odm_combine;
}
/* setup stream encoder in dvi mode */
@@ -710,6 +712,7 @@ void enc401_stream_encoder_map_to_link(
uint32_t stream_enc_inst,
uint32_t link_enc_inst)
{
+ (void)stream_enc_inst;
struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
REG_UPDATE(STREAM_MAPPER_CONTROL,
diff --git a/drivers/gpu/drm/amd/display/dc/dio/virtual/virtual_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/virtual/virtual_link_encoder.c
index 2655bc194a35..5b2bba0eff0e 100644
--- a/drivers/gpu/drm/amd/display/dc/dio/virtual/virtual_link_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/virtual/virtual_link_encoder.c
@@ -30,52 +30,92 @@
static bool virtual_link_encoder_validate_output_with_stream(
struct link_encoder *enc,
- const struct dc_stream_state *stream) { return true; }
+ const struct dc_stream_state *stream) {
+ (void)enc;
+ (void)stream;
+ return true;
+ }
-static void virtual_link_encoder_hw_init(struct link_encoder *enc) {}
+static void virtual_link_encoder_hw_init(struct link_encoder *enc)
+{
+ (void)enc;
+}
static void virtual_link_encoder_setup(
- struct link_encoder *enc,
- enum signal_type signal) {}
+ struct link_encoder *enc, enum signal_type signal) {
+ (void)enc;
+ (void)signal;
+ }
static void virtual_link_encoder_enable_tmds_output(
struct link_encoder *enc,
enum clock_source_id clock_source,
enum dc_color_depth color_depth,
enum signal_type signal,
- uint32_t pixel_clock) {}
+ uint32_t pixel_clock) {
+ (void)enc;
+ (void)clock_source;
+ (void)color_depth;
+ (void)signal;
+ (void)pixel_clock;
+ }
static void virtual_link_encoder_enable_dp_output(
struct link_encoder *enc,
const struct dc_link_settings *link_settings,
- enum clock_source_id clock_source) {}
+ enum clock_source_id clock_source) {
+ (void)enc;
+ (void)link_settings;
+ (void)clock_source;
+ }
static void virtual_link_encoder_enable_dp_mst_output(
struct link_encoder *enc,
const struct dc_link_settings *link_settings,
- enum clock_source_id clock_source) {}
+ enum clock_source_id clock_source) {
+ (void)enc;
+ (void)link_settings;
+ (void)clock_source;
+ }
static void virtual_link_encoder_disable_output(
struct link_encoder *link_enc,
- enum signal_type signal) {}
+ enum signal_type signal) {
+ (void)link_enc;
+ (void)signal;
+ }
static void virtual_link_encoder_dp_set_lane_settings(
struct link_encoder *enc,
const struct dc_link_settings *link_settings,
- const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]) {}
+ const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]) {
+ (void)enc;
+ (void)link_settings;
+ (void)lane_settings;
+ }
static void virtual_link_encoder_dp_set_phy_pattern(
struct link_encoder *enc,
- const struct encoder_set_dp_phy_pattern_param *param) {}
+ const struct encoder_set_dp_phy_pattern_param *param) {
+ (void)enc;
+ (void)param;
+ }
static void virtual_link_encoder_update_mst_stream_allocation_table(
struct link_encoder *enc,
- const struct link_mst_stream_allocation_table *table) {}
+ const struct link_mst_stream_allocation_table *table) {
+ (void)enc;
+ (void)table;
+ }
static void virtual_link_encoder_connect_dig_be_to_fe(
struct link_encoder *enc,
enum engine_id engine,
- bool connect) {}
+ bool connect) {
+ (void)enc;
+ (void)engine;
+ (void)connect;
+ }
static void virtual_link_encoder_destroy(struct link_encoder **enc)
{
@@ -86,6 +126,7 @@ static void virtual_link_encoder_destroy(struct link_encoder **enc)
static void virtual_link_encoder_get_max_link_cap(struct link_encoder *enc,
struct dc_link_settings *link_settings)
{
+ (void)enc;
/* Set Default link settings */
struct dc_link_settings max_link_cap = {LANE_COUNT_FOUR, LINK_RATE_HIGH,
LINK_SPREAD_05_DOWNSPREAD_30KHZ, false, 0};
diff --git a/drivers/gpu/drm/amd/display/dc/dio/virtual/virtual_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/virtual/virtual_stream_encoder.c
index a9c8857476ac..27448f2b2467 100644
--- a/drivers/gpu/drm/amd/display/dc/dio/virtual/virtual_stream_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/virtual/virtual_stream_encoder.c
@@ -31,80 +31,127 @@ static void virtual_stream_encoder_dp_set_stream_attribute(
struct dc_crtc_timing *crtc_timing,
enum dc_color_space output_color_space,
bool use_vsc_sdp_for_colorimetry,
- uint32_t enable_sdp_splitting) {}
+ uint32_t enable_sdp_splitting) {
+ (void)enc;
+ (void)crtc_timing;
+ (void)output_color_space;
+ (void)use_vsc_sdp_for_colorimetry;
+ (void)enable_sdp_splitting;
+ }
static void virtual_stream_encoder_hdmi_set_stream_attribute(
struct stream_encoder *enc,
struct dc_crtc_timing *crtc_timing,
int actual_pix_clk_khz,
- bool enable_audio) {}
+ bool enable_audio) {
+ (void)enc;
+ (void)crtc_timing;
+ (void)actual_pix_clk_khz;
+ (void)enable_audio;
+ }
static void virtual_stream_encoder_dvi_set_stream_attribute(
struct stream_encoder *enc,
struct dc_crtc_timing *crtc_timing,
- bool is_dual_link) {}
+ bool is_dual_link) {
+ (void)enc;
+ (void)crtc_timing;
+ (void)is_dual_link;
+ }
static void virtual_stream_encoder_set_throttled_vcp_size(
struct stream_encoder *enc,
- struct fixed31_32 avg_time_slots_per_mtp)
-{}
+ struct fixed31_32 avg_time_slots_per_mtp) {
+ (void)enc;
+ (void)avg_time_slots_per_mtp;
+ }
static void virtual_stream_encoder_update_hdmi_info_packets(
struct stream_encoder *enc,
- const struct encoder_info_frame *info_frame) {}
+ const struct encoder_info_frame *info_frame) {
+ (void)enc;
+ (void)info_frame;
+ }
static void virtual_stream_encoder_stop_hdmi_info_packets(
- struct stream_encoder *enc) {}
+ struct stream_encoder *enc) {
+ (void)enc;
+ }
static void virtual_stream_encoder_set_avmute(
- struct stream_encoder *enc,
- bool enable) {}
+ struct stream_encoder *enc, bool enable) {
+ (void)enc;
+ (void)enable;
+ }
static void virtual_stream_encoder_update_dp_info_packets(
struct stream_encoder *enc,
- const struct encoder_info_frame *info_frame) {}
+ const struct encoder_info_frame *info_frame) {
+ (void)enc;
+ (void)info_frame;
+ }
static void virtual_stream_encoder_stop_dp_info_packets(
- struct stream_encoder *enc) {}
+ struct stream_encoder *enc) {
+ (void)enc;
+ }
static void virtual_stream_encoder_dp_blank(
struct dc_link *link,
- struct stream_encoder *enc) {}
+ struct stream_encoder *enc) {
+ (void)link;
+ (void)enc;
+ }
static void virtual_stream_encoder_dp_unblank(
struct dc_link *link,
struct stream_encoder *enc,
- const struct encoder_unblank_param *param) {}
+ const struct encoder_unblank_param *param) {
+ (void)enc;
+ (void)link;
+ (void)param;
+ }
static void virtual_audio_mute_control(
- struct stream_encoder *enc,
- bool mute) {}
+ struct stream_encoder *enc, bool mute) {
+ (void)enc;
+ (void)mute;
+ }
static void virtual_stream_encoder_reset_hdmi_stream_attribute(
- struct stream_encoder *enc)
-{}
+ struct stream_encoder *enc)
+{
+ (void)enc;
+}
static void virtual_enc_dp_set_odm_combine(
- struct stream_encoder *enc,
- bool odm_combine)
-{}
+ struct stream_encoder *enc, bool odm_combine) {
+ (void)enc;
+ (void)odm_combine;
+ }
static void virtual_dig_connect_to_otg(
- struct stream_encoder *enc,
- int tg_inst)
-{}
+ struct stream_encoder *enc, int tg_inst) {
+ (void)enc;
+ (void)tg_inst;
+ }
static void virtual_setup_stereo_sync(
- struct stream_encoder *enc,
- int tg_inst,
- bool enable)
-{}
+ struct stream_encoder *enc,
+ int tg_inst, bool enable) {
+ (void)enc;
+ (void)tg_inst;
+ (void)enable;
+ }
static void virtual_stream_encoder_set_dsc_pps_info_packet(
- struct stream_encoder *enc,
- bool enable,
- uint8_t *dsc_packed_pps,
- bool immediate_update)
-{}
+ struct stream_encoder *enc, bool enable, uint8_t *dsc_packed_pps,
+ bool immediate_update)
+{
+ (void)enc;
+ (void)enable;
+ (void)dsc_packed_pps;
+ (void)immediate_update;
+}
static const struct stream_encoder_funcs virtual_str_enc_funcs = {
.dp_set_odm_combine =
diff --git a/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calcs.c
index 74962791302f..61553e24d53e 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calcs.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calcs.c
@@ -525,6 +525,7 @@ static void split_stream_across_pipes(
struct pipe_ctx *primary_pipe,
struct pipe_ctx *secondary_pipe)
{
+ (void)res_ctx;
int pipe_idx = secondary_pipe->pipe_idx;
if (!primary_pipe->plane_state)
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn10/dcn10_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn10/dcn10_fpu.c
index c5e84190c17a..5679b79d6f53 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn10/dcn10_fpu.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn10/dcn10_fpu.c
@@ -76,7 +76,7 @@ struct _vcs_dpi_ip_params_st dcn1_0_ip = {
.line_buffer_size_bits = 589824,
.max_line_buffer_lines = 12,
.IsLineBufferBppFixed = 0,
- .LineBufferFixedBpp = -1,
+ .LineBufferFixedBpp = (unsigned int)-1,
.writeback_luma_buffer_size_kbytes = 12,
.writeback_chroma_buffer_size_kbytes = 8,
.max_num_dpp = 4,
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 7aaf13bbd4e4..887744d56d6a 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
@@ -1316,6 +1316,7 @@ int dcn20_populate_dml_pipes_from_context(struct dc *dc,
display_e2e_pipe_params_st *pipes,
enum dc_validate_mode validate_mode)
{
+ (void)validate_mode;
int pipe_cnt, i;
bool synchronized_vblank = true;
struct resource_context *res_ctx = &context->res_ctx;
@@ -2335,7 +2336,7 @@ bool dcn21_validate_bandwidth_fp(struct dc *dc, struct dc_state *context,
/*Unsafe due to current pipe merge and split logic*/
ASSERT(context != dc->current_state);
- out = dcn21_fast_validate_bw(dc, context, pipes, &pipe_cnt, pipe_split_from, &vlevel, validate_mode);
+ out = dcn21_fast_validate_bw(dc, context, pipes, &pipe_cnt, pipe_split_from, &vlevel, validate_mode, false);
if (pipe_cnt == 0)
goto validate_out;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20.c
index 0c8c4a080c50..f5f636afe33c 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20.c
@@ -501,6 +501,8 @@ static bool CalculatePrefetchSchedule(
double *VUpdateWidthPix,
double *VReadyOffsetPix)
{
+ (void)mode_lib;
+
bool MyError = false;
unsigned int DPPCycles, DISPCLKCycles;
double DSTTotalPixelsAfterScaler, TotalRepeaterDelayTime;
@@ -878,6 +880,7 @@ static unsigned int CalculateVMAndRowBytes(
unsigned int *dpte_row_height,
unsigned int *meta_row_height)
{
+ (void)ViewportWidth;
unsigned int MetaRequestHeight;
unsigned int MetaRequestWidth;
unsigned int MetaSurfWidth;
@@ -2953,6 +2956,7 @@ static double CalculateRemoteSurfaceFlipDelay(
double *TInitXFill,
double *TslvChk)
{
+ (void)mode_lib;
double TSlvSetup, AvgfillRate, result;
*SrcActiveDrainRate = VRatio * SwathWidth * Bpp / LineTime;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c
index c935903b68e1..95b0a3501880 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c
@@ -495,6 +495,7 @@ static bool CalculateDelayAfterScaler(
double *DSTYAfterScaler
)
{
+ (void)ReturnBW;
unsigned int DPPCycles, DISPCLKCycles;
double DataFabricLineDeliveryTimeLuma;
double DataFabricLineDeliveryTimeChroma;
@@ -592,6 +593,8 @@ static bool CalculatePrefetchSchedule(
double *VUpdateWidthPix,
double *VReadyOffsetPix)
{
+ (void)mode_lib;
+
bool MyError = false;
double TotalRepeaterDelayTime;
double Tdm, LineTime, Tsetup;
@@ -938,6 +941,7 @@ static unsigned int CalculateVMAndRowBytes(
unsigned int *dpte_row_height,
unsigned int *meta_row_height)
{
+ (void)ViewportWidth;
unsigned int MetaRequestHeight;
unsigned int MetaRequestWidth;
unsigned int MetaSurfWidth;
@@ -3026,6 +3030,7 @@ static double CalculateRemoteSurfaceFlipDelay(
double *TInitXFill,
double *TslvChk)
{
+ (void)mode_lib;
double TSlvSetup, AvgfillRate, result;
*SrcActiveDrainRate = VRatio * SwathWidth * Bpp / LineTime;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c
index 9c58ff1069d6..591d9618bdc0 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c
@@ -126,6 +126,7 @@ static double get_refcyc_per_delivery(struct display_mode_lib *mode_lib,
unsigned int delivery_width,
unsigned int req_per_swath_ub)
{
+ (void)mode_lib;
double refcyc_per_delivery = 0.0;
if (vratio <= 1.0) {
@@ -1538,6 +1539,9 @@ void dml20_rq_dlg_get_dlg_reg(struct display_mode_lib *mode_lib,
const bool ignore_viewport_pos,
const bool immediate_flip_support)
{
+ (void)vm_en;
+ (void)ignore_viewport_pos;
+ (void)immediate_flip_support;
display_rq_params_st rq_param = {0};
display_dlg_sys_params_st dlg_sys_param = {0};
@@ -1588,6 +1592,7 @@ static void calculate_ttu_cursor(struct display_mode_lib *mode_lib,
unsigned int cur_width,
enum cursor_bpp cur_bpp)
{
+ (void)mode_lib;
unsigned int cur_src_width = cur_width;
unsigned int cur_req_size = 0;
unsigned int cur_req_width = 0;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c
index 570e6e39eb45..d4dddc9d535a 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c
@@ -126,6 +126,7 @@ static double get_refcyc_per_delivery(struct display_mode_lib *mode_lib,
unsigned int delivery_width,
unsigned int req_per_swath_ub)
{
+ (void)mode_lib;
double refcyc_per_delivery = 0.0;
if (vratio <= 1.0) {
@@ -1539,6 +1540,9 @@ void dml20v2_rq_dlg_get_dlg_reg(struct display_mode_lib *mode_lib,
const bool ignore_viewport_pos,
const bool immediate_flip_support)
{
+ (void)vm_en;
+ (void)ignore_viewport_pos;
+ (void)immediate_flip_support;
display_rq_params_st rq_param = {0};
display_dlg_sys_params_st dlg_sys_param = {0};
@@ -1589,6 +1593,7 @@ static void calculate_ttu_cursor(struct display_mode_lib *mode_lib,
unsigned int cur_width,
enum cursor_bpp cur_bpp)
{
+ (void)mode_lib;
unsigned int cur_src_width = cur_width;
unsigned int cur_req_size = 0;
unsigned int cur_req_width = 0;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c
index cd8cca651419..11570a0c9427 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c
@@ -695,6 +695,9 @@ static bool CalculatePrefetchSchedule(
double *VUpdateWidthPix,
double *VReadyOffsetPix)
{
+ (void)mode_lib;
+ (void)XFCEnabled;
+
bool MyError = false;
unsigned int DPPCycles, DISPCLKCycles;
double DSTTotalPixelsAfterScaler, TotalRepeaterDelayTime;
@@ -1290,6 +1293,8 @@ static unsigned int CalculateVMAndRowBytes(
unsigned int *DPDE0BytesFrame,
unsigned int *MetaPTEBytesFrame)
{
+ (void)SourcePixelFormat;
+ (void)ViewportWidth;
unsigned int MPDEBytesFrame;
unsigned int DCCMetaSurfaceBytes;
unsigned int MacroTileSizeBytes;
@@ -3040,6 +3045,7 @@ static double CalculateRemoteSurfaceFlipDelay(
double *TInitXFill,
double *TslvChk)
{
+ (void)mode_lib;
double TSlvSetup, AvgfillRate, result;
*SrcActiveDrainRate = VRatio * SwathWidth * Bpp / LineTime;
@@ -3187,6 +3193,7 @@ static void CalculateFlipSchedule(
double *final_flip_bw,
bool *ImmediateFlipSupportedForPipe)
{
+ (void)mode_lib;
double min_row_time = 0.0;
unsigned int HostVMDynamicLevels;
double TimeForFetchingMetaPTEImmediateFlip;
@@ -5294,6 +5301,15 @@ static void CalculateWatermarksAndDRAMSpeedChangeSupport(
double *StutterEnterPlusExitWatermark,
double *MinActiveDRAMClockChangeLatencySupported)
{
+ (void)DPPCLK;
+ (void)SwathWidthSingleDPPY;
+ (void)DCFCLK;
+ (void)UrgentOutOfOrderReturn;
+ (void)ReturnBW;
+ (void)GPUVMEnable;
+ (void)dpte_group_bytes;
+ (void)MetaChunkSize;
+
double EffectiveLBLatencyHidingY;
double EffectiveLBLatencyHidingC;
double DPPOutputBufferLinesY;
@@ -5304,7 +5320,7 @@ static void CalculateWatermarksAndDRAMSpeedChangeSupport(
double LinesInDETC;
unsigned int LinesInDETYRoundedDownToSwath[DC__NUM_DPP__MAX];
unsigned int LinesInDETCRoundedDownToSwath;
- double FullDETBufferingTimeY[DC__NUM_DPP__MAX];
+ double FullDETBufferingTimeY[DC__NUM_DPP__MAX] = { 0 };
double FullDETBufferingTimeC;
double ActiveDRAMClockChangeLatencyMarginY;
double ActiveDRAMClockChangeLatencyMarginC;
@@ -5885,6 +5901,9 @@ static void CalculateMetaAndPTETimes(
double TimePerVMRequestVBlank[],
double TimePerVMRequestFlip[])
{
+ (void)VRatioPrefetchY;
+ (void)VRatioPrefetchC;
+
unsigned int meta_chunk_width;
unsigned int min_meta_chunk_width;
unsigned int meta_chunk_per_row_int;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c
index f549da082c01..8a611b3bec33 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c
@@ -102,6 +102,7 @@ static double get_refcyc_per_delivery(
unsigned int delivery_width,
unsigned int req_per_swath_ub)
{
+ (void)mode_lib;
double refcyc_per_delivery = 0.0;
if (vratio <= 1.0) {
@@ -1647,6 +1648,9 @@ void dml21_rq_dlg_get_dlg_reg(
const bool ignore_viewport_pos,
const bool immediate_flip_support)
{
+ (void)vm_en;
+ (void)ignore_viewport_pos;
+ (void)immediate_flip_support;
display_rq_params_st rq_param = {0};
display_dlg_sys_params_st dlg_sys_param = {0};
@@ -1702,6 +1706,7 @@ static void calculate_ttu_cursor(
unsigned int cur_width,
enum cursor_bpp cur_bpp)
{
+ (void)mode_lib;
unsigned int cur_src_width = cur_width;
unsigned int cur_req_size = 0;
unsigned int cur_req_width = 0;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c
index e5f5c0663750..0cdd60869ce1 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c
@@ -571,6 +571,7 @@ void dcn30_fpu_update_bw_bounding_box(struct dc *dc,
unsigned int *dcfclk_mhz,
unsigned int *dram_speed_mts)
{
+ (void)bw_params;
unsigned int i;
dc_assert_fp_enabled();
@@ -720,6 +721,7 @@ void dcn3_fpu_build_wm_range_table(struct clk_mgr *base)
void patch_dcn30_soc_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_st *dcn3_0_ip)
{
+ (void)dcn3_0_ip;
dc_assert_fp_enabled();
if (dc->ctx->dc_bios->funcs->get_soc_bb_info) {
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c
index 1df3412be346..634982173190 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c
@@ -778,6 +778,8 @@ static bool CalculatePrefetchSchedule(
double *RequiredPrefetchPixDataBWChroma,
bool *NotEnoughTimeForDynamicMetadata)
{
+ (void)SwathWidthY;
+ (void)SwathWidthC;
struct vba_vars_st *v = &mode_lib->vba;
double DPPCLKDelaySubtotalPlusCNVCFormater = v->DPPCLKDelaySubtotal + v->DPPCLKDelayCNVCFormater;
bool MyError = false;
@@ -1233,6 +1235,10 @@ static void CalculateDCCConfiguration(
unsigned int *IndependentBlockLuma,
unsigned int *IndependentBlockChroma)
{
+ (void)SurfaceWidthChroma;
+ (void)SurfaceHeightChroma;
+ (void)BytePerPixelDETY;
+ (void)BytePerPixelDETC;
int yuv420 = 0;
int horz_div_l = 0;
int horz_div_c = 0;
@@ -1595,6 +1601,7 @@ static unsigned int CalculateVMAndRowBytes(
unsigned int *DPDE0BytesFrame,
unsigned int *MetaPTEBytesFrame)
{
+ (void)SourcePixelFormat;
unsigned int MPDEBytesFrame = 0;
unsigned int DCCMetaSurfaceBytes = 0;
unsigned int MacroTileSizeBytes = 0;
@@ -3068,6 +3075,8 @@ double dml30_CalculateWriteBackDISPCLK(
unsigned int HTotal,
unsigned int WritebackLineBufferSize)
{
+ (void)WritebackPixelFormat;
+ (void)WritebackVRatio;
double DISPCLK_H = 0, DISPCLK_V = 0, DISPCLK_HB = 0;
DISPCLK_H = PixelClock * dml_ceil(WritebackHTaps / 8.0, 1) / WritebackHRatio;
@@ -3086,6 +3095,8 @@ static double CalculateWriteBackDelay(
long WritebackSourceHeight,
unsigned int HTotal)
{
+ (void)WritebackPixelFormat;
+ (void)WritebackHRatio;
double CalculateWriteBackDelay = 0;
double Line_length = 0;
double Output_lines_last_notclamped = 0;
@@ -3199,6 +3210,8 @@ static void CalculateFlipSchedule(
double *final_flip_bw,
bool *ImmediateFlipSupportedForPipe)
{
+ (void)mode_lib;
+ (void)HostVMMinPageSize;
double min_row_time = 0.0;
unsigned int HostVMDynamicLevelsTrips = 0;
double TimeForFetchingMetaPTEImmediateFlip = 0;
@@ -4968,6 +4981,10 @@ static void CalculateWatermarksAndDRAMSpeedChangeSupport(
double BytePerPixelDETC[],
enum clock_change_support *DRAMClockChangeSupport)
{
+ (void)DCFCLK;
+ (void)ReturnBW;
+ (void)DPPCLK;
+ (void)DETBufferSizeC;
struct vba_vars_st *v = &mode_lib->vba;
double EffectiveLBLatencyHidingY = 0;
double EffectiveLBLatencyHidingC = 0;
@@ -5212,6 +5229,8 @@ static void CalculateUrgentBurstFactor(
double *UrgentBurstFactorChroma,
bool *NotEnoughUrgentLatencyHiding)
{
+ (void)DETBufferSizeInKByte;
+ (void)VRatioC;
double LinesInDETLuma = 0;
double LinesInDETChroma = 0;
unsigned int LinesInCursorBuffer = 0;
@@ -5575,6 +5594,8 @@ static void CalculateVMGroupAndRequestTimes(
double TimePerVMRequestVBlank[],
double TimePerVMRequestFlip[])
{
+ (void)dpte_row_width_luma_ub;
+ (void)dpte_row_width_chroma_ub;
int num_group_per_lower_vm_stage = 0;
int num_req_per_lower_vm_stage = 0;
unsigned int k;
@@ -5857,6 +5878,7 @@ static void CalculateSwathAndDETConfiguration(
bool ViewportSizeSupportPerPlane[],
bool *ViewportSizeSupport)
{
+ (void)HRatioChroma;
int MaximumSwathHeightY[DC__NUM_DPP__MAX] = { 0 };
int MaximumSwathHeightC[DC__NUM_DPP__MAX] = { 0 };
int MinimumSwathHeightY = 0;
@@ -6039,6 +6061,7 @@ static void CalculateSwathWidth(
unsigned int swath_width_luma_ub[],
unsigned int swath_width_chroma_ub[])
{
+ (void)BytePerPixY;
unsigned int k, j;
long surface_width_ub_l;
long surface_height_ub_l;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c
index 4fb37df54d59..472ac5ee165f 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c
@@ -50,6 +50,7 @@ static double get_refcyc_per_delivery(struct display_mode_lib *mode_lib,
unsigned int delivery_width,
unsigned int req_per_swath_ub)
{
+ (void)mode_lib;
double refcyc_per_delivery = 0.0;
if (vratio <= 1.0) {
@@ -804,6 +805,7 @@ static void calculate_ttu_cursor(struct display_mode_lib *mode_lib,
unsigned int cur_width,
enum cursor_bpp cur_bpp)
{
+ (void)mode_lib;
unsigned int cur_src_width = cur_width;
unsigned int cur_req_size = 0;
unsigned int cur_req_width = 0;
@@ -896,6 +898,9 @@ static void dml_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib,
const bool ignore_viewport_pos,
const bool immediate_flip_support)
{
+ (void)vm_en;
+ (void)ignore_viewport_pos;
+ (void)immediate_flip_support;
const display_pipe_source_params_st *src = &e2e_pipe_param[pipe_idx].pipe.src;
const display_pipe_dest_params_st *dst = &e2e_pipe_param[pipe_idx].pipe.dest;
const display_output_params_st *dout = &e2e_pipe_param[pipe_idx].dout;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c
index ed59c77bc6f6..9833467722b9 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c
@@ -873,6 +873,11 @@ static bool CalculatePrefetchSchedule(
double *VUpdateWidthPix,
double *VReadyOffsetPix)
{
+ (void)mode_lib;
+ (void)HostVMMinPageSize;
+ (void)SwathWidthY;
+ (void)SwathWidthC;
+
bool MyError = false;
unsigned int DPPCycles, DISPCLKCycles;
double DSTTotalPixelsAfterScaler;
@@ -1491,6 +1496,10 @@ static void CalculateDCCConfiguration(
unsigned int *IndependentBlockLuma,
unsigned int *IndependentBlockChroma)
{
+ (void)SurfaceWidthChroma;
+ (void)SurfaceHeightChroma;
+ (void)BytePerPixelDETY;
+ (void)BytePerPixelDETC;
int yuv420;
int horz_div_l;
int horz_div_c;
@@ -1823,6 +1832,7 @@ static unsigned int CalculateVMAndRowBytes(
int *DPDE0BytesFrame,
int *MetaPTEBytesFrame)
{
+ (void)SourcePixelFormat;
struct vba_vars_st *v = &mode_lib->vba;
unsigned int MPDEBytesFrame;
unsigned int DCCMetaSurfaceBytes;
@@ -3365,6 +3375,8 @@ double dml31_CalculateWriteBackDISPCLK(
unsigned int HTotal,
unsigned int WritebackLineBufferSize)
{
+ (void)WritebackPixelFormat;
+ (void)WritebackVRatio;
double DISPCLK_H, DISPCLK_V, DISPCLK_HB;
DISPCLK_H = PixelClock * dml_ceil(WritebackHTaps / 8.0, 1) / WritebackHRatio;
@@ -3383,6 +3395,8 @@ static double CalculateWriteBackDelay(
int WritebackSourceHeight,
unsigned int HTotal)
{
+ (void)WritebackPixelFormat;
+ (void)WritebackHRatio;
double CalculateWriteBackDelay;
double Line_length;
double Output_lines_last_notclamped;
@@ -5566,6 +5580,9 @@ static void CalculateWatermarksAndDRAMSpeedChangeSupport(
double *Z8StutterExitWatermark,
double *Z8StutterEnterPlusExitWatermark)
{
+ (void)DCFCLK;
+ (void)ReturnBW;
+ (void)DETBufferSizeC;
struct vba_vars_st *v = &mode_lib->vba;
double EffectiveLBLatencyHidingY;
double EffectiveLBLatencyHidingC;
@@ -5831,6 +5848,7 @@ static void CalculateUrgentBurstFactor(
double *UrgentBurstFactorChroma,
bool *NotEnoughUrgentLatencyHiding)
{
+ (void)VRatioC;
double LinesInDETLuma;
double LinesInDETChroma;
unsigned int LinesInCursorBuffer;
@@ -6213,6 +6231,8 @@ static void CalculateVMGroupAndRequestTimes(
double TimePerVMRequestVBlank[],
double TimePerVMRequestFlip[])
{
+ (void)dpte_row_width_luma_ub;
+ (void)dpte_row_width_chroma_ub;
int num_group_per_lower_vm_stage;
int num_req_per_lower_vm_stage;
int k;
@@ -6350,6 +6370,8 @@ static void CalculateStutterEfficiency(
int *Z8NumberOfStutterBurstsPerFrame,
double *StutterPeriod)
{
+ (void)ConfigReturnBufferSizeInKByte;
+
struct vba_vars_st *v = &mode_lib->vba;
double DETBufferingTimeY;
@@ -6649,6 +6671,7 @@ static void CalculateSwathAndDETConfiguration(
bool ViewportSizeSupportPerPlane[],
bool *ViewportSizeSupport)
{
+ (void)HRatioChroma;
int MaximumSwathHeightY[DC__NUM_DPP__MAX];
int MaximumSwathHeightC[DC__NUM_DPP__MAX];
int MinimumSwathHeightY;
@@ -6823,6 +6846,7 @@ static void CalculateSwathWidth(
int swath_width_luma_ub[],
int swath_width_chroma_ub[])
{
+ (void)BytePerPixY;
enum odm_combine_mode MainPlaneODMCombine;
int j, k;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c
index bfeb01477f0c..dfa1bc31eb0a 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c
@@ -51,6 +51,7 @@ static double get_refcyc_per_delivery(
unsigned int delivery_width,
unsigned int req_per_swath_ub)
{
+ (void)mode_lib;
double refcyc_per_delivery = 0.0;
if (vratio <= 1.0) {
@@ -785,6 +786,7 @@ static void calculate_ttu_cursor(
unsigned int cur_width,
enum cursor_bpp cur_bpp)
{
+ (void)mode_lib;
unsigned int cur_src_width = cur_width;
unsigned int cur_req_size = 0;
unsigned int cur_req_width = 0;
@@ -859,6 +861,12 @@ static void dml_rq_dlg_get_dlg_params(
const bool ignore_viewport_pos,
const bool immediate_flip_support)
{
+ (void)cstate_en;
+ (void)pstate_en;
+ (void)vm_en;
+ (void)ignore_viewport_pos;
+ (void)immediate_flip_support;
+ (void)dlg_sys_param;
const display_pipe_source_params_st *src = &e2e_pipe_param[pipe_idx].pipe.src;
const display_pipe_dest_params_st *dst = &e2e_pipe_param[pipe_idx].pipe.dest;
const display_clocks_and_cfg_st *clks = &e2e_pipe_param[pipe_idx].clks_cfg;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c
index df9d50b9b57c..ab016c294ba7 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c
@@ -391,13 +391,9 @@ int dcn314_populate_dml_pipes_from_context_fpu(struct dc *dc, struct dc_state *c
}
context->bw_ctx.dml.ip.det_buffer_size_kbytes = DCN3_14_DEFAULT_DET_SIZE;
- dc->config.enable_4to1MPC = false;
if (pipe_cnt == 1 && pipe->plane_state
&& pipe->plane_state->rotation == ROTATION_ANGLE_0 && !dc->debug.disable_z9_mpc) {
- if (is_dual_plane(pipe->plane_state->format)
- && pipe->plane_state->src_rect.width <= 1920 && pipe->plane_state->src_rect.height <= 1080) {
- dc->config.enable_4to1MPC = true;
- } else if (!is_dual_plane(pipe->plane_state->format) && pipe->plane_state->src_rect.width <= 5120) {
+ if (!is_dual_plane(pipe->plane_state->format) && pipe->plane_state->src_rect.width <= 5120) {
/* Limit to 5k max to avoid forced pipe split when there is not enough detile for swath */
context->bw_ctx.dml.ip.det_buffer_size_kbytes = 192;
pipes[0].pipe.src.unbounded_req_mode = true;
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 9f3938a50240..033fde774337 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
@@ -891,6 +891,11 @@ static bool CalculatePrefetchSchedule(
double *VUpdateWidthPix,
double *VReadyOffsetPix)
{
+ (void)mode_lib;
+ (void)HostVMMinPageSize;
+ (void)SwathWidthY;
+ (void)SwathWidthC;
+
bool MyError = false;
unsigned int DPPCycles, DISPCLKCycles;
double DSTTotalPixelsAfterScaler;
@@ -1508,6 +1513,10 @@ static void CalculateDCCConfiguration(
unsigned int *IndependentBlockLuma,
unsigned int *IndependentBlockChroma)
{
+ (void)SurfaceWidthChroma;
+ (void)SurfaceHeightChroma;
+ (void)BytePerPixelDETY;
+ (void)BytePerPixelDETC;
int yuv420;
int horz_div_l;
int horz_div_c;
@@ -1840,6 +1849,7 @@ static unsigned int CalculateVMAndRowBytes(
int *DPDE0BytesFrame,
int *MetaPTEBytesFrame)
{
+ (void)SourcePixelFormat;
struct vba_vars_st *v = &mode_lib->vba;
unsigned int MPDEBytesFrame;
unsigned int DCCMetaSurfaceBytes;
@@ -3471,6 +3481,8 @@ double dml314_CalculateWriteBackDISPCLK(
unsigned int HTotal,
unsigned int WritebackLineBufferSize)
{
+ (void)WritebackPixelFormat;
+ (void)WritebackVRatio;
double DISPCLK_H, DISPCLK_V, DISPCLK_HB;
DISPCLK_H = PixelClock * dml_ceil(WritebackHTaps / 8.0, 1) / WritebackHRatio;
@@ -3489,6 +3501,8 @@ static double CalculateWriteBackDelay(
int WritebackSourceHeight,
unsigned int HTotal)
{
+ (void)WritebackPixelFormat;
+ (void)WritebackHRatio;
double CalculateWriteBackDelay;
double Line_length;
double Output_lines_last_notclamped;
@@ -5660,6 +5674,9 @@ static void CalculateWatermarksAndDRAMSpeedChangeSupport(
double *Z8StutterExitWatermark,
double *Z8StutterEnterPlusExitWatermark)
{
+ (void)DCFCLK;
+ (void)ReturnBW;
+ (void)DETBufferSizeC;
struct vba_vars_st *v = &mode_lib->vba;
double EffectiveLBLatencyHidingY;
double EffectiveLBLatencyHidingC;
@@ -5925,6 +5942,7 @@ static void CalculateUrgentBurstFactor(
double *UrgentBurstFactorChroma,
bool *NotEnoughUrgentLatencyHiding)
{
+ (void)VRatioC;
double LinesInDETLuma;
double LinesInDETChroma;
unsigned int LinesInCursorBuffer;
@@ -6308,6 +6326,8 @@ static void CalculateVMGroupAndRequestTimes(
double TimePerVMRequestVBlank[],
double TimePerVMRequestFlip[])
{
+ (void)dpte_row_width_luma_ub;
+ (void)dpte_row_width_chroma_ub;
int num_group_per_lower_vm_stage;
int num_req_per_lower_vm_stage;
int k;
@@ -6445,6 +6465,8 @@ static void CalculateStutterEfficiency(
int *Z8NumberOfStutterBurstsPerFrame,
double *StutterPeriod)
{
+ (void)ConfigReturnBufferSizeInKByte;
+
struct vba_vars_st *v = &mode_lib->vba;
double DETBufferingTimeY;
@@ -6743,6 +6765,7 @@ static void CalculateSwathAndDETConfiguration(
bool ViewportSizeSupportPerPlane[],
bool *ViewportSizeSupport)
{
+ (void)HRatioChroma;
int MaximumSwathHeightY[DC__NUM_DPP__MAX];
int MaximumSwathHeightC[DC__NUM_DPP__MAX];
int MinimumSwathHeightY;
@@ -6914,6 +6937,7 @@ static void CalculateSwathWidth(
int swath_width_luma_ub[],
int swath_width_chroma_ub[])
{
+ (void)BytePerPixY;
enum odm_combine_mode MainPlaneODMCombine;
int j, k;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_rq_dlg_calc_314.c b/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_rq_dlg_calc_314.c
index 04df263ff65e..40a916c2a9c6 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_rq_dlg_calc_314.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_rq_dlg_calc_314.c
@@ -139,6 +139,7 @@ static double get_refcyc_per_delivery(
unsigned int delivery_width,
unsigned int req_per_swath_ub)
{
+ (void)mode_lib;
double refcyc_per_delivery = 0.0;
if (vratio <= 1.0) {
@@ -872,6 +873,7 @@ static void calculate_ttu_cursor(
unsigned int cur_width,
enum cursor_bpp cur_bpp)
{
+ (void)mode_lib;
unsigned int cur_src_width = cur_width;
unsigned int cur_req_size = 0;
unsigned int cur_req_width = 0;
@@ -944,6 +946,12 @@ static void dml_rq_dlg_get_dlg_params(
const bool ignore_viewport_pos,
const bool immediate_flip_support)
{
+ (void)cstate_en;
+ (void)pstate_en;
+ (void)vm_en;
+ (void)ignore_viewport_pos;
+ (void)immediate_flip_support;
+ (void)dlg_sys_param;
const display_pipe_source_params_st *src = &e2e_pipe_param[pipe_idx].pipe.src;
const display_pipe_dest_params_st *dst = &e2e_pipe_param[pipe_idx].pipe.dest;
const display_clocks_and_cfg_st *clks = &e2e_pipe_param[pipe_idx].clks_cfg;
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 8a0f128722b0..e29497204df7 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
@@ -3488,6 +3488,7 @@ bool dcn32_allow_subvp_high_refresh_rate(struct dc *dc, struct dc_state *context
*/
double dcn32_determine_max_vratio_prefetch(struct dc *dc, struct dc_state *context)
{
+ (void)dc;
double max_vratio_pre = __DML_MAX_BW_RATIO_PRE__; // Default value is 4
int i;
@@ -3593,6 +3594,7 @@ bool dcn32_find_vactive_pipe(struct dc *dc, const struct dc_state *context, stru
void dcn32_set_clock_limits(const struct _vcs_dpi_soc_bounding_box_st *soc_bb)
{
+ (void)soc_bb;
dc_assert_fp_enabled();
dcn3_2_soc.clock_limits[0].dcfclk_mhz = 1200.0;
}
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c
index 0748ef36a16a..5e72966a8daf 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c
@@ -457,10 +457,11 @@ void dml32_CalculateSwathAndDETConfiguration(
bool ViewportSizeSupportPerSurface[],
bool *ViewportSizeSupport)
{
+ (void)HRatioChroma;
unsigned int MaximumSwathHeightY[DC__NUM_DPP__MAX];
unsigned int MaximumSwathHeightC[DC__NUM_DPP__MAX];
- unsigned int RoundedUpMaxSwathSizeBytesY[DC__NUM_DPP__MAX];
- unsigned int RoundedUpMaxSwathSizeBytesC[DC__NUM_DPP__MAX];
+ unsigned int RoundedUpMaxSwathSizeBytesY[DC__NUM_DPP__MAX] = { 0 };
+ unsigned int RoundedUpMaxSwathSizeBytesC[DC__NUM_DPP__MAX] = { 0 };
unsigned int RoundedUpSwathSizeBytesY;
unsigned int RoundedUpSwathSizeBytesC;
double SwathWidthdoubleDPP[DC__NUM_DPP__MAX];
@@ -716,6 +717,7 @@ void dml32_CalculateSwathWidth(
unsigned int swath_width_luma_ub[], // per-pipe
unsigned int swath_width_chroma_ub[]) // per-pipe
{
+ (void)BytePerPixY;
unsigned int k, j;
enum odm_combine_mode MainSurfaceODMMode;
@@ -2304,6 +2306,7 @@ unsigned int dml32_CalculateVMAndRowBytes(
unsigned int *DPDE0BytesFrame,
unsigned int *MetaPTEBytesFrame)
{
+ (void)SourcePixelFormat;
unsigned int MPDEBytesFrame;
unsigned int DCCMetaSurfaceBytes;
unsigned int ExtraDPDEBytesFrame;
@@ -2745,6 +2748,7 @@ void dml32_CalculateUrgentBurstFactor(
double *UrgentBurstFactorChroma,
bool *NotEnoughUrgentLatencyHiding)
{
+ (void)VRatioC;
double LinesInDETLuma;
double LinesInDETChroma;
unsigned int LinesInCursorBuffer;
@@ -2900,6 +2904,8 @@ double dml32_CalculateWriteBackDelay(
unsigned int WritebackSourceHeight,
unsigned int HTotal)
{
+ (void)WritebackPixelFormat;
+ (void)WritebackHRatio;
double CalculateWriteBackDelay;
double Line_length;
double Output_lines_last_notclamped;
@@ -2977,6 +2983,9 @@ void dml32_UseMinimumDCFCLK(
/* Output */
double DCFCLKState[][2])
{
+ (void)MaxAveragePercentOfIdealSDPPortBWDisplayCanUseInNormalSystemOperation;
+ (void)ReadBandwidthLuma;
+ (void)ReadBandwidthChroma;
unsigned int i, j, k;
unsigned int dummy1;
double dummy2, dummy3;
@@ -2988,7 +2997,7 @@ void dml32_UseMinimumDCFCLK(
for (j = 0; j <= 1; ++j) {
double PixelDCFCLKCyclesRequiredInPrefetch[DC__NUM_DPP__MAX];
double PrefetchPixelLinesTime[DC__NUM_DPP__MAX];
- double DCFCLKRequiredForPeakBandwidthPerSurface[DC__NUM_DPP__MAX];
+ double DCFCLKRequiredForPeakBandwidthPerSurface[DC__NUM_DPP__MAX] = { 0 };
double DynamicMetadataVMExtraLatency[DC__NUM_DPP__MAX];
double MinimumTWait = 0.0;
double DPTEBandwidth;
@@ -3447,6 +3456,8 @@ bool dml32_CalculatePrefetchSchedule(
double *VUpdateWidthPix,
double *VReadyOffsetPix)
{
+ (void)SwathWidthY;
+ (void)SwathWidthC;
double DPPCLKDelaySubtotalPlusCNVCFormater = v->DPPCLKDelaySubtotal + v->DPPCLKDelayCNVCFormater;
bool MyError = false;
unsigned int DPPCycles, DISPCLKCycles;
@@ -4145,6 +4156,7 @@ void dml32_CalculateFlipSchedule(
double *final_flip_bw,
bool *ImmediateFlipSupportedForPipe)
{
+ (void)HostVMMinPageSize;
double min_row_time = 0.0;
unsigned int HostVMDynamicLevelsTrips;
double TimeForFetchingMetaPTEImmediateFlip;
@@ -4287,6 +4299,8 @@ void dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport(
bool *USRRetrainingSupport,
double ActiveDRAMClockChangeLatencyMargin[])
{
+ (void)DCFCLK;
+ (void)ReturnBW;
unsigned int i, j, k;
unsigned int SurfaceWithMinActiveFCLKChangeMargin = 0;
unsigned int DRAMClockChangeSupportNumber = 0;
@@ -4655,6 +4669,8 @@ double dml32_CalculateWriteBackDISPCLK(
unsigned int WritebackLineBufferSize,
double DISPCLKDPPCLKVCOSpeed)
{
+ (void)WritebackPixelFormat;
+ (void)WritebackVRatio;
double DISPCLK_H, DISPCLK_V, DISPCLK_HB;
DISPCLK_H = PixelClock * dml_ceil(WritebackHTaps / 8.0, 1) / WritebackHRatio;
@@ -5166,6 +5182,8 @@ void dml32_CalculateVMGroupAndRequestTimes(
double TimePerVMRequestVBlank[],
double TimePerVMRequestFlip[])
{
+ (void)dpte_row_width_luma_ub;
+ (void)dpte_row_width_chroma_ub;
unsigned int k;
unsigned int num_group_per_lower_vm_stage;
unsigned int num_req_per_lower_vm_stage;
@@ -5321,6 +5339,11 @@ void dml32_CalculateDCCConfiguration(
unsigned int *IndependentBlockLuma,
unsigned int *IndependentBlockChroma)
{
+ (void)SurfaceWidthChroma;
+ (void)SurfaceHeightChroma;
+ (void)TilingFormat;
+ (void)BytePerPixelDETY;
+ (void)BytePerPixelDETC;
typedef enum {
REQ_256Bytes,
REQ_128BytesNonContiguous,
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c
index 8a177d5ae213..7f40048dd67d 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c
@@ -202,6 +202,7 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_5_soc = {
void dcn35_build_wm_range_table_fpu(struct clk_mgr *clk_mgr)
{
+ (void)clk_mgr;
//TODO
}
@@ -528,14 +529,9 @@ int dcn35_populate_dml_pipes_from_context_fpu(struct dc *dc,
}
context->bw_ctx.dml.ip.det_buffer_size_kbytes = 384;/*per guide*/
- dc->config.enable_4to1MPC = false;
if (pipe_cnt == 1 && pipe->plane_state && !dc->debug.disable_z9_mpc) {
- if (is_dual_plane(pipe->plane_state->format)
- && pipe->plane_state->src_rect.width <= 1920 &&
- pipe->plane_state->src_rect.height <= 1080) {
- dc->config.enable_4to1MPC = true;
- } else if (!is_dual_plane(pipe->plane_state->format) &&
+ if (!is_dual_plane(pipe->plane_state->format) &&
pipe->plane_state->src_rect.width <= 5120) {
/*
* Limit to 5k max to avoid forced pipe split when there
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c
index 77023b619f1e..73c2aee57f28 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c
@@ -561,14 +561,9 @@ int dcn351_populate_dml_pipes_from_context_fpu(struct dc *dc,
}
context->bw_ctx.dml.ip.det_buffer_size_kbytes = 384;/*per guide*/
- dc->config.enable_4to1MPC = false;
if (pipe_cnt == 1 && pipe->plane_state && !dc->debug.disable_z9_mpc) {
- if (is_dual_plane(pipe->plane_state->format)
- && pipe->plane_state->src_rect.width <= 1920 &&
- pipe->plane_state->src_rect.height <= 1080) {
- dc->config.enable_4to1MPC = true;
- } else if (!is_dual_plane(pipe->plane_state->format) &&
+ if (!is_dual_plane(pipe->plane_state->format) &&
pipe->plane_state->src_rect.width <= 5120) {
/*
* Limit to 5k max to avoid forced pipe split when there
diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c
index da0cfbb071e6..684779ee54a3 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c
@@ -162,6 +162,7 @@ void dml_log_pipe_params(
display_e2e_pipe_params_st *pipes,
int pipe_cnt)
{
+ (void)mode_lib;
display_pipe_source_params_st *pipe_src;
display_pipe_dest_params_st *pipe_dest;
scaler_ratio_depth_st *scale_ratio_depth;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c
index 12ff65b6a7e5..3f27293a41cb 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c
@@ -49,6 +49,8 @@ void print__rq_params_st(struct display_mode_lib *mode_lib, const struct _vcs_dp
void print__data_rq_sizing_params_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_data_rq_sizing_params_st *rq_sizing)
{
+ (void)mode_lib;
+ (void)rq_sizing;
dml_print("DML_RQ_DLG_CALC: =====================================\n");
dml_print("DML_RQ_DLG_CALC: DISPLAY_DATA_RQ_SIZING_PARAM_ST\n");
dml_print("DML_RQ_DLG_CALC: chunk_bytes = %0d\n", rq_sizing->chunk_bytes);
@@ -64,6 +66,8 @@ void print__data_rq_sizing_params_st(struct display_mode_lib *mode_lib, const st
void print__data_rq_dlg_params_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_data_rq_dlg_params_st *rq_dlg_param)
{
+ (void)mode_lib;
+ (void)rq_dlg_param;
dml_print("DML_RQ_DLG_CALC: =====================================\n");
dml_print("DML_RQ_DLG_CALC: DISPLAY_DATA_RQ_DLG_PARAM_ST\n");
dml_print(
@@ -107,6 +111,8 @@ void print__data_rq_dlg_params_st(struct display_mode_lib *mode_lib, const struc
void print__data_rq_misc_params_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_data_rq_misc_params_st *rq_misc_param)
{
+ (void)mode_lib;
+ (void)rq_misc_param;
dml_print("DML_RQ_DLG_CALC: =====================================\n");
dml_print("DML_RQ_DLG_CALC: DISPLAY_DATA_RQ_MISC_PARAM_ST\n");
dml_print(
@@ -124,6 +130,8 @@ void print__data_rq_misc_params_st(struct display_mode_lib *mode_lib, const stru
void print__dlg_sys_params_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_dlg_sys_params_st *dlg_sys_param)
{
+ (void)dlg_sys_param;
+ (void)mode_lib;
dml_print("DML_RQ_DLG_CALC: =====================================\n");
dml_print("DML_RQ_DLG_CALC: DISPLAY_RQ_DLG_PARAM_ST\n");
dml_print("DML_RQ_DLG_CALC: t_mclk_wm_us = %3.2f\n", dlg_sys_param->t_mclk_wm_us);
@@ -144,6 +152,8 @@ void print__dlg_sys_params_st(struct display_mode_lib *mode_lib, const struct _v
void print__data_rq_regs_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_data_rq_regs_st *rq_regs)
{
+ (void)mode_lib;
+ (void)rq_regs;
dml_print("DML_RQ_DLG_CALC: =====================================\n");
dml_print("DML_RQ_DLG_CALC: DISPLAY_DATA_RQ_REGS_ST\n");
dml_print("DML_RQ_DLG_CALC: chunk_size = 0x%0x\n", rq_regs->chunk_size);
@@ -179,6 +189,8 @@ void print__rq_regs_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_
void print__dlg_regs_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_dlg_regs_st *dlg_regs)
{
+ (void)dlg_regs;
+ (void)mode_lib;
dml_print("DML_RQ_DLG_CALC: =====================================\n");
dml_print("DML_RQ_DLG_CALC: DISPLAY_DLG_REGS_ST\n");
dml_print(
@@ -316,6 +328,8 @@ void print__dlg_regs_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi
void print__ttu_regs_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_ttu_regs_st *ttu_regs)
{
+ (void)mode_lib;
+ (void)ttu_regs;
dml_print("DML_RQ_DLG_CALC: =====================================\n");
dml_print("DML_RQ_DLG_CALC: DISPLAY_TTU_REGS_ST\n");
dml_print(
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c
index 88dc2b97e7bf..cf194bcba455 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c
@@ -104,6 +104,7 @@ static double get_refcyc_per_delivery(
unsigned int delivery_width,
unsigned int req_per_swath_ub)
{
+ (void)mode_lib;
double refcyc_per_delivery = 0.0;
if (vratio <= 1.0) {
@@ -133,6 +134,7 @@ static double get_vratio_pre(
double vinit,
double l_sw)
{
+ (void)mode_lib;
double prefill = dml_floor(vinit, 1);
double vratio_pre = 1.0;
@@ -174,6 +176,7 @@ static void get_swath_need(
unsigned int swath_height,
double vinit)
{
+ (void)mode_lib;
double prefill = dml_floor(vinit, 1);
unsigned int max_partial_sw_int;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/Makefile b/drivers/gpu/drm/amd/display/dc/dml2_0/Makefile
index 70d9f2cd0b60..2625943d7f7e 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/Makefile
@@ -53,25 +53,29 @@ subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dml2_0/dml21/src/inc
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dml2_0/dml21/inc
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dml2_0/dml21/
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/display_mode_core.o := $(dml2_ccflags) $(frame_warn_flag)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/display_mode_util.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml2_wrapper_fpu.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml2_utils.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml2_policy.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml2_translation_helper.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml2_mall_phantom.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml_display_rq_dlg_calc.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml2_dc_resource_mgmt.o := $(dml2_ccflags)
+# Add FPU flags to all dml2 files by default, remove NO_FPU flags.
+# FPU flags step 1: Find all .c files in dal/dc/dml2_0 and it's subfolders
+DML2_ABS_PATH := $(FULL_AMD_DISPLAY_PATH)/dc/dml2_0
+DML2_C_FILES := $(shell find $(DML2_ABS_PATH) -name '*.c' -type f)
+
+# FPU flags step 2: Convert to .o and make paths relative to $(AMDDALPATH)/dc/dml2_0/
+DML2_RELATIVE_O_FILES := $(patsubst $(DML2_ABS_PATH)/%,dc/dml2_0/%,$(patsubst %.c,%.o,$(DML2_C_FILES)))
+# FPU flags step 3: Apply FPU flags to all .o files from dal/dc/dml2_0 and it's subfolders
+$(foreach obj,$(DML2_RELATIVE_O_FILES),$(eval CFLAGS_$(AMDDALPATH)/$(obj) := $(dml2_ccflags)))
+$(foreach obj,$(DML2_RELATIVE_O_FILES),$(eval CFLAGS_REMOVE_$(AMDDALPATH)/$(obj) := $(dml2_rcflags)))
+
+# FPU flags step 4: Replace CFLAGS per file for files with additional flags beyond dml2_ccflags and dml2_rcflags
+CFLAGS_$(AMDDALPATH)/dc/dml2_0/display_mode_core.o := $(dml2_ccflags) $(frame_warn_flag)
+CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.o := $(dml2_ccflags) $(frame_warn_flag)
+CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_utils.o := $(dml2_ccflags) $(frame_warn_flag)
+CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml2_wrapper.o := $(dml2_rcflags)
+CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/dml21_wrapper.o := $(dml2_rcflags)
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/display_mode_core.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/display_mode_util.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml2_wrapper_fpu.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml2_utils.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml2_policy.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml2_translation_helper.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml2_mall_phantom.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml_display_rq_dlg_calc.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml2_dc_resource_mgmt.o := $(dml2_rcflags)
+CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.o := $(dml2_rcflags)
+CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_utils.o := $(dml2_rcflags)
+CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml2_wrapper.o := $(dml2_ccflags)
+CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/dml21_wrapper.o := $(dml2_ccflags)
DML2 = display_mode_core.o display_mode_util.o dml2_wrapper_fpu.o dml2_wrapper.o \
dml2_utils.o dml2_policy.o dml2_translation_helper.o dml2_dc_resource_mgmt.o dml2_mall_phantom.o \
@@ -81,41 +85,6 @@ AMD_DAL_DML2 = $(addprefix $(AMDDALPATH)/dc/dml2_0/,$(DML2))
AMD_DISPLAY_FILES += $(AMD_DAL_DML2)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.o := $(dml2_ccflags) $(frame_warn_flag)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_utils.o := $(dml2_ccflags) $(frame_warn_flag)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_top/dml2_top_interfaces.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_top/dml2_top_soc15.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_factory.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn4.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_factory.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn4.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn42.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_factory.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn3.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_standalone_libraries/lib_float_math.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/dml21_translation_helper.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/dml21_utils.o := $(dml2_ccflags)
-
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_factory.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_utils.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_top/dml2_top_interfaces.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_top/dml2_top_soc15.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn4.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_factory.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn4.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn42.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_factory.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn3.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_standalone_libraries/lib_float_math.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/dml21_translation_helper.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/dml21_utils.o := $(dml2_rcflags)
DML21 := src/dml2_top/dml2_top_interfaces.o
DML21 += src/dml2_top/dml2_top_soc15.o
@@ -134,6 +103,7 @@ DML21 += src/dml2_pmo/dml2_pmo_dcn4_fams2.o
DML21 += src/dml2_standalone_libraries/lib_float_math.o
DML21 += dml21_translation_helper.o
DML21 += dml21_wrapper.o
+DML21 += dml21_wrapper_fpu.o
DML21 += dml21_utils.o
AMD_DAL_DML21 = $(addprefix $(AMDDALPATH)/dc/dml2_0/dml21/,$(DML21))
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_translation_helper.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_translation_helper.c
index 847fab508750..2f0e0048bea8 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_translation_helper.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_translation_helper.c
@@ -90,7 +90,8 @@ static void populate_dml21_timing_config_from_stream_state(struct dml2_timing_cf
struct pipe_ctx *pipe_ctx,
struct dml2_context *dml_ctx)
{
- unsigned int hblank_start, vblank_start, min_hardware_refresh_in_uhz;
+ unsigned int hblank_start, vblank_start;
+ uint64_t min_hardware_refresh_in_uhz;
uint32_t pix_clk_100hz;
timing->h_active = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right + pipe_ctx->dsc_padding_params.dsc_hactive_padding;
@@ -105,7 +106,7 @@ static void populate_dml21_timing_config_from_stream_state(struct dml2_timing_cf
timing->h_total = stream->timing.h_total + pipe_ctx->dsc_padding_params.dsc_htotal_padding;
timing->v_total = stream->timing.v_total;
timing->h_sync_width = stream->timing.h_sync_width;
- timing->interlaced = stream->timing.flags.INTERLACE;
+ timing->interlaced = (stream->timing.flags.INTERLACE != 0);
hblank_start = stream->timing.h_total - stream->timing.h_front_porch;
@@ -137,7 +138,11 @@ static void populate_dml21_timing_config_from_stream_state(struct dml2_timing_cf
(timing->h_total * (long long)calc_max_hardware_v_total(stream)));
}
- timing->drr_config.min_refresh_uhz = max(stream->timing.min_refresh_in_uhz, min_hardware_refresh_in_uhz);
+ {
+ uint64_t min_refresh = max((uint64_t)stream->timing.min_refresh_in_uhz, min_hardware_refresh_in_uhz);
+ ASSERT(min_refresh <= ULONG_MAX);
+ timing->drr_config.min_refresh_uhz = (unsigned long)min_refresh;
+ }
if (dml_ctx->config.callbacks.get_max_flickerless_instant_vtotal_increase &&
stream->ctx->dc->config.enable_fpo_flicker_detection == 1)
@@ -601,27 +606,33 @@ static void populate_dml21_plane_config_from_plane_state(struct dml2_context *dm
plane->composition.viewport.stationary = false;
- if (plane_state->cm.flags.bits.lut3d_dma_enable) {
+ if (plane_state->mcm_luts.lut3d_data.lut3d_src == DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM) {
plane->tdlut.setup_for_tdlut = true;
- switch (plane_state->cm.lut3d_dma.swizzle) {
- case CM_LUT_3D_SWIZZLE_LINEAR_RGB:
- case CM_LUT_3D_SWIZZLE_LINEAR_BGR:
+ switch (plane_state->mcm_luts.lut3d_data.gpu_mem_params.layout) {
+ case DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_RGB:
+ case DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_BGR:
plane->tdlut.tdlut_addressing_mode = dml2_tdlut_sw_linear;
break;
- case CM_LUT_1D_PACKED_LINEAR:
- default:
+ case DC_CM2_GPU_MEM_LAYOUT_1D_PACKED_LINEAR:
plane->tdlut.tdlut_addressing_mode = dml2_tdlut_simple_linear;
break;
}
- switch (plane_state->cm.lut3d_dma.size) {
- case CM_LUT_SIZE_333333:
+ switch (plane_state->mcm_luts.lut3d_data.gpu_mem_params.size) {
+ case DC_CM2_GPU_MEM_SIZE_171717:
+ plane->tdlut.tdlut_width_mode = dml2_tdlut_width_17_cube;
+ break;
+ case DC_CM2_GPU_MEM_SIZE_333333:
plane->tdlut.tdlut_width_mode = dml2_tdlut_width_33_cube;
break;
- case CM_LUT_SIZE_171717:
+ // handling when use case and HW support available
+ case DC_CM2_GPU_MEM_SIZE_454545:
+ case DC_CM2_GPU_MEM_SIZE_656565:
+ break;
+ case DC_CM2_GPU_MEM_SIZE_TRANSFORMED:
default:
- plane->tdlut.tdlut_width_mode = dml2_tdlut_width_17_cube;
+ //plane->tdlut.tdlut_width_mode = dml2_tdlut_width_flatten; // dml2_tdlut_width_flatten undefined
break;
}
}
@@ -691,7 +702,7 @@ unsigned int map_plane_to_dml21_display_cfg(const struct dml2_context *dml_ctx,
if (!dml21_wrapper_get_plane_id(context, stream_id, plane, &plane_id)) {
ASSERT(false);
- return -1;
+ return UINT_MAX;
}
for (i = 0; i < __DML2_WRAPPER_MAX_STREAMS_PLANES__; i++) {
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_utils.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_utils.c
index ab7ec24268be..4724b08c77e1 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_utils.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_utils.c
@@ -420,8 +420,12 @@ static unsigned int dml21_build_fams2_stream_programming_v2(const struct dc *dc,
type = static_base_state->stream_v1.base.type;
/* get information from context */
- static_base_state->stream_v1.base.num_planes = context->stream_status[dc_stream_idx].plane_count;
- static_base_state->stream_v1.base.otg_inst = context->stream_status[dc_stream_idx].primary_otg_inst;
+ ASSERT(context->stream_status[dc_stream_idx].plane_count >= 0 &&
+ context->stream_status[dc_stream_idx].plane_count <= 0xFF);
+ ASSERT(context->stream_status[dc_stream_idx].primary_otg_inst >= 0 &&
+ context->stream_status[dc_stream_idx].primary_otg_inst <= 0xFF);
+ static_base_state->stream_v1.base.num_planes = (uint8_t)context->stream_status[dc_stream_idx].plane_count;
+ static_base_state->stream_v1.base.otg_inst = (uint8_t)context->stream_status[dc_stream_idx].primary_otg_inst;
/* populate pipe masks for planes */
for (dc_plane_idx = 0; dc_plane_idx < context->stream_status[dc_stream_idx].plane_count; dc_plane_idx++) {
@@ -458,7 +462,9 @@ static unsigned int dml21_build_fams2_stream_programming_v2(const struct dc *dc,
switch (dc->debug.fams_version.minor) {
case 1:
default:
- static_sub_state->stream_v1.sub_state.subvp.phantom_otg_inst = phantom_status->primary_otg_inst;
+ ASSERT(phantom_status->primary_otg_inst >= 0 &&
+ phantom_status->primary_otg_inst <= 0xFF);
+ static_sub_state->stream_v1.sub_state.subvp.phantom_otg_inst = (uint8_t)phantom_status->primary_otg_inst;
/* populate pipe masks for phantom planes */
for (dc_plane_idx = 0; dc_plane_idx < phantom_status->plane_count; dc_plane_idx++) {
@@ -516,7 +522,8 @@ void dml21_build_fams2_programming(const struct dc *dc,
context->bw_ctx.bw.dcn.fams2_global_config.num_streams = num_fams2_streams;
}
- context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching = context->bw_ctx.bw.dcn.fams2_global_config.features.bits.enable;
+ context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching =
+ (context->bw_ctx.bw.dcn.fams2_global_config.features.bits.enable != 0);
}
bool dml21_is_plane1_enabled(enum dml2_source_format_class source_format)
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper.c
index 2623e917ec28..7398f8b69adb 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper.c
@@ -9,6 +9,10 @@
#include "dml21_utils.h"
#include "dml21_translation_helper.h"
#include "dml2_dc_resource_mgmt.h"
+#include "dml2_wrapper.h"
+#include "dml2_wrapper_fpu.h"
+#include "dml21_wrapper.h"
+#include "dml21_wrapper_fpu.h"
#include "dc_fpu.h"
#if !defined(DC_RUN_WITH_PREEMPTION_ENABLED)
@@ -34,50 +38,18 @@ static bool dml21_allocate_memory(struct dml2_context **dml_ctx)
(*dml_ctx)->v21.mode_programming.display_config = (*dml_ctx)->v21.mode_support.display_config;
DC_RUN_WITH_PREEMPTION_ENABLED((*dml_ctx)->v21.mode_programming.programming = vzalloc(sizeof(struct dml2_display_cfg_programming)));
+
if (!((*dml_ctx)->v21.mode_programming.programming))
return false;
return true;
}
-static void dml21_populate_configuration_options(const struct dc *in_dc,
- struct dml2_context *dml_ctx,
- const struct dml2_configuration_options *config)
-{
- dml_ctx->config = *config;
-
- /* UCLK P-State options */
- if (in_dc->debug.dml21_force_pstate_method) {
- dml_ctx->config.pmo.force_pstate_method_enable = true;
- for (int i = 0; i < MAX_PIPES; i++)
- dml_ctx->config.pmo.force_pstate_method_values[i] = in_dc->debug.dml21_force_pstate_method_values[i];
- } else {
- dml_ctx->config.pmo.force_pstate_method_enable = false;
- }
-}
-
-static void dml21_init(const struct dc *in_dc, struct dml2_context *dml_ctx, const struct dml2_configuration_options *config)
-{
-
- dml_ctx->architecture = dml2_architecture_21;
-
- dml21_populate_configuration_options(in_dc, dml_ctx, config);
-
- DC_FP_START();
-
- dml21_populate_dml_init_params(&dml_ctx->v21.dml_init, &dml_ctx->config, in_dc);
-
- dml2_initialize_instance(&dml_ctx->v21.dml_init);
-
- DC_FP_END();
-}
-
bool dml21_create(const struct dc *in_dc, struct dml2_context **dml_ctx, const struct dml2_configuration_options *config)
{
/* Allocate memory for initializing DML21 instance */
- if (!dml21_allocate_memory(dml_ctx)) {
+ if (!dml21_allocate_memory(dml_ctx))
return false;
- }
dml21_init(in_dc, *dml_ctx, config);
@@ -90,337 +62,6 @@ void dml21_destroy(struct dml2_context *dml2)
vfree(dml2->v21.mode_programming.programming);
}
-static void dml21_calculate_rq_and_dlg_params(const struct dc *dc, struct dc_state *context, struct resource_context *out_new_hw_state,
- struct dml2_context *in_ctx, unsigned int pipe_cnt)
-{
- unsigned int dml_prog_idx = 0, dc_pipe_index = 0, num_dpps_required = 0;
- struct dml2_per_plane_programming *pln_prog = NULL;
- struct dml2_per_stream_programming *stream_prog = NULL;
- struct pipe_ctx *dc_main_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__];
- struct pipe_ctx *dc_phantom_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__] = {0};
- int num_pipes;
- unsigned int dml_phantom_prog_idx;
-
- context->bw_ctx.bw.dcn.clk.dppclk_khz = 0;
-
- /* copy global DCHUBBUB arbiter registers */
- memcpy(&context->bw_ctx.bw.dcn.arb_regs, &in_ctx->v21.mode_programming.programming->global_regs.arb_regs, sizeof(struct dml2_display_arb_regs));
-
- /* legacy only */
- context->bw_ctx.bw.dcn.compbuf_size_kb = (int)in_ctx->v21.mode_programming.programming->global_regs.arb_regs.compbuf_size * 64;
-
- context->bw_ctx.bw.dcn.mall_ss_size_bytes = 0;
- context->bw_ctx.bw.dcn.mall_ss_psr_active_size_bytes = 0;
- context->bw_ctx.bw.dcn.mall_subvp_size_bytes = 0;
-
- /* phantom's start after main planes */
- dml_phantom_prog_idx = in_ctx->v21.mode_programming.programming->display_config.num_planes;
-
- for (dml_prog_idx = 0; dml_prog_idx < DML2_MAX_PLANES; dml_prog_idx++) {
- pln_prog = &in_ctx->v21.mode_programming.programming->plane_programming[dml_prog_idx];
-
- if (!pln_prog->plane_descriptor)
- continue;
-
- stream_prog = &in_ctx->v21.mode_programming.programming->stream_programming[pln_prog->plane_descriptor->stream_index];
- num_dpps_required = pln_prog->num_dpps_required;
-
- if (num_dpps_required == 0) {
- continue;
- }
- num_pipes = dml21_find_dc_pipes_for_plane(dc, context, in_ctx, dc_main_pipes, dc_phantom_pipes, dml_prog_idx);
-
- if (num_pipes <= 0)
- continue;
-
- /* program each pipe */
- for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) {
- dml21_program_dc_pipe(in_ctx, context, dc_main_pipes[dc_pipe_index], pln_prog, stream_prog);
-
- if (pln_prog->phantom_plane.valid && dc_phantom_pipes[dc_pipe_index]) {
- dml21_program_dc_pipe(in_ctx, context, dc_phantom_pipes[dc_pipe_index], pln_prog, stream_prog);
- }
- }
-
- /* copy per plane mcache allocation */
- memcpy(&context->bw_ctx.bw.dcn.mcache_allocations[dml_prog_idx], &pln_prog->mcache_allocation, sizeof(struct dml2_mcache_surface_allocation));
- if (pln_prog->phantom_plane.valid) {
- memcpy(&context->bw_ctx.bw.dcn.mcache_allocations[dml_phantom_prog_idx],
- &pln_prog->phantom_plane.mcache_allocation,
- sizeof(struct dml2_mcache_surface_allocation));
-
- dml_phantom_prog_idx++;
- }
- }
-
- /* assign global clocks */
- context->bw_ctx.bw.dcn.clk.bw_dppclk_khz = context->bw_ctx.bw.dcn.clk.dppclk_khz;
- context->bw_ctx.bw.dcn.clk.bw_dispclk_khz = context->bw_ctx.bw.dcn.clk.dispclk_khz;
- if (in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.num_clk_values > 1) {
- context->bw_ctx.bw.dcn.clk.max_supported_dispclk_khz =
- in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.clk_values_khz[in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.num_clk_values] * 1000;
- } else {
- context->bw_ctx.bw.dcn.clk.max_supported_dispclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.clk_values_khz[0] * 1000;
- }
-
- if (in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.num_clk_values > 1) {
- context->bw_ctx.bw.dcn.clk.max_supported_dppclk_khz =
- in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.clk_values_khz[in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.num_clk_values] * 1000;
- } else {
- context->bw_ctx.bw.dcn.clk.max_supported_dppclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.clk_values_khz[0] * 1000;
- }
-
- /* get global mall allocation */
- if (dc->res_pool->funcs->calculate_mall_ways_from_bytes) {
- context->bw_ctx.bw.dcn.clk.num_ways = dc->res_pool->funcs->calculate_mall_ways_from_bytes(dc, context->bw_ctx.bw.dcn.mall_subvp_size_bytes);
- } else {
- context->bw_ctx.bw.dcn.clk.num_ways = 0;
- }
-}
-
-static void dml21_prepare_mcache_params(struct dml2_context *dml_ctx, struct dc_state *context, struct dc_mcache_params *mcache_params)
-{
- int dc_plane_idx = 0;
- int dml_prog_idx, stream_idx, plane_idx;
- struct dml2_per_plane_programming *pln_prog = NULL;
-
- for (stream_idx = 0; stream_idx < context->stream_count; stream_idx++) {
- for (plane_idx = 0; plane_idx < context->stream_status[stream_idx].plane_count; plane_idx++) {
- dml_prog_idx = map_plane_to_dml21_display_cfg(dml_ctx, context->streams[stream_idx]->stream_id, context->stream_status[stream_idx].plane_states[plane_idx], context);
- if (dml_prog_idx == INVALID) {
- continue;
- }
- pln_prog = &dml_ctx->v21.mode_programming.programming->plane_programming[dml_prog_idx];
- mcache_params[dc_plane_idx].valid = pln_prog->mcache_allocation.valid;
- mcache_params[dc_plane_idx].num_mcaches_plane0 = pln_prog->mcache_allocation.num_mcaches_plane0;
- mcache_params[dc_plane_idx].num_mcaches_plane1 = pln_prog->mcache_allocation.num_mcaches_plane1;
- mcache_params[dc_plane_idx].requires_dedicated_mall_mcache = pln_prog->mcache_allocation.requires_dedicated_mall_mcache;
- mcache_params[dc_plane_idx].last_slice_sharing.plane0_plane1 = pln_prog->mcache_allocation.last_slice_sharing.plane0_plane1;
- memcpy(mcache_params[dc_plane_idx].mcache_x_offsets_plane0,
- pln_prog->mcache_allocation.mcache_x_offsets_plane0,
- sizeof(int) * (DML2_MAX_MCACHES + 1));
- memcpy(mcache_params[dc_plane_idx].mcache_x_offsets_plane1,
- pln_prog->mcache_allocation.mcache_x_offsets_plane1,
- sizeof(int) * (DML2_MAX_MCACHES + 1));
- dc_plane_idx++;
- }
- }
-}
-
-static bool dml21_mode_check_and_programming(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx)
-{
- bool result = false;
- struct dml2_build_mode_programming_in_out *mode_programming = &dml_ctx->v21.mode_programming;
- struct dc_mcache_params mcache_params[MAX_PLANES] = {0};
-
- memset(&dml_ctx->v21.display_config, 0, sizeof(struct dml2_display_cfg));
- memset(&dml_ctx->v21.dml_to_dc_pipe_mapping, 0, sizeof(struct dml2_dml_to_dc_pipe_mapping));
- memset(&dml_ctx->v21.mode_programming.dml2_instance->scratch.build_mode_programming_locals.mode_programming_params, 0, sizeof(struct dml2_core_mode_programming_in_out));
-
- if (!context)
- return true;
-
- if (context->stream_count == 0) {
- dml21_init_min_clocks_for_dc_state(dml_ctx, context);
- dml21_build_fams2_programming(in_dc, context, dml_ctx);
- return true;
- }
-
- /* scrub phantom's from current dc_state */
- dml_ctx->config.svp_pstate.callbacks.remove_phantom_streams_and_planes(in_dc, context);
- dml_ctx->config.svp_pstate.callbacks.release_phantom_streams_and_planes(in_dc, context);
-
- /* Populate stream, plane mappings and other fields in display config. */
- result = dml21_map_dc_state_into_dml_display_cfg(in_dc, context, dml_ctx);
- if (!result)
- return false;
-
- DC_FP_START();
- result = dml2_build_mode_programming(mode_programming);
- DC_FP_END();
- if (!result)
- return false;
-
- /* Check and map HW resources */
- if (result && !dml_ctx->config.skip_hw_state_mapping) {
- dml21_map_hw_resources(dml_ctx);
- dml2_map_dc_pipes(dml_ctx, context, NULL, &dml_ctx->v21.dml_to_dc_pipe_mapping, in_dc->current_state);
- /* if subvp phantoms are present, expand them into dc context */
- dml21_handle_phantom_streams_planes(in_dc, context, dml_ctx);
-
- if (in_dc->res_pool->funcs->program_mcache_pipe_config) {
- //Prepare mcache params for each plane based on mcache output from DML
- dml21_prepare_mcache_params(dml_ctx, context, mcache_params);
-
- //populate mcache regs to each pipe
- dml_ctx->config.callbacks.allocate_mcache(context, mcache_params);
- }
- }
-
- /* Copy DML CLK, WM and REG outputs to bandwidth context */
- if (result && !dml_ctx->config.skip_hw_state_mapping) {
- dml21_calculate_rq_and_dlg_params(in_dc, context, &context->res_ctx, dml_ctx, in_dc->res_pool->pipe_count);
- dml21_copy_clocks_to_dc_state(dml_ctx, context);
- dml21_extract_watermark_sets(in_dc, &context->bw_ctx.bw.dcn.watermarks, dml_ctx);
- dml21_build_fams2_programming(in_dc, context, dml_ctx);
- }
-
- return true;
-}
-
-static bool dml21_check_mode_support(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx)
-{
- bool is_supported = false;
- struct dml2_initialize_instance_in_out *dml_init = &dml_ctx->v21.dml_init;
- struct dml2_check_mode_supported_in_out *mode_support = &dml_ctx->v21.mode_support;
-
- memset(&dml_ctx->v21.display_config, 0, sizeof(struct dml2_display_cfg));
- memset(&dml_ctx->v21.dml_to_dc_pipe_mapping, 0, sizeof(struct dml2_dml_to_dc_pipe_mapping));
- memset(&dml_ctx->v21.mode_programming.dml2_instance->scratch.check_mode_supported_locals.mode_support_params, 0, sizeof(struct dml2_core_mode_support_in_out));
-
- if (!context || context->stream_count == 0)
- return true;
-
- /* Scrub phantom's from current dc_state */
- dml_ctx->config.svp_pstate.callbacks.remove_phantom_streams_and_planes(in_dc, context);
- dml_ctx->config.svp_pstate.callbacks.release_phantom_streams_and_planes(in_dc, context);
-
- mode_support->dml2_instance = dml_init->dml2_instance;
- dml21_map_dc_state_into_dml_display_cfg(in_dc, context, dml_ctx);
- dml_ctx->v21.mode_programming.dml2_instance->scratch.build_mode_programming_locals.mode_programming_params.programming = dml_ctx->v21.mode_programming.programming;
- DC_FP_START();
- is_supported = dml2_check_mode_supported(mode_support);
- DC_FP_END();
- if (!is_supported)
- return false;
-
- return true;
-}
-
-bool dml21_validate(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx,
- enum dc_validate_mode validate_mode)
-{
- bool out = false;
-
- /* Use dml21_check_mode_support for DC_VALIDATE_MODE_ONLY and DC_VALIDATE_MODE_AND_STATE_INDEX path */
- if (validate_mode != DC_VALIDATE_MODE_AND_PROGRAMMING)
- out = dml21_check_mode_support(in_dc, context, dml_ctx);
- else
- out = dml21_mode_check_and_programming(in_dc, context, dml_ctx);
-
- return out;
-}
-
-void dml21_prepare_mcache_programming(struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx)
-{
- unsigned int dml_prog_idx, dml_phantom_prog_idx, dc_pipe_index;
- int num_pipes;
- struct pipe_ctx *dc_main_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__];
- struct pipe_ctx *dc_phantom_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__] = {0};
-
- struct dml2_per_plane_programming *pln_prog = NULL;
- struct dml2_plane_mcache_configuration_descriptor *mcache_config = NULL;
- struct prepare_mcache_programming_locals *l = &dml_ctx->v21.scratch.prepare_mcache_locals;
-
- if (context->stream_count == 0) {
- return;
- }
-
- memset(&l->build_mcache_programming_params, 0, sizeof(struct dml2_build_mcache_programming_in_out));
- l->build_mcache_programming_params.dml2_instance = dml_ctx->v21.dml_init.dml2_instance;
-
- /* phantom's start after main planes */
- dml_phantom_prog_idx = dml_ctx->v21.mode_programming.programming->display_config.num_planes;
-
- /* Build mcache programming parameters per plane per pipe */
- for (dml_prog_idx = 0; dml_prog_idx < dml_ctx->v21.mode_programming.programming->display_config.num_planes; dml_prog_idx++) {
- pln_prog = &dml_ctx->v21.mode_programming.programming->plane_programming[dml_prog_idx];
-
- mcache_config = &l->build_mcache_programming_params.mcache_configurations[dml_prog_idx];
- memset(mcache_config, 0, sizeof(struct dml2_plane_mcache_configuration_descriptor));
- mcache_config->plane_descriptor = pln_prog->plane_descriptor;
- mcache_config->mcache_allocation = &context->bw_ctx.bw.dcn.mcache_allocations[dml_prog_idx];
- mcache_config->num_pipes = pln_prog->num_dpps_required;
- l->build_mcache_programming_params.num_configurations++;
-
- if (pln_prog->num_dpps_required == 0) {
- continue;
- }
-
- num_pipes = dml21_find_dc_pipes_for_plane(in_dc, context, dml_ctx, dc_main_pipes, dc_phantom_pipes, dml_prog_idx);
- if (num_pipes <= 0 || dc_main_pipes[0]->stream == NULL ||
- dc_main_pipes[0]->plane_state == NULL)
- continue;
-
- /* get config for each pipe */
- for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) {
- ASSERT(dc_main_pipes[dc_pipe_index]);
- dml21_get_pipe_mcache_config(context, dc_main_pipes[dc_pipe_index], pln_prog, &mcache_config->pipe_configurations[dc_pipe_index]);
- }
-
- /* get config for each phantom pipe */
- if (pln_prog->phantom_plane.valid &&
- dc_phantom_pipes[0] &&
- dc_main_pipes[0]->stream &&
- dc_phantom_pipes[0]->plane_state) {
- mcache_config = &l->build_mcache_programming_params.mcache_configurations[dml_phantom_prog_idx];
- memset(mcache_config, 0, sizeof(struct dml2_plane_mcache_configuration_descriptor));
- mcache_config->plane_descriptor = pln_prog->plane_descriptor;
- mcache_config->mcache_allocation = &context->bw_ctx.bw.dcn.mcache_allocations[dml_phantom_prog_idx];
- mcache_config->num_pipes = pln_prog->num_dpps_required;
- l->build_mcache_programming_params.num_configurations++;
-
- for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) {
- ASSERT(dc_phantom_pipes[dc_pipe_index]);
- dml21_get_pipe_mcache_config(context, dc_phantom_pipes[dc_pipe_index], pln_prog, &mcache_config->pipe_configurations[dc_pipe_index]);
- }
-
- /* increment phantom index */
- dml_phantom_prog_idx++;
- }
- }
-
- /* Call to generate mcache programming per plane per pipe for the given display configuration */
- dml2_build_mcache_programming(&l->build_mcache_programming_params);
-
- /* get per plane per pipe mcache programming */
- for (dml_prog_idx = 0; dml_prog_idx < dml_ctx->v21.mode_programming.programming->display_config.num_planes; dml_prog_idx++) {
- pln_prog = &dml_ctx->v21.mode_programming.programming->plane_programming[dml_prog_idx];
-
- num_pipes = dml21_find_dc_pipes_for_plane(in_dc, context, dml_ctx, dc_main_pipes, dc_phantom_pipes, dml_prog_idx);
- if (num_pipes <= 0 || dc_main_pipes[0]->stream == NULL ||
- dc_main_pipes[0]->plane_state == NULL)
- continue;
-
- /* get config for each pipe */
- for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) {
- ASSERT(dc_main_pipes[dc_pipe_index]);
- if (l->build_mcache_programming_params.per_plane_pipe_mcache_regs[dml_prog_idx][dc_pipe_index]) {
- memcpy(&dc_main_pipes[dc_pipe_index]->mcache_regs,
- l->build_mcache_programming_params.per_plane_pipe_mcache_regs[dml_prog_idx][dc_pipe_index],
- sizeof(struct dml2_hubp_pipe_mcache_regs));
- }
- }
-
- /* get config for each phantom pipe */
- if (pln_prog->phantom_plane.valid &&
- dc_phantom_pipes[0] &&
- dc_main_pipes[0]->stream &&
- dc_phantom_pipes[0]->plane_state) {
- for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) {
- ASSERT(dc_phantom_pipes[dc_pipe_index]);
- if (l->build_mcache_programming_params.per_plane_pipe_mcache_regs[dml_phantom_prog_idx][dc_pipe_index]) {
- memcpy(&dc_phantom_pipes[dc_pipe_index]->mcache_regs,
- l->build_mcache_programming_params.per_plane_pipe_mcache_regs[dml_phantom_prog_idx][dc_pipe_index],
- sizeof(struct dml2_hubp_pipe_mcache_regs));
- }
- }
- /* increment phantom index */
- dml_phantom_prog_idx++;
- }
- }
-}
-
void dml21_copy(struct dml2_context *dst_dml_ctx,
struct dml2_context *src_dml_ctx)
{
@@ -446,12 +87,8 @@ void dml21_copy(struct dml2_context *dst_dml_ctx,
dst_dml_ctx->v21.mode_programming.programming = dst_dml2_programming;
- DC_FP_START();
-
/* need to initialize copied instance for internal references to be correct */
dml2_initialize_instance(&dst_dml_ctx->v21.dml_init);
-
- DC_FP_END();
}
bool dml21_create_copy(struct dml2_context **dst_dml_ctx,
@@ -466,8 +103,3 @@ bool dml21_create_copy(struct dml2_context **dst_dml_ctx,
return true;
}
-void dml21_reinit(const struct dc *in_dc, struct dml2_context *dml_ctx, const struct dml2_configuration_options *config)
-{
- dml21_init(in_dc, dml_ctx, config);
-}
-
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper.h
index b508bbcc0e16..c4813c51251b 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper.h
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper.h
@@ -34,36 +34,6 @@ void dml21_copy(struct dml2_context *dst_dml_ctx,
struct dml2_context *src_dml_ctx);
bool dml21_create_copy(struct dml2_context **dst_dml_ctx,
struct dml2_context *src_dml_ctx);
-void dml21_reinit(const struct dc *in_dc, struct dml2_context *dml_ctx, const struct dml2_configuration_options *config);
-
-/**
- * dml21_validate - Determines if a display configuration is supported or not.
- * @in_dc: dc.
- * @context: dc_state to be validated.
- * @dml_ctx: dml21 context.
- * @validate_mode: DC_VALIDATE_MODE_ONLY and DC_VALIDATE_MODE_AND_STATE_INDEX
- * will not populate context.res_ctx.
- *
- * Based on fast_validate option internally would call:
- *
- * -dml21_mode_check_and_programming - for DC_VALIDATE_MODE_AND_PROGRAMMING option
- * Calculates if dc_state can be supported on the input display
- * configuration. If supported, generates the necessary HW
- * programming for the new dc_state.
- *
- * -dml21_check_mode_support - for DC_VALIDATE_MODE_ONLY and DC_VALIDATE_MODE_AND_STATE_INDEX option
- * Calculates if dc_state can be supported for the input display
- * config.
- *
- * Context: Two threads may not invoke this function concurrently unless they reference
- * separate dc_states for validation.
- * Return: True if mode is supported, false otherwise.
- */
-bool dml21_validate(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx,
- enum dc_validate_mode validate_mode);
-
-/* Prepare hubp mcache_regs for hubp mcache ID and split coordinate programming */
-void dml21_prepare_mcache_programming(struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx);
/* Structure for inputting external SOCBB and DCNIP values for tool based debugging. */
struct socbb_ip_params_external {
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper_fpu.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper_fpu.c
new file mode 100644
index 000000000000..cc992af6ac9c
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper_fpu.c
@@ -0,0 +1,381 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#include "dml2_internal_types.h"
+#include "dml_top.h"
+#include "dml2_core_dcn4_calcs.h"
+#include "dml2_internal_shared_types.h"
+#include "dml21_utils.h"
+#include "dml21_translation_helper.h"
+#include "dml2_dc_resource_mgmt.h"
+#include "dml2_wrapper.h"
+#include "dml2_wrapper_fpu.h"
+#include "dml21_wrapper.h"
+#include "dml21_wrapper_fpu.h"
+
+#define INVALID -1
+
+static void dml21_populate_configuration_options(const struct dc *in_dc,
+ struct dml2_context *dml_ctx,
+ const struct dml2_configuration_options *config)
+{
+ dml_ctx->config = *config;
+
+ /* UCLK P-State options */
+ if (in_dc->debug.dml21_force_pstate_method) {
+ dml_ctx->config.pmo.force_pstate_method_enable = true;
+ for (int i = 0; i < MAX_PIPES; i++)
+ dml_ctx->config.pmo.force_pstate_method_values[i] = in_dc->debug.dml21_force_pstate_method_values[i];
+ } else {
+ dml_ctx->config.pmo.force_pstate_method_enable = false;
+ }
+}
+
+void dml21_init(const struct dc *in_dc, struct dml2_context *dml_ctx, const struct dml2_configuration_options *config)
+{
+ dml_ctx->architecture = dml2_architecture_21;
+
+ dml21_populate_configuration_options(in_dc, dml_ctx, config);
+
+ dml21_populate_dml_init_params(&dml_ctx->v21.dml_init, &dml_ctx->config, in_dc);
+
+ dml2_initialize_instance(&dml_ctx->v21.dml_init);
+}
+
+void dml21_reinit(const struct dc *in_dc, struct dml2_context *dml_ctx, const struct dml2_configuration_options *config)
+{
+ dml21_init(in_dc, dml_ctx, config);
+}
+
+static void dml21_calculate_rq_and_dlg_params(const struct dc *dc, struct dc_state *context, struct resource_context *out_new_hw_state,
+ struct dml2_context *in_ctx, unsigned int pipe_cnt)
+{
+ unsigned int dml_prog_idx = 0, dc_pipe_index = 0, num_dpps_required = 0;
+ struct dml2_per_plane_programming *pln_prog = NULL;
+ struct dml2_per_stream_programming *stream_prog = NULL;
+ struct pipe_ctx *dc_main_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__];
+ struct pipe_ctx *dc_phantom_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__] = {0};
+ int num_pipes;
+ unsigned int dml_phantom_prog_idx;
+
+ context->bw_ctx.bw.dcn.clk.dppclk_khz = 0;
+
+ /* copy global DCHUBBUB arbiter registers */
+ memcpy(&context->bw_ctx.bw.dcn.arb_regs, &in_ctx->v21.mode_programming.programming->global_regs.arb_regs, sizeof(struct dml2_display_arb_regs));
+
+ /* legacy only */
+ context->bw_ctx.bw.dcn.compbuf_size_kb = (int)in_ctx->v21.mode_programming.programming->global_regs.arb_regs.compbuf_size * 64;
+
+ context->bw_ctx.bw.dcn.mall_ss_size_bytes = 0;
+ context->bw_ctx.bw.dcn.mall_ss_psr_active_size_bytes = 0;
+ context->bw_ctx.bw.dcn.mall_subvp_size_bytes = 0;
+
+ /* phantom's start after main planes */
+ dml_phantom_prog_idx = in_ctx->v21.mode_programming.programming->display_config.num_planes;
+
+ for (dml_prog_idx = 0; dml_prog_idx < DML2_MAX_PLANES; dml_prog_idx++) {
+ pln_prog = &in_ctx->v21.mode_programming.programming->plane_programming[dml_prog_idx];
+
+ if (!pln_prog->plane_descriptor)
+ continue;
+
+ stream_prog = &in_ctx->v21.mode_programming.programming->stream_programming[pln_prog->plane_descriptor->stream_index];
+ num_dpps_required = pln_prog->num_dpps_required;
+
+ if (num_dpps_required == 0) {
+ continue;
+ }
+ num_pipes = dml21_find_dc_pipes_for_plane(dc, context, in_ctx, dc_main_pipes, dc_phantom_pipes, dml_prog_idx);
+
+ if (num_pipes <= 0)
+ continue;
+
+ /* program each pipe */
+ for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) {
+ dml21_program_dc_pipe(in_ctx, context, dc_main_pipes[dc_pipe_index], pln_prog, stream_prog);
+
+ if (pln_prog->phantom_plane.valid && dc_phantom_pipes[dc_pipe_index]) {
+ dml21_program_dc_pipe(in_ctx, context, dc_phantom_pipes[dc_pipe_index], pln_prog, stream_prog);
+ }
+ }
+
+ /* copy per plane mcache allocation */
+ memcpy(&context->bw_ctx.bw.dcn.mcache_allocations[dml_prog_idx], &pln_prog->mcache_allocation, sizeof(struct dml2_mcache_surface_allocation));
+ if (pln_prog->phantom_plane.valid) {
+ memcpy(&context->bw_ctx.bw.dcn.mcache_allocations[dml_phantom_prog_idx],
+ &pln_prog->phantom_plane.mcache_allocation,
+ sizeof(struct dml2_mcache_surface_allocation));
+
+ dml_phantom_prog_idx++;
+ }
+ }
+
+ /* assign global clocks */
+ context->bw_ctx.bw.dcn.clk.bw_dppclk_khz = context->bw_ctx.bw.dcn.clk.dppclk_khz;
+ context->bw_ctx.bw.dcn.clk.bw_dispclk_khz = context->bw_ctx.bw.dcn.clk.dispclk_khz;
+ if (in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.num_clk_values > 1) {
+ context->bw_ctx.bw.dcn.clk.max_supported_dispclk_khz =
+ in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.clk_values_khz[in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.num_clk_values] * 1000;
+ } else {
+ context->bw_ctx.bw.dcn.clk.max_supported_dispclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.clk_values_khz[0] * 1000;
+ }
+
+ if (in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.num_clk_values > 1) {
+ context->bw_ctx.bw.dcn.clk.max_supported_dppclk_khz =
+ in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.clk_values_khz[in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.num_clk_values] * 1000;
+ } else {
+ context->bw_ctx.bw.dcn.clk.max_supported_dppclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.clk_values_khz[0] * 1000;
+ }
+
+ /* get global mall allocation */
+ if (dc->res_pool->funcs->calculate_mall_ways_from_bytes) {
+ context->bw_ctx.bw.dcn.clk.num_ways = dc->res_pool->funcs->calculate_mall_ways_from_bytes(dc, context->bw_ctx.bw.dcn.mall_subvp_size_bytes);
+ } else {
+ context->bw_ctx.bw.dcn.clk.num_ways = 0;
+ }
+}
+
+static void dml21_prepare_mcache_params(struct dml2_context *dml_ctx, struct dc_state *context, struct dc_mcache_params *mcache_params)
+{
+ int dc_plane_idx = 0;
+ int dml_prog_idx, stream_idx, plane_idx;
+ struct dml2_per_plane_programming *pln_prog = NULL;
+
+ for (stream_idx = 0; stream_idx < context->stream_count; stream_idx++) {
+ for (plane_idx = 0; plane_idx < context->stream_status[stream_idx].plane_count; plane_idx++) {
+ dml_prog_idx = map_plane_to_dml21_display_cfg(dml_ctx, context->streams[stream_idx]->stream_id, context->stream_status[stream_idx].plane_states[plane_idx], context);
+ if (dml_prog_idx == INVALID) {
+ continue;
+ }
+ pln_prog = &dml_ctx->v21.mode_programming.programming->plane_programming[dml_prog_idx];
+ mcache_params[dc_plane_idx].valid = pln_prog->mcache_allocation.valid;
+ mcache_params[dc_plane_idx].num_mcaches_plane0 = pln_prog->mcache_allocation.num_mcaches_plane0;
+ mcache_params[dc_plane_idx].num_mcaches_plane1 = pln_prog->mcache_allocation.num_mcaches_plane1;
+ mcache_params[dc_plane_idx].requires_dedicated_mall_mcache = pln_prog->mcache_allocation.requires_dedicated_mall_mcache;
+ mcache_params[dc_plane_idx].last_slice_sharing.plane0_plane1 = pln_prog->mcache_allocation.last_slice_sharing.plane0_plane1;
+ memcpy(mcache_params[dc_plane_idx].mcache_x_offsets_plane0,
+ pln_prog->mcache_allocation.mcache_x_offsets_plane0,
+ sizeof(int) * (DML2_MAX_MCACHES + 1));
+ memcpy(mcache_params[dc_plane_idx].mcache_x_offsets_plane1,
+ pln_prog->mcache_allocation.mcache_x_offsets_plane1,
+ sizeof(int) * (DML2_MAX_MCACHES + 1));
+ dc_plane_idx++;
+ }
+ }
+}
+
+static bool dml21_check_mode_support(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx)
+{
+ bool is_supported = false;
+ struct dml2_initialize_instance_in_out *dml_init = &dml_ctx->v21.dml_init;
+ struct dml2_check_mode_supported_in_out *mode_support = &dml_ctx->v21.mode_support;
+
+ memset(&dml_ctx->v21.display_config, 0, sizeof(struct dml2_display_cfg));
+ memset(&dml_ctx->v21.dml_to_dc_pipe_mapping, 0, sizeof(struct dml2_dml_to_dc_pipe_mapping));
+ memset(&dml_ctx->v21.mode_programming.dml2_instance->scratch.check_mode_supported_locals.mode_support_params, 0, sizeof(struct dml2_core_mode_support_in_out));
+
+ if (!context || context->stream_count == 0)
+ return true;
+
+ /* Scrub phantom's from current dc_state */
+ dml_ctx->config.svp_pstate.callbacks.remove_phantom_streams_and_planes(in_dc, context);
+ dml_ctx->config.svp_pstate.callbacks.release_phantom_streams_and_planes(in_dc, context);
+
+ mode_support->dml2_instance = dml_init->dml2_instance;
+ dml21_map_dc_state_into_dml_display_cfg(in_dc, context, dml_ctx);
+ dml_ctx->v21.mode_programming.dml2_instance->scratch.build_mode_programming_locals.mode_programming_params.programming = dml_ctx->v21.mode_programming.programming;
+
+ is_supported = dml2_check_mode_supported(mode_support);
+
+ if (!is_supported)
+ return false;
+
+ return true;
+}
+
+static bool dml21_mode_check_and_programming(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx)
+{
+ bool result = false;
+ struct dml2_build_mode_programming_in_out *mode_programming = &dml_ctx->v21.mode_programming;
+ struct dc_mcache_params mcache_params[MAX_PLANES] = {0};
+
+ memset(&dml_ctx->v21.display_config, 0, sizeof(struct dml2_display_cfg));
+ memset(&dml_ctx->v21.dml_to_dc_pipe_mapping, 0, sizeof(struct dml2_dml_to_dc_pipe_mapping));
+ memset(&dml_ctx->v21.mode_programming.dml2_instance->scratch.build_mode_programming_locals.mode_programming_params, 0, sizeof(struct dml2_core_mode_programming_in_out));
+
+ if (!context)
+ return true;
+
+ if (context->stream_count == 0) {
+ dml21_init_min_clocks_for_dc_state(dml_ctx, context);
+ dml21_build_fams2_programming(in_dc, context, dml_ctx);
+ return true;
+ }
+
+ /* scrub phantom's from current dc_state */
+ dml_ctx->config.svp_pstate.callbacks.remove_phantom_streams_and_planes(in_dc, context);
+ dml_ctx->config.svp_pstate.callbacks.release_phantom_streams_and_planes(in_dc, context);
+
+ /* Populate stream, plane mappings and other fields in display config. */
+ result = dml21_map_dc_state_into_dml_display_cfg(in_dc, context, dml_ctx);
+ if (!result)
+ return false;
+
+ result = dml2_build_mode_programming(mode_programming);
+
+ if (!result)
+ return false;
+
+ /* Check and map HW resources */
+ if (result && !dml_ctx->config.skip_hw_state_mapping) {
+ dml21_map_hw_resources(dml_ctx);
+ dml2_map_dc_pipes(dml_ctx, context, NULL, &dml_ctx->v21.dml_to_dc_pipe_mapping, in_dc->current_state);
+ /* if subvp phantoms are present, expand them into dc context */
+ dml21_handle_phantom_streams_planes(in_dc, context, dml_ctx);
+
+ if (in_dc->res_pool->funcs->program_mcache_pipe_config) {
+ //Prepare mcache params for each plane based on mcache output from DML
+ dml21_prepare_mcache_params(dml_ctx, context, mcache_params);
+
+ //populate mcache regs to each pipe
+ dml_ctx->config.callbacks.allocate_mcache(context, mcache_params);
+ }
+ }
+
+ /* Copy DML CLK, WM and REG outputs to bandwidth context */
+ if (result && !dml_ctx->config.skip_hw_state_mapping) {
+ dml21_calculate_rq_and_dlg_params(in_dc, context, &context->res_ctx, dml_ctx, in_dc->res_pool->pipe_count);
+ dml21_copy_clocks_to_dc_state(dml_ctx, context);
+ dml21_extract_watermark_sets(in_dc, &context->bw_ctx.bw.dcn.watermarks, dml_ctx);
+ dml21_build_fams2_programming(in_dc, context, dml_ctx);
+ }
+
+ return true;
+}
+
+bool dml21_validate(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx,
+ enum dc_validate_mode validate_mode)
+{
+ bool out = false;
+
+ /* Use dml21_check_mode_support for DC_VALIDATE_MODE_ONLY and DC_VALIDATE_MODE_AND_STATE_INDEX path */
+ if (validate_mode != DC_VALIDATE_MODE_AND_PROGRAMMING)
+ out = dml21_check_mode_support(in_dc, context, dml_ctx);
+ else
+ out = dml21_mode_check_and_programming(in_dc, context, dml_ctx);
+
+ return out;
+}
+
+void dml21_prepare_mcache_programming(struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx)
+{
+ unsigned int dml_prog_idx, dml_phantom_prog_idx, dc_pipe_index;
+ int num_pipes;
+ struct pipe_ctx *dc_main_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__];
+ struct pipe_ctx *dc_phantom_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__] = {0};
+
+ struct dml2_per_plane_programming *pln_prog = NULL;
+ struct dml2_plane_mcache_configuration_descriptor *mcache_config = NULL;
+ struct prepare_mcache_programming_locals *l = &dml_ctx->v21.scratch.prepare_mcache_locals;
+
+ if (context->stream_count == 0) {
+ return;
+ }
+
+ memset(&l->build_mcache_programming_params, 0, sizeof(struct dml2_build_mcache_programming_in_out));
+ l->build_mcache_programming_params.dml2_instance = dml_ctx->v21.dml_init.dml2_instance;
+
+ /* phantom's start after main planes */
+ dml_phantom_prog_idx = dml_ctx->v21.mode_programming.programming->display_config.num_planes;
+
+ /* Build mcache programming parameters per plane per pipe */
+ for (dml_prog_idx = 0; dml_prog_idx < dml_ctx->v21.mode_programming.programming->display_config.num_planes; dml_prog_idx++) {
+ pln_prog = &dml_ctx->v21.mode_programming.programming->plane_programming[dml_prog_idx];
+
+ mcache_config = &l->build_mcache_programming_params.mcache_configurations[dml_prog_idx];
+ memset(mcache_config, 0, sizeof(struct dml2_plane_mcache_configuration_descriptor));
+ mcache_config->plane_descriptor = pln_prog->plane_descriptor;
+ mcache_config->mcache_allocation = &context->bw_ctx.bw.dcn.mcache_allocations[dml_prog_idx];
+ ASSERT(pln_prog->num_dpps_required <= 0x7F);
+ mcache_config->num_pipes = (char)pln_prog->num_dpps_required;
+ l->build_mcache_programming_params.num_configurations++;
+
+ if (pln_prog->num_dpps_required == 0) {
+ continue;
+ }
+
+ num_pipes = dml21_find_dc_pipes_for_plane(in_dc, context, dml_ctx, dc_main_pipes, dc_phantom_pipes, dml_prog_idx);
+ if (num_pipes <= 0 || dc_main_pipes[0]->stream == NULL ||
+ dc_main_pipes[0]->plane_state == NULL)
+ continue;
+
+ /* get config for each pipe */
+ for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) {
+ ASSERT(dc_main_pipes[dc_pipe_index]);
+ dml21_get_pipe_mcache_config(context, dc_main_pipes[dc_pipe_index], pln_prog, &mcache_config->pipe_configurations[dc_pipe_index]);
+ }
+
+ /* get config for each phantom pipe */
+ if (pln_prog->phantom_plane.valid &&
+ dc_phantom_pipes[0] &&
+ dc_main_pipes[0]->stream &&
+ dc_phantom_pipes[0]->plane_state) {
+ mcache_config = &l->build_mcache_programming_params.mcache_configurations[dml_phantom_prog_idx];
+ memset(mcache_config, 0, sizeof(struct dml2_plane_mcache_configuration_descriptor));
+ mcache_config->plane_descriptor = pln_prog->plane_descriptor;
+ mcache_config->mcache_allocation = &context->bw_ctx.bw.dcn.mcache_allocations[dml_phantom_prog_idx];
+ ASSERT(pln_prog->num_dpps_required <= 0x7F);
+ mcache_config->num_pipes = (char)pln_prog->num_dpps_required;
+ l->build_mcache_programming_params.num_configurations++;
+
+ for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) {
+ ASSERT(dc_phantom_pipes[dc_pipe_index]);
+ dml21_get_pipe_mcache_config(context, dc_phantom_pipes[dc_pipe_index], pln_prog, &mcache_config->pipe_configurations[dc_pipe_index]);
+ }
+
+ /* increment phantom index */
+ dml_phantom_prog_idx++;
+ }
+ }
+
+ /* Call to generate mcache programming per plane per pipe for the given display configuration */
+ dml2_build_mcache_programming(&l->build_mcache_programming_params);
+
+ /* get per plane per pipe mcache programming */
+ for (dml_prog_idx = 0; dml_prog_idx < dml_ctx->v21.mode_programming.programming->display_config.num_planes; dml_prog_idx++) {
+ pln_prog = &dml_ctx->v21.mode_programming.programming->plane_programming[dml_prog_idx];
+
+ num_pipes = dml21_find_dc_pipes_for_plane(in_dc, context, dml_ctx, dc_main_pipes, dc_phantom_pipes, dml_prog_idx);
+ if (num_pipes <= 0 || dc_main_pipes[0]->stream == NULL ||
+ dc_main_pipes[0]->plane_state == NULL)
+ continue;
+
+ /* get config for each pipe */
+ for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) {
+ ASSERT(dc_main_pipes[dc_pipe_index]);
+ if (l->build_mcache_programming_params.per_plane_pipe_mcache_regs[dml_prog_idx][dc_pipe_index]) {
+ memcpy(&dc_main_pipes[dc_pipe_index]->mcache_regs,
+ l->build_mcache_programming_params.per_plane_pipe_mcache_regs[dml_prog_idx][dc_pipe_index],
+ sizeof(struct dml2_hubp_pipe_mcache_regs));
+ }
+ }
+
+ /* get config for each phantom pipe */
+ if (pln_prog->phantom_plane.valid &&
+ dc_phantom_pipes[0] &&
+ dc_main_pipes[0]->stream &&
+ dc_phantom_pipes[0]->plane_state) {
+ for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) {
+ ASSERT(dc_phantom_pipes[dc_pipe_index]);
+ if (l->build_mcache_programming_params.per_plane_pipe_mcache_regs[dml_phantom_prog_idx][dc_pipe_index]) {
+ memcpy(&dc_phantom_pipes[dc_pipe_index]->mcache_regs,
+ l->build_mcache_programming_params.per_plane_pipe_mcache_regs[dml_phantom_prog_idx][dc_pipe_index],
+ sizeof(struct dml2_hubp_pipe_mcache_regs));
+ }
+ }
+ /* increment phantom index */
+ dml_phantom_prog_idx++;
+ }
+ }
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper_fpu.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper_fpu.h
new file mode 100644
index 000000000000..e5d9a456645f
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper_fpu.h
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#ifndef _DML21_WRAPPER_FPU_H_
+#define _DML21_WRAPPER_FPU_H_
+
+#include "os_types.h"
+#include "dml_top_soc_parameter_types.h"
+#include "dml_top_display_cfg_types.h"
+
+struct dc;
+struct dc_state;
+struct dml2_configuration_options;
+struct dml2_context;
+enum dc_validate_mode;
+
+/**
+ * dml21_init - Initialize DML21 context
+ * @in_dc: dc.
+ * @dml_ctx: DML21 context to initialize.
+ * @config: dml21 configuration options.
+ *
+ * Performs FPU-requiring initialization. Must be called with FPU protection.
+ */
+void dml21_init(const struct dc *in_dc, struct dml2_context *dml_ctx, const struct dml2_configuration_options *config);
+
+/**
+ * dml21_validate - Determines if a display configuration is supported or not.
+ * @in_dc: dc.
+ * @context: dc_state to be validated.
+ * @dml_ctx: dml21 context.
+ * @validate_mode: DC_VALIDATE_MODE_ONLY and DC_VALIDATE_MODE_AND_STATE_INDEX
+ * will not populate context.res_ctx.
+ *
+ * Based on fast_validate option internally would call:
+ *
+ * -dml21_mode_check_and_programming - for DC_VALIDATE_MODE_AND_PROGRAMMING option
+ * Calculates if dc_state can be supported on the input display
+ * configuration. If supported, generates the necessary HW
+ * programming for the new dc_state.
+ *
+ * -dml21_check_mode_support - for DC_VALIDATE_MODE_ONLY and DC_VALIDATE_MODE_AND_STATE_INDEX option
+ * Calculates if dc_state can be supported for the input display
+ * config.
+ *
+ * Context: Two threads may not invoke this function concurrently unless they reference
+ * separate dc_states for validation.
+ * Return: True if mode is supported, false otherwise.
+ */
+
+void dml21_reinit(const struct dc *in_dc, struct dml2_context *dml_ctx,
+ const struct dml2_configuration_options *config);
+bool dml21_validate(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx,
+ enum dc_validate_mode validate_mode);
+
+/* Prepare hubp mcache_regs for hubp mcache ID and split coordinate programming */
+void dml21_prepare_mcache_programming(struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx);
+
+#endif /* _DML21_WRAPPER_FPU_H_ */
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_soc_parameter_types.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_soc_parameter_types.h
index ddbb8dfa9ff8..6152155d6073 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_soc_parameter_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_soc_parameter_types.h
@@ -192,6 +192,7 @@ struct dml2_ip_capabilities {
unsigned int max_flip_time_us;
unsigned int max_flip_time_lines;
unsigned int hostvm_mode;
+ bool dcn_mrq_present;
unsigned int subvp_drr_scheduling_margin_us;
unsigned int subvp_prefetch_end_to_mall_start_us;
unsigned int subvp_fw_processing_delay;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4.c
index 608b4a305c65..99fc2f0666e2 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4.c
@@ -187,6 +187,7 @@ static void patch_ip_params_with_ip_caps(struct dml2_core_ip_params *ip_params,
{
ip_params->max_num_dpp = ip_caps->pipe_count;
ip_params->max_num_otg = ip_caps->otg_count;
+ ip_params->max_num_opp = ip_caps->otg_count;
ip_params->num_dsc = ip_caps->num_dsc;
ip_params->max_num_dp2p0_streams = ip_caps->max_num_dp2p0_streams;
ip_params->max_num_dp2p0_outputs = ip_caps->max_num_dp2p0_outputs;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.c
index ca5ac3c0deb5..f6402e199354 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.c
@@ -202,7 +202,7 @@ static unsigned int dml_round_to_multiple(unsigned int num, unsigned int multipl
return (num - remainder);
}
-static unsigned int dml_get_num_active_pipes(int unsigned num_planes, const struct core_display_cfg_support_info *cfg_support_info)
+static unsigned int dml_get_num_active_pipes(unsigned int num_planes, const struct core_display_cfg_support_info *cfg_support_info)
{
unsigned int num_active_pipes = 0;
@@ -546,9 +546,9 @@ static bool dml_is_vertical_rotation(enum dml2_rotation_angle Scan)
return is_vert;
}
-static int unsigned dml_get_gfx_version(enum dml2_swizzle_mode sw_mode)
+static unsigned int dml_get_gfx_version(enum dml2_swizzle_mode sw_mode)
{
- int unsigned version = 0;
+ unsigned int version = 0;
if (sw_mode == dml2_sw_linear ||
sw_mode == dml2_sw_256b_2d ||
@@ -1761,7 +1761,7 @@ static unsigned int CalculateVMAndRowBytes(struct dml2_core_shared_calculate_vm_
*p->PixelPTEBytesPerRow = (unsigned int)((double)*p->dpte_row_width_ub / (double)*p->PixelPTEReqWidth * *p->PTERequestSize);
// VBA_DELTA, VBA doesn't have programming value for pte row height linear.
- *p->dpte_row_height_linear = (unsigned int)1 << (unsigned int)math_floor2(math_log((float)(p->PTEBufferSizeInRequests * PixelPTEReqWidth_linear / p->Pitch), 2.0), 1);
+ *p->dpte_row_height_linear = 1U << (unsigned int)math_floor2(math_log((float)(p->PTEBufferSizeInRequests * PixelPTEReqWidth_linear / p->Pitch), 2.0), 1);
if (*p->dpte_row_height_linear > 128)
*p->dpte_row_height_linear = 128;
@@ -3377,7 +3377,7 @@ static void calculate_cursor_req_attributes(
DML_LOG_VERBOSE("DML::%s: cursor_bytes_per_line = %d\n", __func__, *cursor_bytes_per_line);
DML_LOG_VERBOSE("DML::%s: cursor_bytes_per_chunk = %d\n", __func__, *cursor_bytes_per_chunk);
DML_LOG_VERBOSE("DML::%s: cursor_bytes = %d\n", __func__, *cursor_bytes);
- DML_LOG_VERBOSE("DML::%s: cursor_pitch = %d\n", __func__, cursor_bpp == 2 ? 256 : (unsigned int)1 << (unsigned int)math_ceil2(math_log((float)cursor_width, 2), 1));
+ DML_LOG_VERBOSE("DML::%s: cursor_pitch = %d\n", __func__, cursor_bpp == 2 ? 256 : 1U << (unsigned int)math_ceil2(math_log((float)cursor_width, 2), 1));
#endif
}
@@ -12205,15 +12205,15 @@ static void rq_dlg_get_wm_regs(const struct dml2_display_cfg *display_cfg, const
{
double refclk_freq_in_mhz = (display_cfg->overrides.hw.dlg_ref_clk_mhz > 0) ? (double)display_cfg->overrides.hw.dlg_ref_clk_mhz : mode_lib->soc.dchub_refclk_mhz;
- wm_regs->fclk_pstate = (int unsigned)(mode_lib->mp.Watermark.FCLKChangeWatermark * refclk_freq_in_mhz);
- wm_regs->sr_enter = (int unsigned)(mode_lib->mp.Watermark.StutterEnterPlusExitWatermark * refclk_freq_in_mhz);
- wm_regs->sr_exit = (int unsigned)(mode_lib->mp.Watermark.StutterExitWatermark * refclk_freq_in_mhz);
- wm_regs->sr_enter_z8 = (int unsigned)(mode_lib->mp.Watermark.Z8StutterEnterPlusExitWatermark * refclk_freq_in_mhz);
- wm_regs->sr_exit_z8 = (int unsigned)(mode_lib->mp.Watermark.Z8StutterExitWatermark * refclk_freq_in_mhz);
- wm_regs->temp_read_or_ppt = (int unsigned)(mode_lib->mp.Watermark.temp_read_or_ppt_watermark_us * refclk_freq_in_mhz);
- wm_regs->uclk_pstate = (int unsigned)(mode_lib->mp.Watermark.DRAMClockChangeWatermark * refclk_freq_in_mhz);
- wm_regs->urgent = (int unsigned)(mode_lib->mp.Watermark.UrgentWatermark * refclk_freq_in_mhz);
- wm_regs->usr = (int unsigned)(mode_lib->mp.Watermark.USRRetrainingWatermark * refclk_freq_in_mhz);
+ wm_regs->fclk_pstate = (unsigned int)(mode_lib->mp.Watermark.FCLKChangeWatermark * refclk_freq_in_mhz);
+ wm_regs->sr_enter = (unsigned int)(mode_lib->mp.Watermark.StutterEnterPlusExitWatermark * refclk_freq_in_mhz);
+ wm_regs->sr_exit = (unsigned int)(mode_lib->mp.Watermark.StutterExitWatermark * refclk_freq_in_mhz);
+ wm_regs->sr_enter_z8 = (unsigned int)(mode_lib->mp.Watermark.Z8StutterEnterPlusExitWatermark * refclk_freq_in_mhz);
+ wm_regs->sr_exit_z8 = (unsigned int)(mode_lib->mp.Watermark.Z8StutterExitWatermark * refclk_freq_in_mhz);
+ wm_regs->temp_read_or_ppt = (unsigned int)(mode_lib->mp.Watermark.temp_read_or_ppt_watermark_us * refclk_freq_in_mhz);
+ wm_regs->uclk_pstate = (unsigned int)(mode_lib->mp.Watermark.DRAMClockChangeWatermark * refclk_freq_in_mhz);
+ wm_regs->urgent = (unsigned int)(mode_lib->mp.Watermark.UrgentWatermark * refclk_freq_in_mhz);
+ wm_regs->usr = (unsigned int)(mode_lib->mp.Watermark.USRRetrainingWatermark * refclk_freq_in_mhz);
wm_regs->refcyc_per_trip_to_mem = (unsigned int)(mode_lib->mp.UrgentLatency * refclk_freq_in_mhz);
wm_regs->refcyc_per_meta_trip_to_mem = (unsigned int)(mode_lib->mp.MetaTripToMemory * refclk_freq_in_mhz);
wm_regs->frac_urg_bw_flip = (unsigned int)(mode_lib->mp.FractionOfUrgentBandwidthImmediateFlip * 1000);
@@ -12262,11 +12262,15 @@ static void rq_dlg_get_rq_reg(struct dml2_display_rq_regs *rq_regs,
unsigned int pixel_chunk_bytes = 0;
unsigned int min_pixel_chunk_bytes = 0;
+ unsigned int meta_chunk_bytes = 0;
+ unsigned int min_meta_chunk_bytes = 0;
unsigned int dpte_group_bytes = 0;
unsigned int mpte_group_bytes = 0;
unsigned int p1_pixel_chunk_bytes = 0;
unsigned int p1_min_pixel_chunk_bytes = 0;
+ unsigned int p1_meta_chunk_bytes = 0;
+ unsigned int p1_min_meta_chunk_bytes = 0;
unsigned int p1_dpte_group_bytes = 0;
unsigned int p1_mpte_group_bytes = 0;
@@ -12287,8 +12291,13 @@ static void rq_dlg_get_rq_reg(struct dml2_display_rq_regs *rq_regs,
dpte_group_bytes = (unsigned int)(dml_get_dpte_group_size_in_bytes(mode_lib, pipe_idx));
mpte_group_bytes = (unsigned int)(dml_get_vm_group_size_in_bytes(mode_lib, pipe_idx));
+ meta_chunk_bytes = (unsigned int)(mode_lib->ip.meta_chunk_size_kbytes * 1024);
+ min_meta_chunk_bytes = (unsigned int)(mode_lib->ip.min_meta_chunk_size_bytes);
+
p1_pixel_chunk_bytes = pixel_chunk_bytes;
p1_min_pixel_chunk_bytes = min_pixel_chunk_bytes;
+ p1_meta_chunk_bytes = meta_chunk_bytes;
+ p1_min_meta_chunk_bytes = min_meta_chunk_bytes;
p1_dpte_group_bytes = dpte_group_bytes;
p1_mpte_group_bytes = mpte_group_bytes;
@@ -12309,6 +12318,19 @@ static void rq_dlg_get_rq_reg(struct dml2_display_rq_regs *rq_regs,
else
rq_regs->rq_regs_c.min_chunk_size = log_and_substract_if_non_zero(p1_min_pixel_chunk_bytes, 8 - 1);
+ rq_regs->rq_regs_l.meta_chunk_size = log_and_substract_if_non_zero(meta_chunk_bytes, 10);
+ rq_regs->rq_regs_c.meta_chunk_size = log_and_substract_if_non_zero(p1_meta_chunk_bytes, 10);
+
+ if (min_meta_chunk_bytes == 0)
+ rq_regs->rq_regs_l.min_meta_chunk_size = 0;
+ else
+ rq_regs->rq_regs_l.min_meta_chunk_size = log_and_substract_if_non_zero(min_meta_chunk_bytes, 6 - 1);
+
+ if (min_meta_chunk_bytes == 0)
+ rq_regs->rq_regs_c.min_meta_chunk_size = 0;
+ else
+ rq_regs->rq_regs_c.min_meta_chunk_size = log_and_substract_if_non_zero(p1_min_meta_chunk_bytes, 6 - 1);
+
rq_regs->rq_regs_l.dpte_group_size = log_and_substract_if_non_zero(dpte_group_bytes, 6);
rq_regs->rq_regs_l.mpte_group_size = log_and_substract_if_non_zero(mpte_group_bytes, 6);
rq_regs->rq_regs_c.dpte_group_size = log_and_substract_if_non_zero(p1_dpte_group_bytes, 6);
@@ -12670,7 +12692,7 @@ static void rq_dlg_get_dlg_reg(
disp_dlg_regs->refcyc_per_vm_req_flip = (unsigned int)(math_pow(2, 23) - 1);
- DML_ASSERT(disp_dlg_regs->dst_y_after_scaler < (unsigned int)8);
+ DML_ASSERT(disp_dlg_regs->dst_y_after_scaler < 8U);
DML_ASSERT(disp_dlg_regs->refcyc_x_after_scaler < (unsigned int)math_pow(2, 13));
if (disp_dlg_regs->dst_y_per_pte_row_nom_l >= (unsigned int)math_pow(2, 17)) {
@@ -13226,7 +13248,7 @@ void dml2_core_calcs_get_informative(const struct dml2_core_internal_display_mod
out->informative.misc.cstate_max_cap_mode = dml_get_cstate_max_cap_mode(mode_lib);
- out->min_clocks.dcn4x.dpprefclk_khz = (int unsigned)dml_get_global_dppclk_khz(mode_lib);
+ out->min_clocks.dcn4x.dpprefclk_khz = (unsigned int)dml_get_global_dppclk_khz(mode_lib);
out->informative.qos.max_active_fclk_change_latency_supported = dml_get_fclk_change_latency(mode_lib);
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn4.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn4.c
index d17e59d684fd..ab0b4a4b5d65 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn4.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn4.c
@@ -279,6 +279,26 @@ static bool round_up_and_copy_to_next_dpm(unsigned long min_value, unsigned long
bool result = false;
int index = 0;
+ /* Guard against empty clock tables (e.g. DTBCLK on DCN42B where the
+ * clock is tied off and num_clk_values == 0). Without this check the
+ * else-if branch below would evaluate
+ * clk_values_khz[num_clk_values - 1] with num_clk_values == 0, which
+ * wraps the unsigned char index to 255 — a 235-element out-of-bounds
+ * read on an array of DML_MAX_CLK_TABLE_SIZE (20) entries.
+ *
+ * Semantic: if the clock doesn't exist on this ASIC but no frequency
+ * is required (min_value == 0), the request is trivially satisfied.
+ * If a non-zero frequency is required but the clock is absent, the
+ * configuration is unsupportable.
+ */
+ if (clock_table->num_clk_values == 0) {
+ if (min_value == 0) {
+ *rounded_value = 0;
+ return true;
+ }
+ return false;
+ }
+
if (clock_table->num_clk_values > 2) {
while (index < clock_table->num_clk_values && clock_table->clk_values_khz[index] < min_value)
index++;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn4.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn4.c
index a265f254152c..eab13e1c96fd 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn4.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn4.c
@@ -178,9 +178,12 @@ static bool build_min_clock_table(const struct dml2_soc_bb *soc_bb, struct dml2_
min_table->max_clocks_khz.dispclk = soc_bb->clk_table.dispclk.clk_values_khz[soc_bb->clk_table.dispclk.num_clk_values - 1];
min_table->max_clocks_khz.dppclk = soc_bb->clk_table.dppclk.clk_values_khz[soc_bb->clk_table.dppclk.num_clk_values - 1];
- min_table->max_clocks_khz.dscclk = soc_bb->clk_table.dscclk.clk_values_khz[soc_bb->clk_table.dscclk.num_clk_values - 1];
- min_table->max_clocks_khz.dtbclk = soc_bb->clk_table.dtbclk.clk_values_khz[soc_bb->clk_table.dtbclk.num_clk_values - 1];
- min_table->max_clocks_khz.phyclk = soc_bb->clk_table.phyclk.clk_values_khz[soc_bb->clk_table.phyclk.num_clk_values - 1];
+ min_table->max_clocks_khz.dscclk = (soc_bb->clk_table.dscclk.num_clk_values > 0) ?
+ soc_bb->clk_table.dscclk.clk_values_khz[soc_bb->clk_table.dscclk.num_clk_values - 1] : 0;
+ min_table->max_clocks_khz.dtbclk = (soc_bb->clk_table.dtbclk.num_clk_values > 0) ?
+ soc_bb->clk_table.dtbclk.clk_values_khz[soc_bb->clk_table.dtbclk.num_clk_values - 1] : 0;
+ min_table->max_clocks_khz.phyclk = (soc_bb->clk_table.phyclk.num_clk_values > 0) ?
+ soc_bb->clk_table.phyclk.clk_values_khz[soc_bb->clk_table.phyclk.num_clk_values - 1] : 0;
min_table->max_ss_clocks_khz.dispclk = (unsigned int)((double)min_table->max_clocks_khz.dispclk / (1.0 + soc_bb->dcn_downspread_percent / 100.0));
min_table->max_ss_clocks_khz.dppclk = (unsigned int)((double)min_table->max_clocks_khz.dppclk / (1.0 + soc_bb->dcn_downspread_percent / 100.0));
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn42.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn42.c
index 1f67cbc2c236..3eaeff39ee79 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn42.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn42.c
@@ -54,9 +54,12 @@ static bool build_min_clock_table(const struct dml2_soc_bb *soc_bb, struct dml2_
min_table->max_clocks_khz.dispclk = soc_bb->clk_table.dispclk.clk_values_khz[soc_bb->clk_table.dispclk.num_clk_values - 1];
min_table->max_clocks_khz.dppclk = soc_bb->clk_table.dppclk.clk_values_khz[soc_bb->clk_table.dppclk.num_clk_values - 1];
- min_table->max_clocks_khz.dscclk = soc_bb->clk_table.dscclk.clk_values_khz[soc_bb->clk_table.dscclk.num_clk_values - 1];
- min_table->max_clocks_khz.dtbclk = soc_bb->clk_table.dtbclk.clk_values_khz[soc_bb->clk_table.dtbclk.num_clk_values - 1];
- min_table->max_clocks_khz.phyclk = soc_bb->clk_table.phyclk.clk_values_khz[soc_bb->clk_table.phyclk.num_clk_values - 1];
+ min_table->max_clocks_khz.dscclk = (soc_bb->clk_table.dscclk.num_clk_values > 0) ?
+ soc_bb->clk_table.dscclk.clk_values_khz[soc_bb->clk_table.dscclk.num_clk_values - 1] : 0;
+ min_table->max_clocks_khz.dtbclk = (soc_bb->clk_table.dtbclk.num_clk_values > 0) ?
+ soc_bb->clk_table.dtbclk.clk_values_khz[soc_bb->clk_table.dtbclk.num_clk_values - 1] : 0;
+ min_table->max_clocks_khz.phyclk = (soc_bb->clk_table.phyclk.num_clk_values > 0) ?
+ soc_bb->clk_table.phyclk.clk_values_khz[soc_bb->clk_table.phyclk.num_clk_values - 1] : 0;
min_table->max_ss_clocks_khz.dispclk = (unsigned int)((double)min_table->max_clocks_khz.dispclk / (1.0 + soc_bb->dcn_downspread_percent / 100.0));
min_table->max_ss_clocks_khz.dppclk = (unsigned int)((double)min_table->max_clocks_khz.dppclk / (1.0 + soc_bb->dcn_downspread_percent / 100.0));
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_dc_resource_mgmt.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_dc_resource_mgmt.c
index 74812a7d5e28..6ef93c6fc1cd 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_dc_resource_mgmt.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_dc_resource_mgmt.c
@@ -35,7 +35,7 @@
#define MAX_MPCC_FACTOR 4
struct dc_plane_pipe_pool {
- int pipes_assigned_to_plane[MAX_ODM_FACTOR][MAX_MPCC_FACTOR];
+ unsigned int pipes_assigned_to_plane[MAX_ODM_FACTOR][MAX_MPCC_FACTOR];
bool pipe_used[MAX_ODM_FACTOR][MAX_MPCC_FACTOR];
int num_pipes_assigned_to_plane_for_mpcc_combine;
int num_pipes_assigned_to_plane_for_odm_combine;
@@ -143,7 +143,7 @@ static unsigned int find_pipes_assigned_to_plane(struct dml2_context *ctx,
{
int i;
unsigned int num_found = 0;
- unsigned int plane_id_assigned_to_pipe = -1;
+ unsigned int plane_id_assigned_to_pipe = UINT_MAX;
for (i = 0; i < ctx->config.dcn_pipe_count; i++) {
struct pipe_ctx *pipe = &state->res_ctx.pipe_ctx[i];
@@ -340,8 +340,8 @@ static bool is_pipe_in_candidate_array(const unsigned int pipe_idx,
static bool find_more_pipes_for_stream(struct dml2_context *ctx,
struct dc_state *state, // The state we want to find a free mapping in
unsigned int stream_id, // The stream we want this pipe to drive
- int *assigned_pipes,
- int *assigned_pipe_count,
+ unsigned int *assigned_pipes,
+ unsigned int *assigned_pipe_count,
int pipes_needed,
const struct dc_state *existing_state) // The state (optional) that we want to minimize remapping relative to
{
@@ -366,7 +366,8 @@ static bool find_more_pipes_for_stream(struct dml2_context *ctx,
if (!is_plane_using_pipe(pipe)) {
pipes_needed--;
// TODO: This doens't make sense really, pipe_idx should always be valid
- pipe->pipe_idx = preferred_pipe_candidates[i];
+ ASSERT(preferred_pipe_candidates[i] <= 0xFF);
+ pipe->pipe_idx = (uint8_t)preferred_pipe_candidates[i];
assigned_pipes[(*assigned_pipe_count)++] = pipe->pipe_idx;
}
}
@@ -382,7 +383,8 @@ static bool find_more_pipes_for_stream(struct dml2_context *ctx,
if (!is_plane_using_pipe(pipe)) {
pipes_needed--;
// TODO: This doens't make sense really, pipe_idx should always be valid
- pipe->pipe_idx = i;
+ ASSERT(i >= 0 && i <= 0xFF);
+ pipe->pipe_idx = (uint8_t)i;
assigned_pipes[(*assigned_pipe_count)++] = pipe->pipe_idx;
}
}
@@ -393,7 +395,8 @@ static bool find_more_pipes_for_stream(struct dml2_context *ctx,
if (!is_plane_using_pipe(pipe)) {
pipes_needed--;
// TODO: This doens't make sense really, pipe_idx should always be valid
- pipe->pipe_idx = last_resort_pipe_candidates[i];
+ ASSERT(last_resort_pipe_candidates[i] <= 0xFF);
+ pipe->pipe_idx = (uint8_t)last_resort_pipe_candidates[i];
assigned_pipes[(*assigned_pipe_count)++] = pipe->pipe_idx;
}
}
@@ -406,8 +409,8 @@ static bool find_more_pipes_for_stream(struct dml2_context *ctx,
static bool find_more_free_pipes(struct dml2_context *ctx,
struct dc_state *state, // The state we want to find a free mapping in
unsigned int stream_id, // The stream we want this pipe to drive
- int *assigned_pipes,
- int *assigned_pipe_count,
+ unsigned int *assigned_pipes,
+ unsigned int *assigned_pipe_count,
int pipes_needed,
const struct dc_state *existing_state) // The state (optional) that we want to minimize remapping relative to
{
@@ -432,7 +435,8 @@ static bool find_more_free_pipes(struct dml2_context *ctx,
if (is_pipe_free(pipe)) {
pipes_needed--;
// TODO: This doens't make sense really, pipe_idx should always be valid
- pipe->pipe_idx = preferred_pipe_candidates[i];
+ ASSERT(preferred_pipe_candidates[i] <= 0xFF);
+ pipe->pipe_idx = (uint8_t)preferred_pipe_candidates[i];
assigned_pipes[(*assigned_pipe_count)++] = pipe->pipe_idx;
}
}
@@ -448,7 +452,8 @@ static bool find_more_free_pipes(struct dml2_context *ctx,
if (is_pipe_free(pipe)) {
pipes_needed--;
// TODO: This doens't make sense really, pipe_idx should always be valid
- pipe->pipe_idx = i;
+ ASSERT(i >= 0 && i <= 0xFF);
+ pipe->pipe_idx = (uint8_t)i;
assigned_pipes[(*assigned_pipe_count)++] = pipe->pipe_idx;
}
}
@@ -459,7 +464,8 @@ static bool find_more_free_pipes(struct dml2_context *ctx,
if (is_pipe_free(pipe)) {
pipes_needed--;
// TODO: This doens't make sense really, pipe_idx should always be valid
- pipe->pipe_idx = last_resort_pipe_candidates[i];
+ ASSERT(last_resort_pipe_candidates[i] <= 0xFF);
+ pipe->pipe_idx = (uint8_t)last_resort_pipe_candidates[i];
assigned_pipes[(*assigned_pipe_count)++] = pipe->pipe_idx;
}
}
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_mall_phantom.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_mall_phantom.c
index d56e58ce26c7..9bbe4e058be7 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_mall_phantom.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_mall_phantom.c
@@ -555,7 +555,8 @@ static bool subvp_vblank_schedulable(struct dml2_context *ctx, struct dc_state *
if (!found && pipe_mall_type == SUBVP_NONE) {
// Found pipe which is not SubVP or Phantom (i.e. the VBLANK pipe).
- vblank_index = i;
+ ASSERT(i <= 0xFF);
+ vblank_index = (uint8_t)i;
found = true;
}
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_translation_helper.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_translation_helper.c
index d834cb595afa..cf3a69aba638 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_translation_helper.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_translation_helper.c
@@ -330,8 +330,8 @@ void dml2_init_soc_states(struct dml2_context *dml2, const struct dc *in_dc,
{
struct dml2_policy_build_synthetic_soc_states_scratch *s = &dml2->v20.scratch.create_scratch.build_synthetic_socbb_scratch;
struct dml2_policy_build_synthetic_soc_states_params *p = &dml2->v20.scratch.build_synthetic_socbb_params;
- unsigned int dcfclk_stas_mhz[NUM_DCFCLK_STAS] = {0};
- unsigned int dcfclk_stas_mhz_new[NUM_DCFCLK_STAS_NEW] = {0};
+ int dcfclk_stas_mhz[NUM_DCFCLK_STAS] = {0};
+ int dcfclk_stas_mhz_new[NUM_DCFCLK_STAS_NEW] = {0};
unsigned int dml_project = dml2->v20.dml_core_ctx.project;
unsigned int i = 0;
@@ -765,7 +765,7 @@ static void populate_dml_timing_cfg_from_stream_state(struct dml_timing_cfg_st *
out->PixelClock[location] *= 2;
out->HTotal[location] = in->timing.h_total;
out->VTotal[location] = in->timing.v_total;
- out->Interlace[location] = in->timing.flags.INTERLACE;
+ out->Interlace[location] = (in->timing.flags.INTERLACE != 0);
hblank_start = in->timing.h_total - in->timing.h_front_porch;
out->HBlankEnd[location] = hblank_start
- in->timing.h_addressable
@@ -1174,12 +1174,12 @@ static unsigned int map_plane_to_dml_display_cfg(const struct dml2_context *dml2
const struct dc_state *context, const struct dml_display_cfg_st *dml_dispcfg, unsigned int stream_id, int plane_index)
{
unsigned int plane_id;
- int i = 0;
- int location = -1;
+ unsigned int i = 0;
+ unsigned int location = UINT_MAX;
if (!get_plane_id(context->bw_ctx.dml2, context, plane, stream_id, plane_index, &plane_id)) {
ASSERT(false);
- return -1;
+ return UINT_MAX;
}
for (i = 0; i < __DML2_WRAPPER_MAX_STREAMS_PLANES__; i++) {
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_utils.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_utils.c
index 9a33158b63bf..6c7cdf102906 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_utils.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_utils.c
@@ -255,7 +255,8 @@ static void populate_pipe_ctx_dlg_params_from_dml(struct pipe_ctx *pipe_ctx, str
pipe_ctx->pipe_dlg_param.vupdate_width = dml_get_vupdate_width(mode_lib, pipe_idx);
pipe_ctx->pipe_dlg_param.vready_offset = dml_get_vready_offset(mode_lib, pipe_idx);
- pipe_ctx->pipe_dlg_param.otg_inst = pipe_ctx->stream_res.tg->inst;
+ ASSERT(pipe_ctx->stream_res.tg->inst >= 0 && pipe_ctx->stream_res.tg->inst <= 0xFF);
+ pipe_ctx->pipe_dlg_param.otg_inst = (unsigned char)pipe_ctx->stream_res.tg->inst;
pipe_ctx->pipe_dlg_param.hactive = hactive;
pipe_ctx->pipe_dlg_param.vactive = vactive;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.c
index 408559d6fb2d..93b7613fc4f2 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.c
@@ -6,8 +6,24 @@
*/
#include "dml2_internal_types.h"
+#include "dml2_wrapper.h"
#include "dml2_wrapper_fpu.h"
+#include "dml21_wrapper.h"
+#include "dml21_wrapper_fpu.h"
+#include "dc_fpu.h"
+
+#if !defined(DC_RUN_WITH_PREEMPTION_ENABLED)
+#define DC_RUN_WITH_PREEMPTION_ENABLED(code) code
+#endif // !DC_RUN_WITH_PREEMPTION_ENABLED
+
+struct dml2_context *dml2_allocate_memory(void)
+{
+ struct dml2_context *dml2;
+
+ DC_RUN_WITH_PREEMPTION_ENABLED(dml2 = vzalloc(sizeof(struct dml2_context)));
+ return dml2;
+}
bool dml2_validate(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml2,
enum dc_validate_mode validate_mode)
{
@@ -23,16 +39,12 @@ bool dml2_validate(const struct dc *in_dc, struct dc_state *context, struct dml2
return out;
}
- DC_FP_START();
-
/* Use dml_validate_only for DC_VALIDATE_MODE_ONLY and DC_VALIDATE_MODE_AND_STATE_INDEX path */
if (validate_mode != DC_VALIDATE_MODE_AND_PROGRAMMING)
out = dml2_validate_only(context, validate_mode);
else
out = dml2_validate_and_build_resource(in_dc, context, validate_mode);
- DC_FP_END();
-
return out;
}
@@ -70,15 +82,12 @@ static void dml2_init(const struct dc *in_dc, const struct dml2_configuration_op
break;
}
- DC_FP_START();
-
initialize_dml2_ip_params(*dml2, in_dc, &(*dml2)->v20.dml_core_ctx.ip);
initialize_dml2_soc_bbox(*dml2, in_dc, &(*dml2)->v20.dml_core_ctx.soc);
initialize_dml2_soc_states(*dml2, in_dc, &(*dml2)->v20.dml_core_ctx.soc, &(*dml2)->v20.dml_core_ctx.states);
- DC_FP_END();
}
bool dml2_create(const struct dc *in_dc, const struct dml2_configuration_options *config, struct dml2_context **dml2)
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper_fpu.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper_fpu.c
index 203eef747262..66624cfc27b1 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper_fpu.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper_fpu.c
@@ -31,8 +31,10 @@
#include "dml2_translation_helper.h"
#include "dml2_mall_phantom.h"
#include "dml2_dc_resource_mgmt.h"
-#include "dml21_wrapper.h"
+#include "dml2_wrapper.h"
#include "dml2_wrapper_fpu.h"
+#include "dml21_wrapper.h"
+#include "dml21_wrapper_fpu.h"
void initialize_dml2_ip_params(struct dml2_context *dml2, const struct dc *in_dc, struct ip_params_st *out)
{
@@ -546,11 +548,6 @@ void dml2_apply_debug_options(const struct dc *dc, struct dml2_context *dml2)
}
}
-inline struct dml2_context *dml2_allocate_memory(void)
-{
- return (struct dml2_context *) vzalloc(sizeof(struct dml2_context));
-}
-
void dml2_destroy(struct dml2_context *dml2)
{
if (!dml2)
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.c
index 0e70ffc784b1..ef605e0a75e3 100644
--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.c
+++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.c
@@ -288,6 +288,7 @@ void dpp1_cnv_setup (
enum dc_color_space input_color_space,
struct cnv_alpha_2bit_lut *alpha_2bit_lut)
{
+ (void)alpha_2bit_lut;
uint32_t pixel_format;
uint32_t alpha_en;
enum pixel_format_description fmt ;
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp_dscl.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp_dscl.c
index 808bca9fb804..0d2c9fcd3362 100644
--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp_dscl.c
+++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp_dscl.c
@@ -102,7 +102,7 @@ static int dpp1_dscl_get_pixel_depth_val(enum lb_pixel_depth depth)
}
}
-static bool dpp1_dscl_is_video_format(enum pixel_format format)
+static bool dpp1_dscl_is_video_format(enum dc_pixel_format format)
{
if (format >= PIXEL_FORMAT_VIDEO_BEGIN
&& format <= PIXEL_FORMAT_VIDEO_END)
@@ -111,7 +111,7 @@ static bool dpp1_dscl_is_video_format(enum pixel_format format)
return false;
}
-static bool dpp1_dscl_is_420_format(enum pixel_format format)
+static bool dpp1_dscl_is_420_format(enum dc_pixel_format format)
{
if (format == PIXEL_FORMAT_420BPP8 ||
format == PIXEL_FORMAT_420BPP10)
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp.c
index c433f4b876e9..8d5000790904 100644
--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp.c
+++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp.c
@@ -92,7 +92,10 @@ void dpp2_power_on_obuf(
void dpp2_dummy_program_input_lut(
struct dpp *dpp_base,
const struct dc_gamma *gamma)
-{}
+{
+ (void)dpp_base;
+ (void)gamma;
+}
static void dpp2_cnv_setup (
struct dpp *dpp_base,
@@ -369,7 +372,11 @@ void oppn20_dummy_program_regamma_pwl(
struct dpp *dpp,
const struct pwl_params *params,
enum opp_regamma mode)
-{}
+{
+ (void)dpp;
+ (void)params;
+ (void)mode;
+}
static struct dpp_funcs dcn20_dpp_funcs = {
.dpp_read_state = dpp20_read_state,
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp_cm.c
index 31613372e214..26f9485f165d 100644
--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp_cm.c
+++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp_cm.c
@@ -1016,6 +1016,7 @@ static void dpp20_set_3dlut_mode(
bool is_color_channel_12bits,
bool is_lut_size17x17x17)
{
+ (void)is_color_channel_12bits;
uint32_t lut_mode;
struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c
index 8a146968ee15..e7880fc61b4a 100644
--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c
+++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c
@@ -1307,6 +1307,7 @@ static void dpp3_set_3dlut_mode(
bool is_color_channel_12bits,
bool is_lut_size17x17x17)
{
+ (void)is_color_channel_12bits;
uint32_t lut_mode;
struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base);
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp_cm.c
index 3284084ca7ad..8170a86ad0ea 100644
--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp_cm.c
+++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp_cm.c
@@ -80,6 +80,7 @@ static void dpp3_program_gammcor_lut(
uint32_t num,
bool is_ram_a)
{
+ (void)is_ram_a;
uint32_t i;
struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base);
uint32_t last_base_value_red = rgb[num-1].red_reg + rgb[num-1].delta_red_reg;
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_cm.c
index 62bf7cea21d8..821d5173b59f 100644
--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_cm.c
+++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_cm.c
@@ -132,6 +132,9 @@ void dpp401_set_cursor_position(
uint32_t width,
uint32_t height)
{
+ (void)param;
+ (void)width;
+ (void)height;
struct dcn401_dpp *dpp = TO_DCN401_DPP(dpp_base);
uint32_t cur_en = pos->enable ? 1 : 0;
@@ -237,6 +240,8 @@ void dpp401_set_cursor_matrix(
enum dc_color_space color_space,
struct dc_csc_transform cursor_csc_color_matrix)
{
+ (void)color_space;
+ (void)cursor_csc_color_matrix;
//Since we don't have cursor matrix information, force bypass mode by passing in unknown color space
dpp401_program_cursor_csc(dpp_base, COLOR_SPACE_UNKNOWN, NULL);
}
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c
index 8b6155f9122f..8b7e55e337d3 100644
--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c
+++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c
@@ -94,7 +94,7 @@ static int dpp401_dscl_get_pixel_depth_val(enum lb_pixel_depth depth)
}
}
-static bool dpp401_dscl_is_video_format(enum pixel_format format)
+static bool dpp401_dscl_is_video_format(enum dc_pixel_format format)
{
if (format >= PIXEL_FORMAT_VIDEO_BEGIN
&& format <= PIXEL_FORMAT_VIDEO_END)
@@ -103,7 +103,7 @@ static bool dpp401_dscl_is_video_format(enum pixel_format format)
return false;
}
-static bool dpp401_dscl_is_420_format(enum pixel_format format)
+static bool dpp401_dscl_is_420_format(enum dc_pixel_format format)
{
if (format == PIXEL_FORMAT_420BPP8 ||
format == PIXEL_FORMAT_420BPP10)
diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.c
index c1bdbb38c690..3bf737195bac 100644
--- a/drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.c
+++ b/drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.c
@@ -107,6 +107,11 @@ void dsc401_read_state(struct display_stream_compressor *dsc, struct dcn_dsc_sta
REG_GET(DSCC_PPS_CONFIG7, SLICE_BPG_OFFSET, &s->dsc_slice_bpg_offset);
REG_GET_2(DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_FORWARD_EN, &s->dsc_fw_en,
DSCRM_DSC_OPP_PIPE_SOURCE, &s->dsc_opp_source);
+ REG_GET(DSCC_PPS_CONFIG1, BLOCK_PRED_ENABLE, &s->dsc_block_pred_enable);
+ REG_GET(DSCC_PPS_CONFIG0, LINEBUF_DEPTH, &s->dsc_line_buf_depth);
+ REG_GET(DSCC_PPS_CONFIG0, DSC_VERSION_MINOR, &s->dsc_version_minor);
+ REG_GET(DSCC_CONFIG1, DSCC_RATE_CONTROL_BUFFER_MODEL_SIZE, &s->dsc_rc_buffer_size);
+ REG_GET(DSCC_PPS_CONFIG0, SIMPLE_422, &s->dsc_simple_422);
}
diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dsc.h b/drivers/gpu/drm/amd/display/dc/dsc/dsc.h
index ad7ef83694ea..a16c60d8532f 100644
--- a/drivers/gpu/drm/amd/display/dc/dsc/dsc.h
+++ b/drivers/gpu/drm/amd/display/dc/dsc/dsc.h
@@ -64,6 +64,11 @@ struct dcn_dsc_state {
uint32_t dsc_chunk_size;
uint32_t dsc_fw_en;
uint32_t dsc_opp_source;
+ uint32_t dsc_block_pred_enable;
+ uint32_t dsc_line_buf_depth;
+ uint32_t dsc_version_minor;
+ uint32_t dsc_rc_buffer_size;
+ uint32_t dsc_simple_422;
};
struct dcn_dsc_reg_state {
diff --git a/drivers/gpu/drm/amd/display/dc/dwb/dcn30/dcn30_dwb.c b/drivers/gpu/drm/amd/display/dc/dwb/dcn30/dcn30_dwb.c
index bc058f682438..0ee4f83a02eb 100644
--- a/drivers/gpu/drm/amd/display/dc/dwb/dcn30/dcn30_dwb.c
+++ b/drivers/gpu/drm/amd/display/dc/dwb/dcn30/dcn30_dwb.c
@@ -45,6 +45,7 @@
static bool dwb3_get_caps(struct dwbc *dwbc, struct dwb_caps *caps)
{
+ (void)dwbc;
if (caps) {
caps->adapter_id = 0; /* we only support 1 adapter currently */
caps->hw_version = DCN_VERSION_3_0;
diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_translate_dcn42.c b/drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_translate_dcn42.c
index dcbcf6b85abf..e7e1d9979876 100644
--- a/drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_translate_dcn42.c
+++ b/drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_translate_dcn42.c
@@ -45,6 +45,7 @@ static bool offset_to_id(
enum gpio_id *id,
uint32_t *en)
{
+ (void)mask;
switch (offset) {
/* HPD */
case REG(HPD0_DC_HPD_INT_STATUS):
diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c
index f3d562c8df4c..d81a71ac00d2 100644
--- a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c
+++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c
@@ -60,6 +60,7 @@ bool dal_hw_factory_init(
enum dce_version dce_version,
enum dce_environment dce_environment)
{
+ (void)dce_environment;
switch (dce_version) {
#if defined(CONFIG_DRM_AMD_DC_SI)
case DCE_VERSION_6_0:
diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c
index 660510842ecf..f0d400972897 100644
--- a/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c
+++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c
@@ -199,5 +199,6 @@ void dal_hw_gpio_construct(
void dal_hw_gpio_destruct(
struct hw_gpio *pin)
{
+ (void)pin;
ASSERT(!pin->base.opened);
}
diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c
index 1c977fc4d0e3..e6e36a912b13 100644
--- a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c
+++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c
@@ -64,6 +64,7 @@ bool dal_hw_translate_init(
enum dce_version dce_version,
enum dce_environment dce_environment)
{
+ (void)dce_environment;
switch (dce_version) {
#if defined(CONFIG_DRM_AMD_DC_SI)
case DCE_VERSION_6_0:
diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn31/dcn31_hubbub.c b/drivers/gpu/drm/amd/display/dc/hubbub/dcn31/dcn31_hubbub.c
index 5a03758e3de6..3c298192f359 100644
--- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn31/dcn31_hubbub.c
+++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn31/dcn31_hubbub.c
@@ -943,6 +943,7 @@ static void hubbub31_get_dchub_ref_freq(struct hubbub *hubbub,
unsigned int dccg_ref_freq_inKhz,
unsigned int *dchub_ref_freq_inKhz)
{
+ (void)dccg_ref_freq_inKhz;
struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
uint32_t ref_div = 0;
uint32_t ref_en = 0;
diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn35/dcn35_hubbub.c b/drivers/gpu/drm/amd/display/dc/hubbub/dcn35/dcn35_hubbub.c
index 43ba399f4822..82d4e3e0e5e8 100644
--- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn35/dcn35_hubbub.c
+++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn35/dcn35_hubbub.c
@@ -259,6 +259,7 @@ void hubbub35_get_dchub_ref_freq(struct hubbub *hubbub,
unsigned int dccg_ref_freq_inKhz,
unsigned int *dchub_ref_freq_inKhz)
{
+ (void)dccg_ref_freq_inKhz;
struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
uint32_t ref_div = 0;
uint32_t ref_en = 0;
diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c b/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c
index b0a4b68cf359..3b9542c08f3d 100644
--- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c
+++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c
@@ -70,6 +70,7 @@ bool hubbub401_program_urgent_watermarks(
unsigned int refclk_mhz,
bool safe_to_lower)
{
+ (void)refclk_mhz;
struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
bool wm_pending = false;
@@ -188,6 +189,7 @@ bool hubbub401_program_stutter_watermarks(
unsigned int refclk_mhz,
bool safe_to_lower)
{
+ (void)refclk_mhz;
struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
bool wm_pending = false;
@@ -287,6 +289,7 @@ bool hubbub401_program_pstate_watermarks(
unsigned int refclk_mhz,
bool safe_to_lower)
{
+ (void)refclk_mhz;
struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
bool wm_pending = false;
@@ -414,6 +417,7 @@ bool hubbub401_program_usr_watermarks(
unsigned int refclk_mhz,
bool safe_to_lower)
{
+ (void)refclk_mhz;
struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
bool wm_pending = false;
diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn42/dcn42_hubbub.c b/drivers/gpu/drm/amd/display/dc/hubbub/dcn42/dcn42_hubbub.c
index d6e6fbaa041b..73b6b0ffcb74 100644
--- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn42/dcn42_hubbub.c
+++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn42/dcn42_hubbub.c
@@ -6,6 +6,7 @@
#include "dcn31/dcn31_hubbub.h"
#include "dcn32/dcn32_hubbub.h"
#include "dcn35/dcn35_hubbub.h"
+#include "dcn401/dcn401_hubbub.h"
#include "dcn42/dcn42_hubbub.h"
#include "dm_services.h"
#include "reg_helper.h"
@@ -429,15 +430,6 @@ static void hubbub42_allow_self_refresh_control(struct hubbub *hubbub, bool allo
REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL,
DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, 0,
DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, !allow);
-
- if (!allow && hubbub->ctx->dc->debug.disable_stutter) {/*controlled by registry key*/
- REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL,
- DCHUBBUB_ARB_ALLOW_DCFCLK_DEEP_SLEEP_FORCE_VALUE, 0,
- DCHUBBUB_ARB_ALLOW_DCFCLK_DEEP_SLEEP_FORCE_ENABLE, 1);
- REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL,
- DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, 0,
- DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, 1);
- }
}
static void hubbub42_set_sdp_control(struct hubbub *hubbub, bool dc_control)
{
@@ -494,6 +486,48 @@ static bool hubbub42_program_watermarks(
return wm_pending;
}
+static void hubbub42_set_request_limit(struct hubbub *hubbub, int memory_channel_count, int words_per_channel)
+{
+ (void)memory_channel_count;
+ (void)words_per_channel;
+ struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
+ uint32_t request_limit = 96; //MAX(12 * memory_channel_count, 96);
+
+ REG_UPDATE(SDPIF_REQUEST_RATE_LIMIT, SDPIF_REQUEST_RATE_LIMIT, request_limit);
+}
+
+static bool dcn42_program_arbiter(struct hubbub *hubbub, struct dml2_display_arb_regs *arb_regs,
+ bool safe_to_lower)
+{
+ struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
+
+ bool wm_pending = false;
+ uint32_t temp;
+
+ /* request backpressure and outstanding return threshold (unused)*/
+ //REG_UPDATE(DCHUBBUB_TIMEOUT_DETECTION_CTRL1, DCHUBBUB_TIMEOUT_REQ_STALL_THRESHOLD, arb_regs->req_stall_threshold);
+
+ /* 401 delta: do not update P-State stall threshold (handled by fw) */
+ // REG_UPDATE(DCHUBBUB_TIMEOUT_DETECTION_CTRL2, DCHUBBUB_TIMEOUT_PSTATE_STALL_THRESHOLD, arb_regs->pstate_stall_threshold);
+
+ if (safe_to_lower || arb_regs->allow_sdpif_rate_limit_when_cstate_req > hubbub2->allow_sdpif_rate_limit_when_cstate_req) {
+ hubbub2->allow_sdpif_rate_limit_when_cstate_req = arb_regs->allow_sdpif_rate_limit_when_cstate_req;
+
+ /* only update the required bits */
+ REG_GET(DCHUBBUB_CTRL_STATUS, DCHUBBUB_HW_DEBUG, &temp);
+ if (hubbub2->allow_sdpif_rate_limit_when_cstate_req) {
+ temp |= (1 << 5);
+ } else {
+ temp &= ~(1 << 5);
+ }
+ REG_UPDATE(DCHUBBUB_CTRL_STATUS, DCHUBBUB_HW_DEBUG, temp);
+ } else {
+ wm_pending = true;
+ }
+
+ return wm_pending;
+}
+
static const struct hubbub_funcs hubbub42_funcs = {
.update_dchub = hubbub2_update_dchub,
.init_dchub_sys_ctx = hubbub31_init_dchub_sys_ctx,
@@ -509,13 +543,16 @@ static const struct hubbub_funcs hubbub42_funcs = {
.force_wm_propagate_to_pipes = hubbub32_force_wm_propagate_to_pipes,
.force_pstate_change_control = hubbub3_force_pstate_change_control,
.init_watermarks = hubbub35_init_watermarks,
- .program_det_size = dcn32_program_det_size,
- .program_compbuf_size = dcn35_program_compbuf_size,
- .init_crb = dcn35_init_crb,
+ .init_crb = dcn401_init_crb,
+ .dchvm_init = dcn35_dchvm_init,
.hubbub_read_state = hubbub2_read_state,
.force_usr_retraining_allow = hubbub32_force_usr_retraining_allow,
- .dchubbub_init = hubbub35_init,
- .dchvm_init = dcn35_dchvm_init,
+ .set_request_limit = hubbub42_set_request_limit,
+ .program_det_segments = dcn401_program_det_segments,
+ .program_compbuf_segments = dcn401_program_compbuf_segments,
+ .wait_for_det_update = dcn401_wait_for_det_update,
+ .program_arbiter = dcn42_program_arbiter,
+ .hubbub_read_reg_state = hubbub3_read_reg_state
};
void hubbub42_construct(struct dcn20_hubbub *hubbub2,
diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn10/dcn10_hubp.c b/drivers/gpu/drm/amd/display/dc/hubp/dcn10/dcn10_hubp.c
index 6378e3fd7249..7c97a774141f 100644
--- a/drivers/gpu/drm/amd/display/dc/hubp/dcn10/dcn10_hubp.c
+++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn10/dcn10_hubp.c
@@ -143,6 +143,7 @@ void hubp1_program_tiling(
const struct dc_tiling_info *info,
const enum surface_pixel_format pixel_format)
{
+ (void)pixel_format;
struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp);
REG_UPDATE_6(DCSURF_ADDR_CONFIG,
@@ -563,6 +564,7 @@ void hubp1_program_surface_config(
bool horizontal_mirror,
unsigned int compat_level)
{
+ (void)compat_level;
hubp1_dcc_control(hubp, dcc->enable, dcc->independent_64b_blks);
hubp1_program_tiling(hubp, tiling_info, format);
hubp1_program_size(hubp, format, plane_size, dcc);
diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.c b/drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.c
index 92288de4cc10..ceee5165fd6a 100644
--- a/drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.c
+++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.c
@@ -313,6 +313,7 @@ static void hubp2_program_tiling(
const struct dc_tiling_info *info,
const enum surface_pixel_format pixel_format)
{
+ (void)pixel_format;
REG_UPDATE_3(DCSURF_ADDR_CONFIG,
NUM_PIPES, log_2(info->gfx9.num_pipes),
PIPE_INTERLEAVE, info->gfx9.pipe_interleave,
@@ -557,6 +558,7 @@ void hubp2_program_surface_config(
bool horizontal_mirror,
unsigned int compat_level)
{
+ (void)compat_level;
struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
hubp2_dcc_control(hubp, dcc->enable, dcc->independent_64b_blks);
diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn30/dcn30_hubp.c b/drivers/gpu/drm/amd/display/dc/hubp/dcn30/dcn30_hubp.c
index 0cc6f4558989..e2708e30eb1b 100644
--- a/drivers/gpu/drm/amd/display/dc/hubp/dcn30/dcn30_hubp.c
+++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn30/dcn30_hubp.c
@@ -321,6 +321,7 @@ void hubp3_program_tiling(
const struct dc_tiling_info *info,
const enum surface_pixel_format pixel_format)
{
+ (void)pixel_format;
REG_UPDATE_4(DCSURF_ADDR_CONFIG,
NUM_PIPES, log_2(info->gfx9.num_pipes),
PIPE_INTERLEAVE, info->gfx9.pipe_interleave,
@@ -418,6 +419,7 @@ void hubp3_program_surface_config(
bool horizontal_mirror,
unsigned int compat_level)
{
+ (void)compat_level;
struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
hubp3_dcc_control_sienna_cichlid(hubp, dcc);
diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn35/dcn35_hubp.c b/drivers/gpu/drm/amd/display/dc/hubp/dcn35/dcn35_hubp.c
index 79c583e258c7..c879f4901c7d 100644
--- a/drivers/gpu/drm/amd/display/dc/hubp/dcn35/dcn35_hubp.c
+++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn35/dcn35_hubp.c
@@ -179,6 +179,7 @@ void hubp35_program_surface_config(
bool horizontal_mirror,
unsigned int compat_level)
{
+ (void)compat_level;
struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
hubp3_dcc_control_sienna_cichlid(hubp, dcc);
diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c b/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c
index 4985e885952d..5a816442deee 100644
--- a/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c
+++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c
@@ -657,6 +657,7 @@ void hubp401_program_tiling(
const struct dc_tiling_info *info,
const enum surface_pixel_format pixel_format)
{
+ (void)pixel_format;
/* DCSURF_ADDR_CONFIG still shows up in reg spec, but does not need to be programmed for DCN4x
* All 4 fields NUM_PIPES, PIPE_INTERLEAVE, MAX_COMPRESSED_FRAGS and NUM_PKRS are irrelevant.
*
@@ -671,6 +672,7 @@ void hubp401_program_size(
const struct plane_size *plane_size,
struct dc_plane_dcc_param *dcc)
{
+ (void)dcc;
struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
uint32_t pitch, pitch_c;
bool use_pitch_c = false;
@@ -709,6 +711,7 @@ void hubp401_program_surface_config(
bool horizontal_mirror,
unsigned int compat_level)
{
+ (void)compat_level;
struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
hubp401_dcc_control(hubp, dcc);
@@ -812,9 +815,8 @@ void hubp401_cursor_set_position(
int x_pos_viewport = 0;
int x_hot_viewport = 0;
uint32_t cur_en = pos->enable ? 1 : 0;
-
+ uint32_t x_hotspot_clamped = pos->x_hotspot;
hubp->curs_pos = *pos;
-
/* Recout is zero for pipes if the entire dst_rect is contained
* within preceeding ODM slices.
*/
@@ -845,6 +847,8 @@ void hubp401_cursor_set_position(
ASSERT(param->h_scale_ratio.value);
+ if (x_hotspot_clamped > 0xFF)
+ x_hotspot_clamped = 0xFF;
if (param->h_scale_ratio.value)
dst_x_offset = dc_fixpt_floor(dc_fixpt_div(
dc_fixpt_from_int(dst_x_offset),
@@ -865,7 +869,7 @@ void hubp401_cursor_set_position(
CURSOR_Y_POSITION, pos->y);
REG_SET_2(CURSOR_HOT_SPOT, 0,
- CURSOR_HOT_SPOT_X, pos->x_hotspot,
+ CURSOR_HOT_SPOT_X, x_hotspot_clamped,
CURSOR_HOT_SPOT_Y, pos->y_hotspot);
REG_SET(CURSOR_DST_OFFSET, 0,
diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.c b/drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.c
index 0e33c739f459..ad6badcceb12 100644
--- a/drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.c
+++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.c
@@ -245,6 +245,39 @@ static void hubp42_program_deadline(
REFCYC_PER_VM_DMDATA, dlg_attr->refcyc_per_vm_dmdata);
}
+void hubp42_program_requestor(
+ struct hubp *hubp,
+ struct dml2_display_rq_regs *rq_regs)
+{
+ struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
+
+ REG_UPDATE(HUBPRET_CONTROL,
+ DET_BUF_PLANE1_BASE_ADDRESS, rq_regs->plane1_base_address);
+ REG_SET_4(DCN_EXPANSION_MODE, 0,
+ DRQ_EXPANSION_MODE, rq_regs->drq_expansion_mode,
+ PRQ_EXPANSION_MODE, rq_regs->prq_expansion_mode,
+ MRQ_EXPANSION_MODE, rq_regs->mrq_expansion_mode,
+ CRQ_EXPANSION_MODE, rq_regs->crq_expansion_mode);
+ REG_SET_8(DCHUBP_REQ_SIZE_CONFIG, 0,
+ CHUNK_SIZE, rq_regs->rq_regs_l.chunk_size,
+ MIN_CHUNK_SIZE, rq_regs->rq_regs_l.min_chunk_size,
+ META_CHUNK_SIZE, rq_regs->rq_regs_l.meta_chunk_size,
+ MIN_META_CHUNK_SIZE, rq_regs->rq_regs_l.min_meta_chunk_size,
+ DPTE_GROUP_SIZE, rq_regs->rq_regs_l.dpte_group_size,
+ VM_GROUP_SIZE, rq_regs->rq_regs_l.mpte_group_size,
+ SWATH_HEIGHT, rq_regs->rq_regs_l.swath_height,
+ PTE_ROW_HEIGHT_LINEAR, rq_regs->rq_regs_l.pte_row_height_linear);
+ REG_SET_7(DCHUBP_REQ_SIZE_CONFIG_C, 0,
+ CHUNK_SIZE_C, rq_regs->rq_regs_c.chunk_size,
+ MIN_CHUNK_SIZE_C, rq_regs->rq_regs_c.min_chunk_size,
+ META_CHUNK_SIZE_C, rq_regs->rq_regs_c.meta_chunk_size,
+ MIN_META_CHUNK_SIZE_C, rq_regs->rq_regs_c.min_meta_chunk_size,
+ DPTE_GROUP_SIZE_C, rq_regs->rq_regs_c.dpte_group_size,
+ SWATH_HEIGHT_C, rq_regs->rq_regs_c.swath_height,
+ PTE_ROW_HEIGHT_LINEAR_C, rq_regs->rq_regs_c.pte_row_height_linear);
+}
+
+
void hubp42_setup(
struct hubp *hubp,
struct dml2_dchub_per_pipe_register_set *pipe_regs,
@@ -255,7 +288,7 @@ void hubp42_setup(
* disable the requestors is not needed
*/
hubp401_vready_at_or_After_vsync(hubp, pipe_global_sync, timing);
- hubp401_program_requestor(hubp, &pipe_regs->rq_regs);
+ hubp42_program_requestor(hubp, &pipe_regs->rq_regs);
hubp42_program_deadline(hubp, &pipe_regs->dlg_regs, &pipe_regs->ttu_regs);
}
static void hubp42_program_surface_config(
@@ -268,6 +301,7 @@ static void hubp42_program_surface_config(
bool horizontal_mirror,
unsigned int compat_level)
{
+ (void)compat_level;
struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
hubp3_dcc_control_sienna_cichlid(hubp, dcc);
diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.h b/drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.h
index 486c8907413a..88bb1337ab9d 100644
--- a/drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.h
+++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.h
@@ -48,6 +48,8 @@
HUBP_SF(CURSOR0_0_HUBP_3DLUT_ADDRESS_LOW, HUBP_3DLUT_ADDRESS_LOW, mask_sh),\
HUBP_SF(CURSOR0_0_HUBP_3DLUT_DLG_PARAM, REFCYC_PER_3DLUT_GROUP, mask_sh)
+struct dml2_display_rq_regs;
+
bool hubp42_construct(
struct dcn20_hubp *hubp2,
struct dc_context *ctx,
@@ -64,6 +66,10 @@ void hubp42_program_3dlut_fl_config(struct hubp *hubp,
void hubp42_read_state(struct hubp *hubp);
+void hubp42_program_requestor(
+ struct hubp *hubp,
+ struct dml2_display_rq_regs *rq_regs);
+
void hubp42_setup(
struct hubp *hubp,
struct dml2_dchub_per_pipe_register_set *pipe_regs,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
index 8a17cc036399..5273ca09fe12 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
@@ -201,6 +201,8 @@ static void enable_display_pipe_clock_gating(
struct dc_context *ctx,
bool clock_gating)
{
+ (void)ctx;
+ (void)clock_gating;
/*TODO*/
}
@@ -284,6 +286,7 @@ static bool
dce110_set_input_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx,
const struct dc_plane_state *plane_state)
{
+ (void)dc;
struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp;
const struct dc_transfer_func *tf = NULL;
struct ipp_prescale_params prescale_params = { 0 };
@@ -488,15 +491,15 @@ dce110_translate_regamma_to_hw_format(const struct dc_transfer_func *output_tf,
seg_distr[8] = 4;
seg_distr[9] = 4;
seg_distr[10] = 0;
- seg_distr[11] = -1;
- seg_distr[12] = -1;
- seg_distr[13] = -1;
- seg_distr[14] = -1;
- seg_distr[15] = -1;
+ seg_distr[11] = (uint32_t)-1;
+ seg_distr[12] = (uint32_t)-1;
+ seg_distr[13] = (uint32_t)-1;
+ seg_distr[14] = (uint32_t)-1;
+ seg_distr[15] = (uint32_t)-1;
}
for (k = 0; k < 16; k++) {
- if (seg_distr[k] != -1)
+ if (seg_distr[k] != (uint32_t)-1)
hw_points += (1 << seg_distr[k]);
}
@@ -607,6 +610,7 @@ static bool
dce110_set_output_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx,
const struct dc_stream_state *stream)
{
+ (void)dc;
struct transform *xfm = pipe_ctx->plane_res.xfm;
xfm->funcs->opp_power_on_regamma_lut(xfm, true);
@@ -1539,6 +1543,7 @@ static enum dc_status dce110_enable_stream_timing(
struct dc_state *context,
struct dc *dc)
{
+ (void)context;
struct dc_stream_state *stream = pipe_ctx->stream;
struct pipe_ctx *pipe_ctx_old = &dc->current_state->res_ctx.
pipe_ctx[pipe_ctx->pipe_idx];
@@ -1568,7 +1573,7 @@ static enum dc_status dce110_enable_stream_timing(
return DC_ERROR_UNEXPECTED;
}
- if (dc_is_hdmi_tmds_signal(stream->signal)) {
+ if (dc_is_tmds_signal(stream->signal)) {
stream->link->phy_state.symclk_ref_cnts.otg = 1;
if (stream->link->phy_state.symclk_state == SYMCLK_OFF_TX_OFF)
stream->link->phy_state.symclk_state = SYMCLK_ON_TX_OFF;
@@ -1986,7 +1991,7 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context)
struct pipe_ctx *pipe_ctx = NULL;
struct dce_hwseq *hws = dc->hwseq;
int edp_with_sink_num;
- int edp_num;
+ unsigned int edp_num;
int edp_stream_num;
int i;
bool can_apply_edp_fast_boot = false;
@@ -2418,7 +2423,7 @@ static void dce110_reset_hw_ctx_wrap(
BREAK_TO_DEBUGGER();
}
pipe_ctx_old->stream_res.tg->funcs->disable_crtc(pipe_ctx_old->stream_res.tg);
- if (dc_is_hdmi_tmds_signal(pipe_ctx_old->stream->signal))
+ if (dc_is_tmds_signal(pipe_ctx_old->stream->signal))
pipe_ctx_old->stream->link->phy_state.symclk_ref_cnts.otg = 0;
pipe_ctx_old->plane_res.mi->funcs->free_mem_input(
pipe_ctx_old->plane_res.mi, dc->current_state->stream_count);
@@ -2728,6 +2733,7 @@ static void program_gamut_remap(struct pipe_ctx *pipe_ctx)
static void update_plane_addr(const struct dc *dc,
struct pipe_ctx *pipe_ctx)
{
+ (void)dc;
struct dc_plane_state *plane_state = pipe_ctx->plane_state;
if (plane_state == NULL)
@@ -2814,6 +2820,8 @@ static void dce110_enable_timing_synchronization(
int group_size,
struct pipe_ctx *grouped_pipes[])
{
+ (void)state;
+ (void)group_index;
struct dcp_gsl_params gsl_params = { 0 };
int i;
DC_LOGGER_INIT(dc->ctx);
@@ -2889,6 +2897,8 @@ static void dce110_enable_per_frame_crtc_position_reset(
static void dce110_init_pipes(struct dc *dc, struct dc_state *context)
{
+ (void)context;
+ (void)dc;
// Do nothing
}
@@ -3154,10 +3164,13 @@ static void dce110_post_unlock_program_front_end(
struct dc *dc,
struct dc_state *context)
{
+ (void)dc;
+ (void)context;
}
static void dce110_power_down_fe(struct dc *dc, struct dc_state *state, struct pipe_ctx *pipe_ctx)
{
+ (void)state;
struct dce_hwseq *hws = dc->hwseq;
int fe_idx = pipe_ctx->plane_res.mi ?
pipe_ctx->plane_res.mi->inst : pipe_ctx->pipe_idx;
@@ -3178,6 +3191,9 @@ static void dce110_wait_for_mpcc_disconnect(
struct resource_pool *res_pool,
struct pipe_ctx *pipe_ctx)
{
+ (void)dc;
+ (void)res_pool;
+ (void)pipe_ctx;
/* do nothing*/
}
@@ -3187,6 +3203,10 @@ static void program_output_csc(struct dc *dc,
uint16_t *matrix,
int opp_id)
{
+ (void)dc;
+ (void)colorspace;
+ (void)matrix;
+ (void)opp_id;
int i;
struct out_csc_color_matrix tbl_entry;
@@ -3331,6 +3351,7 @@ void dce110_enable_lvds_link_output(struct dc_link *link,
enum clock_source_id clock_source,
uint32_t pixel_clock)
{
+ (void)link_res;
link->link_enc->funcs->enable_lvds_output(
link->link_enc,
clock_source,
@@ -3345,6 +3366,7 @@ void dce110_enable_tmds_link_output(struct dc_link *link,
enum dc_color_depth color_depth,
uint32_t pixel_clock)
{
+ (void)link_res;
link->link_enc->funcs->enable_tmds_output(
link->link_enc,
clock_source,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce120/dce120_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce120/dce120_hwseq.c
index 2a62f63d0357..0689bbf12ad8 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dce120/dce120_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dce120/dce120_hwseq.c
@@ -154,6 +154,10 @@ static bool dce120_enable_display_power_gating(
struct dc_bios *dcb,
enum pipe_gating_control power_gating)
{
+ (void)dc;
+ (void)controller_id;
+ (void)dcb;
+ (void)power_gating;
/* disable for bringup */
#if 0
enum bp_result bp_result = BP_RESULT_OK;
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
index 17ff66d9a617..756ce8379538 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
@@ -86,6 +86,7 @@ static void print_microsec(struct dc_context *dc_ctx,
struct dc_log_buffer_ctx *log_ctx,
uint32_t ref_cycle)
{
+ (void)log_ctx;
const uint32_t ref_clk_mhz = dc_ctx->dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000;
static const unsigned int frac = 1000;
uint32_t us_x10 = (ref_cycle * frac) / ref_clk_mhz;
@@ -252,6 +253,7 @@ void dcn10_lock_all_pipes(struct dc *dc,
static void log_mpc_crc(struct dc *dc,
struct dc_log_buffer_ctx *log_ctx)
{
+ (void)log_ctx;
struct dc_context *dc_ctx = dc->ctx;
struct dce_hwseq *hws = dc->hwseq;
@@ -450,6 +452,7 @@ static void dcn10_log_hubp_states(struct dc *dc, void *log_ctx)
static void dcn10_log_color_state(struct dc *dc,
struct dc_log_buffer_ctx *log_ctx)
{
+ (void)log_ctx;
struct dc_context *dc_ctx = dc->ctx;
struct resource_pool *pool = dc->res_pool;
bool is_gamut_remap_available = false;
@@ -813,6 +816,7 @@ void dcn10_log_hw_state(struct dc *dc,
bool dcn10_did_underflow_occur(struct dc *dc, struct pipe_ctx *pipe_ctx)
{
+ (void)dc;
struct hubp *hubp = pipe_ctx->plane_res.hubp;
struct timing_generator *tg = pipe_ctx->stream_res.tg;
@@ -1181,6 +1185,7 @@ enum dc_status dcn10_enable_stream_timing(
struct dc_state *context,
struct dc *dc)
{
+ (void)context;
struct dc_stream_state *stream = pipe_ctx->stream;
enum dc_color_space color_space;
struct tg_color black_color = {0};
@@ -1284,6 +1289,7 @@ static void dcn10_reset_back_end_for_pipe(
struct pipe_ctx *pipe_ctx,
struct dc_state *context)
{
+ (void)context;
int i;
struct dc_link *link;
DC_LOGGER_INIT(dc->ctx);
@@ -1551,6 +1557,7 @@ void dcn10_plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx)
void dcn10_disable_plane(struct dc *dc, struct dc_state *state, struct pipe_ctx *pipe_ctx)
{
+ (void)state;
struct dce_hwseq *hws = dc->hwseq;
DC_LOGGER_INIT(dc->ctx);
@@ -1904,7 +1911,7 @@ void dcn10_power_down_on_boot(struct dc *dc)
{
struct dc_link *edp_links[MAX_NUM_EDP];
struct dc_link *edp_link = NULL;
- int edp_num;
+ unsigned int edp_num;
int i = 0;
dc_get_edp_links(dc, edp_links, &edp_num);
@@ -2004,6 +2011,7 @@ static bool patch_address_for_sbs_tb_stereo(
void dcn10_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_ctx)
{
+ (void)dc;
bool addr_patched = false;
PHYSICAL_ADDRESS_LOC addr;
struct dc_plane_state *plane_state = pipe_ctx->plane_state;
@@ -2030,6 +2038,7 @@ void dcn10_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_ctx)
bool dcn10_set_input_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx,
const struct dc_plane_state *plane_state)
{
+ (void)dc;
struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
const struct dc_transfer_func *tf = NULL;
bool result = true;
@@ -2472,6 +2481,7 @@ void dcn10_enable_vblanks_synchronization(
int group_size,
struct pipe_ctx *grouped_pipes[])
{
+ (void)group_index;
struct output_pixel_processor *opp;
struct timing_generator *tg;
int i, width = 0, height = 0, master;
@@ -2537,6 +2547,7 @@ void dcn10_enable_timing_synchronization(
int group_size,
struct pipe_ctx *grouped_pipes[])
{
+ (void)group_index;
struct output_pixel_processor *opp;
struct timing_generator *tg;
int i, width = 0, height = 0;
@@ -2641,6 +2652,7 @@ static void mmhub_read_vm_system_aperture_settings(struct dcn10_hubp *hubp1,
struct vm_system_aperture_param *apt,
struct dce_hwseq *hws)
{
+ (void)hubp1;
PHYSICAL_ADDRESS_LOC physical_page_number;
uint32_t logical_addr_low;
uint32_t logical_addr_high;
@@ -2666,6 +2678,7 @@ static void mmhub_read_vm_context0_settings(struct dcn10_hubp *hubp1,
struct vm_context0_param *vm0,
struct dce_hwseq *hws)
{
+ (void)hubp1;
PHYSICAL_ADDRESS_LOC fb_base;
PHYSICAL_ADDRESS_LOC fb_offset;
uint32_t fb_base_value;
@@ -2724,6 +2737,7 @@ static void dcn10_enable_plane(
struct pipe_ctx *pipe_ctx,
struct dc_state *context)
{
+ (void)context;
struct dce_hwseq *hws = dc->hwseq;
if (dc->debug.sanity_checks) {
@@ -2821,6 +2835,8 @@ void dcn10_program_output_csc(struct dc *dc,
uint16_t *matrix,
int opp_id)
{
+ (void)dc;
+ (void)opp_id;
if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) {
if (pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment != NULL) {
@@ -3586,6 +3602,10 @@ bool dcn10_dummy_display_power_gating(
struct dc_bios *dcb,
enum pipe_gating_control power_gating)
{
+ (void)dc;
+ (void)controller_id;
+ (void)dcb;
+ (void)power_gating;
return true;
}
@@ -4052,6 +4072,7 @@ enum dc_status dcn10_set_clock(struct dc *dc,
uint32_t clk_khz,
uint32_t stepping)
{
+ (void)stepping;
struct dc_state *context = dc->current_state;
struct dc_clock_config clock_cfg = {0};
struct dc_clocks *current_clocks = &context->bw_ctx.bw.dcn.clk;
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
index 307e8f8060e6..288e4edaa9a2 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
@@ -75,6 +75,7 @@
void dcn20_log_color_state(struct dc *dc,
struct dc_log_buffer_ctx *log_ctx)
{
+ (void)log_ctx;
struct dc_context *dc_ctx = dc->ctx;
struct resource_pool *pool = dc->res_pool;
bool is_gamut_remap_available = false;
@@ -379,6 +380,7 @@ void dcn20_program_triple_buffer(
struct pipe_ctx *pipe_ctx,
bool enable_triple_buffer)
{
+ (void)dc;
if (pipe_ctx->plane_res.hubp && pipe_ctx->plane_res.hubp->funcs) {
pipe_ctx->plane_res.hubp->funcs->hubp_enable_tripleBuffer(
pipe_ctx->plane_res.hubp,
@@ -893,7 +895,7 @@ enum dc_status dcn20_enable_stream_timing(
dccg->funcs->set_dtbclk_dto(dccg, &dto_params);
}
- if (dc_is_hdmi_tmds_signal(stream->signal)) {
+ if (dc_is_tmds_signal(stream->signal)) {
stream->link->phy_state.symclk_ref_cnts.otg = 1;
if (stream->link->phy_state.symclk_state == SYMCLK_OFF_TX_OFF)
stream->link->phy_state.symclk_state = SYMCLK_ON_TX_OFF;
@@ -1175,6 +1177,8 @@ bool dcn20_set_input_transfer_func(struct dc *dc,
void dcn20_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx)
{
+ (void)context;
+ (void)dc;
struct pipe_ctx *odm_pipe;
int opp_cnt = 1;
int opp_inst[MAX_PIPES] = { pipe_ctx->stream_res.opp->inst };
@@ -1297,6 +1301,7 @@ static void dcn20_power_on_plane_resources(
void dcn20_enable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx,
struct dc_state *context)
{
+ (void)context;
//if (dc->debug.sanity_checks) {
// dcn10_verify_allow_pstate_change_high(dc);
//}
@@ -2652,6 +2657,7 @@ void dcn20_init_vm_ctx(
struct dc_virtual_addr_space_config *va_config,
int vmid)
{
+ (void)hws;
struct dcn_hubbub_virt_addr_config config;
if (vmid == 0) {
@@ -2670,6 +2676,7 @@ void dcn20_init_vm_ctx(
int dcn20_init_sys_ctx(struct dce_hwseq *hws, struct dc *dc, struct dc_phy_addr_space_config *pa_config)
{
+ (void)hws;
struct dcn_hubbub_phys_addr_config config;
config.system_aperture.fb_top = pa_config->system_aperture.fb_top;
@@ -2799,6 +2806,7 @@ void dcn20_reset_back_end_for_pipe(
struct pipe_ctx *pipe_ctx,
struct dc_state *context)
{
+ (void)context;
struct dc_link *link = pipe_ctx->stream->link;
const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);
struct dccg *dccg = dc->res_pool->dccg;
@@ -2856,7 +2864,7 @@ void dcn20_reset_back_end_for_pipe(
* the case where the same symclk is shared across multiple otg
* instances
*/
- if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal))
+ if (dc_is_tmds_signal(pipe_ctx->stream->signal))
link->phy_state.symclk_ref_cnts.otg = 0;
if (link->phy_state.symclk_state == SYMCLK_ON_TX_OFF) {
link_hwss->disable_link_output(link,
@@ -3245,6 +3253,7 @@ void dcn20_set_disp_pattern_generator(const struct dc *dc,
const struct tg_color *solid_color,
int width, int height, int offset)
{
+ (void)dc;
pipe_ctx->stream_res.opp->funcs->opp_set_disp_pattern_generator(pipe_ctx->stream_res.opp, test_pattern,
color_space, color_depth, solid_color, width, height, offset);
}
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c
index d04cfd403b7e..2aa0f1de8103 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c
@@ -75,6 +75,7 @@
void dcn30_log_color_state(struct dc *dc,
struct dc_log_buffer_ctx *log_ctx)
{
+ (void)log_ctx;
struct dc_context *dc_ctx = dc->ctx;
struct resource_pool *pool = dc->res_pool;
bool is_gamut_remap_available = false;
@@ -645,7 +646,7 @@ void dcn30_init_hw(struct dc *dc)
struct dc_bios *dcb = dc->ctx->dc_bios;
struct resource_pool *res_pool = dc->res_pool;
int i;
- int edp_num;
+ unsigned int edp_num;
uint32_t backlight = MAX_BACKLIGHT_LEVEL;
uint32_t user_level = MAX_BACKLIGHT_LEVEL;
@@ -1183,6 +1184,7 @@ void dcn30_set_disp_pattern_generator(const struct dc *dc,
const struct tg_color *solid_color,
int width, int height, int offset)
{
+ (void)dc;
pipe_ctx->stream_res.opp->funcs->opp_set_disp_pattern_generator(pipe_ctx->stream_res.opp, test_pattern,
color_space, color_depth, solid_color, width, height, offset);
}
@@ -1237,6 +1239,7 @@ void dcn30_get_underflow_debug_data(const struct dc *dc,
struct timing_generator *tg,
struct dc_underflow_debug_data *out_data)
{
+ (void)tg;
struct hubbub *hubbub = dc->res_pool->hubbub;
if (hubbub) {
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn303/dcn303_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn303/dcn303_hwseq.c
index 3bc56ac346f3..6e1877a8682d 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn303/dcn303_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn303/dcn303_hwseq.c
@@ -45,20 +45,31 @@
void dcn303_dpp_pg_control(struct dce_hwseq *hws, unsigned int dpp_inst, bool power_on)
{
+ (void)dpp_inst;
+ (void)hws;
+ (void)power_on;
/*DCN303 removes PG registers*/
}
void dcn303_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on)
{
+ (void)hubp_inst;
+ (void)hws;
+ (void)power_on;
/*DCN303 removes PG registers*/
}
void dcn303_dsc_pg_control(struct dce_hwseq *hws, unsigned int dsc_inst, bool power_on)
{
+ (void)dsc_inst;
+ (void)hws;
+ (void)power_on;
/*DCN303 removes PG registers*/
}
void dcn303_enable_power_gating_plane(struct dce_hwseq *hws, bool enable)
{
+ (void)enable;
+ (void)hws;
/*DCN303 removes PG registers*/
}
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c
index 94f63fd54e3e..b4afb2bc4493 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c
@@ -484,6 +484,7 @@ void dcn31_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool p
int dcn31_init_sys_ctx(struct dce_hwseq *hws, struct dc *dc, struct dc_phy_addr_space_config *pa_config)
{
+ (void)hws;
struct dcn_hubbub_phys_addr_config config = {0};
config.system_aperture.fb_top = pa_config->system_aperture.fb_top;
@@ -511,6 +512,7 @@ static void dcn31_reset_back_end_for_pipe(
struct pipe_ctx *pipe_ctx,
struct dc_state *context)
{
+ (void)context;
struct dc_link *link;
if (pipe_ctx->stream_res.stream_enc == NULL) {
@@ -548,7 +550,7 @@ static void dcn31_reset_back_end_for_pipe(
* the case where the same symclk is shared across multiple otg
* instances
*/
- if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal))
+ if (dc_is_tmds_signal(pipe_ctx->stream->signal))
link->phy_state.symclk_ref_cnts.otg = 0;
if (pipe_ctx->top_pipe == NULL) {
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c
index 3e239124c17d..858a06b03b57 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c
@@ -172,6 +172,7 @@ static unsigned int get_odm_config(struct pipe_ctx *pipe_ctx, unsigned int *opp_
void dcn314_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx)
{
+ (void)context;
struct pipe_ctx *odm_pipe;
int opp_cnt = 0;
int opp_inst[MAX_PIPES] = {0};
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
index a0aaa727e9fa..b45ceb570a5c 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
@@ -570,6 +570,7 @@ bool dcn32_set_output_transfer_func(struct dc *dc,
struct pipe_ctx *pipe_ctx,
const struct dc_stream_state *stream)
{
+ (void)dc;
int mpcc_id = pipe_ctx->plane_res.hubp->inst;
struct mpc *mpc = pipe_ctx->stream_res.opp->ctx->dc->res_pool->mpc;
const struct pwl_params *params = NULL;
@@ -757,6 +758,9 @@ static void dcn32_initialize_min_clocks(struct dc *dc)
{
struct dc_clocks *clocks = &dc->current_state->bw_ctx.bw.dcn.clk;
+ if (!dc->clk_mgr || !dc->clk_mgr->bw_params || !dc->clk_mgr->funcs)
+ return;
+
clocks->dcfclk_deep_sleep_khz = DCN3_2_DCFCLK_DS_INIT_KHZ;
clocks->dcfclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].dcfclk_mhz * 1000;
clocks->socclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].socclk_mhz * 1000;
@@ -765,9 +769,10 @@ static void dcn32_initialize_min_clocks(struct dc *dc)
clocks->ref_dtbclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].dtbclk_mhz * 1000;
clocks->fclk_p_state_change_support = true;
clocks->p_state_change_support = true;
+
if (dc->debug.disable_boot_optimizations) {
clocks->dispclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].dispclk_mhz * 1000;
- } else {
+ } else if (dc->clk_mgr->funcs->get_dispclk_from_dentist) {
/* Even though DPG_EN = 1 for the connected display, it still requires the
* correct timing so we cannot set DISPCLK to min freq or it could cause
* audio corruption. Read current DISPCLK from DENTIST and request the same
@@ -776,10 +781,10 @@ static void dcn32_initialize_min_clocks(struct dc *dc)
clocks->dispclk_khz = dc->clk_mgr->funcs->get_dispclk_from_dentist(dc->clk_mgr);
}
- dc->clk_mgr->funcs->update_clocks(
- dc->clk_mgr,
- dc->current_state,
- true);
+ if (dc->clk_mgr->funcs->update_clocks)
+ dc->clk_mgr->funcs->update_clocks(dc->clk_mgr,
+ dc->current_state,
+ true);
}
void dcn32_init_hw(struct dc *dc)
@@ -789,7 +794,7 @@ void dcn32_init_hw(struct dc *dc)
struct dc_bios *dcb = dc->ctx->dc_bios;
struct resource_pool *res_pool = dc->res_pool;
int i;
- int edp_num;
+ unsigned int edp_num;
uint32_t backlight = MAX_BACKLIGHT_LEVEL;
uint32_t user_level = MAX_BACKLIGHT_LEVEL;
@@ -1007,7 +1012,8 @@ void dcn32_init_hw(struct dc *dc)
DMUB_FW_VERSION(7, 0, 35)) {
/* FAMS2 is disabled */
dc->debug.fams2_config.bits.enable = false;
- if (dc->debug.using_dml2 && dc->res_pool->funcs->update_bw_bounding_box) {
+ if (dc->debug.using_dml2 && dc->res_pool->funcs->update_bw_bounding_box &&
+ dc->clk_mgr && dc->clk_mgr->bw_params) {
/* update bounding box if FAMS2 disabled */
dc->res_pool->funcs->update_bw_bounding_box(dc, dc->clk_mgr->bw_params);
}
@@ -1138,6 +1144,7 @@ static unsigned int get_odm_config(struct pipe_ctx *pipe_ctx, unsigned int *opp_
void dcn32_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx)
{
+ (void)context;
struct pipe_ctx *odm_pipe;
int opp_cnt = 0;
int opp_inst[MAX_PIPES] = {0};
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
index b5f60f59382e..f133b52ea958 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
@@ -428,6 +428,7 @@ static unsigned int get_odm_config(struct pipe_ctx *pipe_ctx, unsigned int *opp_
void dcn35_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx)
{
+ (void)context;
struct pipe_ctx *odm_pipe;
int opp_cnt = 0;
int opp_inst[MAX_PIPES] = {0};
@@ -520,7 +521,7 @@ void dcn35_power_down_on_boot(struct dc *dc)
{
struct dc_link *edp_links[MAX_NUM_EDP];
struct dc_link *edp_link = NULL;
- int edp_num;
+ unsigned int edp_num;
int i = 0;
dc_get_edp_links(dc, edp_links, &edp_num);
@@ -816,6 +817,7 @@ void dcn35_init_pipes(struct dc *dc, struct dc_state *context)
void dcn35_enable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx,
struct dc_state *context)
{
+ (void)context;
struct dpp *dpp = pipe_ctx->plane_res.dpp;
/* enable DCFCLK current DCHUB */
@@ -921,7 +923,7 @@ void dcn35_calc_blocks_to_gate(struct dc *dc, struct dc_state *context,
bool hpo_frl_stream_enc_acquired = false;
bool hpo_dp_stream_enc_acquired = false;
int i = 0, j = 0;
- int edp_num = 0;
+ unsigned int edp_num = 0;
struct dc_link *edp_links[MAX_NUM_EDP] = { NULL };
memset(update_state, 0, sizeof(struct pg_block_update));
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
index 357899116ecd..9768b8f6b6fb 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
@@ -140,9 +140,10 @@ void dcn401_init_hw(struct dc *dc)
struct dc_bios *dcb = dc->ctx->dc_bios;
struct resource_pool *res_pool = dc->res_pool;
int i;
- int edp_num;
+ unsigned int edp_num;
uint32_t backlight = MAX_BACKLIGHT_LEVEL;
uint32_t user_level = MAX_BACKLIGHT_LEVEL;
+ bool dchub_ref_freq_changed;
int current_dchub_ref_freq = 0;
if (dc->clk_mgr && dc->clk_mgr->funcs && dc->clk_mgr->funcs->init_clocks) {
@@ -357,20 +358,25 @@ void dcn401_init_hw(struct dc *dc)
dc->caps.dmub_caps.psr = dc->ctx->dmub_srv->dmub->feature_caps.psr;
dc->caps.dmub_caps.mclk_sw = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch_ver > 0;
dc->caps.dmub_caps.fams_ver = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch_ver;
+
+ /* sw and fw FAMS versions must match for support */
dc->debug.fams2_config.bits.enable &=
- dc->caps.dmub_caps.fams_ver == dc->debug.fams_version.ver; // sw & fw fams versions must match for support
- if ((!dc->debug.fams2_config.bits.enable && dc->res_pool->funcs->update_bw_bounding_box)
- || res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000 != current_dchub_ref_freq) {
+ dc->caps.dmub_caps.fams_ver == dc->debug.fams_version.ver;
+ dchub_ref_freq_changed =
+ res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000 != current_dchub_ref_freq;
+ if ((!dc->debug.fams2_config.bits.enable || dchub_ref_freq_changed) &&
+ dc->res_pool->funcs->update_bw_bounding_box &&
+ dc->clk_mgr && dc->clk_mgr->bw_params) {
/* update bounding box if FAMS2 disabled, or if dchub clk has changed */
- if (dc->clk_mgr)
- dc->res_pool->funcs->update_bw_bounding_box(dc,
- dc->clk_mgr->bw_params);
+ dc->res_pool->funcs->update_bw_bounding_box(dc,
+ dc->clk_mgr->bw_params);
}
}
}
void dcn401_trigger_3dlut_dma_load(struct dc *dc, struct pipe_ctx *pipe_ctx)
{
+ (void)dc;
struct hubp *hubp = pipe_ctx->plane_res.hubp;
if (hubp->funcs->hubp_enable_3dlut_fl) {
@@ -551,6 +557,7 @@ bool dcn401_set_output_transfer_func(struct dc *dc,
struct pipe_ctx *pipe_ctx,
const struct dc_stream_state *stream)
{
+ (void)dc;
int mpcc_id = pipe_ctx->plane_res.hubp->inst;
struct mpc *mpc = pipe_ctx->stream_res.opp->ctx->dc->res_pool->mpc;
const struct pwl_params *params = NULL;
@@ -612,6 +619,7 @@ static void enable_stream_timing_calc(
struct drr_params *params,
unsigned int *event_triggers)
{
+ (void)dc;
struct dc_stream_state *stream = pipe_ctx->stream;
int i;
@@ -1389,6 +1397,7 @@ void dcn401_dmub_hw_control_lock(struct dc *dc,
struct dc_state *context,
bool lock)
{
+ (void)context;
/* use always for now */
union dmub_inbox0_cmd_lock_hw hw_lock_cmd = { 0 };
@@ -1863,6 +1872,7 @@ void dcn401_reset_back_end_for_pipe(
struct pipe_ctx *pipe_ctx,
struct dc_state *context)
{
+ (void)context;
struct dc_link *link = pipe_ctx->stream->link;
const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);
@@ -1918,7 +1928,7 @@ void dcn401_reset_back_end_for_pipe(
* the case where the same symclk is shared across multiple otg
* instances
*/
- if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal))
+ if (dc_is_tmds_signal(pipe_ctx->stream->signal))
link->phy_state.symclk_ref_cnts.otg = 0;
if (link->phy_state.symclk_state == SYMCLK_ON_TX_OFF) {
link_hwss->disable_link_output(link,
@@ -3238,6 +3248,7 @@ void dcn401_update_writeback_sequence(
struct dc_state *context,
struct block_sequence_state *seq_state)
{
+ (void)context;
struct dwbc *dwb;
struct mcif_wb *mcif_wb;
@@ -3443,6 +3454,7 @@ void dcn401_enable_plane_sequence(struct dc *dc, struct pipe_ctx *pipe_ctx,
struct dc_state *context,
struct block_sequence_state *seq_state)
{
+ (void)context;
struct dce_hwseq *hws = dc->hwseq;
uint32_t org_ip_request_cntl = 0;
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.c
index 8e12dc1297c4..46f2f9833d9e 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.c
@@ -66,9 +66,10 @@ void dcn42_init_hw(struct dc *dc)
struct dc_bios *dcb = dc->ctx->dc_bios;
struct resource_pool *res_pool = dc->res_pool;
int i;
- int edp_num;
+ unsigned int edp_num;
uint32_t backlight = MAX_BACKLIGHT_LEVEL;
uint32_t user_level = MAX_BACKLIGHT_LEVEL;
+ bool dchub_ref_freq_changed;
int current_dchub_ref_freq = 0;
if (dc->clk_mgr && dc->clk_mgr->funcs && dc->clk_mgr->funcs->init_clocks) {
@@ -203,7 +204,8 @@ void dcn42_init_hw(struct dc *dc)
for (i = 0; i < dc->link_count; i++) {
struct dc_link *link = dc->links[i];
- if (link->link_enc->funcs->is_dig_enabled &&
+ if (link && link->link_enc &&
+ link->link_enc->funcs->is_dig_enabled &&
link->link_enc->funcs->is_dig_enabled(link->link_enc) &&
hws->funcs.power_down) {
hws->funcs.power_down(dc);
@@ -260,8 +262,12 @@ void dcn42_init_hw(struct dc *dc)
if (dc->res_pool->hubbub->funcs->init_crb)
dc->res_pool->hubbub->funcs->init_crb(dc->res_pool->hubbub);
- if (dc->res_pool->hubbub->funcs->set_request_limit && dc->config.sdpif_request_limit_words_per_umc > 0)
- dc->res_pool->hubbub->funcs->set_request_limit(dc->res_pool->hubbub, dc->clk_mgr->bw_params->num_channels, dc->config.sdpif_request_limit_words_per_umc);
+ if (dc->res_pool->hubbub->funcs->set_request_limit &&
+ dc->clk_mgr && dc->clk_mgr->bw_params &&
+ dc->config.sdpif_request_limit_words_per_umc > 0)
+ dc->res_pool->hubbub->funcs->set_request_limit(dc->res_pool->hubbub,
+ dc->clk_mgr->bw_params->num_channels,
+ dc->config.sdpif_request_limit_words_per_umc);
// Get DMCUB capabilities
if (dc->ctx->dmub_srv) {
@@ -269,13 +275,18 @@ void dcn42_init_hw(struct dc *dc)
dc->caps.dmub_caps.psr = dc->ctx->dmub_srv->dmub->feature_caps.psr;
dc->caps.dmub_caps.mclk_sw = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch_ver > 0;
dc->caps.dmub_caps.fams_ver = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch_ver;
+
+ /* sw and fw FAMS versions must match for support */
dc->debug.fams2_config.bits.enable &=
- dc->caps.dmub_caps.fams_ver == dc->debug.fams_version.ver; // sw & fw fams versions must match for support
- if ((!dc->debug.fams2_config.bits.enable && dc->res_pool->funcs->update_bw_bounding_box)
- || res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000 != current_dchub_ref_freq) {
+ dc->caps.dmub_caps.fams_ver == dc->debug.fams_version.ver;
+ dchub_ref_freq_changed =
+ res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000 != current_dchub_ref_freq;
+
+ if ((!dc->debug.fams2_config.bits.enable || dchub_ref_freq_changed) &&
+ dc->res_pool->funcs->update_bw_bounding_box &&
+ dc->clk_mgr && dc->clk_mgr->bw_params) {
/* update bounding box if FAMS2 disabled, or if dchub clk has changed */
- if (dc->clk_mgr)
- dc->res_pool->funcs->update_bw_bounding_box(dc, dc->clk_mgr->bw_params);
+ dc->res_pool->funcs->update_bw_bounding_box(dc, dc->clk_mgr->bw_params);
}
}
if (dc->res_pool->pg_cntl) {
@@ -375,6 +386,7 @@ void dcn42_program_cm_hist(
struct pipe_ctx *pipe_ctx,
const struct dc_plane_state *plane_state)
{
+ (void)dc;
struct dpp *dpp = pipe_ctx->plane_res.dpp;
if (dpp && dpp->funcs->dpp_cm_hist_control)
@@ -989,6 +1001,7 @@ void dcn42_root_clock_control(struct dc *dc,
}
void dcn42_setup_stereo(struct pipe_ctx *pipe_ctx, struct dc *dc)
{
+ (void)dc;
struct crtc_stereo_flags flags = { 0 };
struct dc_stream_state *stream = pipe_ctx->stream;
@@ -1052,7 +1065,7 @@ void dcn42_power_down_on_boot(struct dc *dc)
{
struct dc_link *edp_links[MAX_NUM_EDP];
struct dc_link *edp_link = NULL;
- int edp_num;
+ unsigned int edp_num;
int i = 0;
dc_get_edp_links(dc, edp_links, &edp_num);
diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h
index 43579b0e1482..e960ca9062ad 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h
@@ -214,6 +214,7 @@ struct resource_funcs {
unsigned int index);
void (*get_panel_config_defaults)(struct dc_panel_config *panel_config);
+ void (*get_default_tiling_info)(struct dc_tiling_info *tiling_info);
void (*build_pipe_pix_clk_params)(struct pipe_ctx *pipe_ctx);
/*
* Get indicator of power from a context that went through full validation
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h
index b152f6879495..51581c10fd6b 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h
@@ -256,7 +256,7 @@ struct default_adjustment {
enum dc_color_space out_color_space;
enum dc_color_space in_color_space;
enum dc_color_depth color_depth;
- enum pixel_format surface_pixel_format;
+ enum dc_pixel_format surface_pixel_format;
enum graphics_csc_adjust_type csc_adjust_type;
bool force_hw_default;
};
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h
index 5a1d9b708a9d..30990355985d 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h
@@ -160,7 +160,7 @@ struct scaler_data {
struct scaling_ratios ratios;
struct scl_inits inits;
struct sharpness_adj sharpness;
- enum pixel_format format;
+ enum dc_pixel_format format;
struct line_buffer_params lb_params;
// Below struct holds the scaler values to program hw registers
struct dscl_prog_data dscl_prog_data;
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c
index 676df39079fc..015f3659cf77 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c
@@ -92,7 +92,7 @@ static struct irq_source_info_funcs vupdate_irq_info_funcs = {
.enable_mask = DC_HPD_INT_CONTROL__DC_HPD_INT_EN_MASK,\
.enable_value = {\
DC_HPD_INT_CONTROL__DC_HPD_INT_EN_MASK,\
- ~DC_HPD_INT_CONTROL__DC_HPD_INT_EN_MASK\
+ (uint32_t)~DC_HPD_INT_CONTROL__DC_HPD_INT_EN_MASK\
},\
.ack_reg = mmHPD ## reg_num ## _DC_HPD_INT_CONTROL,\
.ack_mask = DC_HPD_INT_CONTROL__DC_HPD_INT_ACK_MASK,\
@@ -107,7 +107,7 @@ static struct irq_source_info_funcs vupdate_irq_info_funcs = {
.enable_mask = DC_HPD_INT_CONTROL__DC_HPD_RX_INT_EN_MASK,\
.enable_value = {\
DC_HPD_INT_CONTROL__DC_HPD_RX_INT_EN_MASK,\
- ~DC_HPD_INT_CONTROL__DC_HPD_RX_INT_EN_MASK },\
+ (uint32_t)~DC_HPD_INT_CONTROL__DC_HPD_RX_INT_EN_MASK },\
.ack_reg = mmHPD ## reg_num ## _DC_HPD_INT_CONTROL,\
.ack_mask = DC_HPD_INT_CONTROL__DC_HPD_RX_INT_ACK_MASK,\
.ack_value = DC_HPD_INT_CONTROL__DC_HPD_RX_INT_ACK_MASK,\
@@ -121,7 +121,7 @@ static struct irq_source_info_funcs vupdate_irq_info_funcs = {
GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK,\
.enable_value = {\
GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK,\
- ~GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK},\
+ (uint32_t)~GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK},\
.ack_reg = mmDCP ## reg_num ## _GRPH_INTERRUPT_STATUS,\
.ack_mask = GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK,\
.ack_value = GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK,\
@@ -136,7 +136,7 @@ static struct irq_source_info_funcs vupdate_irq_info_funcs = {
CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK,\
.enable_value = {\
CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK,\
- ~CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK},\
+ (uint32_t)~CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK},\
.ack_reg = mmCRTC ## reg_num ## _CRTC_V_UPDATE_INT_STATUS,\
.ack_mask =\
CRTC_V_UPDATE_INT_STATUS__CRTC_V_UPDATE_INT_CLEAR_MASK,\
@@ -152,7 +152,7 @@ static struct irq_source_info_funcs vupdate_irq_info_funcs = {
CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK,\
.enable_value = {\
CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK,\
- ~CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK},\
+ (uint32_t)~CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK},\
.ack_reg = mmCRTC ## reg_num ## _CRTC_VERTICAL_INTERRUPT0_CONTROL,\
.ack_mask =\
CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_CLEAR_MASK,\
@@ -183,6 +183,7 @@ bool dal_irq_service_dummy_set(struct irq_service *irq_service,
const struct irq_source_info *info,
bool enable)
{
+ (void)enable;
DC_LOG_ERROR("%s: called for non-implemented irq source, src_id=%u, ext_id=%u\n",
__func__, info->src_id, info->ext_id);
@@ -328,6 +329,7 @@ enum dc_irq_source to_dal_irq_source_dce110(
uint32_t src_id,
uint32_t ext_id)
{
+ (void)irq_service;
switch (src_id) {
case VISLANDS30_IV_SRCID_D1_VERTICAL_INTERRUPT0:
return DC_IRQ_SOURCE_VBLANK1;
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c b/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c
index b473dae2abbb..dbab6e3737a1 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c
@@ -79,7 +79,7 @@ static struct irq_source_info_funcs vupdate_irq_info_funcs = {
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
.enable_value = {\
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
- ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
+ (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
},\
.ack_reg = SRI(reg2, block, reg_num),\
.ack_mask = \
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c b/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c
index b5c5f42cf8f2..3e19dfdd0474 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c
@@ -68,7 +68,7 @@ static struct irq_source_info_funcs vupdate_irq_info_funcs = {
.enable_mask = DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN_MASK,\
.enable_value = {\
DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN_MASK,\
- ~DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN_MASK\
+ (uint32_t)~DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN_MASK\
},\
.ack_reg = mmDC_HPD ## reg_num ## _INT_CONTROL,\
.ack_mask = DC_HPD1_INT_CONTROL__DC_HPD1_INT_ACK_MASK,\
@@ -83,7 +83,7 @@ static struct irq_source_info_funcs vupdate_irq_info_funcs = {
.enable_mask = DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_EN_MASK,\
.enable_value = {\
DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_EN_MASK,\
- ~DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_EN_MASK },\
+ (uint32_t)~DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_EN_MASK },\
.ack_reg = mmDC_HPD ## reg_num ## _INT_CONTROL,\
.ack_mask = DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_ACK_MASK,\
.ack_value = DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_ACK_MASK,\
@@ -98,7 +98,7 @@ static struct irq_source_info_funcs vupdate_irq_info_funcs = {
GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK,\
.enable_value = {\
GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK,\
- ~GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK},\
+ (uint32_t)~GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK},\
.ack_reg = mmDCP ## reg_num ## _GRPH_INTERRUPT_STATUS,\
.ack_mask = GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK,\
.ack_value = GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK,\
@@ -113,7 +113,7 @@ static struct irq_source_info_funcs vupdate_irq_info_funcs = {
CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK,\
.enable_value = {\
CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK,\
- ~CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK},\
+ (uint32_t)~CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK},\
.ack_reg = mmCRTC ## reg_num ## _CRTC_V_UPDATE_INT_STATUS,\
.ack_mask =\
CRTC_V_UPDATE_INT_STATUS__CRTC_V_UPDATE_INT_CLEAR_MASK,\
@@ -129,7 +129,7 @@ static struct irq_source_info_funcs vupdate_irq_info_funcs = {
CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK,\
.enable_value = {\
CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK,\
- ~CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK},\
+ (uint32_t)~CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK},\
.ack_reg = mmCRTC ## reg_num ## _CRTC_VERTICAL_INTERRUPT0_CONTROL,\
.ack_mask =\
CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_CLEAR_MASK,\
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c b/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c
index ca2e13702fbb..0bdb62b883aa 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c
@@ -42,6 +42,9 @@ static enum dc_irq_source to_dal_irq_source_dcn10(struct irq_service *irq_servic
uint32_t src_id,
uint32_t ext_id)
{
+ (void)irq_service;
+ (void)src_id;
+ (void)ext_id;
switch (src_id) {
case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP:
return DC_IRQ_SOURCE_VBLANK1;
@@ -176,7 +179,7 @@ static struct irq_source_info_funcs vupdate_no_lock_irq_info_funcs = {
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
.enable_value = {\
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
- ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
+ (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
},\
.ack_reg = SRI(reg2, block, reg_num),\
.ack_mask = \
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn20/irq_service_dcn20.c b/drivers/gpu/drm/amd/display/dc/irq/dcn20/irq_service_dcn20.c
index 1c4c51abc259..8a0f4b5d6956 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/dcn20/irq_service_dcn20.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/dcn20/irq_service_dcn20.c
@@ -43,6 +43,9 @@ static enum dc_irq_source to_dal_irq_source_dcn20(
uint32_t src_id,
uint32_t ext_id)
{
+ (void)irq_service;
+ (void)src_id;
+ (void)ext_id;
switch (src_id) {
case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP:
return DC_IRQ_SOURCE_VBLANK1;
@@ -179,7 +182,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = {
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
.enable_value = {\
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
- ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
+ (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
},\
.ack_reg = SRI(reg2, block, reg_num),\
.ack_mask = \
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c b/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c
index 9e0881472e38..9d13c0cc91f0 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c
@@ -42,6 +42,9 @@ static enum dc_irq_source to_dal_irq_source_dcn21(struct irq_service *irq_servic
uint32_t src_id,
uint32_t ext_id)
{
+ (void)irq_service;
+ (void)src_id;
+ (void)ext_id;
switch (src_id) {
case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP:
return DC_IRQ_SOURCE_VBLANK1;
@@ -189,7 +192,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = {
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
.enable_value = {\
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
- ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
+ (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
},\
.ack_reg = SRI(reg2, block, reg_num),\
.ack_mask = \
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn30/irq_service_dcn30.c b/drivers/gpu/drm/amd/display/dc/irq/dcn30/irq_service_dcn30.c
index 92bcd35723ca..78338af86666 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/dcn30/irq_service_dcn30.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/dcn30/irq_service_dcn30.c
@@ -50,6 +50,9 @@ static enum dc_irq_source to_dal_irq_source_dcn30(
uint32_t src_id,
uint32_t ext_id)
{
+ (void)irq_service;
+ (void)src_id;
+ (void)ext_id;
switch (src_id) {
case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP:
return DC_IRQ_SOURCE_VBLANK1;
@@ -196,7 +199,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = {
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
.enable_value = {\
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
- ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
+ (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
},\
.ack_reg = SRI(reg2, block, reg_num),\
.ack_mask = \
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn302/irq_service_dcn302.c b/drivers/gpu/drm/amd/display/dc/irq/dcn302/irq_service_dcn302.c
index 16685d066c1a..2f47a9fbcd43 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/dcn302/irq_service_dcn302.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/dcn302/irq_service_dcn302.c
@@ -37,6 +37,9 @@
static enum dc_irq_source to_dal_irq_source_dcn302(struct irq_service *irq_service, uint32_t src_id, uint32_t ext_id)
{
+ (void)ext_id;
+ (void)irq_service;
+ (void)src_id;
switch (src_id) {
case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP:
return DC_IRQ_SOURCE_VBLANK1;
@@ -180,7 +183,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = {
.enable_mask = block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
.enable_value = {\
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
- ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
+ (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
},\
.ack_reg = SRI(reg2, block, reg_num),\
.ack_mask = block ## reg_num ## _ ## reg2 ## __ ## mask2 ## _MASK,\
@@ -199,7 +202,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = {
reg1 ## __ ## mask1 ## _MASK,\
.enable_value = {\
reg1 ## __ ## mask1 ## _MASK,\
- ~reg1 ## __ ## mask1 ## _MASK \
+ (uint32_t)~reg1 ## __ ## mask1 ## _MASK \
},\
.ack_reg = SRI_DMUB(reg2),\
.ack_mask = \
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn303/irq_service_dcn303.c b/drivers/gpu/drm/amd/display/dc/irq/dcn303/irq_service_dcn303.c
index 01d83e1922d6..236a7278a8cf 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/dcn303/irq_service_dcn303.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/dcn303/irq_service_dcn303.c
@@ -38,6 +38,9 @@ static enum dc_irq_source to_dal_irq_source_dcn303(struct irq_service *irq_servi
uint32_t src_id,
uint32_t ext_id)
{
+ (void)irq_service;
+ (void)src_id;
+ (void)ext_id;
switch (src_id) {
case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP:
return DC_IRQ_SOURCE_VBLANK1;
@@ -123,7 +126,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = {
.enable_mask = block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
.enable_value = {\
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
- ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
+ (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
},\
.ack_reg = SRI(reg2, block, reg_num),\
.ack_mask = block ## reg_num ## _ ## reg2 ## __ ## mask2 ## _MASK,\
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn31/irq_service_dcn31.c b/drivers/gpu/drm/amd/display/dc/irq/dcn31/irq_service_dcn31.c
index 2114c5669e6e..213e5da31b19 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/dcn31/irq_service_dcn31.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/dcn31/irq_service_dcn31.c
@@ -40,6 +40,9 @@ static enum dc_irq_source to_dal_irq_source_dcn31(struct irq_service *irq_servic
uint32_t src_id,
uint32_t ext_id)
{
+ (void)irq_service;
+ (void)src_id;
+ (void)ext_id;
switch (src_id) {
case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP:
return DC_IRQ_SOURCE_VBLANK1;
@@ -184,7 +187,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = {
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
.enable_value = {\
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
- ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
+ (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
},\
.ack_reg = SRI(reg2, block, reg_num),\
.ack_mask = \
@@ -198,7 +201,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = {
reg1 ## __ ## mask1 ## _MASK,\
.enable_value = {\
reg1 ## __ ## mask1 ## _MASK,\
- ~reg1 ## __ ## mask1 ## _MASK \
+ (uint32_t)~reg1 ## __ ## mask1 ## _MASK \
},\
.ack_reg = SRI_DMUB(reg2),\
.ack_mask = \
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn314/irq_service_dcn314.c b/drivers/gpu/drm/amd/display/dc/irq/dcn314/irq_service_dcn314.c
index 16f158e0fb60..8aacc229b002 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/dcn314/irq_service_dcn314.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/dcn314/irq_service_dcn314.c
@@ -42,6 +42,9 @@ static enum dc_irq_source to_dal_irq_source_dcn314(struct irq_service *irq_servi
uint32_t src_id,
uint32_t ext_id)
{
+ (void)irq_service;
+ (void)src_id;
+ (void)ext_id;
switch (src_id) {
case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP:
return DC_IRQ_SOURCE_VBLANK1;
@@ -186,7 +189,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = {
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
.enable_value = {\
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
- ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
+ (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
},\
.ack_reg = SRI(reg2, block, reg_num),\
.ack_mask = \
@@ -200,7 +203,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = {
reg1 ## __ ## mask1 ## _MASK,\
.enable_value = {\
reg1 ## __ ## mask1 ## _MASK,\
- ~reg1 ## __ ## mask1 ## _MASK \
+ (uint32_t)~reg1 ## __ ## mask1 ## _MASK \
},\
.ack_reg = SRI_DMUB(reg2),\
.ack_mask = \
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn315/irq_service_dcn315.c b/drivers/gpu/drm/amd/display/dc/irq/dcn315/irq_service_dcn315.c
index 8ee03c006ad6..b3bddc87afed 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/dcn315/irq_service_dcn315.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/dcn315/irq_service_dcn315.c
@@ -47,6 +47,9 @@ static enum dc_irq_source to_dal_irq_source_dcn315(
uint32_t src_id,
uint32_t ext_id)
{
+ (void)irq_service;
+ (void)src_id;
+ (void)ext_id;
switch (src_id) {
case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP:
return DC_IRQ_SOURCE_VBLANK1;
@@ -191,7 +194,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = {
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
.enable_value = {\
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
- ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
+ (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
},\
.ack_reg = SRI(reg2, block, reg_num),\
.ack_mask = \
@@ -205,7 +208,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = {
reg1 ## __ ## mask1 ## _MASK,\
.enable_value = {\
reg1 ## __ ## mask1 ## _MASK,\
- ~reg1 ## __ ## mask1 ## _MASK \
+ (uint32_t)~reg1 ## __ ## mask1 ## _MASK \
},\
.ack_reg = SRI_DMUB(reg2),\
.ack_mask = \
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn32/irq_service_dcn32.c b/drivers/gpu/drm/amd/display/dc/irq/dcn32/irq_service_dcn32.c
index 07e6f7dd6b99..f407ba72acdb 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/dcn32/irq_service_dcn32.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/dcn32/irq_service_dcn32.c
@@ -41,6 +41,9 @@ static enum dc_irq_source to_dal_irq_source_dcn32(
uint32_t src_id,
uint32_t ext_id)
{
+ (void)irq_service;
+ (void)src_id;
+ (void)ext_id;
switch (src_id) {
case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP:
return DC_IRQ_SOURCE_VBLANK1;
@@ -195,7 +198,7 @@ static struct irq_source_info_funcs vline2_irq_info_funcs = {
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
.enable_value = {\
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
- ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
+ (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
},\
.ack_reg = SRI(reg2, block, reg_num),\
.ack_mask = \
@@ -209,7 +212,7 @@ static struct irq_source_info_funcs vline2_irq_info_funcs = {
reg1 ## __ ## mask1 ## _MASK,\
.enable_value = {\
reg1 ## __ ## mask1 ## _MASK,\
- ~reg1 ## __ ## mask1 ## _MASK \
+ (uint32_t)~reg1 ## __ ## mask1 ## _MASK \
},\
.ack_reg = SRI_DMUB(reg2),\
.ack_mask = \
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn35/irq_service_dcn35.c b/drivers/gpu/drm/amd/display/dc/irq/dcn35/irq_service_dcn35.c
index 3d28a5007f53..2f2985075f88 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/dcn35/irq_service_dcn35.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/dcn35/irq_service_dcn35.c
@@ -39,6 +39,9 @@ static enum dc_irq_source to_dal_irq_source_dcn35(
uint32_t src_id,
uint32_t ext_id)
{
+ (void)irq_service;
+ (void)src_id;
+ (void)ext_id;
switch (src_id) {
case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP:
return DC_IRQ_SOURCE_VBLANK1;
@@ -184,7 +187,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = {
REG_STRUCT[base + reg_num].enable_value[0] = \
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
REG_STRUCT[base + reg_num].enable_value[1] = \
- ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK, \
+ (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK, \
REG_STRUCT[base + reg_num].ack_reg = SRI(reg2, block, reg_num),\
REG_STRUCT[base + reg_num].ack_mask = \
block ## reg_num ## _ ## reg2 ## __ ## mask2 ## _MASK,\
@@ -198,7 +201,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = {
REG_STRUCT[base].enable_value[0] = \
reg1 ## __ ## mask1 ## _MASK,\
REG_STRUCT[base].enable_value[1] = \
- ~reg1 ## __ ## mask1 ## _MASK, \
+ (uint32_t)~reg1 ## __ ## mask1 ## _MASK, \
REG_STRUCT[base].ack_reg = SRI_DMUB(reg2),\
REG_STRUCT[base].ack_mask = \
reg2 ## __ ## mask2 ## _MASK,\
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn351/irq_service_dcn351.c b/drivers/gpu/drm/amd/display/dc/irq/dcn351/irq_service_dcn351.c
index f716c2590876..1ed75b53e131 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/dcn351/irq_service_dcn351.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/dcn351/irq_service_dcn351.c
@@ -18,6 +18,9 @@ static enum dc_irq_source to_dal_irq_source_dcn351(
uint32_t src_id,
uint32_t ext_id)
{
+ (void)irq_service;
+ (void)src_id;
+ (void)ext_id;
switch (src_id) {
case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP:
return DC_IRQ_SOURCE_VBLANK1;
@@ -163,7 +166,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = {
REG_STRUCT[base + reg_num].enable_value[0] = \
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
REG_STRUCT[base + reg_num].enable_value[1] = \
- ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK, \
+ (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK, \
REG_STRUCT[base + reg_num].ack_reg = SRI(reg2, block, reg_num),\
REG_STRUCT[base + reg_num].ack_mask = \
block ## reg_num ## _ ## reg2 ## __ ## mask2 ## _MASK,\
@@ -177,7 +180,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = {
REG_STRUCT[base].enable_value[0] = \
reg1 ## __ ## mask1 ## _MASK,\
REG_STRUCT[base].enable_value[1] = \
- ~reg1 ## __ ## mask1 ## _MASK, \
+ (uint32_t)~reg1 ## __ ## mask1 ## _MASK, \
REG_STRUCT[base].ack_reg = SRI_DMUB(reg2),\
REG_STRUCT[base].ack_mask = \
reg2 ## __ ## mask2 ## _MASK,\
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn36/irq_service_dcn36.c b/drivers/gpu/drm/amd/display/dc/irq/dcn36/irq_service_dcn36.c
index e718004901cf..4c321c26f02f 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/dcn36/irq_service_dcn36.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/dcn36/irq_service_dcn36.c
@@ -17,6 +17,9 @@ static enum dc_irq_source to_dal_irq_source_dcn36(
uint32_t src_id,
uint32_t ext_id)
{
+ (void)irq_service;
+ (void)src_id;
+ (void)ext_id;
switch (src_id) {
case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP:
return DC_IRQ_SOURCE_VBLANK1;
@@ -162,7 +165,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = {
REG_STRUCT[base + reg_num].enable_value[0] = \
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
REG_STRUCT[base + reg_num].enable_value[1] = \
- ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK, \
+ (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK, \
REG_STRUCT[base + reg_num].ack_reg = SRI(reg2, block, reg_num),\
REG_STRUCT[base + reg_num].ack_mask = \
block ## reg_num ## _ ## reg2 ## __ ## mask2 ## _MASK,\
@@ -176,7 +179,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = {
REG_STRUCT[base].enable_value[0] = \
reg1 ## __ ## mask1 ## _MASK,\
REG_STRUCT[base].enable_value[1] = \
- ~reg1 ## __ ## mask1 ## _MASK, \
+ (uint32_t)~reg1 ## __ ## mask1 ## _MASK, \
REG_STRUCT[base].ack_reg = SRI_DMUB(reg2),\
REG_STRUCT[base].ack_mask = \
reg2 ## __ ## mask2 ## _MASK,\
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn401/irq_service_dcn401.c b/drivers/gpu/drm/amd/display/dc/irq/dcn401/irq_service_dcn401.c
index 2cde50b2ae22..059c5c636fd9 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/dcn401/irq_service_dcn401.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/dcn401/irq_service_dcn401.c
@@ -20,6 +20,9 @@ static enum dc_irq_source to_dal_irq_source_dcn401(
uint32_t src_id,
uint32_t ext_id)
{
+ (void)irq_service;
+ (void)src_id;
+ (void)ext_id;
switch (src_id) {
case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP:
return DC_IRQ_SOURCE_VBLANK1;
@@ -175,7 +178,7 @@ static struct irq_source_info_funcs vline2_irq_info_funcs = {
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
.enable_value = {\
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
- ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
+ (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
},\
.ack_reg = SRI(reg2, block, reg_num),\
.ack_mask = \
@@ -189,7 +192,7 @@ static struct irq_source_info_funcs vline2_irq_info_funcs = {
reg1 ## __ ## mask1 ## _MASK,\
.enable_value = {\
reg1 ## __ ## mask1 ## _MASK,\
- ~reg1 ## __ ## mask1 ## _MASK \
+ (uint32_t)~reg1 ## __ ## mask1 ## _MASK \
},\
.ack_reg = SRI_DMUB(reg2),\
.ack_mask = \
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn42/irq_service_dcn42.c b/drivers/gpu/drm/amd/display/dc/irq/dcn42/irq_service_dcn42.c
index 19e0741c62cd..f4d1ce9079de 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/dcn42/irq_service_dcn42.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/dcn42/irq_service_dcn42.c
@@ -19,6 +19,9 @@ static enum dc_irq_source to_dal_irq_source_dcn42(
uint32_t src_id,
uint32_t ext_id)
{
+ (void)irq_service;
+ (void)src_id;
+ (void)ext_id;
switch (src_id) {
case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP:
return DC_IRQ_SOURCE_VBLANK1;
@@ -173,7 +176,7 @@ static struct irq_source_info_funcs vline2_irq_info_funcs = {
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
.enable_value = {\
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
- ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
+ (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
},\
.ack_reg = SRI(reg2, block, reg_num),\
.ack_mask = \
@@ -187,7 +190,7 @@ static struct irq_source_info_funcs vline2_irq_info_funcs = {
reg1 ## __ ## mask1 ## _MASK,\
.enable_value = {\
reg1 ## __ ## mask1 ## _MASK,\
- ~reg1 ## __ ## mask1 ## _MASK \
+ (uint32_t)~reg1 ## __ ## mask1 ## _MASK \
},\
.ack_reg = SRI_DMUB(reg2),\
.ack_mask = \
diff --git a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c
index 693d852b1c40..060460abc377 100644
--- a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c
+++ b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c
@@ -66,6 +66,7 @@ static void dp_retrain_link_dp_test(struct dc_link *link,
struct dc_link_settings *link_setting,
bool skip_video_pattern)
{
+ (void)skip_video_pattern;
struct pipe_ctx *pipes[MAX_PIPES];
struct dc_state *state = link->dc->current_state;
struct dc_stream_update stream_update = { 0 };
@@ -483,6 +484,7 @@ static void set_crtc_test_pattern(struct dc_link *link,
enum dp_test_pattern test_pattern,
enum dp_test_pattern_color_space test_pattern_color_space)
{
+ (void)test_pattern_color_space;
enum controller_dp_test_pattern controller_test_pattern;
enum dc_color_depth color_depth = pipe_ctx->
stream->timing.display_color_depth;
diff --git a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dpia.c b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dpia.c
index 81bf3c5e1fdf..2a87b23582f3 100644
--- a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dpia.c
+++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dpia.c
@@ -81,6 +81,10 @@ static void set_dio_dpia_lane_settings(struct dc_link *link,
const struct dc_link_settings *link_settings,
const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX])
{
+ (void)link;
+ (void)link_res;
+ (void)link_settings;
+ (void)lane_settings;
}
static void enable_dpia_link_output(struct dc_link *link,
@@ -145,13 +149,9 @@ static void disable_dpia_link_output(struct dc_link *link,
}
static const struct link_hwss dpia_link_hwss = {
- .setup_stream_encoder = setup_dio_stream_encoder,
- .reset_stream_encoder = reset_dio_stream_encoder,
- .setup_stream_attribute = setup_dio_stream_attribute,
- .disable_link_output = disable_dpia_link_output,
- .setup_audio_output = setup_dio_audio_output,
- .enable_audio_packet = enable_dio_audio_packet,
- .disable_audio_packet = disable_dio_audio_packet,
+ /* Ensure initialization order matches the declaration in link_hwss.h
+ * for strict compiler compliance and consistency across HWSS implementations
+ */
.ext = {
.set_throttled_vcp_size = set_dio_throttled_vcp_size,
.enable_dp_link_output = enable_dpia_link_output,
@@ -159,6 +159,14 @@ static const struct link_hwss dpia_link_hwss = {
.set_dp_lane_settings = set_dio_dpia_lane_settings,
.update_stream_allocation_table = update_dpia_stream_allocation_table,
},
+
+ .setup_stream_encoder = setup_dio_stream_encoder,
+ .reset_stream_encoder = reset_dio_stream_encoder,
+ .setup_stream_attribute = setup_dio_stream_attribute,
+ .disable_link_output = disable_dpia_link_output,
+ .setup_audio_output = setup_dio_audio_output,
+ .enable_audio_packet = enable_dio_audio_packet,
+ .disable_audio_packet = disable_dio_audio_packet,
};
bool can_use_dpia_link_hwss(const struct dc_link *link,
diff --git a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_dp.c b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_dp.c
index cec68c5dba13..dbbedeeed298 100644
--- a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_dp.c
+++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_dp.c
@@ -110,6 +110,8 @@ void enable_hpo_dp_link_output(struct dc_link *link,
enum clock_source_id clock_source,
const struct dc_link_settings *link_settings)
{
+ (void)signal;
+ (void)clock_source;
if (!link_res->hpo_dp_link_enc) {
DC_LOG_ERROR("%s: invalid hpo_dp_link_enc\n", __func__);
return;
@@ -160,6 +162,7 @@ static void set_hpo_dp_lane_settings(struct dc_link *link,
const struct dc_link_settings *link_settings,
const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX])
{
+ (void)link;
link_res->hpo_dp_link_enc->funcs->set_ffe(
link_res->hpo_dp_link_enc,
link_settings,
@@ -170,6 +173,7 @@ void update_hpo_dp_stream_allocation_table(struct dc_link *link,
const struct link_resource *link_res,
const struct link_mst_stream_allocation_table *table)
{
+ (void)link;
link_res->hpo_dp_link_enc->funcs->update_stream_allocation_table(
link_res->hpo_dp_link_enc,
table);
@@ -178,6 +182,7 @@ void update_hpo_dp_stream_allocation_table(struct dc_link *link,
void setup_hpo_dp_audio_output(struct pipe_ctx *pipe_ctx,
struct audio_output *audio_output, uint32_t audio_inst)
{
+ (void)audio_output;
pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_audio_setup(
pipe_ctx->stream_res.hpo_dp_stream_enc,
audio_inst,
@@ -218,6 +223,7 @@ static const struct link_hwss hpo_dp_link_hwss = {
bool can_use_hpo_dp_link_hwss(const struct dc_link *link,
const struct link_resource *link_res)
{
+ (void)link;
return link_res->hpo_dp_link_enc != NULL;
}
diff --git a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.c b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.c
index 55c5148de800..6d5b7450b205 100644
--- a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.c
+++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.c
@@ -74,6 +74,7 @@ static void dp_hpo_fixed_vs_pe_retimer_set_tx_ffe(struct dc_link *link,
static void dp_hpo_fixed_vs_pe_retimer_program_override_test_pattern(struct dc_link *link,
struct encoder_set_dp_phy_pattern_param *tp_params)
{
+ (void)tp_params;
uint8_t clk_src = 0xC4;
uint8_t pattern = 0x4F; /* SQ128 */
diff --git a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_virtual.c b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_virtual.c
index 64742c24f7e6..3aa1375cec71 100644
--- a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_virtual.c
+++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_virtual.c
@@ -27,20 +27,26 @@
void virtual_setup_stream_encoder(struct pipe_ctx *pipe_ctx)
{
+ (void)pipe_ctx;
}
void virtual_setup_stream_attribute(struct pipe_ctx *pipe_ctx)
{
+ (void)pipe_ctx;
}
void virtual_reset_stream_encoder(struct pipe_ctx *pipe_ctx)
{
+ (void)pipe_ctx;
}
static void virtual_disable_link_output(struct dc_link *link,
const struct link_resource *link_res,
enum signal_type signal)
{
+ (void)link;
+ (void)link_res;
+ (void)signal;
}
static const struct link_hwss virtual_link_hwss = {
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_detection.c b/drivers/gpu/drm/amd/display/dc/link/link_detection.c
index f992c2d16748..59851924bfcd 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_detection.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_detection.c
@@ -784,6 +784,7 @@ static void verify_link_capability_destructive(struct dc_link *link,
struct dc_sink *sink,
enum dc_detect_reason reason)
{
+ (void)sink;
bool should_prepare_phy_clocks =
should_prepare_phy_clocks_for_link_verification(link->dc, reason);
@@ -822,6 +823,7 @@ static void verify_link_capability_non_destructive(struct dc_link *link)
static bool should_verify_link_capability_destructively(struct dc_link *link,
enum dc_detect_reason reason)
{
+ (void)reason;
bool destrictive = false;
struct dc_link_settings max_link_cap;
bool is_link_enc_unavailable = false;
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_validation.c b/drivers/gpu/drm/amd/display/dc/link/link_validation.c
index acdc162de535..eb791285ed06 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_validation.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_validation.c
@@ -391,6 +391,7 @@ static const struct dc_tunnel_settings *get_dp_tunnel_settings(const struct dc_s
*/
enum dc_status link_validate_dp_tunnel_bandwidth(const struct dc *dc, const struct dc_state *new_ctx)
{
+ (void)dc;
struct dc_validation_dpia_set dpia_link_sets[MAX_DPIA_NUM] = { 0 };
uint8_t link_count = 0;
enum dc_status result = DC_OK;
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c
index 08e2b572e0ff..ddff0db4ce70 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c
@@ -554,6 +554,7 @@ enum link_training_result dp_check_link_loss_status(
struct dc_link *link,
const struct link_training_settings *link_training_setting)
{
+ (void)link_training_setting;
enum link_training_result status = LINK_TRAINING_SUCCESS;
union lane_status lane_status;
union lane_align_status_updated dpcd_lane_status_updated;
@@ -1387,6 +1388,7 @@ bool dp_set_hw_training_pattern(
enum dc_dp_training_pattern pattern,
uint32_t offset)
{
+ (void)offset;
enum dp_test_pattern test_pattern = DP_TEST_PATTERN_UNSUPPORTED;
switch (pattern) {
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_128b_132b.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_128b_132b.c
index 11565f187ac7..1a6bfc45927d 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_128b_132b.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_128b_132b.c
@@ -158,6 +158,7 @@ static enum link_training_result dp_perform_128b_132b_cds_done_sequence(
const struct link_resource *link_res,
struct link_training_settings *lt_settings)
{
+ (void)link_res;
/* Assumption: assume hardware has transmitted eq pattern */
enum dc_status status = DC_OK;
enum link_training_result result = LINK_TRAINING_SUCCESS;
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c
index 603537ffd128..34fa76d97b83 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c
@@ -172,6 +172,7 @@ static uint8_t dpia_build_set_config_data(
struct dc_link *link,
struct link_training_settings *lt_settings)
{
+ (void)link;
union dpia_set_config_data data;
data.raw = 0;
@@ -290,6 +291,7 @@ static enum link_training_result dpia_training_cr_non_transparent(
struct link_training_settings *lt_settings,
uint32_t hop)
{
+ (void)link_res;
enum link_training_result result = LINK_TRAINING_CR_FAIL_LANE0;
uint8_t repeater_cnt = 0; /* Number of hops/repeaters in display path. */
enum dc_status status = DC_ERROR_UNEXPECTED;
@@ -457,6 +459,7 @@ static enum link_training_result dpia_training_cr_transparent(
const struct link_resource *link_res,
struct link_training_settings *lt_settings)
{
+ (void)link_res;
enum link_training_result result = LINK_TRAINING_CR_FAIL_LANE0;
enum dc_status status;
uint32_t retries_cr = 0; /* Number of consecutive attempts with same VS or PE. */
@@ -585,6 +588,7 @@ static enum link_training_result dpia_training_eq_non_transparent(
struct link_training_settings *lt_settings,
uint32_t hop)
{
+ (void)link_res;
enum link_training_result result = LINK_TRAINING_EQ_FAIL_EQ;
uint8_t repeater_cnt = 0; /* Number of hops/repeaters in display path. */
uint32_t retries_eq = 0;
@@ -730,6 +734,7 @@ static enum link_training_result dpia_training_eq_transparent(
const struct link_resource *link_res,
struct link_training_settings *lt_settings)
{
+ (void)link_res;
enum link_training_result result = LINK_TRAINING_EQ_FAIL_EQ;
uint32_t retries_eq = 0;
enum dc_status status;
@@ -991,6 +996,7 @@ enum link_training_result dpia_perform_link_training(
const struct dc_link_settings *link_setting,
bool skip_video_pattern)
{
+ (void)skip_video_pattern;
enum link_training_result result;
struct link_training_settings lt_settings = {0};
uint8_t repeater_cnt = 0; /* Number of hops/repeaters in display path. */
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dpcd.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dpcd.c
index 584b9295a12a..e4c2aa2bc364 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dpcd.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dpcd.c
@@ -180,6 +180,7 @@ static void dpcd_reduce_address_range(
uint8_t * const reduced_data,
const uint32_t reduced_size)
{
+ (void)extended_size;
const uint32_t offset = reduced_address - extended_address;
/*
diff --git a/drivers/gpu/drm/amd/display/dc/mpc/dcn30/dcn30_mpc.c b/drivers/gpu/drm/amd/display/dc/mpc/dcn30/dcn30_mpc.c
index 6bfd2c1294e5..4c7bb0522a8c 100644
--- a/drivers/gpu/drm/amd/display/dc/mpc/dcn30/dcn30_mpc.c
+++ b/drivers/gpu/drm/amd/display/dc/mpc/dcn30/dcn30_mpc.c
@@ -117,6 +117,9 @@ void mpc3_set_out_rate_control(
bool rate_2x_mode,
struct mpc_dwb_flow_control *flow_control)
{
+ (void)enable;
+ (void)rate_2x_mode;
+ (void)flow_control;
struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
/* Always disable mpc out rate and flow control.
@@ -908,6 +911,7 @@ static void mpc3_set_3dlut_mode(
bool is_lut_size17x17x17,
uint32_t rmu_idx)
{
+ (void)is_color_channel_12bits;
uint32_t lut_mode;
struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
@@ -1428,7 +1432,7 @@ uint32_t mpcc3_acquire_rmu(struct mpc *mpc, int mpcc_id, int rmu_idx)
}
//no vacant RMU units or invalid parameters acquire_post_bldn_3dlut
- return -1;
+ return (uint32_t)-1;
}
static int mpcc3_release_rmu(struct mpc *mpc, int mpcc_id)
diff --git a/drivers/gpu/drm/amd/display/dc/mpc/dcn32/dcn32_mpc.c b/drivers/gpu/drm/amd/display/dc/mpc/dcn32/dcn32_mpc.c
index badcef027b84..1f15ada109b6 100644
--- a/drivers/gpu/drm/amd/display/dc/mpc/dcn32/dcn32_mpc.c
+++ b/drivers/gpu/drm/amd/display/dc/mpc/dcn32/dcn32_mpc.c
@@ -884,6 +884,7 @@ void mpc32_set_3dlut_mode(
bool is_lut_size17x17x17,
uint32_t mpcc_id)
{
+ (void)is_color_channel_12bits;
uint32_t lut_mode;
struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
diff --git a/drivers/gpu/drm/amd/display/dc/opp/dcn10/dcn10_opp.c b/drivers/gpu/drm/amd/display/dc/opp/dcn10/dcn10_opp.c
index 45d418636d0c..b49bd155cad4 100644
--- a/drivers/gpu/drm/amd/display/dc/opp/dcn10/dcn10_opp.c
+++ b/drivers/gpu/drm/amd/display/dc/opp/dcn10/dcn10_opp.c
@@ -250,6 +250,7 @@ void opp1_set_dyn_expansion(
enum dc_color_depth color_dpth,
enum signal_type signal)
{
+ (void)color_sp;
struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp);
REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.c
index 6f7b0f816f2a..9e66b9b97c63 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.c
@@ -164,6 +164,7 @@ void optc1_program_timing(
const enum signal_type signal,
bool use_vbios)
{
+ (void)use_vbios;
struct dc_crtc_timing patched_crtc_timing;
uint32_t asic_blank_end;
uint32_t asic_blank_start;
@@ -855,6 +856,8 @@ void optc1_set_early_control(
struct timing_generator *optc,
uint32_t early_cntl)
{
+ (void)optc;
+ (void)early_cntl;
/* asic design change, do not need this control
* empty for share caller logic
*/
@@ -1249,6 +1252,7 @@ void optc1_get_crtc_scanoutpos(
static void optc1_enable_stereo(struct timing_generator *optc,
const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags)
{
+ (void)timing;
struct optc *optc1 = DCN10TG_FROM_TG(optc);
if (flags) {
diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.c
index e7a90a437fff..39ce4d4a61a1 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.c
@@ -181,6 +181,7 @@ void optc2_set_odm_bypass(struct timing_generator *optc,
void optc2_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt,
int segment_width, int last_segment_width)
{
+ (void)last_segment_width;
struct optc *optc1 = DCN10TG_FROM_TG(optc);
uint32_t memory_mask;
@@ -261,6 +262,7 @@ static void optc2_align_vblanks(
uint8_t master_clock_divider,
uint8_t slave_clock_divider)
{
+ (void)slave_clock_divider;
/* accessing slave OTG registers */
struct optc *optc1 = DCN10TG_FROM_TG(optc_slave);
diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn30/dcn30_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn30/dcn30_optc.c
index ee4665aa49e9..d72574db1f07 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn30/dcn30_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn30/dcn30_optc.c
@@ -218,6 +218,7 @@ void optc3_set_odm_bypass(struct timing_generator *optc,
void optc3_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt,
int segment_width, int last_segment_width)
{
+ (void)last_segment_width;
struct optc *optc1 = DCN10TG_FROM_TG(optc);
uint32_t memory_mask = 0;
diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.c
index 893d2aff1f82..5f53f8747812 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.c
@@ -43,6 +43,7 @@
static void optc31_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt,
int segment_width, int last_segment_width)
{
+ (void)last_segment_width;
struct optc *optc1 = DCN10TG_FROM_TG(optc);
uint32_t memory_mask = 0;
int mem_count_per_opp = (segment_width + 2559) / 2560;
diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.c
index 43ff957288b2..a7cf34937b2f 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.c
@@ -50,6 +50,7 @@
static void optc314_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt,
int segment_width, int last_segment_width)
{
+ (void)last_segment_width;
struct optc *optc1 = DCN10TG_FROM_TG(optc);
uint32_t memory_mask = 0;
int h_active = segment_width * opp_cnt;
diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c
index 3dcb0d0c931c..60e546b69a05 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c
@@ -45,6 +45,7 @@
static void optc32_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt,
int segment_width, int last_segment_width)
{
+ (void)last_segment_width;
struct optc *optc1 = DCN10TG_FROM_TG(optc);
uint32_t memory_mask = 0;
int h_active = segment_width * opp_cnt;
diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c
index 5aafd0eedf66..a880e4a6d165 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c
@@ -58,6 +58,7 @@
static void optc35_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt,
int segment_width, int last_segment_width)
{
+ (void)last_segment_width;
struct optc *optc1 = DCN10TG_FROM_TG(optc);
uint32_t memory_mask = 0;
int h_active = segment_width * opp_cnt;
diff --git a/drivers/gpu/drm/amd/display/dc/pg/dcn42/dcn42_pg_cntl.c b/drivers/gpu/drm/amd/display/dc/pg/dcn42/dcn42_pg_cntl.c
index 3685080ce9dc..96290538a889 100644
--- a/drivers/gpu/drm/amd/display/dc/pg/dcn42/dcn42_pg_cntl.c
+++ b/drivers/gpu/drm/amd/display/dc/pg/dcn42/dcn42_pg_cntl.c
@@ -176,11 +176,12 @@ void pg_cntl42_hubp_dpp_pg_control(struct pg_cntl *pg_cntl, unsigned int hubp_dp
uint32_t pwr_status = power_on ? 0 : 2;
uint32_t org_ip_request_cntl;
bool block_enabled;
+ bool skip_pg = pg_cntl->ctx->dc->debug.ignore_pg ||
+ pg_cntl->ctx->dc->debug.disable_hubp_power_gate ||
+ pg_cntl->ctx->dc->debug.disable_dpp_power_gate ||
+ pg_cntl->ctx->dc->idle_optimizations_allowed;
- if (pg_cntl->ctx->dc->debug.ignore_pg ||
- pg_cntl->ctx->dc->debug.disable_hubp_power_gate ||
- pg_cntl->ctx->dc->debug.disable_dpp_power_gate ||
- pg_cntl->ctx->dc->idle_optimizations_allowed)
+ if (skip_pg && !power_on)
return;
block_enabled = pg_cntl42_hubp_dpp_pg_status(pg_cntl, hubp_dpp_inst);
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c
index 92c123aca0c9..caafebe92129 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c
@@ -632,6 +632,7 @@ static struct link_encoder *dce100_link_encoder_create(
struct dc_context *ctx,
const struct encoder_init_data *enc_init_data)
{
+ (void)ctx;
struct dce110_link_encoder *enc110 =
kzalloc_obj(struct dce110_link_encoder);
int link_regs_id;
@@ -650,9 +651,6 @@ static struct link_encoder *dce100_link_encoder_create(
return &enc110->base;
}
- if (enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs))
- return NULL;
-
link_regs_id =
map_transmitter_id_to_phy_instance(enc_init_data->transmitter);
@@ -661,7 +659,8 @@ static struct link_encoder *dce100_link_encoder_create(
&link_enc_feature,
&link_enc_regs[link_regs_id],
&link_enc_aux_regs[enc_init_data->channel - 1],
- &link_enc_hpd_regs[enc_init_data->hpd_source]);
+ enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs) ?
+ NULL : &link_enc_hpd_regs[enc_init_data->hpd_source]);
return &enc110->base;
}
@@ -851,6 +850,7 @@ static enum dc_status build_mapped_resource(
struct dc_state *context,
struct dc_stream_state *stream)
{
+ (void)dc;
struct pipe_ctx *pipe_ctx = resource_get_otg_master_for_stream(&context->res_ctx, stream);
if (!pipe_ctx)
@@ -868,6 +868,7 @@ enum dc_status dce100_validate_bandwidth(
struct dc_state *context,
enum dc_validate_mode validate_mode)
{
+ (void)validate_mode;
int i;
bool at_least_one_pipe = false;
struct dc_stream_state *stream = NULL;
@@ -928,6 +929,7 @@ enum dc_status dce100_validate_global(
struct dc *dc,
struct dc_state *context)
{
+ (void)dc;
if (!dce100_validate_surface_sets(context))
return DC_FAIL_SURFACE_VALIDATE;
@@ -963,6 +965,7 @@ static void dce100_destroy_resource_pool(struct resource_pool **pool)
enum dc_status dce100_validate_plane(const struct dc_plane_state *plane_state, struct dc_caps *caps)
{
+ (void)caps;
if (plane_state->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
return DC_OK;
@@ -1041,7 +1044,7 @@ static bool dce100_resource_construct(
pool->base.res_cap = &res_cap;
pool->base.funcs = &dce100_res_pool_funcs;
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE;
bp = ctx->dc_bios;
@@ -1113,7 +1116,7 @@ static bool dce100_resource_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE;
pool->base.pipe_count = res_cap.num_timing_generator;
pool->base.timing_generator_count = pool->base.res_cap->num_timing_generator;
dc->caps.max_downscale_ratio = 200;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dce110/dce110_resource.c
index 95852d277c22..f83acfe7a15e 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dce110/dce110_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dce110/dce110_resource.c
@@ -667,11 +667,12 @@ static struct link_encoder *dce110_link_encoder_create(
struct dc_context *ctx,
const struct encoder_init_data *enc_init_data)
{
+ (void)ctx;
struct dce110_link_encoder *enc110 =
kzalloc_obj(struct dce110_link_encoder);
int link_regs_id;
- if (!enc110 || enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs))
+ if (!enc110)
return NULL;
link_regs_id =
@@ -682,7 +683,8 @@ static struct link_encoder *dce110_link_encoder_create(
&link_enc_feature,
&link_enc_regs[link_regs_id],
&link_enc_aux_regs[enc_init_data->channel - 1],
- &link_enc_hpd_regs[enc_init_data->hpd_source]);
+ enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs) ?
+ NULL : &link_enc_hpd_regs[enc_init_data->hpd_source]);
return &enc110->base;
}
@@ -970,6 +972,7 @@ static enum dc_status dce110_validate_bandwidth(
struct dc_state *context,
enum dc_validate_mode validate_mode)
{
+ (void)validate_mode;
bool result = false;
DC_LOG_BANDWIDTH_CALCS(
@@ -1042,6 +1045,7 @@ static enum dc_status dce110_validate_bandwidth(
static enum dc_status dce110_validate_plane(const struct dc_plane_state *plane_state,
struct dc_caps *caps)
{
+ (void)caps;
if (((plane_state->dst_rect.width * 2) < plane_state->src_rect.width) ||
((plane_state->dst_rect.height * 2) < plane_state->src_rect.height))
return DC_FAIL_SURFACE_VALIDATE;
@@ -1098,6 +1102,7 @@ static enum dc_status dce110_validate_global(
struct dc *dc,
struct dc_state *context)
{
+ (void)dc;
if (!dce110_validate_surface_sets(context))
return DC_FAIL_SURFACE_VALIDATE;
@@ -1129,6 +1134,7 @@ static struct pipe_ctx *dce110_acquire_underlay(
const struct resource_pool *pool,
const struct pipe_ctx *opp_head_pipe)
{
+ (void)cur_ctx;
struct dc_stream_state *stream = opp_head_pipe->stream;
struct dc *dc = stream->ctx->dc;
struct dce_hwseq *hws = dc->hwseq;
@@ -1353,6 +1359,7 @@ static bool dce110_resource_construct(
struct dce110_resource_pool *pool,
struct hw_asic_id asic_id)
{
+ (void)asic_id;
unsigned int i;
struct dc_context *ctx = dc->ctx;
struct dc_bios *bp;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.c
index 58c6a00397cf..458b14e4cb97 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.c
@@ -628,11 +628,12 @@ static struct link_encoder *dce112_link_encoder_create(
struct dc_context *ctx,
const struct encoder_init_data *enc_init_data)
{
+ (void)ctx;
struct dce110_link_encoder *enc110 =
kzalloc_obj(struct dce110_link_encoder);
int link_regs_id;
- if (!enc110 || enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs))
+ if (!enc110)
return NULL;
link_regs_id =
@@ -643,7 +644,8 @@ static struct link_encoder *dce112_link_encoder_create(
&link_enc_feature,
&link_enc_regs[link_regs_id],
&link_enc_aux_regs[enc_init_data->channel - 1],
- &link_enc_hpd_regs[enc_init_data->hpd_source]);
+ enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs) ?
+ NULL : &link_enc_hpd_regs[enc_init_data->hpd_source]);
return &enc110->base;
}
@@ -851,6 +853,7 @@ static struct clock_source *find_matching_pll(
const struct resource_pool *pool,
const struct dc_stream_state *const stream)
{
+ (void)res_ctx;
switch (stream->link->link_enc->transmitter) {
case TRANSMITTER_UNIPHY_A:
return pool->clock_sources[DCE112_CLK_SRC_PLL0];
@@ -874,6 +877,7 @@ static enum dc_status build_mapped_resource(
struct dc_state *context,
struct dc_stream_state *stream)
{
+ (void)dc;
struct pipe_ctx *pipe_ctx = resource_get_otg_master_for_stream(&context->res_ctx, stream);
if (!pipe_ctx)
@@ -891,6 +895,7 @@ enum dc_status dce112_validate_bandwidth(
struct dc_state *context,
enum dc_validate_mode validate_mode)
{
+ (void)validate_mode;
bool result = false;
DC_LOG_BANDWIDTH_CALCS(
@@ -1036,6 +1041,7 @@ static enum dc_status dce112_validate_global(
struct dc *dc,
struct dc_state *context)
{
+ (void)dc;
if (!dce112_validate_surface_sets(context))
return DC_FAIL_SURFACE_VALIDATE;
@@ -1239,7 +1245,7 @@ static bool dce112_resource_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE;
pool->base.pipe_count = pool->base.res_cap->num_timing_generator;
pool->base.timing_generator_count = pool->base.res_cap->num_timing_generator;
dc->caps.max_downscale_ratio = 200;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dce120/dce120_resource.c
index 71d76b021375..56bbf9dc1691 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dce120/dce120_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dce120/dce120_resource.c
@@ -712,11 +712,12 @@ static struct link_encoder *dce120_link_encoder_create(
struct dc_context *ctx,
const struct encoder_init_data *enc_init_data)
{
+ (void)ctx;
struct dce110_link_encoder *enc110 =
kzalloc_obj(struct dce110_link_encoder);
int link_regs_id;
- if (!enc110 || enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs))
+ if (!enc110)
return NULL;
link_regs_id =
@@ -727,7 +728,8 @@ static struct link_encoder *dce120_link_encoder_create(
&link_enc_feature,
&link_enc_regs[link_regs_id],
&link_enc_aux_regs[enc_init_data->channel - 1],
- &link_enc_hpd_regs[enc_init_data->hpd_source]);
+ enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs) ?
+ NULL : &link_enc_hpd_regs[enc_init_data->hpd_source]);
return &enc110->base;
}
@@ -1080,7 +1082,7 @@ static bool dce120_resource_construct(
/* TODO: Fill more data from GreenlandAsicCapability.cpp */
pool->base.pipe_count = res_cap.num_timing_generator;
pool->base.timing_generator_count = pool->base.res_cap->num_timing_generator;
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE;
dc->caps.max_downscale_ratio = 200;
dc->caps.i2c_speed_in_khz = 100;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dce60/dce60_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dce60/dce60_resource.c
index a57d68427812..6a25dcfcdf17 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dce60/dce60_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dce60/dce60_resource.c
@@ -746,18 +746,16 @@ static struct link_encoder *dce60_link_encoder_create(
return &enc110->base;
}
- if (enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs))
- return NULL;
-
link_regs_id =
map_transmitter_id_to_phy_instance(enc_init_data->transmitter);
dce60_link_encoder_construct(enc110,
- enc_init_data,
- &link_enc_feature,
- &link_enc_regs[link_regs_id],
- &link_enc_aux_regs[enc_init_data->channel - 1],
- &link_enc_hpd_regs[enc_init_data->hpd_source]);
+ enc_init_data,
+ &link_enc_feature,
+ &link_enc_regs[link_regs_id],
+ &link_enc_aux_regs[enc_init_data->channel - 1],
+ enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs) ?
+ NULL : &link_enc_hpd_regs[enc_init_data->hpd_source]);
return &enc110->base;
}
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dce80/dce80_resource.c
index d66d8ac6d897..33be49b3c1b1 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dce80/dce80_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dce80/dce80_resource.c
@@ -734,6 +734,7 @@ static struct link_encoder *dce80_link_encoder_create(
struct dc_context *ctx,
const struct encoder_init_data *enc_init_data)
{
+ (void)ctx;
struct dce110_link_encoder *enc110 =
kzalloc_obj(struct dce110_link_encoder);
int link_regs_id;
@@ -752,9 +753,6 @@ static struct link_encoder *dce80_link_encoder_create(
return &enc110->base;
}
- if (enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs))
- return NULL;
-
link_regs_id =
map_transmitter_id_to_phy_instance(enc_init_data->transmitter);
@@ -763,7 +761,8 @@ static struct link_encoder *dce80_link_encoder_create(
&link_enc_feature,
&link_enc_regs[link_regs_id],
&link_enc_aux_regs[enc_init_data->channel - 1],
- &link_enc_hpd_regs[enc_init_data->hpd_source]);
+ enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs) ?
+ NULL : &link_enc_hpd_regs[enc_init_data->hpd_source]);
return &enc110->base;
}
@@ -936,7 +935,7 @@ static bool dce80_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE;
pool->base.pipe_count = res_cap.num_timing_generator;
pool->base.timing_generator_count = res_cap.num_timing_generator;
dc->caps.max_downscale_ratio = 200;
@@ -1139,7 +1138,7 @@ static bool dce81_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE;
pool->base.pipe_count = res_cap_81.num_timing_generator;
pool->base.timing_generator_count = res_cap_81.num_timing_generator;
dc->caps.max_downscale_ratio = 200;
@@ -1339,7 +1338,7 @@ static bool dce83_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE;
pool->base.pipe_count = res_cap_83.num_timing_generator;
pool->base.timing_generator_count = res_cap_83.num_timing_generator;
dc->caps.max_downscale_ratio = 200;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.c
index bbe185e15eb6..0fdebe63d355 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.c
@@ -71,6 +71,7 @@
#include "dce/dce_dmcu.h"
#include "dce/dce_aux.h"
#include "dce/dce_i2c.h"
+#include "dio/dcn10/dcn10_dio.h"
#ifndef mmDP0_DP_DPHY_INTERNAL_CTRL
#define mmDP0_DP_DPHY_INTERNAL_CTRL 0x210f
@@ -444,6 +445,33 @@ static const struct dcn_hubbub_mask hubbub_mask = {
HUBBUB_MASK_SH_LIST_DCN10(_MASK)
};
+static const struct dcn_dio_registers dio_regs = {
+ DIO_REG_LIST_DCN10()
+};
+
+#define DIO_MASK_SH_LIST(mask_sh)\
+ HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
+
+static const struct dcn_dio_shift dio_shift = {
+ DIO_MASK_SH_LIST(__SHIFT)
+};
+
+static const struct dcn_dio_mask dio_mask = {
+ DIO_MASK_SH_LIST(_MASK)
+};
+
+static struct dio *dcn10_dio_create(struct dc_context *ctx)
+{
+ struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
+
+ if (!dio10)
+ return NULL;
+
+ dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
+
+ return &dio10->base;
+}
+
static int map_transmitter_id_to_phy_instance(
enum transmitter transmitter)
{
@@ -736,6 +764,7 @@ static struct link_encoder *dcn10_link_encoder_create(
struct dc_context *ctx,
const struct encoder_init_data *enc_init_data)
{
+ (void)ctx;
struct dcn10_link_encoder *enc10 =
kzalloc_obj(struct dcn10_link_encoder);
int link_regs_id;
@@ -917,6 +946,11 @@ static void dcn10_resource_destruct(struct dcn10_resource_pool *pool)
kfree(pool->base.hubbub);
pool->base.hubbub = NULL;
+ if (pool->base.dio != NULL) {
+ kfree(TO_DCN10_DIO(pool->base.dio));
+ pool->base.dio = NULL;
+ }
+
for (i = 0; i < pool->base.pipe_count; i++) {
if (pool->base.opps[i] != NULL)
pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]);
@@ -1049,6 +1083,7 @@ static enum dc_status build_mapped_resource(
struct dc_state *context,
struct dc_stream_state *stream)
{
+ (void)dc;
struct pipe_ctx *pipe_ctx = resource_get_otg_master_for_stream(&context->res_ctx, stream);
if (!pipe_ctx)
@@ -1083,6 +1118,7 @@ static struct pipe_ctx *dcn10_acquire_free_pipe_for_layer(
const struct resource_pool *pool,
const struct pipe_ctx *opp_head_pipe)
{
+ (void)cur_ctx;
struct resource_context *res_ctx = &new_ctx->res_ctx;
struct pipe_ctx *head_pipe = resource_get_otg_master_for_stream(res_ctx, opp_head_pipe->stream);
struct pipe_ctx *idle_pipe = resource_find_free_secondary_pipe_legacy(res_ctx, pool, head_pipe);
@@ -1273,6 +1309,12 @@ static const struct dc_cap_funcs cap_funcs = {
.get_dcc_compression_cap = dcn10_get_dcc_compression_cap
};
+void dcn10_get_default_tiling_info(struct dc_tiling_info *tiling_info)
+{
+ tiling_info->gfxversion = DcGfxVersion9;
+ tiling_info->gfx9.swizzle = DC_SW_LINEAR;
+}
+
static const struct resource_funcs dcn10_res_pool_funcs = {
.destroy = dcn10_destroy_resource_pool,
.link_enc_create = dcn10_link_encoder_create,
@@ -1284,7 +1326,8 @@ static const struct resource_funcs dcn10_res_pool_funcs = {
.add_stream_to_ctx = dcn10_add_stream_to_ctx,
.patch_unknown_plane_state = dcn10_patch_unknown_plane_state,
.find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link,
- .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe
+ .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe,
+ .get_default_tiling_info = dcn10_get_default_tiling_info
};
static uint32_t read_pipe_fuses(struct dc_context *ctx)
@@ -1339,7 +1382,7 @@ static bool dcn10_resource_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE;
/* max pipe num for ASIC before check pipe fuses */
pool->base.pipe_count = pool->base.res_cap->num_timing_generator;
@@ -1653,6 +1696,14 @@ static bool dcn10_resource_construct(
goto fail;
}
+ /* DIO */
+ pool->base.dio = dcn10_dio_create(ctx);
+ if (pool->base.dio == NULL) {
+ BREAK_TO_DEBUGGER();
+ dm_error("DC: failed to create dio!\n");
+ goto fail;
+ }
+
if (!resource_construct(num_virtual_links, dc, &pool->base,
&res_create_funcs))
goto fail;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.h
index 7bc1be53e800..c7409298caa9 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.h
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.h
@@ -53,5 +53,7 @@ struct stream_encoder *dcn10_find_first_free_match_stream_enc_for_link(
unsigned int dcn10_get_vstartup_for_pipe(struct pipe_ctx *pipe_ctx);
+void dcn10_get_default_tiling_info(struct dc_tiling_info *tiling_info);
+
#endif /* __DC_RESOURCE_DCN10_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c
index 366576b1c617..a99829f23965 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c
@@ -82,6 +82,7 @@
#include "dce/dce_dmcu.h"
#include "dce/dce_aux.h"
#include "dce/dce_i2c.h"
+#include "dio/dcn10/dcn10_dio.h"
#include "vm_helper.h"
#include "link_enc_cfg.h"
@@ -550,6 +551,33 @@ static const struct dcn_hubbub_mask hubbub_mask = {
HUBBUB_MASK_SH_LIST_DCN20(_MASK)
};
+static const struct dcn_dio_registers dio_regs = {
+ DIO_REG_LIST_DCN10()
+};
+
+#define DIO_MASK_SH_LIST(mask_sh)\
+ HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
+
+static const struct dcn_dio_shift dio_shift = {
+ DIO_MASK_SH_LIST(__SHIFT)
+};
+
+static const struct dcn_dio_mask dio_mask = {
+ DIO_MASK_SH_LIST(_MASK)
+};
+
+static struct dio *dcn20_dio_create(struct dc_context *ctx)
+{
+ struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
+
+ if (!dio10)
+ return NULL;
+
+ dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
+
+ return &dio10->base;
+}
+
#define vmid_regs(id)\
[id] = {\
DCN20_VMID_REG_LIST(id)\
@@ -916,6 +944,7 @@ struct link_encoder *dcn20_link_encoder_create(
struct dc_context *ctx,
const struct encoder_init_data *enc_init_data)
{
+ (void)ctx;
struct dcn20_link_encoder *enc20 =
kzalloc_obj(struct dcn20_link_encoder);
int link_regs_id;
@@ -1104,6 +1133,12 @@ static void dcn20_resource_destruct(struct dcn20_resource_pool *pool)
kfree(pool->base.hubbub);
pool->base.hubbub = NULL;
}
+
+ if (pool->base.dio != NULL) {
+ kfree(TO_DCN10_DIO(pool->base.dio));
+ pool->base.dio = NULL;
+ }
+
for (i = 0; i < pool->base.pipe_count; i++) {
if (pool->base.dpps[i] != NULL)
dcn20_dpp_destroy(&pool->base.dpps[i]);
@@ -1310,6 +1345,7 @@ static enum dc_status build_pipe_hw_param(struct pipe_ctx *pipe_ctx)
enum dc_status dcn20_build_mapped_resource(const struct dc *dc, struct dc_state *context, struct dc_stream_state *stream)
{
+ (void)dc;
enum dc_status status = DC_OK;
struct pipe_ctx *pipe_ctx = resource_get_otg_master_for_stream(&context->res_ctx, stream);
@@ -1537,6 +1573,7 @@ void dcn20_split_stream_for_mpc(
struct pipe_ctx *primary_pipe,
struct pipe_ctx *secondary_pipe)
{
+ (void)res_ctx;
int pipe_idx = secondary_pipe->pipe_idx;
struct pipe_ctx *sec_bot_pipe = secondary_pipe->bottom_pipe;
@@ -1682,6 +1719,7 @@ struct pipe_ctx *dcn20_find_secondary_pipe(struct dc *dc,
const struct resource_pool *pool,
const struct pipe_ctx *primary_pipe)
{
+ (void)pool;
struct pipe_ctx *secondary_pipe = NULL;
if (dc && primary_pipe) {
@@ -1814,6 +1852,11 @@ void dcn20_merge_pipes_for_validate(
}
}
+static bool is_dual_plane(enum surface_pixel_format format)
+{
+ return format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN || format == SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA;
+}
+
int dcn20_validate_apply_pipe_split_flags(
struct dc *dc,
struct dc_state *context,
@@ -1898,8 +1941,15 @@ int dcn20_validate_apply_pipe_split_flags(
for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
int pipe_plane = v->pipe_plane[pipe_idx];
- bool split4mpc = context->stream_count == 1 && plane_count == 1
- && dc->config.enable_4to1MPC && dc->res_pool->pipe_count >= 4;
+ bool split4mpc = false;
+
+ if (context->stream_count == 1 && plane_count == 1
+ && dc->config.allow_4to1MPC && dc->res_pool->pipe_count >= 4
+ && !dc->debug.disable_z9_mpc
+ && pipe->plane_state && is_dual_plane(pipe->plane_state->format)
+ && pipe->plane_state->src_rect.width <= 1920
+ && pipe->plane_state->src_rect.height <= 1080)
+ split4mpc = true;
if (!context->res_ctx.pipe_ctx[i].stream)
continue;
@@ -2149,6 +2199,7 @@ struct pipe_ctx *dcn20_acquire_free_pipe_for_layer(
const struct resource_pool *pool,
const struct pipe_ctx *opp_head)
{
+ (void)cur_ctx;
struct resource_context *res_ctx = &new_ctx->res_ctx;
struct pipe_ctx *otg_master = resource_get_otg_master_for_stream(res_ctx, opp_head->stream);
struct pipe_ctx *sec_dpp_pipe = resource_find_free_secondary_pipe_legacy(res_ctx, pool, otg_master);
@@ -2232,7 +2283,8 @@ static const struct resource_funcs dcn20_res_pool_funcs = {
.set_mcif_arb_params = dcn20_set_mcif_arb_params,
.populate_dml_pipes = dcn20_populate_dml_pipes_from_context,
.find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link,
- .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe
+ .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe,
+ .get_default_tiling_info = dcn10_get_default_tiling_info
};
bool dcn20_dwbc_create(struct dc_context *ctx, struct resource_pool *pool)
@@ -2330,6 +2382,7 @@ static struct _vcs_dpi_ip_params_st *get_asic_rev_ip_params(
static enum dml_project get_dml_project_version(uint32_t hw_internal_rev)
{
+ (void)hw_internal_rev;
return DML_PROJECT_NAVI10v2;
}
@@ -2416,7 +2469,7 @@ static bool dcn20_resource_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE;
dc->caps.max_downscale_ratio = 200;
dc->caps.i2c_speed_in_khz = 100;
@@ -2690,6 +2743,14 @@ static bool dcn20_resource_construct(
goto create_fail;
}
+ /* DIO */
+ pool->base.dio = dcn20_dio_create(ctx);
+ if (pool->base.dio == NULL) {
+ BREAK_TO_DEBUGGER();
+ dm_error("DC: failed to create dio!\n");
+ goto create_fail;
+ }
+
for (i = 0; i < pool->base.res_cap->num_dsc; i++) {
pool->base.dscs[i] = dcn20_dsc_create(ctx, i);
if (pool->base.dscs[i] == NULL) {
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c
index 4ea76e46ab15..02b7dc07ad53 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c
@@ -56,6 +56,7 @@
#include "dce/dce_aux.h"
#include "dce/dce_i2c.h"
#include "dcn10/dcn10_resource.h"
+#include "dio/dcn10/dcn10_dio.h"
#include "cyan_skillfish_ip_offset.h"
@@ -755,6 +756,33 @@ static struct hubbub *dcn201_hubbub_create(struct dc_context *ctx)
return &hubbub->base;
}
+static const struct dcn_dio_registers dio_regs = {
+ DIO_REG_LIST_DCN10()
+};
+
+#define DIO_MASK_SH_LIST(mask_sh)\
+ HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
+
+static const struct dcn_dio_shift dio_shift = {
+ DIO_MASK_SH_LIST(__SHIFT)
+};
+
+static const struct dcn_dio_mask dio_mask = {
+ DIO_MASK_SH_LIST(_MASK)
+};
+
+static struct dio *dcn201_dio_create(struct dc_context *ctx)
+{
+ struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
+
+ if (!dio10)
+ return NULL;
+
+ dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
+
+ return &dio10->base;
+}
+
static struct timing_generator *dcn201_timing_generator_create(
struct dc_context *ctx,
uint32_t instance)
@@ -930,6 +958,11 @@ static void dcn201_resource_destruct(struct dcn201_resource_pool *pool)
pool->base.hubbub = NULL;
}
+ if (pool->base.dio != NULL) {
+ kfree(TO_DCN10_DIO(pool->base.dio));
+ pool->base.dio = NULL;
+ }
+
for (i = 0; i < pool->base.pipe_count; i++) {
if (pool->base.dpps[i] != NULL)
dcn201_dpp_destroy(&pool->base.dpps[i]);
@@ -1081,7 +1114,8 @@ static struct resource_funcs dcn201_res_pool_funcs = {
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
.set_mcif_arb_params = dcn20_set_mcif_arb_params,
.find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link,
- .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe
+ .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe,
+ .get_default_tiling_info = dcn10_get_default_tiling_info
};
static bool dcn201_resource_construct(
@@ -1276,6 +1310,14 @@ static bool dcn201_resource_construct(
goto create_fail;
}
+ /* DIO */
+ pool->base.dio = dcn201_dio_create(ctx);
+ if (pool->base.dio == NULL) {
+ BREAK_TO_DEBUGGER();
+ dm_error("DC: failed to create dio!\n");
+ goto create_fail;
+ }
+
if (!resource_construct(num_virtual_links, dc, &pool->base,
&res_create_funcs))
goto create_fail;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c
index 0f4307f8f3dd..54ebf8cf607f 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c
@@ -84,6 +84,7 @@
#include "dce/dce_dmcu.h"
#include "dce/dce_aux.h"
#include "dce/dce_i2c.h"
+#include "dio/dcn10/dcn10_dio.h"
#include "dcn21_resource.h"
#include "vm_helper.h"
#include "dcn20/dcn20_vmid.h"
@@ -329,6 +330,25 @@ static const struct dcn_hubbub_mask hubbub_mask = {
HUBBUB_MASK_SH_LIST_DCN21(_MASK)
};
+static const struct dcn_dio_registers dio_regs = {
+ DIO_REG_LIST_DCN10()
+};
+
+static const struct dcn_dio_shift dio_shift = { 0 };
+
+static const struct dcn_dio_mask dio_mask = { 0 };
+
+static struct dio *dcn21_dio_create(struct dc_context *ctx)
+{
+ struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
+
+ if (!dio10)
+ return NULL;
+
+ dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
+
+ return &dio10->base;
+}
#define vmid_regs(id)\
[id] = {\
@@ -677,6 +697,12 @@ static void dcn21_resource_destruct(struct dcn21_resource_pool *pool)
kfree(pool->base.hubbub);
pool->base.hubbub = NULL;
}
+
+ if (pool->base.dio != NULL) {
+ kfree(TO_DCN10_DIO(pool->base.dio));
+ pool->base.dio = NULL;
+ }
+
for (i = 0; i < pool->base.pipe_count; i++) {
if (pool->base.dpps[i] != NULL)
dcn20_dpp_destroy(&pool->base.dpps[i]);
@@ -772,7 +798,8 @@ bool dcn21_fast_validate_bw(struct dc *dc,
int *pipe_cnt_out,
int *pipe_split_from,
int *vlevel_out,
- enum dc_validate_mode validate_mode)
+ enum dc_validate_mode validate_mode,
+ bool allow_self_refresh_only)
{
bool out = false;
int split[MAX_PIPES] = { 0 };
@@ -803,18 +830,23 @@ bool dcn21_fast_validate_bw(struct dc *dc,
vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt);
if (vlevel > context->bw_ctx.dml.soc.num_states) {
- /*
- * If mode is unsupported or there's still no p-state support then
- * fall back to favoring voltage.
- *
- * We don't actually support prefetch mode 2, so require that we
- * at least support prefetch mode 1.
- */
- context->bw_ctx.dml.soc.allow_dram_self_refresh_or_dram_clock_change_in_vblank =
- dm_allow_self_refresh;
- vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt);
- if (vlevel > context->bw_ctx.dml.soc.num_states)
+
+ if (allow_self_refresh_only) {
+ /*
+ * If mode is unsupported or there's still no p-state support then
+ * fall back to favoring voltage.
+ *
+ * We don't actually support prefetch mode 2, so require that we
+ * at least support prefetch mode 1.
+ */
+ context->bw_ctx.dml.soc.allow_dram_self_refresh_or_dram_clock_change_in_vblank =
+ dm_allow_self_refresh;
+ vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt);
+ if (vlevel > context->bw_ctx.dml.soc.num_states)
+ goto validate_fail;
+ } else {
goto validate_fail;
+ }
}
vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, vlevel, split, merge);
@@ -1293,6 +1325,7 @@ static struct link_encoder *dcn21_link_encoder_create(
struct dc_context *ctx,
const struct encoder_init_data *enc_init_data)
{
+ (void)ctx;
struct dcn21_link_encoder *enc21 =
kzalloc_obj(struct dcn21_link_encoder);
int link_regs_id;
@@ -1378,7 +1411,8 @@ static const struct resource_funcs dcn21_res_pool_funcs = {
.find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link,
.update_bw_bounding_box = dcn21_update_bw_bounding_box,
.get_panel_config_defaults = dcn21_get_panel_config_defaults,
- .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe
+ .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe,
+ .get_default_tiling_info = dcn10_get_default_tiling_info
};
static bool dcn21_resource_construct(
@@ -1401,7 +1435,7 @@ static bool dcn21_resource_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE;
/* max pipe num for ASIC before check pipe fuses */
pool->base.pipe_count = pool->base.res_cap->num_timing_generator;
@@ -1654,6 +1688,14 @@ static bool dcn21_resource_construct(
goto create_fail;
}
+ /* DIO */
+ pool->base.dio = dcn21_dio_create(ctx);
+ if (pool->base.dio == NULL) {
+ BREAK_TO_DEBUGGER();
+ dm_error("DC: failed to create dio!\n");
+ goto create_fail;
+ }
+
for (i = 0; i < pool->base.res_cap->num_dsc; i++) {
pool->base.dscs[i] = dcn21_dsc_create(ctx, i);
if (pool->base.dscs[i] == NULL) {
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.h
index a017fd9854d1..23d3a36872bb 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.h
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.h
@@ -51,6 +51,7 @@ bool dcn21_fast_validate_bw(
int *pipe_cnt_out,
int *pipe_split_from,
int *vlevel_out,
- enum dc_validate_mode validate_mode);
+ enum dc_validate_mode validate_mode,
+ bool allow_self_refresh_only);
#endif /* _DCN21_RESOURCE_H_ */
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c
index 2fa86b9587ed..4a864689c44f 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c
@@ -60,6 +60,7 @@
#include "dml/display_mode_vba.h"
#include "dcn30/dcn30_dccg.h"
#include "dcn10/dcn10_resource.h"
+#include "dio/dcn10/dcn10_dio.h"
#include "link_service.h"
#include "dce/dce_panel_cntl.h"
@@ -886,6 +887,33 @@ static struct hubbub *dcn30_hubbub_create(struct dc_context *ctx)
return &hubbub3->base;
}
+static const struct dcn_dio_registers dio_regs = {
+ DIO_REG_LIST_DCN10()
+};
+
+#define DIO_MASK_SH_LIST(mask_sh)\
+ HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
+
+static const struct dcn_dio_shift dio_shift = {
+ DIO_MASK_SH_LIST(__SHIFT)
+};
+
+static const struct dcn_dio_mask dio_mask = {
+ DIO_MASK_SH_LIST(_MASK)
+};
+
+static struct dio *dcn30_dio_create(struct dc_context *ctx)
+{
+ struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
+
+ if (!dio10)
+ return NULL;
+
+ dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
+
+ return &dio10->base;
+}
+
static struct timing_generator *dcn30_timing_generator_create(
struct dc_context *ctx,
uint32_t instance)
@@ -924,6 +952,7 @@ static struct link_encoder *dcn30_link_encoder_create(
struct dc_context *ctx,
const struct encoder_init_data *enc_init_data)
{
+ (void)ctx;
struct dcn20_link_encoder *enc20 =
kzalloc_obj(struct dcn20_link_encoder);
@@ -1095,6 +1124,12 @@ static void dcn30_resource_destruct(struct dcn30_resource_pool *pool)
kfree(pool->base.hubbub);
pool->base.hubbub = NULL;
}
+
+ if (pool->base.dio != NULL) {
+ kfree(TO_DCN10_DIO(pool->base.dio));
+ pool->base.dio = NULL;
+ }
+
for (i = 0; i < pool->base.pipe_count; i++) {
if (pool->base.dpps[i] != NULL)
dcn30_dpp_destroy(&pool->base.dpps[i]);
@@ -1641,6 +1676,8 @@ noinline bool dcn30_internal_validate_bw(
if (!pipes)
return false;
+ dcn20_merge_pipes_for_validate(dc, context);
+
context->bw_ctx.dml.vba.maxMpcComb = 0;
context->bw_ctx.dml.vba.VoltageLevel = 0;
context->bw_ctx.dml.vba.DRAMClockChangeSupport[0][0] = dm_dram_clock_change_vactive;
@@ -2248,7 +2285,8 @@ static const struct resource_funcs dcn30_res_pool_funcs = {
.update_bw_bounding_box = dcn30_update_bw_bounding_box,
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
.get_panel_config_defaults = dcn30_get_panel_config_defaults,
- .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe
+ .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe,
+ .get_default_tiling_info = dcn10_get_default_tiling_info
};
#define CTX ctx
@@ -2294,7 +2332,7 @@ static bool dcn30_resource_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)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;
@@ -2464,6 +2502,14 @@ static bool dcn30_resource_construct(
goto create_fail;
}
+ /* DIO */
+ pool->base.dio = dcn30_dio_create(ctx);
+ if (pool->base.dio == NULL) {
+ BREAK_TO_DEBUGGER();
+ dm_error("DC: failed to create dio!\n");
+ goto create_fail;
+ }
+
/* HUBPs, DPPs, OPPs and TGs */
for (i = 0; i < pool->base.pipe_count; i++) {
pool->base.hubps[i] = dcn30_hubp_create(ctx, i);
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn301/dcn301_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn301/dcn301_resource.c
index 7842bee57e63..a74b150cbe9c 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn301/dcn301_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn301/dcn301_resource.c
@@ -59,6 +59,7 @@
#include "dml/display_mode_vba.h"
#include "dcn301/dcn301_dccg.h"
#include "dcn10/dcn10_resource.h"
+#include "dio/dcn10/dcn10_dio.h"
#include "dcn30/dcn30_dio_stream_encoder.h"
#include "dcn301/dcn301_dio_link_encoder.h"
#include "dcn301/dcn301_panel_cntl.h"
@@ -843,6 +844,33 @@ static struct hubbub *dcn301_hubbub_create(struct dc_context *ctx)
return &hubbub3->base;
}
+static const struct dcn_dio_registers dio_regs = {
+ DIO_REG_LIST_DCN10()
+};
+
+#define DIO_MASK_SH_LIST(mask_sh)\
+ HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
+
+static const struct dcn_dio_shift dio_shift = {
+ DIO_MASK_SH_LIST(__SHIFT)
+};
+
+static const struct dcn_dio_mask dio_mask = {
+ DIO_MASK_SH_LIST(_MASK)
+};
+
+static struct dio *dcn301_dio_create(struct dc_context *ctx)
+{
+ struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
+
+ if (!dio10)
+ return NULL;
+
+ dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
+
+ return &dio10->base;
+}
+
static struct timing_generator *dcn301_timing_generator_create(
struct dc_context *ctx, uint32_t instance)
{
@@ -880,6 +908,7 @@ static struct link_encoder *dcn301_link_encoder_create(
struct dc_context *ctx,
const struct encoder_init_data *enc_init_data)
{
+ (void)ctx;
struct dcn20_link_encoder *enc20 =
kzalloc_obj(struct dcn20_link_encoder);
@@ -1066,6 +1095,12 @@ static void dcn301_destruct(struct dcn301_resource_pool *pool)
kfree(pool->base.hubbub);
pool->base.hubbub = NULL;
}
+
+ if (pool->base.dio != NULL) {
+ kfree(TO_DCN10_DIO(pool->base.dio));
+ pool->base.dio = NULL;
+ }
+
for (i = 0; i < pool->base.pipe_count; i++) {
if (pool->base.dpps[i] != NULL)
dcn301_dpp_destroy(&pool->base.dpps[i]);
@@ -1400,7 +1435,8 @@ static struct resource_funcs dcn301_res_pool_funcs = {
.release_post_bldn_3dlut = dcn30_release_post_bldn_3dlut,
.update_bw_bounding_box = dcn301_update_bw_bounding_box,
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
- .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe
+ .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe,
+ .get_default_tiling_info = dcn10_get_default_tiling_info,
};
static bool dcn301_resource_construct(
@@ -1427,7 +1463,7 @@ static bool dcn301_resource_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)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;
@@ -1582,6 +1618,14 @@ static bool dcn301_resource_construct(
goto create_fail;
}
+ /* DIO */
+ pool->base.dio = dcn301_dio_create(ctx);
+ if (pool->base.dio == NULL) {
+ BREAK_TO_DEBUGGER();
+ dm_error("DC: failed to create dio!\n");
+ goto create_fail;
+ }
+
j = 0;
/* HUBPs, DPPs, OPPs and TGs */
for (i = 0; i < pool->base.pipe_count; i++) {
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c
index 1874d5d6b782..539c5aa6bffa 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c
@@ -46,6 +46,7 @@
#include "dml/dcn30/dcn30_fpu.h"
#include "dcn10/dcn10_resource.h"
+#include "dio/dcn10/dcn10_dio.h"
#include "link_service.h"
@@ -253,6 +254,33 @@ static const struct dcn20_vmid_mask vmid_masks = {
DCN20_VMID_MASK_SH_LIST(_MASK)
};
+static const struct dcn_dio_registers dio_regs = {
+ DIO_REG_LIST_DCN10()
+};
+
+#define DIO_MASK_SH_LIST(mask_sh)\
+ HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
+
+static const struct dcn_dio_shift dio_shift = {
+ DIO_MASK_SH_LIST(__SHIFT)
+};
+
+static const struct dcn_dio_mask dio_mask = {
+ DIO_MASK_SH_LIST(_MASK)
+};
+
+static struct dio *dcn302_dio_create(struct dc_context *ctx)
+{
+ struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
+
+ if (!dio10)
+ return NULL;
+
+ dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
+
+ return &dio10->base;
+}
+
static struct hubbub *dcn302_hubbub_create(struct dc_context *ctx)
{
int i;
@@ -894,6 +922,7 @@ static struct link_encoder *dcn302_link_encoder_create(
struct dc_context *ctx,
const struct encoder_init_data *enc_init_data)
{
+ (void)ctx;
struct dcn20_link_encoder *enc20 = kzalloc_obj(struct dcn20_link_encoder);
if (!enc20 || enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs))
@@ -1022,6 +1051,11 @@ static void dcn302_resource_destruct(struct resource_pool *pool)
pool->hubbub = NULL;
}
+ if (pool->dio != NULL) {
+ kfree(TO_DCN10_DIO(pool->dio));
+ pool->dio = NULL;
+ }
+
for (i = 0; i < pool->pipe_count; i++) {
if (pool->dpps[i] != NULL) {
kfree(TO_DCN20_DPP(pool->dpps[i]));
@@ -1155,7 +1189,8 @@ static struct resource_funcs dcn302_res_pool_funcs = {
.update_bw_bounding_box = dcn302_update_bw_bounding_box,
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
.get_panel_config_defaults = dcn302_get_panel_config_defaults,
- .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe
+ .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe,
+ .get_default_tiling_info = dcn10_get_default_tiling_info
};
static struct dc_cap_funcs cap_funcs = {
@@ -1217,7 +1252,7 @@ static bool dcn302_resource_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE;
pool->pipe_count = pool->res_cap->num_timing_generator;
pool->mpcc_count = pool->res_cap->num_timing_generator;
dc->caps.max_downscale_ratio = 600;
@@ -1372,6 +1407,14 @@ static bool dcn302_resource_construct(
goto create_fail;
}
+ /* DIO */
+ pool->dio = dcn302_dio_create(ctx);
+ if (pool->dio == NULL) {
+ BREAK_TO_DEBUGGER();
+ dm_error("DC: failed to create dio!\n");
+ goto create_fail;
+ }
+
/* HUBPs, DPPs, OPPs and TGs */
for (i = 0; i < pool->pipe_count; i++) {
pool->hubps[i] = dcn302_hubp_create(ctx, i);
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c
index d52201cb359f..529eccb4ed3b 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c
@@ -46,6 +46,7 @@
#include "dml/dcn30/dcn30_fpu.h"
#include "dcn10/dcn10_resource.h"
+#include "dio/dcn10/dcn10_dio.h"
#include "link_service.h"
@@ -249,6 +250,33 @@ static const struct dcn20_vmid_mask vmid_masks = {
DCN20_VMID_MASK_SH_LIST(_MASK)
};
+static const struct dcn_dio_registers dio_regs = {
+ DIO_REG_LIST_DCN10()
+};
+
+#define DIO_MASK_SH_LIST(mask_sh)\
+ HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
+
+static const struct dcn_dio_shift dio_shift = {
+ DIO_MASK_SH_LIST(__SHIFT)
+};
+
+static const struct dcn_dio_mask dio_mask = {
+ DIO_MASK_SH_LIST(_MASK)
+};
+
+static struct dio *dcn303_dio_create(struct dc_context *ctx)
+{
+ struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
+
+ if (!dio10)
+ return NULL;
+
+ dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
+
+ return &dio10->base;
+}
+
static struct hubbub *dcn303_hubbub_create(struct dc_context *ctx)
{
int i;
@@ -839,6 +867,7 @@ static struct link_encoder *dcn303_link_encoder_create(
struct dc_context *ctx,
const struct encoder_init_data *enc_init_data)
{
+ (void)ctx;
struct dcn20_link_encoder *enc20 = kzalloc_obj(struct dcn20_link_encoder);
if (!enc20 || enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs))
@@ -966,6 +995,11 @@ static void dcn303_resource_destruct(struct resource_pool *pool)
pool->hubbub = NULL;
}
+ if (pool->dio != NULL) {
+ kfree(TO_DCN10_DIO(pool->dio));
+ pool->dio = NULL;
+ }
+
for (i = 0; i < pool->pipe_count; i++) {
if (pool->dpps[i] != NULL) {
kfree(TO_DCN20_DPP(pool->dpps[i]));
@@ -1099,7 +1133,8 @@ static struct resource_funcs dcn303_res_pool_funcs = {
.update_bw_bounding_box = dcn303_update_bw_bounding_box,
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
.get_panel_config_defaults = dcn303_get_panel_config_defaults,
- .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe
+ .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe,
+ .get_default_tiling_info = dcn10_get_default_tiling_info
};
static struct dc_cap_funcs cap_funcs = {
@@ -1158,7 +1193,7 @@ static bool dcn303_resource_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE;
pool->pipe_count = pool->res_cap->num_timing_generator;
pool->mpcc_count = pool->res_cap->num_timing_generator;
dc->caps.max_downscale_ratio = 600;
@@ -1304,6 +1339,14 @@ static bool dcn303_resource_construct(
goto create_fail;
}
+ /* DIO */
+ pool->dio = dcn303_dio_create(ctx);
+ if (pool->dio == NULL) {
+ BREAK_TO_DEBUGGER();
+ dm_error("DC: failed to create dio!\n");
+ goto create_fail;
+ }
+
/* HUBPs, DPPs, OPPs and TGs */
for (i = 0; i < pool->pipe_count; i++) {
pool->hubps[i] = dcn303_hubp_create(ctx, i);
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c
index 2055f1f8af65..ee4bc2c2e73a 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c
@@ -64,6 +64,7 @@
#include "dce/dce_audio.h"
#include "dce/dce_hwseq.h"
#include "clk_mgr.h"
+#include "dio/dcn10/dcn10_dio.h"
#include "dio/virtual/virtual_stream_encoder.h"
#include "dce110/dce110_resource.h"
#include "dml/display_mode_vba.h"
@@ -810,6 +811,21 @@ static const struct dcn20_vmid_mask vmid_masks = {
DCN20_VMID_MASK_SH_LIST(_MASK)
};
+static const struct dcn_dio_registers dio_regs = {
+ DIO_REG_LIST_DCN10()
+};
+
+#define DIO_MASK_SH_LIST(mask_sh)\
+ HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
+
+static const struct dcn_dio_shift dio_shift = {
+ DIO_MASK_SH_LIST(__SHIFT)
+};
+
+static const struct dcn_dio_mask dio_mask = {
+ DIO_MASK_SH_LIST(_MASK)
+};
+
static const struct resource_caps res_cap_dcn31 = {
.num_timing_generator = 4,
.num_opp = 4,
@@ -1021,6 +1037,18 @@ static struct mpc *dcn31_mpc_create(
return &mpc30->base;
}
+static struct dio *dcn31_dio_create(struct dc_context *ctx)
+{
+ struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
+
+ if (!dio10)
+ return NULL;
+
+ dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
+
+ return &dio10->base;
+}
+
static struct hubbub *dcn31_hubbub_create(struct dc_context *ctx)
{
int i;
@@ -1090,6 +1118,7 @@ static struct link_encoder *dcn31_link_encoder_create(
struct dc_context *ctx,
const struct encoder_init_data *enc_init_data)
{
+ (void)ctx;
struct dcn20_link_encoder *enc20 =
kzalloc_obj(struct dcn20_link_encoder);
@@ -1396,6 +1425,10 @@ static void dcn31_resource_destruct(struct dcn31_resource_pool *pool)
kfree(pool->base.hubbub);
pool->base.hubbub = NULL;
}
+ if (pool->base.dio != NULL) {
+ kfree(TO_DCN10_DIO(pool->base.dio));
+ pool->base.dio = NULL;
+ }
for (i = 0; i < pool->base.pipe_count; i++) {
if (pool->base.dpps[i] != NULL)
dcn31_dpp_destroy(&pool->base.dpps[i]);
@@ -1699,12 +1732,9 @@ int dcn31_populate_dml_pipes_from_context(
pipe_cnt++;
}
context->bw_ctx.dml.ip.det_buffer_size_kbytes = DCN3_1_DEFAULT_DET_SIZE;
- dc->config.enable_4to1MPC = false;
+
if (pipe_cnt == 1 && pipe->plane_state && !dc->debug.disable_z9_mpc) {
- if (is_dual_plane(pipe->plane_state->format)
- && pipe->plane_state->src_rect.width <= 1920 && pipe->plane_state->src_rect.height <= 1080) {
- dc->config.enable_4to1MPC = true;
- } else if (!is_dual_plane(pipe->plane_state->format) && pipe->plane_state->src_rect.width <= 5120) {
+ if (!is_dual_plane(pipe->plane_state->format) && pipe->plane_state->src_rect.width <= 5120) {
/* Limit to 5k max to avoid forced pipe split when there is not enough detile for swath */
context->bw_ctx.dml.ip.det_buffer_size_kbytes = 192;
pipes[0].pipe.src.unbounded_req_mode = true;
@@ -1851,6 +1881,7 @@ static struct resource_funcs dcn31_res_pool_funcs = {
.get_det_buffer_size = dcn31_get_det_buffer_size,
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe,
.update_dc_state_for_encoder_switch = dcn31_update_dc_state_for_encoder_switch,
+ .get_default_tiling_info = dcn10_get_default_tiling_info,
.build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params
};
@@ -1896,7 +1927,7 @@ static bool dcn31_resource_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)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;
@@ -1921,6 +1952,9 @@ static bool dcn31_resource_construct(
dc->caps.is_apu = true;
dc->caps.zstate_support = true;
+ /* Enable 4to1MPC by default */
+ dc->config.allow_4to1MPC = true;
+
/* Color pipeline capabilities */
dc->caps.color.dpp.dcn_arch = 1;
dc->caps.color.dpp.input_lut_shared = 0;
@@ -2063,6 +2097,14 @@ static bool dcn31_resource_construct(
goto create_fail;
}
+ /* DIO */
+ pool->base.dio = dcn31_dio_create(ctx);
+ if (pool->base.dio == NULL) {
+ BREAK_TO_DEBUGGER();
+ dm_error("DC: failed to create dio!\n");
+ goto create_fail;
+ }
+
/* HUBPs, DPPs, OPPs and TGs */
for (i = 0; i < pool->base.pipe_count; i++) {
pool->base.hubps[i] = dcn31_hubp_create(ctx, i);
@@ -2242,6 +2284,7 @@ enum dc_status dcn31_update_dc_state_for_encoder_switch(struct dc_link *link,
struct pipe_ctx *pipes,
struct audio_output *audio_output)
{
+ (void)link_setting;
struct dc_state *state = link->dc->current_state;
int i;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c
index 1939f720ba29..5acc545bbe7f 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c
@@ -66,6 +66,7 @@
#include "dce/dce_audio.h"
#include "dce/dce_hwseq.h"
#include "clk_mgr.h"
+#include "dio/dcn10/dcn10_dio.h"
#include "dio/virtual/virtual_stream_encoder.h"
#include "dce110/dce110_resource.h"
#include "dml/display_mode_vba.h"
@@ -822,6 +823,21 @@ static const struct dcn20_vmid_mask vmid_masks = {
DCN20_VMID_MASK_SH_LIST(_MASK)
};
+static const struct dcn_dio_registers dio_regs = {
+ DIO_REG_LIST_DCN10()
+};
+
+#define DIO_MASK_SH_LIST(mask_sh)\
+ HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
+
+static const struct dcn_dio_shift dio_shift = {
+ DIO_MASK_SH_LIST(__SHIFT)
+};
+
+static const struct dcn_dio_mask dio_mask = {
+ DIO_MASK_SH_LIST(_MASK)
+};
+
static const struct resource_caps res_cap_dcn314 = {
.num_timing_generator = 4,
.num_opp = 4,
@@ -1079,6 +1095,18 @@ static struct mpc *dcn31_mpc_create(
return &mpc30->base;
}
+static struct dio *dcn314_dio_create(struct dc_context *ctx)
+{
+ struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
+
+ if (!dio10)
+ return NULL;
+
+ dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
+
+ return &dio10->base;
+}
+
static struct hubbub *dcn31_hubbub_create(struct dc_context *ctx)
{
int i;
@@ -1148,6 +1176,7 @@ static struct link_encoder *dcn31_link_encoder_create(
struct dc_context *ctx,
const struct encoder_init_data *enc_init_data)
{
+ (void)ctx;
struct dcn20_link_encoder *enc20 =
kzalloc_obj(struct dcn20_link_encoder);
@@ -1455,6 +1484,10 @@ static void dcn314_resource_destruct(struct dcn314_resource_pool *pool)
kfree(pool->base.hubbub);
pool->base.hubbub = NULL;
}
+ if (pool->base.dio != NULL) {
+ kfree(TO_DCN10_DIO(pool->base.dio));
+ pool->base.dio = NULL;
+ }
for (i = 0; i < pool->base.pipe_count; i++) {
if (pool->base.dpps[i] != NULL)
dcn31_dpp_destroy(&pool->base.dpps[i]);
@@ -1782,7 +1815,8 @@ static struct resource_funcs dcn314_res_pool_funcs = {
.get_det_buffer_size = dcn31_get_det_buffer_size,
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe,
.update_dc_state_for_encoder_switch = dcn31_update_dc_state_for_encoder_switch,
- .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params
+ .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params,
+ .get_default_tiling_info = dcn10_get_default_tiling_info
};
static struct clock_source *dcn30_clock_source_create(
@@ -1826,9 +1860,12 @@ static bool dcn314_resource_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)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;
+
+ /* Enable 4to1MPC by default */
+ dc->config.allow_4to1MPC = true;
dc->caps.max_downscale_ratio = 400;
dc->caps.i2c_speed_in_khz = 100;
dc->caps.i2c_speed_in_khz_hdcp = 100;
@@ -1987,6 +2024,14 @@ static bool dcn314_resource_construct(
goto create_fail;
}
+ /* DIO */
+ pool->base.dio = dcn314_dio_create(ctx);
+ if (pool->base.dio == NULL) {
+ BREAK_TO_DEBUGGER();
+ dm_error("DC: failed to create dio!\n");
+ goto create_fail;
+ }
+
/* HUBPs, DPPs, OPPs and TGs */
for (i = 0; i < pool->base.pipe_count; i++) {
pool->base.hubps[i] = dcn31_hubp_create(ctx, i);
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c
index e8377c190f63..2ca673114841 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c
@@ -63,6 +63,7 @@
#include "dce/dce_audio.h"
#include "dce/dce_hwseq.h"
#include "clk_mgr.h"
+#include "dio/dcn10/dcn10_dio.h"
#include "dio/virtual/virtual_stream_encoder.h"
#include "dce110/dce110_resource.h"
#include "dml/display_mode_vba.h"
@@ -809,6 +810,21 @@ static const struct dcn20_vmid_mask vmid_masks = {
DCN20_VMID_MASK_SH_LIST(_MASK)
};
+static const struct dcn_dio_registers dio_regs = {
+ DIO_REG_LIST_DCN10()
+};
+
+#define DIO_MASK_SH_LIST(mask_sh)\
+ HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
+
+static const struct dcn_dio_shift dio_shift = {
+ DIO_MASK_SH_LIST(__SHIFT)
+};
+
+static const struct dcn_dio_mask dio_mask = {
+ DIO_MASK_SH_LIST(_MASK)
+};
+
static const struct resource_caps res_cap_dcn31 = {
.num_timing_generator = 4,
.num_opp = 4,
@@ -1020,6 +1036,18 @@ static struct mpc *dcn31_mpc_create(
return &mpc30->base;
}
+static struct dio *dcn315_dio_create(struct dc_context *ctx)
+{
+ struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
+
+ if (!dio10)
+ return NULL;
+
+ dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
+
+ return &dio10->base;
+}
+
static struct hubbub *dcn31_hubbub_create(struct dc_context *ctx)
{
int i;
@@ -1089,6 +1117,7 @@ static struct link_encoder *dcn31_link_encoder_create(
struct dc_context *ctx,
const struct encoder_init_data *enc_init_data)
{
+ (void)ctx;
struct dcn20_link_encoder *enc20 =
kzalloc_obj(struct dcn20_link_encoder);
@@ -1397,6 +1426,10 @@ static void dcn315_resource_destruct(struct dcn315_resource_pool *pool)
kfree(pool->base.hubbub);
pool->base.hubbub = NULL;
}
+ if (pool->base.dio != NULL) {
+ kfree(TO_DCN10_DIO(pool->base.dio));
+ pool->base.dio = NULL;
+ }
for (i = 0; i < pool->base.pipe_count; i++) {
if (pool->base.dpps[i] != NULL)
dcn31_dpp_destroy(&pool->base.dpps[i]);
@@ -1785,11 +1818,9 @@ static int dcn315_populate_dml_pipes_from_context(
if (context->bw_ctx.dml.ip.det_buffer_size_kbytes > DCN3_15_MAX_DET_SIZE)
context->bw_ctx.dml.ip.det_buffer_size_kbytes = DCN3_15_MAX_DET_SIZE;
- dc->config.enable_4to1MPC = false;
if (pipe_cnt == 1 && pipe->plane_state && !dc->debug.disable_z9_mpc) {
if (is_dual_plane(pipe->plane_state->format)
&& pipe->plane_state->src_rect.width <= 1920 && pipe->plane_state->src_rect.height <= 1080) {
- dc->config.enable_4to1MPC = true;
context->bw_ctx.dml.ip.det_buffer_size_kbytes =
(max_usable_det / DCN3_15_CRB_SEGMENT_SIZE_KB / 4) * DCN3_15_CRB_SEGMENT_SIZE_KB;
} else if (!is_dual_plane(pipe->plane_state->format)
@@ -1846,7 +1877,8 @@ static struct resource_funcs dcn315_res_pool_funcs = {
.get_det_buffer_size = dcn31_get_det_buffer_size,
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe,
.update_dc_state_for_encoder_switch = dcn31_update_dc_state_for_encoder_switch,
- .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params
+ .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params,
+ .get_default_tiling_info = dcn10_get_default_tiling_info
};
static bool dcn315_resource_construct(
@@ -1867,8 +1899,11 @@ static bool dcn315_resource_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE;
pool->base.pipe_count = pool->base.res_cap->num_timing_generator;
+
+ /* Enable 4to1MPC by default */
+ dc->config.allow_4to1MPC = true;
pool->base.mpcc_count = pool->base.res_cap->num_timing_generator;
dc->caps.max_downscale_ratio = 600;
dc->caps.i2c_speed_in_khz = 100;
@@ -2012,6 +2047,14 @@ static bool dcn315_resource_construct(
goto create_fail;
}
+ /* DIO */
+ pool->base.dio = dcn315_dio_create(ctx);
+ if (pool->base.dio == NULL) {
+ BREAK_TO_DEBUGGER();
+ dm_error("DC: failed to create dio!\n");
+ goto create_fail;
+ }
+
/* HUBPs, DPPs, OPPs and TGs */
for (i = 0; i < pool->base.pipe_count; i++) {
pool->base.hubps[i] = dcn31_hubp_create(ctx, i);
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c
index 045ce01bd74e..2242df112a3f 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c
@@ -63,6 +63,7 @@
#include "dce/dce_audio.h"
#include "dce/dce_hwseq.h"
#include "clk_mgr.h"
+#include "dio/dcn10/dcn10_dio.h"
#include "dio/virtual/virtual_stream_encoder.h"
#include "dce110/dce110_resource.h"
#include "dml/display_mode_vba.h"
@@ -804,6 +805,21 @@ static const struct dcn20_vmid_mask vmid_masks = {
DCN20_VMID_MASK_SH_LIST(_MASK)
};
+static const struct dcn_dio_registers dio_regs = {
+ DIO_REG_LIST_DCN10()
+};
+
+#define DIO_MASK_SH_LIST(mask_sh)\
+ HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
+
+static const struct dcn_dio_shift dio_shift = {
+ DIO_MASK_SH_LIST(__SHIFT)
+};
+
+static const struct dcn_dio_mask dio_mask = {
+ DIO_MASK_SH_LIST(_MASK)
+};
+
static const struct resource_caps res_cap_dcn31 = {
.num_timing_generator = 4,
.num_opp = 4,
@@ -1013,6 +1029,18 @@ static struct mpc *dcn31_mpc_create(
return &mpc30->base;
}
+static struct dio *dcn316_dio_create(struct dc_context *ctx)
+{
+ struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
+
+ if (!dio10)
+ return NULL;
+
+ dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
+
+ return &dio10->base;
+}
+
static struct hubbub *dcn31_hubbub_create(struct dc_context *ctx)
{
int i;
@@ -1082,6 +1110,7 @@ static struct link_encoder *dcn31_link_encoder_create(
struct dc_context *ctx,
const struct encoder_init_data *enc_init_data)
{
+ (void)ctx;
struct dcn20_link_encoder *enc20 =
kzalloc_obj(struct dcn20_link_encoder);
@@ -1392,6 +1421,10 @@ static void dcn316_resource_destruct(struct dcn316_resource_pool *pool)
kfree(pool->base.hubbub);
pool->base.hubbub = NULL;
}
+ if (pool->base.dio != NULL) {
+ kfree(TO_DCN10_DIO(pool->base.dio));
+ pool->base.dio = NULL;
+ }
for (i = 0; i < pool->base.pipe_count; i++) {
if (pool->base.dpps[i] != NULL)
dcn31_dpp_destroy(&pool->base.dpps[i]);
@@ -1669,11 +1702,9 @@ static int dcn316_populate_dml_pipes_from_context(
if (context->bw_ctx.dml.ip.det_buffer_size_kbytes > DCN3_16_MAX_DET_SIZE)
context->bw_ctx.dml.ip.det_buffer_size_kbytes = DCN3_16_MAX_DET_SIZE;
ASSERT(context->bw_ctx.dml.ip.det_buffer_size_kbytes >= DCN3_16_DEFAULT_DET_SIZE);
- dc->config.enable_4to1MPC = false;
if (pipe_cnt == 1 && pipe->plane_state && !dc->debug.disable_z9_mpc) {
if (is_dual_plane(pipe->plane_state->format)
&& pipe->plane_state->src_rect.width <= 1920 && pipe->plane_state->src_rect.height <= 1080) {
- dc->config.enable_4to1MPC = true;
context->bw_ctx.dml.ip.det_buffer_size_kbytes =
(max_usable_det / DCN3_16_CRB_SEGMENT_SIZE_KB / 4) * DCN3_16_CRB_SEGMENT_SIZE_KB;
} else if (!is_dual_plane(pipe->plane_state->format)) {
@@ -1721,7 +1752,8 @@ static struct resource_funcs dcn316_res_pool_funcs = {
.get_det_buffer_size = dcn31_get_det_buffer_size,
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe,
.update_dc_state_for_encoder_switch = dcn31_update_dc_state_for_encoder_switch,
- .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params
+ .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params,
+ .get_default_tiling_info = dcn10_get_default_tiling_info
};
static bool dcn316_resource_construct(
@@ -1742,9 +1774,13 @@ static bool dcn316_resource_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)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;
+
+ /* Enable 4to1MPC by default */
+ dc->config.allow_4to1MPC = true;
+
dc->caps.max_downscale_ratio = 600;
dc->caps.i2c_speed_in_khz = 100;
dc->caps.i2c_speed_in_khz_hdcp = 5; /*1.5 w/a applied by default*/
@@ -1887,6 +1923,14 @@ static bool dcn316_resource_construct(
goto create_fail;
}
+ /* DIO */
+ pool->base.dio = dcn316_dio_create(ctx);
+ if (pool->base.dio == NULL) {
+ BREAK_TO_DEBUGGER();
+ dm_error("DC: failed to create dio!\n");
+ goto create_fail;
+ }
+
/* HUBPs, DPPs, OPPs and TGs */
for (i = 0; i < pool->base.pipe_count; i++) {
pool->base.hubps[i] = dcn31_hubp_create(ctx, i);
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
index 7ebb7d1193af..82f81b586986 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
@@ -66,6 +66,7 @@
#include "dce/dce_hwseq.h"
#include "clk_mgr.h"
#include "dio/virtual/virtual_stream_encoder.h"
+#include "dio/dcn10/dcn10_dio.h"
#include "dml/display_mode_vba.h"
#include "dcn32/dcn32_dccg.h"
#include "dcn10/dcn10_resource.h"
@@ -643,6 +644,19 @@ static const struct dcn20_vmid_mask vmid_masks = {
DCN20_VMID_MASK_SH_LIST(_MASK)
};
+static struct dcn_dio_registers dio_regs;
+
+#define DIO_MASK_SH_LIST(mask_sh)\
+ HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
+
+static const struct dcn_dio_shift dio_shift = {
+ DIO_MASK_SH_LIST(__SHIFT)
+};
+
+static const struct dcn_dio_mask dio_mask = {
+ DIO_MASK_SH_LIST(_MASK)
+};
+
static const struct resource_caps res_cap_dcn32 = {
.num_timing_generator = 4,
.num_opp = 4,
@@ -833,6 +847,22 @@ static struct clock_source *dcn32_clock_source_create(
return NULL;
}
+static struct dio *dcn32_dio_create(struct dc_context *ctx)
+{
+ struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
+
+ if (!dio10)
+ return NULL;
+
+#undef REG_STRUCT
+#define REG_STRUCT dio_regs
+ DIO_REG_LIST_DCN10();
+
+ dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
+
+ return &dio10->base;
+}
+
static struct hubbub *dcn32_hubbub_create(struct dc_context *ctx)
{
int i;
@@ -1494,6 +1524,11 @@ static void dcn32_resource_destruct(struct dcn32_resource_pool *pool)
if (pool->base.dccg != NULL)
dcn_dccg_destroy(&pool->base.dccg);
+ if (pool->base.dio != NULL) {
+ kfree(TO_DCN10_DIO(pool->base.dio));
+ pool->base.dio = NULL;
+ }
+
if (pool->base.oem_device != NULL) {
struct dc *dc = pool->base.oem_device->ctx->dc;
@@ -1785,7 +1820,10 @@ static bool dml1_validate(struct dc *dc, struct dc_state *context, enum dc_valid
dc->res_pool->funcs->calculate_wm_and_dlg(dc, context, pipes, pipe_cnt, vlevel);
+ DC_FP_START();
dcn32_override_min_req_memclk(dc, context);
+ DC_FP_END();
+
dcn32_override_min_req_dcfclk(dc, context);
BW_VAL_TRACE_END_WATERMARKS();
@@ -2109,6 +2147,7 @@ static struct resource_funcs dcn32_res_pool_funcs = {
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
.update_soc_for_wm_a = dcn30_update_soc_for_wm_a,
.add_phantom_pipes = dcn32_add_phantom_pipes,
+ .get_default_tiling_info = dcn10_get_default_tiling_info,
.build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params,
.calculate_mall_ways_from_bytes = dcn32_calculate_mall_ways_from_bytes,
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe,
@@ -2187,7 +2226,7 @@ static bool dcn32_resource_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE;
pool->base.timing_generator_count = num_pipes;
pool->base.pipe_count = num_pipes;
pool->base.mpcc_count = num_pipes;
@@ -2370,6 +2409,14 @@ static bool dcn32_resource_construct(
goto create_fail;
}
+ /* DIO */
+ pool->base.dio = dcn32_dio_create(ctx);
+ if (pool->base.dio == NULL) {
+ BREAK_TO_DEBUGGER();
+ dm_error("DC: failed to create dio!\n");
+ goto create_fail;
+ }
+
/* HUBPs, DPPs, OPPs, TGs, ABMs */
for (i = 0, j = 0; i < pool->base.res_cap->num_timing_generator; i++) {
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource_helpers.c b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource_helpers.c
index f5a4e97c40ce..4808c793590f 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource_helpers.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource_helpers.c
@@ -41,6 +41,7 @@ uint32_t dcn32_helper_calculate_mall_bytes_for_cursor(
struct pipe_ctx *pipe_ctx,
bool ignore_cursor_buf)
{
+ (void)dc;
struct hubp *hubp = pipe_ctx->plane_res.hubp;
uint32_t cursor_size = hubp->curs_attr.pitch * hubp->curs_attr.height;
uint32_t cursor_mall_size_bytes = 0;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c
index c1582c27ac87..c8c81870d50e 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c
@@ -69,6 +69,7 @@
#include "dce/dce_hwseq.h"
#include "clk_mgr.h"
#include "dio/virtual/virtual_stream_encoder.h"
+#include "dio/dcn10/dcn10_dio.h"
#include "dml/display_mode_vba.h"
#include "dcn32/dcn32_dccg.h"
#include "dcn10/dcn10_resource.h"
@@ -639,6 +640,19 @@ static const struct dcn20_vmid_mask vmid_masks = {
DCN20_VMID_MASK_SH_LIST(_MASK)
};
+static struct dcn_dio_registers dio_regs;
+
+#define DIO_MASK_SH_LIST(mask_sh)\
+ HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
+
+static const struct dcn_dio_shift dio_shift = {
+ DIO_MASK_SH_LIST(__SHIFT)
+};
+
+static const struct dcn_dio_mask dio_mask = {
+ DIO_MASK_SH_LIST(_MASK)
+};
+
static const struct resource_caps res_cap_dcn321 = {
.num_timing_generator = 4,
.num_opp = 4,
@@ -827,6 +841,22 @@ static struct clock_source *dcn321_clock_source_create(
return NULL;
}
+static struct dio *dcn321_dio_create(struct dc_context *ctx)
+{
+ struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
+
+ if (!dio10)
+ return NULL;
+
+#undef REG_STRUCT
+#define REG_STRUCT dio_regs
+ DIO_REG_LIST_DCN10();
+
+ dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
+
+ return &dio10->base;
+}
+
static struct hubbub *dcn321_hubbub_create(struct dc_context *ctx)
{
int i;
@@ -1474,6 +1504,11 @@ static void dcn321_resource_destruct(struct dcn321_resource_pool *pool)
if (pool->base.dccg != NULL)
dcn_dccg_destroy(&pool->base.dccg);
+ if (pool->base.dio != NULL) {
+ kfree(TO_DCN10_DIO(pool->base.dio));
+ pool->base.dio = NULL;
+ }
+
if (pool->base.oem_device != NULL) {
struct dc *dc = pool->base.oem_device->ctx->dc;
@@ -1619,6 +1654,7 @@ static struct resource_funcs dcn321_res_pool_funcs = {
.calculate_mall_ways_from_bytes = dcn32_calculate_mall_ways_from_bytes,
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe,
.get_max_hw_cursor_size = dcn32_get_max_hw_cursor_size,
+ .get_default_tiling_info = dcn10_get_default_tiling_info,
};
static uint32_t read_pipe_fuses(struct dc_context *ctx)
@@ -1694,7 +1730,7 @@ static bool dcn321_resource_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE;
pool->base.timing_generator_count = num_pipes;
pool->base.pipe_count = num_pipes;
pool->base.mpcc_count = num_pipes;
@@ -1872,6 +1908,14 @@ static bool dcn321_resource_construct(
goto create_fail;
}
+ /* DIO */
+ pool->base.dio = dcn321_dio_create(ctx);
+ if (pool->base.dio == NULL) {
+ BREAK_TO_DEBUGGER();
+ dm_error("DC: failed to create dio!\n");
+ goto create_fail;
+ }
+
/* HUBPs, DPPs, OPPs, TGs, ABMs */
for (i = 0, j = 0; i < pool->base.res_cap->num_timing_generator; i++) {
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c
index 3494a40cea99..2a1b0b152501 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c
@@ -71,6 +71,7 @@
#include "dce/dce_hwseq.h"
#include "clk_mgr.h"
#include "dio/virtual/virtual_stream_encoder.h"
+#include "dio/dcn10/dcn10_dio.h"
#include "dce110/dce110_resource.h"
#include "dml/display_mode_vba.h"
#include "dcn35/dcn35_dccg.h"
@@ -664,6 +665,19 @@ static const struct dcn20_vmid_mask vmid_masks = {
DCN20_VMID_MASK_SH_LIST(_MASK)
};
+static struct dcn_dio_registers dio_regs;
+
+#define DIO_MASK_SH_LIST(mask_sh)\
+ HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
+
+static const struct dcn_dio_shift dio_shift = {
+ DIO_MASK_SH_LIST(__SHIFT)
+};
+
+static const struct dcn_dio_mask dio_mask = {
+ DIO_MASK_SH_LIST(_MASK)
+};
+
static const struct resource_caps res_cap_dcn35 = {
.num_timing_generator = 4,
.num_opp = 4,
@@ -973,6 +987,22 @@ static struct mpc *dcn35_mpc_create(
return &mpc30->base;
}
+static struct dio *dcn35_dio_create(struct dc_context *ctx)
+{
+ struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
+
+ if (!dio10)
+ return NULL;
+
+#undef REG_STRUCT
+#define REG_STRUCT dio_regs
+ DIO_REG_LIST_DCN10();
+
+ dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
+
+ return &dio10->base;
+}
+
static struct hubbub *dcn35_hubbub_create(struct dc_context *ctx)
{
int i;
@@ -1563,6 +1593,11 @@ static void dcn35_resource_destruct(struct dcn35_resource_pool *pool)
if (pool->base.dccg != NULL)
dcn_dccg_destroy(&pool->base.dccg);
+
+ if (pool->base.dio != NULL) {
+ kfree(TO_DCN10_DIO(pool->base.dio));
+ pool->base.dio = NULL;
+ }
}
static struct hubp *dcn35_hubp_create(
@@ -1738,9 +1773,11 @@ static enum dc_status dcn35_validate_bandwidth(struct dc *dc,
{
bool out = false;
+ DC_FP_START();
out = dml2_validate(dc, context,
context->power_source == DC_POWER_SOURCE_DC ? context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2,
validate_mode);
+ DC_FP_END();
if (validate_mode != DC_VALIDATE_MODE_AND_PROGRAMMING)
return out ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE;
@@ -1774,6 +1811,12 @@ static int populate_dml_pipes_from_context_fpu(struct dc *dc,
return ret;
}
+void dcn35_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params)
+{
+ DC_FP_START();
+ dcn35_update_bw_bounding_box_fpu(dc, bw_params);
+ DC_FP_END();
+}
static struct resource_funcs dcn35_res_pool_funcs = {
.destroy = dcn35_destroy_resource_pool,
.link_enc_create = dcn35_link_encoder_create,
@@ -1795,14 +1838,15 @@ static struct resource_funcs dcn35_res_pool_funcs = {
.find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link,
.acquire_post_bldn_3dlut = dcn30_acquire_post_bldn_3dlut,
.release_post_bldn_3dlut = dcn30_release_post_bldn_3dlut,
- .update_bw_bounding_box = dcn35_update_bw_bounding_box_fpu,
+ .update_bw_bounding_box = dcn35_update_bw_bounding_box,
.patch_unknown_plane_state = dcn35_patch_unknown_plane_state,
.get_panel_config_defaults = dcn35_get_panel_config_defaults,
.get_preferred_eng_id_dpia = dcn35_get_preferred_eng_id_dpia,
.get_det_buffer_size = dcn31_get_det_buffer_size,
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe,
.update_dc_state_for_encoder_switch = dcn31_update_dc_state_for_encoder_switch,
- .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params
+ .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params,
+ .get_default_tiling_info = dcn10_get_default_tiling_info
};
static bool dcn35_resource_construct(
@@ -1826,6 +1870,9 @@ static bool dcn35_resource_construct(
clk_src_regs_init(3, D),
clk_src_regs_init(4, E);
+ /* Enable 4to1MPC by default */
+ dc->config.allow_4to1MPC = true;
+
#undef REG_STRUCT
#define REG_STRUCT abm_regs
abm_regs_init(0),
@@ -1846,7 +1893,7 @@ static bool dcn35_resource_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)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;
@@ -2033,6 +2080,14 @@ static bool dcn35_resource_construct(
goto create_fail;
}
+ /* DIO */
+ pool->base.dio = dcn35_dio_create(ctx);
+ if (pool->base.dio == NULL) {
+ BREAK_TO_DEBUGGER();
+ dm_error("DC: failed to create dio!\n");
+ goto create_fail;
+ }
+
/* HUBPs, DPPs, OPPs and TGs */
for (i = 0; i < pool->base.pipe_count; i++) {
pool->base.hubps[i] = dcn35_hubp_create(ctx, i);
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.h
index 9c56ae76e0c7..6c2c61c711b9 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.h
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.h
@@ -312,4 +312,5 @@ struct resource_pool *dcn35_create_resource_pool(
#define DPP_REG_LIST_DCN35_RI(id)\
DPP_REG_LIST_DCN30_COMMON_RI(id)
+void dcn35_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params);
#endif /* _DCN35_RESOURCE_H_ */
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c
index 080bc7f24ffa..bfd1016aa780 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c
@@ -50,6 +50,7 @@
#include "dce/dce_hwseq.h"
#include "clk_mgr.h"
#include "dio/virtual/virtual_stream_encoder.h"
+#include "dio/dcn10/dcn10_dio.h"
#include "dce110/dce110_resource.h"
#include "dml/display_mode_vba.h"
#include "dcn35/dcn35_dccg.h"
@@ -644,6 +645,19 @@ static const struct dcn20_vmid_mask vmid_masks = {
DCN20_VMID_MASK_SH_LIST(_MASK)
};
+static struct dcn_dio_registers dio_regs;
+
+#define DIO_MASK_SH_LIST(mask_sh)\
+ HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
+
+static const struct dcn_dio_shift dio_shift = {
+ DIO_MASK_SH_LIST(__SHIFT)
+};
+
+static const struct dcn_dio_mask dio_mask = {
+ DIO_MASK_SH_LIST(_MASK)
+};
+
static const struct resource_caps res_cap_dcn351 = {
.num_timing_generator = 4,
.num_opp = 4,
@@ -953,6 +967,22 @@ static struct mpc *dcn35_mpc_create(
return &mpc30->base;
}
+static struct dio *dcn351_dio_create(struct dc_context *ctx)
+{
+ struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
+
+ if (!dio10)
+ return NULL;
+
+#undef REG_STRUCT
+#define REG_STRUCT dio_regs
+ DIO_REG_LIST_DCN10();
+
+ dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
+
+ return &dio10->base;
+}
+
static struct hubbub *dcn35_hubbub_create(struct dc_context *ctx)
{
int i;
@@ -1543,6 +1573,11 @@ static void dcn351_resource_destruct(struct dcn351_resource_pool *pool)
if (pool->base.dccg != NULL)
dcn_dccg_destroy(&pool->base.dccg);
+
+ if (pool->base.dio != NULL) {
+ kfree(TO_DCN10_DIO(pool->base.dio));
+ pool->base.dio = NULL;
+ }
}
static struct hubp *dcn35_hubp_create(
@@ -1718,9 +1753,11 @@ static enum dc_status dcn351_validate_bandwidth(struct dc *dc,
{
bool out = false;
+ DC_FP_START();
out = dml2_validate(dc, context,
context->power_source == DC_POWER_SOURCE_DC ? context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2,
validate_mode);
+ DC_FP_END();
if (validate_mode != DC_VALIDATE_MODE_AND_PROGRAMMING)
return out ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE;
@@ -1747,6 +1784,12 @@ static int populate_dml_pipes_from_context_fpu(struct dc *dc,
}
+static void dcn351_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params)
+{
+ DC_FP_START();
+ dcn351_update_bw_bounding_box_fpu(dc, bw_params);
+ DC_FP_END();
+}
static struct resource_funcs dcn351_res_pool_funcs = {
.destroy = dcn351_destroy_resource_pool,
.link_enc_create = dcn35_link_encoder_create,
@@ -1768,14 +1811,15 @@ static struct resource_funcs dcn351_res_pool_funcs = {
.find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link,
.acquire_post_bldn_3dlut = dcn30_acquire_post_bldn_3dlut,
.release_post_bldn_3dlut = dcn30_release_post_bldn_3dlut,
- .update_bw_bounding_box = dcn351_update_bw_bounding_box_fpu,
+ .update_bw_bounding_box = dcn351_update_bw_bounding_box,
.patch_unknown_plane_state = dcn35_patch_unknown_plane_state,
.get_panel_config_defaults = dcn35_get_panel_config_defaults,
.get_preferred_eng_id_dpia = dcn351_get_preferred_eng_id_dpia,
.get_det_buffer_size = dcn31_get_det_buffer_size,
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe,
.update_dc_state_for_encoder_switch = dcn31_update_dc_state_for_encoder_switch,
- .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params
+ .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params,
+ .get_default_tiling_info = dcn10_get_default_tiling_info
};
static bool dcn351_resource_construct(
@@ -1799,6 +1843,9 @@ static bool dcn351_resource_construct(
clk_src_regs_init(3, D),
clk_src_regs_init(4, E);
+ /* Enable 4to1MPC by default */
+ dc->config.allow_4to1MPC = true;
+
#undef REG_STRUCT
#define REG_STRUCT abm_regs
abm_regs_init(0),
@@ -1819,7 +1866,7 @@ static bool dcn351_resource_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)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;
@@ -2005,6 +2052,14 @@ static bool dcn351_resource_construct(
goto create_fail;
}
+ /* DIO */
+ pool->base.dio = dcn351_dio_create(ctx);
+ if (pool->base.dio == NULL) {
+ BREAK_TO_DEBUGGER();
+ dm_error("DC: failed to create dio!\n");
+ goto create_fail;
+ }
+
/* HUBPs, DPPs, OPPs and TGs */
for (i = 0; i < pool->base.pipe_count; i++) {
pool->base.hubps[i] = dcn35_hubp_create(ctx, i);
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c
index af51ac4ea59e..07a6675a7329 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c
@@ -50,6 +50,7 @@
#include "dce/dce_hwseq.h"
#include "clk_mgr.h"
#include "dio/virtual/virtual_stream_encoder.h"
+#include "dio/dcn10/dcn10_dio.h"
#include "dce110/dce110_resource.h"
#include "dml/display_mode_vba.h"
#include "dcn35/dcn35_dccg.h"
@@ -651,6 +652,19 @@ static const struct dcn20_vmid_mask vmid_masks = {
DCN20_VMID_MASK_SH_LIST(_MASK)
};
+static struct dcn_dio_registers dio_regs;
+
+#define DIO_MASK_SH_LIST(mask_sh)\
+ HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
+
+static const struct dcn_dio_shift dio_shift = {
+ DIO_MASK_SH_LIST(__SHIFT)
+};
+
+static const struct dcn_dio_mask dio_mask = {
+ DIO_MASK_SH_LIST(_MASK)
+};
+
static const struct resource_caps res_cap_dcn36 = {
.num_timing_generator = 4,
.num_opp = 4,
@@ -960,6 +974,22 @@ static struct mpc *dcn35_mpc_create(
return &mpc30->base;
}
+static struct dio *dcn36_dio_create(struct dc_context *ctx)
+{
+ struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
+
+ if (!dio10)
+ return NULL;
+
+#undef REG_STRUCT
+#define REG_STRUCT dio_regs
+ DIO_REG_LIST_DCN10();
+
+ dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
+
+ return &dio10->base;
+}
+
static struct hubbub *dcn35_hubbub_create(struct dc_context *ctx)
{
int i;
@@ -1550,6 +1580,11 @@ static void dcn36_resource_destruct(struct dcn36_resource_pool *pool)
if (pool->base.dccg != NULL)
dcn_dccg_destroy(&pool->base.dccg);
+
+ if (pool->base.dio != NULL) {
+ kfree(TO_DCN10_DIO(pool->base.dio));
+ pool->base.dio = NULL;
+ }
}
static struct hubp *dcn35_hubp_create(
@@ -1725,9 +1760,11 @@ static enum dc_status dcn35_validate_bandwidth(struct dc *dc,
{
bool out = false;
+ DC_FP_START();
out = dml2_validate(dc, context,
context->power_source == DC_POWER_SOURCE_DC ? context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2,
validate_mode);
+ DC_FP_END();
if (validate_mode != DC_VALIDATE_MODE_AND_PROGRAMMING)
return out ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE;
@@ -1775,13 +1812,14 @@ static struct resource_funcs dcn36_res_pool_funcs = {
.find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link,
.acquire_post_bldn_3dlut = dcn30_acquire_post_bldn_3dlut,
.release_post_bldn_3dlut = dcn30_release_post_bldn_3dlut,
- .update_bw_bounding_box = dcn35_update_bw_bounding_box_fpu,
+ .update_bw_bounding_box = dcn35_update_bw_bounding_box,
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
.get_panel_config_defaults = dcn35_get_panel_config_defaults,
.get_preferred_eng_id_dpia = dcn36_get_preferred_eng_id_dpia,
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe,
.update_dc_state_for_encoder_switch = dcn31_update_dc_state_for_encoder_switch,
- .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params
+ .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params,
+ .get_default_tiling_info = dcn10_get_default_tiling_info,
};
static bool dcn36_resource_construct(
@@ -1825,7 +1863,7 @@ static bool dcn36_resource_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)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;
@@ -2012,6 +2050,14 @@ static bool dcn36_resource_construct(
goto create_fail;
}
+ /* DIO */
+ pool->base.dio = dcn36_dio_create(ctx);
+ if (pool->base.dio == NULL) {
+ BREAK_TO_DEBUGGER();
+ dm_error("DC: failed to create dio!\n");
+ goto create_fail;
+ }
+
/* HUBPs, DPPs, OPPs and TGs */
for (i = 0; i < pool->base.pipe_count; i++) {
pool->base.hubps[i] = dcn35_hubp_create(ctx, i);
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c
index e37aab939a41..cb93bfbe9e9e 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c
@@ -1643,8 +1643,10 @@ static struct dc_cap_funcs cap_funcs = {
.get_subvp_en = dcn32_subvp_in_use,
};
-static void dcn401_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params)
+static void dcn401_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_params)
{
+ dc_assert_fp_enabled();
+
/* re-calculate the available MALL size if required */
if (bw_params->num_channels > 0) {
dc->caps.max_cab_allocation_bytes = dcn401_calc_num_avail_chans_for_mall(
@@ -1653,17 +1655,19 @@ static void dcn401_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *b
dc->caps.mall_size_total = dc->caps.max_cab_allocation_bytes;
}
- DC_FP_START();
-
if (dc->debug.using_dml2 && dc->current_state && dc->current_state->bw_ctx.dml2)
dml2_reinit(dc, &dc->dml2_options, &dc->current_state->bw_ctx.dml2);
if (dc->debug.using_dml2 && dc->current_state && dc->current_state->bw_ctx.dml2_dc_power_source)
dml2_reinit(dc, &dc->dml2_dc_power_options, &dc->current_state->bw_ctx.dml2_dc_power_source);
+}
+static void dcn401_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params)
+{
+ DC_FP_START();
+ dcn401_update_bw_bounding_box_fpu(dc, bw_params);
DC_FP_END();
}
-
enum dc_status dcn401_patch_unknown_plane_state(struct dc_plane_state *plane_state)
{
plane_state->tiling_info.gfxversion = DcGfxAddr3;
@@ -1688,10 +1692,13 @@ enum dc_status dcn401_validate_bandwidth(struct dc *dc,
}
}
- if (dc->debug.using_dml2)
+ if (dc->debug.using_dml2) {
+ DC_FP_START();
status = dml2_validate(dc, context,
context->power_source == DC_POWER_SOURCE_DC ? context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2,
validate_mode) ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE;
+ DC_FP_END();
+ }
if (validate_mode == DC_VALIDATE_MODE_AND_PROGRAMMING && status == DC_OK && dc_state_is_subvp_in_use(context)) {
/* check new stream configuration still supports cursor if subvp used */
@@ -1710,10 +1717,13 @@ enum dc_status dcn401_validate_bandwidth(struct dc *dc,
if (validate_mode == DC_VALIDATE_MODE_AND_PROGRAMMING && status == DC_FAIL_HW_CURSOR_SUPPORT) {
/* attempt to validate again with subvp disabled due to cursor */
- if (dc->debug.using_dml2)
+ if (dc->debug.using_dml2) {
+ DC_FP_START();
status = dml2_validate(dc, context,
context->power_source == DC_POWER_SOURCE_DC ? context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2,
validate_mode) ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE;
+ DC_FP_END();
+ }
}
return status;
@@ -1722,9 +1732,13 @@ enum dc_status dcn401_validate_bandwidth(struct dc *dc,
void dcn401_prepare_mcache_programming(struct dc *dc,
struct dc_state *context)
{
- if (dc->debug.using_dml21)
+ if (dc->debug.using_dml21) {
+ DC_FP_START();
dml2_prepare_mcache_programming(dc, context,
- context->power_source == DC_POWER_SOURCE_DC ? context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2);
+ context->power_source == DC_POWER_SOURCE_DC ?
+ context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2);
+ DC_FP_END();
+ }
}
static void dcn401_build_pipe_pix_clk_params(struct pipe_ctx *pipe_ctx)
@@ -1790,7 +1804,7 @@ static void dcn401_build_pipe_pix_clk_params(struct pipe_ctx *pipe_ctx)
}
}
-static int dcn401_get_power_profile(const struct dc_state *context)
+int dcn401_get_power_profile(const struct dc_state *context)
{
int uclk_mhz = context->bw_ctx.bw.dcn.clk.dramclk_khz / 1000;
int dpm_level = 0;
@@ -1839,9 +1853,16 @@ static struct resource_funcs dcn401_res_pool_funcs = {
.calculate_mall_ways_from_bytes = dcn32_calculate_mall_ways_from_bytes,
.get_power_profile = dcn401_get_power_profile,
.get_vstartup_for_pipe = dcn401_get_vstartup_for_pipe,
- .get_max_hw_cursor_size = dcn32_get_max_hw_cursor_size
+ .get_max_hw_cursor_size = dcn32_get_max_hw_cursor_size,
+ .get_default_tiling_info = dcn401_get_default_tiling_info
};
+void dcn401_get_default_tiling_info(struct dc_tiling_info *tiling_info)
+{
+ tiling_info->gfxversion = DcGfxAddr3;
+ tiling_info->gfx_addr3.swizzle = DC_ADDR3_SW_LINEAR;
+}
+
static uint32_t read_pipe_fuses(struct dc_context *ctx)
{
uint32_t value = REG_READ(CC_DC_PIPE_DIS);
@@ -1908,7 +1929,7 @@ static bool dcn401_resource_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE;
pool->base.timing_generator_count = num_pipes;
pool->base.pipe_count = num_pipes;
pool->base.mpcc_count = num_pipes;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h
index 08bec1755617..47f82b818262 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h
@@ -28,8 +28,11 @@ enum dc_status dcn401_validate_bandwidth(struct dc *dc,
void dcn401_prepare_mcache_programming(struct dc *dc, struct dc_state *context);
+void dcn401_get_default_tiling_info(struct dc_tiling_info *tiling_info);
+
unsigned int dcn401_get_vstartup_for_pipe(struct pipe_ctx *pipe_ctx);
+int dcn401_get_power_profile(const struct dc_state *context);
/* Following are definitions for run time init of reg offsets */
/* HUBP */
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c
index aef187bcf5c3..c0d37f00fed9 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c
@@ -760,6 +760,9 @@ static const struct dc_debug_options debug_defaults_drv = {
.disable_z10 = false,
.ignore_pg = true,
.disable_stutter_for_wm_program = true,
+ .min_deep_sleep_dcfclk_khz = 8000,
+ .replay_skip_crtc_disabled = true,
+ .psr_skip_crtc_disable = true,
};
static const struct dc_check_config config_defaults = {
@@ -1693,37 +1696,51 @@ static void dcn42_destroy_resource_pool(struct resource_pool **pool)
static struct dc_cap_funcs cap_funcs = {
.get_dcc_compression_cap = dcn20_get_dcc_compression_cap};
-static void dcn42_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params)
+static void dcn42_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_params)
{
- DC_FP_START();
+ (void)bw_params;
+ dc_assert_fp_enabled();
+
if (dc->current_state && dc->current_state->bw_ctx.dml2)
dml2_reinit(dc, &dc->dml2_options, &dc->current_state->bw_ctx.dml2);
- DC_FP_END();
}
+static void dcn42_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params)
+{
+ DC_FP_START();
+ dcn42_update_bw_bounding_box_fpu(dc, bw_params);
+ DC_FP_END();
+}
enum dc_status dcn42_validate_bandwidth(struct dc *dc,
struct dc_state *context,
enum dc_validate_mode validate_mode)
{
bool out = false;
+ DC_FP_START();
+
out = dml2_validate(dc, context, context->bw_ctx.dml2,
validate_mode);
- DC_FP_START();
+
if (validate_mode == DC_VALIDATE_MODE_AND_PROGRAMMING) {
/*not required for mode enumeration*/
dcn42_decide_zstate_support(dc, context);
}
+
DC_FP_END();
+
return out ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE;
}
void dcn42_prepare_mcache_programming(struct dc *dc,
struct dc_state *context)
{
- if (dc->debug.using_dml21)
+ if (dc->debug.using_dml21) {
+ DC_FP_START();
dml2_prepare_mcache_programming(dc, context,
context->power_source == DC_POWER_SOURCE_DC ?
- context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2);
+ context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2);
+ DC_FP_END();
+ }
}
/* Create a minimal link encoder object not associated with a particular
* physical connector.
@@ -1758,6 +1775,8 @@ static unsigned int dcn42_get_max_hw_cursor_size(const struct dc *dc,
struct dc_state *state,
const struct dc_stream_state *stream)
{
+ (void)state;
+ (void)stream;
return dc->caps.max_cursor_size;
}
static struct resource_funcs dcn42_res_pool_funcs = {
@@ -1782,7 +1801,7 @@ static struct resource_funcs dcn42_res_pool_funcs = {
.acquire_post_bldn_3dlut = dcn32_acquire_post_bldn_3dlut,
.release_post_bldn_3dlut = dcn32_release_post_bldn_3dlut,
.update_bw_bounding_box = dcn42_update_bw_bounding_box,
- .patch_unknown_plane_state = dcn401_patch_unknown_plane_state,
+ .patch_unknown_plane_state = dcn35_patch_unknown_plane_state,
.get_panel_config_defaults = dcn42_get_panel_config_defaults,
.get_preferred_eng_id_dpia = dcn42_get_preferred_eng_id_dpia,
.update_soc_for_wm_a = dcn30_update_soc_for_wm_a,
@@ -1790,8 +1809,10 @@ static struct resource_funcs dcn42_res_pool_funcs = {
.calculate_mall_ways_from_bytes = dcn32_calculate_mall_ways_from_bytes,
.prepare_mcache_programming = dcn42_prepare_mcache_programming,
.build_pipe_pix_clk_params = dcn42_build_pipe_pix_clk_params,
+ .get_power_profile = dcn401_get_power_profile,
.get_vstartup_for_pipe = dcn401_get_vstartup_for_pipe,
.get_max_hw_cursor_size = dcn42_get_max_hw_cursor_size,
+ .get_default_tiling_info = dcn10_get_default_tiling_info
};
static uint32_t read_pipe_fuses(struct dc_context *ctx)
@@ -1861,7 +1882,7 @@ static bool dcn42_resource_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE;
pool->base.timing_generator_count = pool->base.res_cap->num_timing_generator;
pool->base.pipe_count = num_pipes;
pool->base.mpcc_count = num_pipes;
@@ -2015,7 +2036,7 @@ static bool dcn42_resource_construct(
dc->config.dcn_override_sharpness_range.hdr_rgb_mid = 1500;
dc->config.use_pipe_ctx_sync_logic = true;
- dc->config.dc_mode_clk_limit_support = true;
+ dc->config.dc_mode_clk_limit_support = false;
dc->config.enable_windowed_mpo_odm = true;
/* Use psp mailbox to enable assr */
dc->config.use_assr_psp_message = true;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.h
index a9b26df14520..60acf0e423d9 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.h
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.h
@@ -481,6 +481,8 @@
SRI_ARR(OPTC_INPUT_CLOCK_CONTROL, ODM, inst), \
SRI_ARR(OPTC_DATA_SOURCE_SELECT, ODM, inst), \
SRI_ARR(OPTC_INPUT_GLOBAL_CONTROL, ODM, inst), \
+ SRI_ARR(OPTC_RSMU_UNDERFLOW, ODM, inst), \
+ SRI_ARR(OPTC_UNDERFLOW_THRESHOLD, ODM, inst), \
SRI_ARR(CONTROL, VTG, inst), \
SRI_ARR(OTG_VERT_SYNC_CONTROL, OTG, inst), \
SRI_ARR(OTG_GSL_CONTROL, OTG, inst), \
@@ -584,5 +586,6 @@ enum dc_status dcn42_validate_bandwidth(struct dc *dc,
enum dc_validate_mode validate_mode);
void dcn42_prepare_mcache_programming(struct dc *dc, struct dc_state *context);
+int dcn42_get_power_profile(const struct dc_state *context);
#endif /* _DCN42_RESOURCE_H_ */
diff --git a/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn42/dcn42_soc_and_ip_translator.c b/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn42/dcn42_soc_and_ip_translator.c
index fd9c24b5df53..146a6e47934b 100644
--- a/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn42/dcn42_soc_and_ip_translator.c
+++ b/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn42/dcn42_soc_and_ip_translator.c
@@ -93,6 +93,10 @@ static void dcn42_convert_dc_clock_table_to_soc_bb_clock_table(
}
}
vmin_limit->dispclk_khz = min(dc_clk_table->entries[0].dispclk_mhz * 1000, vmin_limit->dispclk_khz);
+ /* dispclk is always fine-grain */
+ dml_clk_table->dispclk.num_clk_values = dc_clk_table->num_entries_per_clk.num_dispclk_levels >= 2 ? 2 : 1;
+ dml_clk_table->dispclk.clk_values_khz[0] = 0;
+ dml_clk_table->dispclk.clk_values_khz[1] = dc_clk_table->entries[dc_clk_table->num_entries_per_clk.num_dispclk_levels - 1].dispclk_mhz * 1000;
}
/* dppclk */
@@ -105,6 +109,10 @@ static void dcn42_convert_dc_clock_table_to_soc_bb_clock_table(
dml_clk_table->dppclk.clk_values_khz[i] = 0;
}
}
+ /* dppclk is always fine-grain */
+ dml_clk_table->dppclk.num_clk_values = dc_clk_table->num_entries_per_clk.num_dppclk_levels >= 2 ? 2 : 1;
+ dml_clk_table->dppclk.clk_values_khz[0] = 0;
+ dml_clk_table->dppclk.clk_values_khz[1] = dc_clk_table->entries[dc_clk_table->num_entries_per_clk.num_dppclk_levels - 1].dppclk_mhz * 1000;
}
/* dtbclk */
@@ -151,6 +159,7 @@ static void dcn42_update_soc_bb_with_values_from_clk_mgr(struct dml2_soc_bb *soc
static void apply_soc_bb_updates(struct dml2_soc_bb *soc_bb, const struct dc *dc, const struct dml2_configuration_options *config)
{
+ (void)config;
/* Individual modification can be overwritten even if it was obtained by a previous function.
* Modifications are acquired in order of priority (lowest to highest).
*/
diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
index e11e32afac6b..fe9431cea3e5 100644
--- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
+++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
@@ -4437,6 +4437,7 @@ enum dmub_cmd_replay_general_subtype {
REPLAY_GENERAL_CMD_VIDEO_CONFERENCING,
REPLAY_GENERAL_CMD_SET_CONTINUOUSLY_RESYNC,
REPLAY_GENERAL_CMD_SET_COASTING_VTOTAL_WITHOUT_FRAME_UPDATE,
+ REPLAY_GENERAL_CMD_LIVE_CAPTURE_WITH_CVT,
};
struct dmub_alpm_auxless_data {
@@ -6271,6 +6272,7 @@ struct dmub_cmd_edid_cea_amd_vsdb {
uint16_t amd_vsdb_version; /**< AMD VSDB version */
uint16_t min_frame_rate; /**< Maximum frame rate */
uint16_t max_frame_rate; /**< Minimum frame rate */
+ uint8_t freesync_mccs_vcp_code; /**< Freesync MCCS VCP code */
};
/**
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c
index 54df2147e4dc..0b152926f75b 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c
@@ -194,6 +194,7 @@ void dmub_dcn20_setup_windows(struct dmub_srv *dmub,
const struct dmub_window *cw6,
const struct dmub_window *region6)
{
+ (void)region6;
union dmub_addr offset;
uint64_t fb_base, fb_offset;
@@ -396,6 +397,7 @@ union dmub_fw_boot_status dmub_dcn20_get_fw_boot_status(struct dmub_srv *dmub)
void dmub_dcn20_enable_dmub_boot_options(struct dmub_srv *dmub, const struct dmub_srv_hw_params *params)
{
+ (void)params;
union dmub_fw_boot_options boot_options = {0};
REG_WRITE(DMCUB_SCRATCH14, boot_options.all);
@@ -460,20 +462,26 @@ void dmub_dcn20_get_diagnostic_data(struct dmub_srv *dmub)
dmub->debug.inbox0_size = REG_READ(DMCUB_INBOX0_SIZE);
REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_dmub_enabled);
- dmub->debug.is_dmcub_enabled = is_dmub_enabled;
+ ASSERT(is_dmub_enabled <= 0xFF);
+ dmub->debug.is_dmcub_enabled = (uint8_t)is_dmub_enabled;
REG_GET(DMCUB_CNTL, DMCUB_SOFT_RESET, &is_soft_reset);
- dmub->debug.is_dmcub_soft_reset = is_soft_reset;
+ ASSERT(is_soft_reset <= 0xFF);
+ dmub->debug.is_dmcub_soft_reset = (uint8_t)is_soft_reset;
REG_GET(DMCUB_SEC_CNTL, DMCUB_SEC_RESET_STATUS, &is_sec_reset);
- dmub->debug.is_dmcub_secure_reset = is_sec_reset;
+ ASSERT(is_sec_reset <= 0xFF);
+ dmub->debug.is_dmcub_secure_reset = (uint8_t)is_sec_reset;
REG_GET(DMCUB_CNTL, DMCUB_TRACEPORT_EN, &is_traceport_enabled);
- dmub->debug.is_traceport_en = is_traceport_enabled;
+ ASSERT(is_traceport_enabled <= 0xFF);
+ dmub->debug.is_traceport_en = (uint8_t)is_traceport_enabled;
REG_GET(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_ENABLE, &is_cw0_enabled);
- dmub->debug.is_cw0_enabled = is_cw0_enabled;
+ ASSERT(is_cw0_enabled <= 0xFF);
+ dmub->debug.is_cw0_enabled = (uint8_t)is_cw0_enabled;
REG_GET(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE, &is_cw6_enabled);
- dmub->debug.is_cw6_enabled = is_cw6_enabled;
+ ASSERT(is_cw6_enabled <= 0xFF);
+ dmub->debug.is_cw6_enabled = (uint8_t)is_cw6_enabled;
}
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c
index 84a6eb3f677d..23a33db07edc 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c
@@ -127,6 +127,7 @@ void dmub_dcn30_setup_windows(struct dmub_srv *dmub,
const struct dmub_window *cw6,
const struct dmub_window *region6)
{
+ (void)region6;
union dmub_addr offset;
/* sienna_cichlid has hardwired virtual addressing for CW2-CW7 */
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c
index a0cefc03b21d..478d79a6e246 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c
@@ -195,6 +195,8 @@ void dmub_dcn31_setup_windows(struct dmub_srv *dmub,
const struct dmub_window *cw6,
const struct dmub_window *region6)
{
+ (void)cw2;
+ (void)region6;
union dmub_addr offset;
offset = cw3->offset;
@@ -466,25 +468,32 @@ void dmub_dcn31_get_diagnostic_data(struct dmub_srv *dmub)
dmub->debug.outbox1_size = REG_READ(DMCUB_OUTBOX1_SIZE);
REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_dmub_enabled);
- dmub->debug.is_dmcub_enabled = is_dmub_enabled;
+ ASSERT(is_dmub_enabled <= 0xFF);
+ dmub->debug.is_dmcub_enabled = (uint8_t)is_dmub_enabled;
REG_GET(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS, &is_pwait);
- dmub->debug.is_pwait = is_pwait;
+ ASSERT(is_pwait <= 0xFF);
+ dmub->debug.is_pwait = (uint8_t)is_pwait;
REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &is_soft_reset);
- dmub->debug.is_dmcub_soft_reset = is_soft_reset;
+ ASSERT(is_soft_reset <= 0xFF);
+ dmub->debug.is_dmcub_soft_reset = (uint8_t)is_soft_reset;
REG_GET(DMCUB_SEC_CNTL, DMCUB_SEC_RESET_STATUS, &is_sec_reset);
- dmub->debug.is_dmcub_secure_reset = is_sec_reset;
+ ASSERT(is_sec_reset <= 0xFF);
+ dmub->debug.is_dmcub_secure_reset = (uint8_t)is_sec_reset;
REG_GET(DMCUB_CNTL, DMCUB_TRACEPORT_EN, &is_traceport_enabled);
- dmub->debug.is_traceport_en = is_traceport_enabled;
+ ASSERT(is_traceport_enabled <= 0xFF);
+ dmub->debug.is_traceport_en = (uint8_t)is_traceport_enabled;
REG_GET(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_ENABLE, &is_cw0_enabled);
- dmub->debug.is_cw0_enabled = is_cw0_enabled;
+ ASSERT(is_cw0_enabled <= 0xFF);
+ dmub->debug.is_cw0_enabled = (uint8_t)is_cw0_enabled;
REG_GET(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE, &is_cw6_enabled);
- dmub->debug.is_cw6_enabled = is_cw6_enabled;
+ ASSERT(is_cw6_enabled <= 0xFF);
+ dmub->debug.is_cw6_enabled = (uint8_t)is_cw6_enabled;
}
bool dmub_dcn31_should_detect(struct dmub_srv *dmub)
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.c
index 2f99a2772599..3f9fb9e05b79 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.c
@@ -237,6 +237,8 @@ void dmub_dcn32_setup_windows(struct dmub_srv *dmub,
const struct dmub_window *cw6,
const struct dmub_window *region6)
{
+ (void)cw2;
+ (void)region6;
union dmub_addr offset;
offset = cw3->offset;
@@ -486,19 +488,24 @@ void dmub_dcn32_get_diagnostic_data(struct dmub_srv *dmub)
dmub->debug.outbox1_size = REG_READ(DMCUB_OUTBOX1_SIZE);
REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_dmub_enabled);
- dmub->debug.is_dmcub_enabled = is_dmub_enabled;
+ ASSERT(is_dmub_enabled <= 0xFF);
+ dmub->debug.is_dmcub_enabled = (uint8_t)is_dmub_enabled;
REG_GET(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS, &is_pwait);
- dmub->debug.is_pwait = is_pwait;
+ ASSERT(is_pwait <= 0xFF);
+ dmub->debug.is_pwait = (uint8_t)is_pwait;
REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &is_soft_reset);
- dmub->debug.is_dmcub_soft_reset = is_soft_reset;
+ ASSERT(is_soft_reset <= 0xFF);
+ dmub->debug.is_dmcub_soft_reset = (uint8_t)is_soft_reset;
REG_GET(DMCUB_CNTL, DMCUB_TRACEPORT_EN, &is_traceport_enabled);
- dmub->debug.is_traceport_en = is_traceport_enabled;
+ ASSERT(is_traceport_enabled <= 0xFF);
+ dmub->debug.is_traceport_en = (uint8_t)is_traceport_enabled;
REG_GET(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE, &is_cw6_enabled);
- dmub->debug.is_cw6_enabled = is_cw6_enabled;
+ ASSERT(is_cw6_enabled <= 0xFF);
+ dmub->debug.is_cw6_enabled = (uint8_t)is_cw6_enabled;
dmub->debug.gpint_datain0 = REG_READ(DMCUB_GPINT_DATAIN0);
}
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c
index 639f9835e5e9..69fb6084232e 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c
@@ -222,6 +222,7 @@ void dmub_dcn35_setup_windows(struct dmub_srv *dmub,
const struct dmub_window *cw6,
const struct dmub_window *region6)
{
+ (void)cw2;
union dmub_addr offset;
offset = cw3->offset;
@@ -402,7 +403,7 @@ void dmub_dcn35_enable_dmub_boot_options(struct dmub_srv *dmub, const struct dmu
union dmub_fw_boot_options boot_options = {0};
if (!dmub->dpia_supported) {
- dmub->dpia_supported = dmub_dcn35_get_fw_boot_option(dmub).bits.enable_dpia;
+ dmub->dpia_supported = dmub_dcn35_get_fw_boot_option(dmub).bits.enable_dpia != 0;
}
boot_options.bits.z10_disable = params->disable_z10;
@@ -508,19 +509,24 @@ void dmub_dcn35_get_diagnostic_data(struct dmub_srv *dmub)
dmub->debug.outbox1_size = REG_READ(DMCUB_OUTBOX1_SIZE);
REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_dmub_enabled);
- dmub->debug.is_dmcub_enabled = is_dmub_enabled;
+ ASSERT(is_dmub_enabled <= 0xFF);
+ dmub->debug.is_dmcub_enabled = (uint8_t)is_dmub_enabled;
REG_GET(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS, &is_pwait);
- dmub->debug.is_pwait = is_pwait;
+ ASSERT(is_pwait <= 0xFF);
+ dmub->debug.is_pwait = (uint8_t)is_pwait;
REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &is_soft_reset);
- dmub->debug.is_dmcub_soft_reset = is_soft_reset;
+ ASSERT(is_soft_reset <= 0xFF);
+ dmub->debug.is_dmcub_soft_reset = (uint8_t)is_soft_reset;
REG_GET(DMCUB_CNTL, DMCUB_TRACEPORT_EN, &is_traceport_enabled);
- dmub->debug.is_traceport_en = is_traceport_enabled;
+ ASSERT(is_traceport_enabled <= 0xFF);
+ dmub->debug.is_traceport_en = (uint8_t)is_traceport_enabled;
REG_GET(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE, &is_cw6_enabled);
- dmub->debug.is_cw6_enabled = is_cw6_enabled;
+ ASSERT(is_cw6_enabled <= 0xFF);
+ dmub->debug.is_cw6_enabled = (uint8_t)is_cw6_enabled;
dmub->debug.gpint_datain0 = REG_READ(DMCUB_GPINT_DATAIN0);
}
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.c
index 16ed07f0e96d..e5a78df80d72 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.c
@@ -213,6 +213,7 @@ void dmub_dcn401_setup_windows(struct dmub_srv *dmub,
const struct dmub_window *cw6,
const struct dmub_window *region6)
{
+ (void)cw2;
union dmub_addr offset;
offset = cw3->offset;
@@ -473,25 +474,32 @@ void dmub_dcn401_get_diagnostic_data(struct dmub_srv *dmub)
dmub->debug.outbox1_size = REG_READ(DMCUB_OUTBOX1_SIZE);
REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_dmub_enabled);
- dmub->debug.is_dmcub_enabled = is_dmub_enabled;
+ ASSERT(is_dmub_enabled <= 0xFF);
+ dmub->debug.is_dmcub_enabled = (uint8_t)is_dmub_enabled;
REG_GET(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS, &is_pwait);
- dmub->debug.is_pwait = is_pwait;
+ ASSERT(is_pwait <= 0xFF);
+ dmub->debug.is_pwait = (uint8_t)is_pwait;
REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &is_soft_reset);
- dmub->debug.is_dmcub_soft_reset = is_soft_reset;
+ ASSERT(is_soft_reset <= 0xFF);
+ dmub->debug.is_dmcub_soft_reset = (uint8_t)is_soft_reset;
REG_GET(DMCUB_SEC_CNTL, DMCUB_SEC_RESET_STATUS, &is_sec_reset);
- dmub->debug.is_dmcub_secure_reset = is_sec_reset;
+ ASSERT(is_sec_reset <= 0xFF);
+ dmub->debug.is_dmcub_secure_reset = (uint8_t)is_sec_reset;
REG_GET(DMCUB_CNTL, DMCUB_TRACEPORT_EN, &is_traceport_enabled);
- dmub->debug.is_traceport_en = is_traceport_enabled;
+ ASSERT(is_traceport_enabled <= 0xFF);
+ dmub->debug.is_traceport_en = (uint8_t)is_traceport_enabled;
REG_GET(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_ENABLE, &is_cw0_enabled);
- dmub->debug.is_cw0_enabled = is_cw0_enabled;
+ ASSERT(is_cw0_enabled <= 0xFF);
+ dmub->debug.is_cw0_enabled = (uint8_t)is_cw0_enabled;
REG_GET(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE, &is_cw6_enabled);
- dmub->debug.is_cw6_enabled = is_cw6_enabled;
+ ASSERT(is_cw6_enabled <= 0xFF);
+ dmub->debug.is_cw6_enabled = (uint8_t)is_cw6_enabled;
dmub->debug.gpint_datain0 = REG_READ(DMCUB_GPINT_DATAIN0);
}
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn42.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn42.c
index 4d274b7034e8..a09aa19ad379 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn42.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn42.c
@@ -39,13 +39,14 @@ void dmub_srv_dcn42_regs_init(struct dmub_srv *dmub, struct dc_context *ctx)
void dmub_dcn42_enable_dmub_boot_options(struct dmub_srv *dmub, const struct dmub_srv_hw_params *params)
{
union dmub_fw_boot_options boot_options = {0};
- union dmub_fw_boot_options cur_boot_options = {0};
- cur_boot_options = dmub_dcn42_get_fw_boot_option(dmub);
+ if (!dmub->dpia_supported) {
+ dmub->dpia_supported = dmub_dcn42_get_fw_boot_option(dmub).bits.enable_dpia != 0;
+ }
boot_options.bits.z10_disable = params->disable_z10;
boot_options.bits.dpia_supported = params->dpia_supported;
- boot_options.bits.enable_dpia = cur_boot_options.bits.enable_dpia && !params->disable_dpia;
+ boot_options.bits.enable_dpia = dmub->dpia_supported && !params->disable_dpia;
boot_options.bits.usb4_cm_version = params->usb4_cm_version;
boot_options.bits.dpia_hpd_int_enable_supported = params->dpia_hpd_int_enable_supported;
boot_options.bits.power_optimization = params->power_optimization;
@@ -228,6 +229,7 @@ void dmub_dcn42_setup_windows(struct dmub_srv *dmub,
const struct dmub_window *cw6,
const struct dmub_window *region6)
{
+ (void)cw2;
union dmub_addr offset;
offset = cw3->offset;
@@ -320,11 +322,9 @@ void dmub_dcn42_set_outbox1_rptr(struct dmub_srv *dmub, uint32_t rptr_offset)
bool dmub_dcn42_is_supported(struct dmub_srv *dmub)
{
- uint32_t supported = 0;
-
- REG_GET(CC_DC_PIPE_DIS, DC_DMCUB_ENABLE, &supported);
-
- return supported;
+ // DCN without DMUB is not a supported configuration; safe to assume that it is always
+ // present.
+ return true;
}
union dmub_fw_boot_options dmub_dcn42_get_fw_boot_option(struct dmub_srv *dmub)
@@ -677,25 +677,32 @@ void dmub_dcn42_get_diagnostic_data(struct dmub_srv *dmub)
dmub->debug.outbox1_size = REG_READ(DMCUB_OUTBOX1_SIZE);
REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_dmub_enabled);
- dmub->debug.is_dmcub_enabled = is_dmub_enabled;
+ ASSERT(is_dmub_enabled <= 0xFF);
+ dmub->debug.is_dmcub_enabled = (uint8_t)is_dmub_enabled;
REG_GET(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS, &is_pwait);
- dmub->debug.is_pwait = is_pwait;
+ ASSERT(is_pwait <= 0xFF);
+ dmub->debug.is_pwait = (uint8_t)is_pwait;
REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &is_soft_reset);
- dmub->debug.is_dmcub_soft_reset = is_soft_reset;
+ ASSERT(is_soft_reset <= 0xFF);
+ dmub->debug.is_dmcub_soft_reset = (uint8_t)is_soft_reset;
REG_GET(DMCUB_SEC_CNTL, DMCUB_SEC_RESET_STATUS, &is_sec_reset);
- dmub->debug.is_dmcub_secure_reset = is_sec_reset;
+ ASSERT(is_sec_reset <= 0xFF);
+ dmub->debug.is_dmcub_secure_reset = (uint8_t)is_sec_reset;
REG_GET(DMCUB_CNTL, DMCUB_TRACEPORT_EN, &is_traceport_enabled);
- dmub->debug.is_traceport_en = is_traceport_enabled;
+ ASSERT(is_traceport_enabled <= 0xFF);
+ dmub->debug.is_traceport_en = (uint8_t)is_traceport_enabled;
REG_GET(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_ENABLE, &is_cw0_enabled);
- dmub->debug.is_cw0_enabled = is_cw0_enabled;
+ ASSERT(is_cw0_enabled <= 0xFF);
+ dmub->debug.is_cw0_enabled = (uint8_t)is_cw0_enabled;
REG_GET(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE, &is_cw6_enabled);
- dmub->debug.is_cw6_enabled = is_cw6_enabled;
+ ASSERT(is_cw6_enabled <= 0xFF);
+ dmub->debug.is_cw6_enabled = (uint8_t)is_cw6_enabled;
dmub->debug.gpint_datain0 = REG_READ(DMCUB_GPINT_DATAIN0);
}
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn42.h b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn42.h
index a49d88ab0455..c53f7691d1a8 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn42.h
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn42.h
@@ -34,7 +34,101 @@ struct dmub_srv;
/* DCN42 register definitions. */
#define DMUB_DCN42_REGS() \
- DMUB_DCN35_REGS() \
+ DMUB_SR(DMCUB_CNTL) \
+ DMUB_SR(DMCUB_CNTL2) \
+ DMUB_SR(DMCUB_SEC_CNTL) \
+ DMUB_SR(DMCUB_INBOX0_SIZE) \
+ DMUB_SR(DMCUB_INBOX0_RPTR) \
+ DMUB_SR(DMCUB_INBOX0_WPTR) \
+ DMUB_SR(DMCUB_INBOX1_BASE_ADDRESS) \
+ DMUB_SR(DMCUB_INBOX1_SIZE) \
+ DMUB_SR(DMCUB_INBOX1_RPTR) \
+ DMUB_SR(DMCUB_INBOX1_WPTR) \
+ DMUB_SR(DMCUB_OUTBOX0_BASE_ADDRESS) \
+ DMUB_SR(DMCUB_OUTBOX0_SIZE) \
+ DMUB_SR(DMCUB_OUTBOX0_RPTR) \
+ DMUB_SR(DMCUB_OUTBOX0_WPTR) \
+ DMUB_SR(DMCUB_OUTBOX1_BASE_ADDRESS) \
+ DMUB_SR(DMCUB_OUTBOX1_SIZE) \
+ DMUB_SR(DMCUB_OUTBOX1_RPTR) \
+ DMUB_SR(DMCUB_OUTBOX1_WPTR) \
+ DMUB_SR(DMCUB_REGION3_CW0_OFFSET) \
+ DMUB_SR(DMCUB_REGION3_CW1_OFFSET) \
+ DMUB_SR(DMCUB_REGION3_CW2_OFFSET) \
+ DMUB_SR(DMCUB_REGION3_CW3_OFFSET) \
+ DMUB_SR(DMCUB_REGION3_CW4_OFFSET) \
+ DMUB_SR(DMCUB_REGION3_CW5_OFFSET) \
+ DMUB_SR(DMCUB_REGION3_CW6_OFFSET) \
+ DMUB_SR(DMCUB_REGION3_CW7_OFFSET) \
+ DMUB_SR(DMCUB_REGION3_CW0_OFFSET_HIGH) \
+ DMUB_SR(DMCUB_REGION3_CW1_OFFSET_HIGH) \
+ DMUB_SR(DMCUB_REGION3_CW2_OFFSET_HIGH) \
+ DMUB_SR(DMCUB_REGION3_CW3_OFFSET_HIGH) \
+ DMUB_SR(DMCUB_REGION3_CW4_OFFSET_HIGH) \
+ DMUB_SR(DMCUB_REGION3_CW5_OFFSET_HIGH) \
+ DMUB_SR(DMCUB_REGION3_CW6_OFFSET_HIGH) \
+ DMUB_SR(DMCUB_REGION3_CW7_OFFSET_HIGH) \
+ DMUB_SR(DMCUB_REGION3_CW0_BASE_ADDRESS) \
+ DMUB_SR(DMCUB_REGION3_CW1_BASE_ADDRESS) \
+ DMUB_SR(DMCUB_REGION3_CW2_BASE_ADDRESS) \
+ DMUB_SR(DMCUB_REGION3_CW3_BASE_ADDRESS) \
+ DMUB_SR(DMCUB_REGION3_CW4_BASE_ADDRESS) \
+ DMUB_SR(DMCUB_REGION3_CW5_BASE_ADDRESS) \
+ DMUB_SR(DMCUB_REGION3_CW6_BASE_ADDRESS) \
+ DMUB_SR(DMCUB_REGION3_CW7_BASE_ADDRESS) \
+ DMUB_SR(DMCUB_REGION3_CW0_TOP_ADDRESS) \
+ DMUB_SR(DMCUB_REGION3_CW1_TOP_ADDRESS) \
+ DMUB_SR(DMCUB_REGION3_CW2_TOP_ADDRESS) \
+ DMUB_SR(DMCUB_REGION3_CW3_TOP_ADDRESS) \
+ DMUB_SR(DMCUB_REGION3_CW4_TOP_ADDRESS) \
+ DMUB_SR(DMCUB_REGION3_CW5_TOP_ADDRESS) \
+ DMUB_SR(DMCUB_REGION3_CW6_TOP_ADDRESS) \
+ DMUB_SR(DMCUB_REGION3_CW7_TOP_ADDRESS) \
+ DMUB_SR(DMCUB_REGION4_OFFSET) \
+ DMUB_SR(DMCUB_REGION4_OFFSET_HIGH) \
+ DMUB_SR(DMCUB_REGION4_TOP_ADDRESS) \
+ DMUB_SR(DMCUB_REGION5_OFFSET) \
+ DMUB_SR(DMCUB_REGION5_OFFSET_HIGH) \
+ DMUB_SR(DMCUB_REGION5_TOP_ADDRESS) \
+ DMUB_SR(DMCUB_REGION6_OFFSET) \
+ DMUB_SR(DMCUB_REGION6_OFFSET_HIGH) \
+ DMUB_SR(DMCUB_REGION6_TOP_ADDRESS) \
+ DMUB_SR(DMCUB_SCRATCH0) \
+ DMUB_SR(DMCUB_SCRATCH1) \
+ DMUB_SR(DMCUB_SCRATCH2) \
+ DMUB_SR(DMCUB_SCRATCH3) \
+ DMUB_SR(DMCUB_SCRATCH4) \
+ DMUB_SR(DMCUB_SCRATCH5) \
+ DMUB_SR(DMCUB_SCRATCH6) \
+ DMUB_SR(DMCUB_SCRATCH7) \
+ DMUB_SR(DMCUB_SCRATCH8) \
+ DMUB_SR(DMCUB_SCRATCH9) \
+ DMUB_SR(DMCUB_SCRATCH10) \
+ DMUB_SR(DMCUB_SCRATCH11) \
+ DMUB_SR(DMCUB_SCRATCH12) \
+ DMUB_SR(DMCUB_SCRATCH13) \
+ DMUB_SR(DMCUB_SCRATCH14) \
+ DMUB_SR(DMCUB_SCRATCH15) \
+ DMUB_SR(DMCUB_SCRATCH16) \
+ DMUB_SR(DMCUB_SCRATCH17) \
+ DMUB_SR(DMCUB_SCRATCH18) \
+ DMUB_SR(DMCUB_SCRATCH19) \
+ DMUB_SR(DMCUB_SCRATCH20) \
+ DMUB_SR(DMCUB_SCRATCH21) \
+ DMUB_SR(DMCUB_GPINT_DATAIN0) \
+ DMUB_SR(DMCUB_GPINT_DATAIN1) \
+ DMUB_SR(DMCUB_GPINT_DATAOUT) \
+ DMUB_SR(MMHUBBUB_SOFT_RESET) \
+ DMUB_SR(DCN_VM_FB_LOCATION_BASE) \
+ DMUB_SR(DCN_VM_FB_OFFSET) \
+ DMUB_SR(DMCUB_TIMER_CURRENT) \
+ DMUB_SR(DMCUB_INST_FETCH_FAULT_ADDR) \
+ DMUB_SR(DMCUB_UNDEFINED_ADDRESS_FAULT_ADDR) \
+ DMUB_SR(DMCUB_DATA_WRITE_FAULT_ADDR) \
+ DMUB_SR(DMCUB_REGION3_TMR_AXI_SPACE) \
+ DMUB_SR(DMCUB_INTERRUPT_ENABLE) \
+ DMUB_SR(DMCUB_INTERRUPT_ACK) \
+ DMUB_SR(DMU_CLK_CNTL) \
DMUB_SR(DMCUB_INTERRUPT_STATUS) \
DMUB_SR(DMCUB_REG_INBOX0_RDY) \
DMUB_SR(DMCUB_REG_INBOX0_MSG0) \
@@ -59,7 +153,45 @@ struct dmub_srv;
DMUB_SR(HOST_INTERRUPT_CSR)
#define DMUB_DCN42_FIELDS() \
- DMUB_DCN35_FIELDS() \
+ DMUB_SF(DMCUB_CNTL, DMCUB_ENABLE) \
+ DMUB_SF(DMCUB_CNTL, DMCUB_TRACEPORT_EN) \
+ DMUB_SF(DMCUB_CNTL2, DMCUB_SOFT_RESET) \
+ DMUB_SF(DMCUB_SEC_CNTL, DMCUB_SEC_RESET) \
+ DMUB_SF(DMCUB_SEC_CNTL, DMCUB_MEM_UNIT_ID) \
+ DMUB_SF(DMCUB_SEC_CNTL, DMCUB_SEC_RESET_STATUS) \
+ DMUB_SF(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_TOP_ADDRESS) \
+ DMUB_SF(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_ENABLE) \
+ DMUB_SF(DMCUB_REGION3_CW1_TOP_ADDRESS, DMCUB_REGION3_CW1_TOP_ADDRESS) \
+ DMUB_SF(DMCUB_REGION3_CW1_TOP_ADDRESS, DMCUB_REGION3_CW1_ENABLE) \
+ DMUB_SF(DMCUB_REGION3_CW2_TOP_ADDRESS, DMCUB_REGION3_CW2_TOP_ADDRESS) \
+ DMUB_SF(DMCUB_REGION3_CW2_TOP_ADDRESS, DMCUB_REGION3_CW2_ENABLE) \
+ DMUB_SF(DMCUB_REGION3_CW3_TOP_ADDRESS, DMCUB_REGION3_CW3_TOP_ADDRESS) \
+ DMUB_SF(DMCUB_REGION3_CW3_TOP_ADDRESS, DMCUB_REGION3_CW3_ENABLE) \
+ DMUB_SF(DMCUB_REGION3_CW4_TOP_ADDRESS, DMCUB_REGION3_CW4_TOP_ADDRESS) \
+ DMUB_SF(DMCUB_REGION3_CW4_TOP_ADDRESS, DMCUB_REGION3_CW4_ENABLE) \
+ DMUB_SF(DMCUB_REGION3_CW5_TOP_ADDRESS, DMCUB_REGION3_CW5_TOP_ADDRESS) \
+ DMUB_SF(DMCUB_REGION3_CW5_TOP_ADDRESS, DMCUB_REGION3_CW5_ENABLE) \
+ DMUB_SF(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_TOP_ADDRESS) \
+ DMUB_SF(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE) \
+ DMUB_SF(DMCUB_REGION3_CW7_TOP_ADDRESS, DMCUB_REGION3_CW7_TOP_ADDRESS) \
+ DMUB_SF(DMCUB_REGION3_CW7_TOP_ADDRESS, DMCUB_REGION3_CW7_ENABLE) \
+ DMUB_SF(DMCUB_REGION4_TOP_ADDRESS, DMCUB_REGION4_TOP_ADDRESS) \
+ DMUB_SF(DMCUB_REGION4_TOP_ADDRESS, DMCUB_REGION4_ENABLE) \
+ DMUB_SF(DMCUB_REGION5_TOP_ADDRESS, DMCUB_REGION5_TOP_ADDRESS) \
+ DMUB_SF(DMCUB_REGION5_TOP_ADDRESS, DMCUB_REGION5_ENABLE) \
+ DMUB_SF(DMCUB_REGION6_TOP_ADDRESS, DMCUB_REGION6_TOP_ADDRESS) \
+ DMUB_SF(DMCUB_REGION6_TOP_ADDRESS, DMCUB_REGION6_ENABLE) \
+ DMUB_SF(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET) \
+ DMUB_SF(DCN_VM_FB_LOCATION_BASE, FB_BASE) \
+ DMUB_SF(DCN_VM_FB_OFFSET, FB_OFFSET) \
+ DMUB_SF(DMCUB_INBOX0_WPTR, DMCUB_INBOX0_WPTR) \
+ DMUB_SF(DMCUB_REGION3_TMR_AXI_SPACE, DMCUB_REGION3_TMR_AXI_SPACE) \
+ DMUB_SF(DMCUB_INTERRUPT_ENABLE, DMCUB_GPINT_IH_INT_EN) \
+ DMUB_SF(DMCUB_INTERRUPT_ACK, DMCUB_GPINT_IH_INT_ACK) \
+ DMUB_SF(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS) \
+ DMUB_SF(DMU_CLK_CNTL, LONO_DISPCLK_GATE_DISABLE) \
+ DMUB_SF(DMU_CLK_CNTL, LONO_SOCCLK_GATE_DISABLE) \
+ DMUB_SF(DMU_CLK_CNTL, LONO_DMCUBCLK_GATE_DISABLE) \
DMUB_SF(DMCUB_INTERRUPT_STATUS, DMCUB_REG_OUTBOX0_RSP_INT_STAT) \
DMUB_SF(HOST_INTERRUPT_CSR, HOST_REG_INBOX0_RSP_INT_ACK) \
DMUB_SF(HOST_INTERRUPT_CSR, HOST_REG_INBOX0_RSP_INT_STAT) \
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_reg.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_reg.c
index ca0c8a54b635..b5566ef8d4f3 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_reg.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_reg.c
@@ -45,6 +45,7 @@ static void set_reg_field_values(struct dmub_reg_value_masks *field_value_mask,
uint32_t mask1, uint32_t field_value1,
va_list ap)
{
+ (void)addr;
uint32_t shift, mask, field_value;
int i = 1;
@@ -57,8 +58,9 @@ static void set_reg_field_values(struct dmub_reg_value_masks *field_value_mask,
mask = va_arg(ap, uint32_t);
field_value = va_arg(ap, uint32_t);
+ ASSERT(shift <= 0xFF);
set_reg_field_value_masks(field_value_mask, field_value, mask,
- shift);
+ (uint8_t)shift);
i++;
}
}
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 3bba256a288d..10d23f5f5d94 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
@@ -1034,8 +1034,8 @@ enum dmub_status dmub_srv_wait_for_auto_load(struct dmub_srv *dmub,
static void dmub_srv_update_reg_inbox0_status(struct dmub_srv *dmub)
{
if (dmub->reg_inbox0.is_pending) {
- dmub->reg_inbox0.is_pending = dmub->hw_funcs.read_reg_inbox0_rsp_int_status &&
- !dmub->hw_funcs.read_reg_inbox0_rsp_int_status(dmub);
+ dmub->reg_inbox0.is_pending = (dmub->hw_funcs.read_reg_inbox0_rsp_int_status &&
+ !dmub->hw_funcs.read_reg_inbox0_rsp_int_status(dmub)) != 0;
if (!dmub->reg_inbox0.is_pending) {
/* ack the rsp interrupt */
@@ -1320,7 +1320,7 @@ void dmub_srv_set_power_state(struct dmub_srv *dmub, enum dmub_srv_power_state_t
enum dmub_status dmub_srv_reg_cmd_execute(struct dmub_srv *dmub, union dmub_rb_cmd *cmd)
{
- uint32_t num_pending = 0;
+ uint64_t num_pending = 0;
if (!dmub->hw_init)
return DMUB_STATUS_INVALID;
@@ -1348,7 +1348,7 @@ enum dmub_status dmub_srv_reg_cmd_execute(struct dmub_srv *dmub, union dmub_rb_c
dmub->reg_inbox0.num_submitted++;
dmub->reg_inbox0.is_pending = true;
- dmub->reg_inbox0.is_multi_pending = cmd->cmd_common.header.multi_cmd_pending;
+ dmub->reg_inbox0.is_multi_pending = cmd->cmd_common.header.multi_cmd_pending != 0;
return DMUB_STATUS_OK;
}
diff --git a/drivers/gpu/drm/amd/display/modules/color/color_gamma.c b/drivers/gpu/drm/amd/display/modules/color/color_gamma.c
index 2639163b8ba2..1f225d0d6c44 100644
--- a/drivers/gpu/drm/amd/display/modules/color/color_gamma.c
+++ b/drivers/gpu/drm/amd/display/modules/color/color_gamma.c
@@ -896,6 +896,7 @@ static void build_de_pq(struct pwl_float_data_ex *de_pq,
uint32_t hw_points_num,
const struct hw_x_point *coordinate_x)
{
+ (void)coordinate_x;
uint32_t i;
struct fixed31_32 output;
struct fixed31_32 *de_pq_table = mod_color_get_table(type_de_pq_table);
@@ -1339,6 +1340,7 @@ static void scale_gamma_dx(struct pwl_float_data *pwl_rgb,
const struct dc_gamma *ramp,
struct dividers dividers)
{
+ (void)dividers;
uint32_t i;
struct fixed31_32 min = dc_fixpt_zero;
struct fixed31_32 max = dc_fixpt_one;
diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
index 19de72173052..c9150019aab0 100644
--- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
+++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
@@ -114,6 +114,7 @@ static unsigned int calc_duration_in_us_from_v_total(
const struct mod_vrr_params *in_vrr,
unsigned int v_total)
{
+ (void)in_vrr;
unsigned int duration_in_us =
(unsigned int)(div64_u64(((unsigned long long)(v_total)
* 10000) * stream->timing.h_total,
@@ -218,6 +219,7 @@ static void update_v_total_for_static_ramp(
const struct dc_stream_state *stream,
struct mod_vrr_params *in_out_vrr)
{
+ (void)core_freesync;
unsigned int v_total = 0;
unsigned int current_duration_in_us =
calc_duration_in_us_from_v_total(
@@ -292,6 +294,7 @@ static void apply_below_the_range(struct core_freesync *core_freesync,
unsigned int last_render_time_in_us,
struct mod_vrr_params *in_out_vrr)
{
+ (void)core_freesync;
unsigned int inserted_frame_duration_in_us = 0;
unsigned int mid_point_frames_ceil = 0;
unsigned int mid_point_frames_floor = 0;
@@ -447,6 +450,7 @@ static void apply_fixed_refresh(struct core_freesync *core_freesync,
unsigned int last_render_time_in_us,
struct mod_vrr_params *in_out_vrr)
{
+ (void)core_freesync;
bool update = false;
unsigned int max_render_time_in_us = in_out_vrr->max_duration_in_us;
@@ -545,6 +549,7 @@ static bool vrr_settings_require_update(struct core_freesync *core_freesync,
unsigned int max_refresh_in_uhz,
struct mod_vrr_params *in_vrr)
{
+ (void)core_freesync;
if (in_vrr->state != in_config->state) {
return true;
} else if (in_vrr->state == VRR_STATE_ACTIVE_FIXED &&
@@ -946,6 +951,7 @@ void mod_freesync_build_vrr_infopacket(struct mod_freesync *mod_freesync,
struct dc_info_packet *infopacket,
bool pack_sdp_v1_3)
{
+ (void)mod_freesync;
/* SPD info packet for FreeSync
* VTEM info packet for HdmiVRR
* Check if Freesync is supported. Return if false. If true,
diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h
index 26a351a184f3..d07387a961dd 100644
--- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h
+++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h
@@ -501,6 +501,7 @@ static inline void callback_in_ms(uint16_t time, struct mod_hdcp_output *output)
static inline void set_watchdog_in_ms(struct mod_hdcp *hdcp, uint16_t time,
struct mod_hdcp_output *output)
{
+ (void)hdcp;
output->watchdog_timer_needed = 1;
output->watchdog_timer_delay = time;
}
diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_4_2_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_4_2_0_offset.h
index 52fbf2dc1899..3755a984681a 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_4_2_0_offset.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_4_2_0_offset.h
@@ -9036,6 +9036,8 @@
// base address: 0x40
#define regODM1_OPTC_INPUT_GLOBAL_CONTROL 0x1ada
#define regODM1_OPTC_INPUT_GLOBAL_CONTROL_BASE_IDX 2
+#define regODM1_OPTC_RSMU_UNDERFLOW 0x1adb
+#define regODM1_OPTC_RSMU_UNDERFLOW_BASE_IDX 2
#define regODM1_OPTC_UNDERFLOW_THRESHOLD 0x1adc
#define regODM1_OPTC_UNDERFLOW_THRESHOLD_BASE_IDX 2
#define regODM1_OPTC_DATA_SOURCE_SELECT 0x1add
@@ -9060,6 +9062,8 @@
// base address: 0x80
#define regODM2_OPTC_INPUT_GLOBAL_CONTROL 0x1aea
#define regODM2_OPTC_INPUT_GLOBAL_CONTROL_BASE_IDX 2
+#define regODM2_OPTC_RSMU_UNDERFLOW 0x1aeb
+#define regODM2_OPTC_RSMU_UNDERFLOW_BASE_IDX 2
#define regODM2_OPTC_UNDERFLOW_THRESHOLD 0x1aec
#define regODM2_OPTC_UNDERFLOW_THRESHOLD_BASE_IDX 2
#define regODM2_OPTC_DATA_SOURCE_SELECT 0x1aed
@@ -9084,6 +9088,8 @@
// base address: 0xc0
#define regODM3_OPTC_INPUT_GLOBAL_CONTROL 0x1afa
#define regODM3_OPTC_INPUT_GLOBAL_CONTROL_BASE_IDX 2
+#define regODM3_OPTC_RSMU_UNDERFLOW 0x1afb
+#define regODM3_OPTC_RSMU_UNDERFLOW_BASE_IDX 2
#define regODM3_OPTC_UNDERFLOW_THRESHOLD 0x1afc
#define regODM3_OPTC_UNDERFLOW_THRESHOLD_BASE_IDX 2
#define regODM3_OPTC_DATA_SOURCE_SELECT 0x1afd
diff --git a/drivers/gpu/drm/amd/include/atomfirmware.h b/drivers/gpu/drm/amd/include/atomfirmware.h
index 18f9642a42ee..62f7ed0b2066 100644
--- a/drivers/gpu/drm/amd/include/atomfirmware.h
+++ b/drivers/gpu/drm/amd/include/atomfirmware.h
@@ -1695,7 +1695,9 @@ struct atom_integrated_system_info_v2_3 {
uint8_t gpu_package_id;
struct edp_info_table edp1_info;
struct edp_info_table edp2_info;
- uint32_t reserved2[8];
+ uint32_t cpuid;
+ uint32_t vram_bit_width;
+ uint32_t reserved2[6];
struct atom_external_display_connection_info extdispconninfo;
uint8_t UMACarveoutVersion;
uint8_t UMACarveoutIndexMax;
@@ -1770,6 +1772,7 @@ enum atom_dmi_t17_mem_type_def{
Hbm2MemType, ///< Assign 33 to HBM2
Ddr5MemType, ///< Assign 34 to DDR5
LpDdr5MemType, ///< Assign 35 to LPDDR5
+ LpDdr5xMemType, ///< Assign 36 to LPDDR5x
};
diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
index a9b73f4fd466..1bbf531de5ed 100644
--- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h
+++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
@@ -119,6 +119,7 @@ enum pp_clock_type {
PP_ISPXCLK,
OD_SCLK,
OD_MCLK,
+ OD_FCLK,
OD_VDDC_CURVE,
OD_RANGE,
OD_VDDGFX_OFFSET,
@@ -208,6 +209,7 @@ enum {
enum PP_OD_DPM_TABLE_COMMAND {
PP_OD_EDIT_SCLK_VDDC_TABLE,
PP_OD_EDIT_MCLK_VDDC_TABLE,
+ PP_OD_EDIT_FCLK_TABLE,
PP_OD_EDIT_CCLK_VDDC_TABLE,
PP_OD_EDIT_VDDC_CURVE,
PP_OD_RESTORE_DEFAULT_TABLE,
@@ -585,8 +587,61 @@ enum amdgpu_metrics_attr_id {
AMDGPU_METRICS_ATTR_ID_GFX_LOW_UTILIZATION_ACC,
AMDGPU_METRICS_ATTR_ID_GFX_BELOW_HOST_LIMIT_TOTAL_ACC,
AMDGPU_METRICS_ATTR_ID_TEMPERATURE_HBM,
+ AMDGPU_METRICS_ATTR_ID_TEMPERATURE_MID,
AMDGPU_METRICS_ATTR_ID_TEMPERATURE_AID,
AMDGPU_METRICS_ATTR_ID_TEMPERATURE_XCD,
+ AMDGPU_METRICS_ATTR_ID_LABEL_VERSION,
+ AMDGPU_METRICS_ATTR_ID_NODE_ID,
+ AMDGPU_METRICS_ATTR_ID_NODE_TEMP_RETIMER,
+ AMDGPU_METRICS_ATTR_ID_NODE_TEMP_IBC,
+ AMDGPU_METRICS_ATTR_ID_NODE_TEMP_IBC_2,
+ AMDGPU_METRICS_ATTR_ID_NODE_TEMP_VDD18_VR,
+ AMDGPU_METRICS_ATTR_ID_NODE_TEMP_04_HBM_B_VR,
+ AMDGPU_METRICS_ATTR_ID_NODE_TEMP_04_HBM_D_VR,
+ AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDCR_SOCIO_A,
+ AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDCR_SOCIO_C,
+ AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDCR_X0,
+ AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDCR_X1,
+ AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDIO_HBM_B,
+ AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDIO_HBM_D,
+ AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDIO_04_HBM_B,
+ AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDIO_04_HBM_D,
+ AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDCR_HBM_B,
+ AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDCR_HBM_D,
+ AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDCR_075_HBM_B,
+ AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDCR_075_HBM_D,
+ AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDIO_11_GTA_A,
+ AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDIO_11_GTA_C,
+ AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDAN_075_GTA_A,
+ AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDAN_075_GTA_C,
+ AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDCR_075_UCIE,
+ AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDIO_065_UCIEAA,
+ AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDIO_065_UCIEAM_A,
+ AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDIO_065_UCIEAM_C,
+ AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDAN_075,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_UBB_FPGA,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_UBB_FRONT,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_UBB_BACK,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_UBB_OAM7,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_UBB_IBC,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_UBB_UFPGA,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_UBB_OAM1,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_OAM_0_1_HSC,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_OAM_2_3_HSC,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_OAM_4_5_HSC,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_OAM_6_7_HSC,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_UBB_FPGA_0V72_VR,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_UBB_FPGA_3V3_VR,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_RETIMER_0_1_2_3_1V2_VR,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_RETIMER_4_5_6_7_1V2_VR,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_RETIMER_0_1_0V9_VR,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_RETIMER_4_5_0V9_VR,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_RETIMER_2_3_0V9_VR,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_RETIMER_6_7_0V9_VR,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_OAM_0_1_2_3_3V3_VR,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_OAM_4_5_6_7_3V3_VR,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_IBC_HSC,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_IBC,
AMDGPU_METRICS_ATTR_ID_MAX,
};
@@ -1839,4 +1894,16 @@ enum amdgpu_xgmi_link_status {
AMDGPU_XGMI_LINK_NA = 2,
};
+struct amdgpu_gpuboard_temp_metrics_v1_1 {
+ struct metrics_table_header common_header;
+ int attr_count;
+ struct gpu_metrics_attr metrics_attrs[];
+};
+
+struct amdgpu_baseboard_temp_metrics_v1_1 {
+ struct metrics_table_header common_header;
+ int attr_count;
+ struct gpu_metrics_attr metrics_attrs[];
+};
+
#endif
diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c
index eca93a9d0b84..62b0b1ef0d10 100644
--- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c
@@ -33,6 +33,7 @@
#include <linux/hwmon-sysfs.h>
#include <linux/nospec.h>
#include <linux/pm_runtime.h>
+#include <linux/string_choices.h>
#include <asm/processor.h>
#define MAX_NUM_OF_FEATURES_PER_SUBSET 8
@@ -680,6 +681,8 @@ static ssize_t amdgpu_set_pp_table(struct device *dev,
* - minimum(not available for Vega20 and Navi1x) and maximum memory
* clock labeled OD_MCLK
*
+ * - minimum and maximum fabric clock labeled OD_FCLK (SMU13)
+ *
* - three <frequency, voltage> points labeled OD_VDDC_CURVE.
* They can be used to calibrate the sclk voltage curve. This is
* available for Vega20 and NV1X.
@@ -715,10 +718,11 @@ static ssize_t amdgpu_set_pp_table(struct device *dev,
* - First select manual using power_dpm_force_performance_level
*
* - For clock frequency setting, enter a new value by writing a
- * string that contains "s/m index clock" to the file. The index
+ * string that contains "s/m/f index clock" to the file. The index
* should be 0 if to set minimum clock. And 1 if to set maximum
* clock. E.g., "s 0 500" will update minimum sclk to be 500 MHz.
- * "m 1 800" will update maximum mclk to be 800Mhz. For core
+ * "m 1 800" will update maximum mclk to be 800Mhz. "f 1 1600" will
+ * update maximum fabric clock to be 1600Mhz. For core
* clocks on VanGogh, the string contains "p core index clock".
* E.g., "p 2 0 800" would set the minimum core clock on core
* 2 to 800Mhz.
@@ -768,6 +772,8 @@ static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev,
type = PP_OD_EDIT_CCLK_VDDC_TABLE;
else if (*buf == 'm')
type = PP_OD_EDIT_MCLK_VDDC_TABLE;
+ else if (*buf == 'f')
+ type = PP_OD_EDIT_FCLK_TABLE;
else if (*buf == 'r')
type = PP_OD_RESTORE_DEFAULT_TABLE;
else if (*buf == 'c')
@@ -843,9 +849,10 @@ static ssize_t amdgpu_get_pp_od_clk_voltage(struct device *dev,
struct amdgpu_device *adev = drm_to_adev(ddev);
int size = 0;
int ret;
- enum pp_clock_type od_clocks[6] = {
+ enum pp_clock_type od_clocks[] = {
OD_SCLK,
OD_MCLK,
+ OD_FCLK,
OD_VDDC_CURVE,
OD_RANGE,
OD_VDDGFX_OFFSET,
@@ -857,10 +864,8 @@ static ssize_t amdgpu_get_pp_od_clk_voltage(struct device *dev,
if (ret)
return ret;
- for (clk_index = 0 ; clk_index < 6 ; clk_index++) {
- ret = amdgpu_dpm_emit_clock_levels(adev, od_clocks[clk_index], buf, &size);
- if (ret)
- break;
+ for (clk_index = 0 ; clk_index < ARRAY_SIZE(od_clocks) ; clk_index++) {
+ amdgpu_dpm_emit_clock_levels(adev, od_clocks[clk_index], buf, &size);
}
if (size == 0)
@@ -1588,7 +1593,7 @@ static ssize_t amdgpu_get_thermal_throttling_logging(struct device *dev,
return sysfs_emit(buf, "%s: thermal throttling logging %s, with interval %d seconds\n",
adev_to_drm(adev)->unique,
- atomic_read(&adev->throttling_logging_enabled) ? "enabled" : "disabled",
+ str_enabled_disabled(atomic_read(&adev->throttling_logging_enabled)),
adev->throttling_logging_rs.interval / HZ + 1);
}
@@ -1910,8 +1915,6 @@ static int ss_bias_attr_update(struct amdgpu_device *adev, struct amdgpu_device_
static int pp_od_clk_voltage_attr_update(struct amdgpu_device *adev, struct amdgpu_device_attr *attr,
uint32_t mask, enum amdgpu_device_attr_states *states)
{
- uint32_t gc_ver = amdgpu_ip_version(adev, GC_HWIP, 0);
-
*states = ATTR_STATE_SUPPORTED;
if (!amdgpu_dpm_is_overdrive_supported(adev)) {
@@ -1919,10 +1922,8 @@ static int pp_od_clk_voltage_attr_update(struct amdgpu_device *adev, struct amdg
return 0;
}
- /* Enable pp_od_clk_voltage node for gc 9.4.3, 9.4.4, 9.5.0 SRIOV/BM support */
- if (gc_ver == IP_VERSION(9, 4, 3) ||
- gc_ver == IP_VERSION(9, 4, 4) ||
- gc_ver == IP_VERSION(9, 5, 0)) {
+ /* Enable pp_od_clk_voltage node for gc 9.4.3, 9.4.4, 9.5.0, 12.1.0 SRIOV/BM support */
+ if (amdgpu_is_multi_aid(adev)) {
if (amdgpu_sriov_multi_vf_mode(adev))
*states = ATTR_STATE_UNSUPPORTED;
return 0;
@@ -2000,9 +2001,7 @@ static int pp_dpm_clk_default_attr_update(struct amdgpu_device *adev, struct amd
gc_ver == IP_VERSION(11, 5, 0) ||
gc_ver == IP_VERSION(11, 0, 2) ||
gc_ver == IP_VERSION(11, 0, 3) ||
- gc_ver == IP_VERSION(9, 4, 3) ||
- gc_ver == IP_VERSION(9, 4, 4) ||
- gc_ver == IP_VERSION(9, 5, 0)))
+ amdgpu_is_multi_aid(adev)))
*states = ATTR_STATE_UNSUPPORTED;
} else if (DEVICE_ATTR_IS(pp_dpm_vclk1)) {
if (!((gc_ver == IP_VERSION(10, 3, 1) ||
@@ -2023,9 +2022,7 @@ static int pp_dpm_clk_default_attr_update(struct amdgpu_device *adev, struct amd
gc_ver == IP_VERSION(11, 5, 0) ||
gc_ver == IP_VERSION(11, 0, 2) ||
gc_ver == IP_VERSION(11, 0, 3) ||
- gc_ver == IP_VERSION(9, 4, 3) ||
- gc_ver == IP_VERSION(9, 4, 4) ||
- gc_ver == IP_VERSION(9, 5, 0)))
+ amdgpu_is_multi_aid(adev)))
*states = ATTR_STATE_UNSUPPORTED;
} else if (DEVICE_ATTR_IS(pp_dpm_dclk1)) {
if (!((gc_ver == IP_VERSION(10, 3, 1) ||
@@ -2035,9 +2032,7 @@ static int pp_dpm_clk_default_attr_update(struct amdgpu_device *adev, struct amd
*states = ATTR_STATE_UNSUPPORTED;
} else if (DEVICE_ATTR_IS(pp_dpm_pcie)) {
if (gc_ver == IP_VERSION(9, 4, 2) ||
- gc_ver == IP_VERSION(9, 4, 3) ||
- gc_ver == IP_VERSION(9, 4, 4) ||
- gc_ver == IP_VERSION(9, 5, 0))
+ amdgpu_is_multi_aid(adev))
*states = ATTR_STATE_UNSUPPORTED;
}
@@ -2241,7 +2236,7 @@ static ssize_t amdgpu_show_npm_status(struct device *dev,
if (r)
return r;
- return sysfs_emit(buf, "%s\n", npower ? "enabled" : "disabled");
+ return sysfs_emit(buf, "%s\n", str_enabled_disabled(npower));
}
/**
@@ -2651,6 +2646,7 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_
case IP_VERSION(11, 0, 3):
case IP_VERSION(12, 0, 0):
case IP_VERSION(12, 0, 1):
+ case IP_VERSION(12, 1, 0):
*states = ATTR_STATE_SUPPORTED;
break;
default:
@@ -3732,8 +3728,7 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,
/* Skip crit temp on APU */
if ((((adev->flags & AMD_IS_APU) && (adev->family >= AMDGPU_FAMILY_CZ)) ||
- (gc_ver == IP_VERSION(9, 4, 3) || gc_ver == IP_VERSION(9, 4, 4) ||
- gc_ver == IP_VERSION(9, 5, 0))) &&
+ amdgpu_is_multi_aid(adev)) &&
(attr == &sensor_dev_attr_temp1_crit.dev_attr.attr ||
attr == &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr))
return 0;
@@ -3815,18 +3810,14 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,
if ((adev->family == AMDGPU_FAMILY_SI || /* not implemented yet */
adev->family == AMDGPU_FAMILY_KV || /* not implemented yet */
- (gc_ver == IP_VERSION(9, 4, 3) ||
- gc_ver == IP_VERSION(9, 4, 4) ||
- gc_ver == IP_VERSION(9, 5, 0))) &&
+ amdgpu_is_multi_aid(adev)) &&
(attr == &sensor_dev_attr_in0_input.dev_attr.attr ||
attr == &sensor_dev_attr_in0_label.dev_attr.attr))
return 0;
/* only APUs other than gc 9,4,3 have vddnb */
if ((!(adev->flags & AMD_IS_APU) ||
- (gc_ver == IP_VERSION(9, 4, 3) ||
- gc_ver == IP_VERSION(9, 4, 4) ||
- gc_ver == IP_VERSION(9, 5, 0))) &&
+ amdgpu_is_multi_aid(adev)) &&
(attr == &sensor_dev_attr_in1_input.dev_attr.attr ||
attr == &sensor_dev_attr_in1_label.dev_attr.attr))
return 0;
@@ -3855,9 +3846,7 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,
return 0;
/* hotspot temperature for gc 9,4,3*/
- if (gc_ver == IP_VERSION(9, 4, 3) ||
- gc_ver == IP_VERSION(9, 4, 4) ||
- gc_ver == IP_VERSION(9, 5, 0)) {
+ if (amdgpu_is_multi_aid(adev)) {
if (attr == &sensor_dev_attr_temp1_input.dev_attr.attr ||
attr == &sensor_dev_attr_temp1_emergency.dev_attr.attr ||
attr == &sensor_dev_attr_temp1_label.dev_attr.attr)
diff --git a/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c b/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c
index 61b1c5aa74cb..36942467d4ad 100644
--- a/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c
+++ b/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c
@@ -3454,9 +3454,11 @@ static void si_apply_state_adjust_rules(struct amdgpu_device *adev,
if (adev->asic_type == CHIP_HAINAN) {
if ((adev->pdev->revision == 0x81) ||
(adev->pdev->revision == 0xC3) ||
+ (adev->pdev->device == 0x6660) ||
(adev->pdev->device == 0x6664) ||
(adev->pdev->device == 0x6665) ||
- (adev->pdev->device == 0x6667)) {
+ (adev->pdev->device == 0x6667) ||
+ (adev->pdev->device == 0x666F)) {
max_sclk = 75000;
}
if ((adev->pdev->revision == 0xC3) ||
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr.c
index 2b5ac21fee39..1d6e30269d56 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr.c
@@ -104,6 +104,21 @@ int hwmgr_early_init(struct pp_hwmgr *hwmgr)
PP_GFXOFF_MASK);
hwmgr->pp_table_version = PP_TABLE_V0;
hwmgr->od_enabled = false;
+ switch (hwmgr->chip_id) {
+ case CHIP_BONAIRE:
+ /* R9 M380 in iMac 2015: SMU hangs when enabling MCLK DPM
+ * R7 260X cards with old MC ucode: MCLK DPM is unstable
+ */
+ if (adev->pdev->subsystem_vendor == 0x106B ||
+ adev->pdev->device == 0x6658) {
+ dev_info(adev->dev, "disabling MCLK DPM on quirky ASIC");
+ adev->pm.pp_feature &= ~PP_MCLK_DPM_MASK;
+ hwmgr->feature_mask &= ~PP_MCLK_DPM_MASK;
+ }
+ break;
+ default:
+ break;
+ }
smu7_init_function_pointers(hwmgr);
break;
case AMDGPU_FAMILY_CZ:
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
index e38222877f7e..8c37aa452569 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
@@ -787,7 +787,7 @@ static int smu7_setup_dpm_tables_v0(struct pp_hwmgr *hwmgr)
hwmgr->dyn_state.vddc_dependency_on_mclk;
struct phm_cac_leakage_table *std_voltage_table =
hwmgr->dyn_state.cac_leakage_table;
- uint32_t i;
+ uint32_t i, clk;
PP_ASSERT_WITH_CODE(allowed_vdd_sclk_table != NULL,
"SCLK dependency table is missing. This table is mandatory", return -EINVAL);
@@ -804,10 +804,12 @@ static int smu7_setup_dpm_tables_v0(struct pp_hwmgr *hwmgr)
data->dpm_table.sclk_table.count = 0;
for (i = 0; i < allowed_vdd_sclk_table->count; i++) {
+ clk = min(allowed_vdd_sclk_table->entries[i].clk, data->sclk_cap);
+
if (i == 0 || data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count-1].value !=
- allowed_vdd_sclk_table->entries[i].clk) {
+ clk) {
data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count].value =
- allowed_vdd_sclk_table->entries[i].clk;
+ clk;
data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count].enabled = (i == 0) ? 1 : 0;
data->dpm_table.sclk_table.count++;
}
@@ -2794,11 +2796,11 @@ static int smu7_patch_dependency_tables_with_leakage(struct pp_hwmgr *hwmgr)
if (tmp)
return -EINVAL;
- tmp = smu7_patch_vddc(hwmgr, hwmgr->dyn_state.vddc_dep_on_dal_pwrl);
+ tmp = smu7_patch_vddci(hwmgr, hwmgr->dyn_state.vddci_dependency_on_mclk);
if (tmp)
return -EINVAL;
- tmp = smu7_patch_vddci(hwmgr, hwmgr->dyn_state.vddci_dependency_on_mclk);
+ tmp = smu7_patch_vddc(hwmgr, hwmgr->dyn_state.vddc_dependency_on_display_clock);
if (tmp)
return -EINVAL;
@@ -2883,8 +2885,8 @@ static int smu7_set_private_data_based_on_pptable_v0(struct pp_hwmgr *hwmgr)
static int smu7_hwmgr_backend_fini(struct pp_hwmgr *hwmgr)
{
- kfree(hwmgr->dyn_state.vddc_dep_on_dal_pwrl);
- hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL;
+ kfree(hwmgr->dyn_state.vddc_dependency_on_display_clock);
+ hwmgr->dyn_state.vddc_dependency_on_display_clock = NULL;
kfree(hwmgr->backend);
hwmgr->backend = NULL;
@@ -2955,6 +2957,70 @@ static int smu7_update_edc_leakage_table(struct pp_hwmgr *hwmgr)
return ret;
}
+static int smu7_init_voltage_dependency_on_display_clock_table(struct pp_hwmgr *hwmgr)
+{
+ struct phm_clock_voltage_dependency_table *table;
+
+ if (!amdgpu_device_ip_get_ip_block(hwmgr->adev, AMD_IP_BLOCK_TYPE_DCE))
+ return 0;
+
+ table = kzalloc(struct_size(table, entries, 4), GFP_KERNEL);
+ if (!table)
+ return -ENOMEM;
+
+ if (hwmgr->chip_id >= CHIP_POLARIS10) {
+ table->entries[0].clk = 38918;
+ table->entries[1].clk = 45900;
+ table->entries[2].clk = 66700;
+ table->entries[3].clk = 113200;
+
+ table->entries[0].v = 700;
+ table->entries[1].v = 740;
+ table->entries[2].v = 800;
+ table->entries[3].v = 900;
+ } else {
+ if (hwmgr->chip_family == AMDGPU_FAMILY_CZ) {
+ table->entries[0].clk = 35200;
+ table->entries[1].clk = 35200;
+ table->entries[2].clk = 46700;
+ table->entries[3].clk = 64300;
+ } else {
+ table->entries[0].clk = 0;
+ table->entries[1].clk = 35200;
+ table->entries[2].clk = 54000;
+ table->entries[3].clk = 62500;
+ }
+
+ table->entries[0].v = 0;
+ table->entries[1].v = 720;
+ table->entries[2].v = 810;
+ table->entries[3].v = 900;
+ }
+
+ table->count = 4;
+ hwmgr->dyn_state.vddc_dependency_on_display_clock = table;
+ return 0;
+}
+
+static void smu7_set_sclk_cap(struct pp_hwmgr *hwmgr)
+{
+ struct amdgpu_device *adev = hwmgr->adev;
+ struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
+
+ data->sclk_cap = 0xffffffff;
+
+ if (hwmgr->od_enabled)
+ return;
+
+ /* R9 390X board: last sclk dpm level is unstable, use lower sclk */
+ if (adev->pdev->device == 0x67B0 &&
+ adev->pdev->subsystem_vendor == 0x1043)
+ data->sclk_cap = 104000; /* 1040 MHz */
+
+ if (data->sclk_cap != 0xffffffff)
+ dev_info(adev->dev, "sclk cap: %u kHz on quirky ASIC\n", data->sclk_cap * 10);
+}
+
static int smu7_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
{
struct amdgpu_device *adev = hwmgr->adev;
@@ -2966,6 +3032,7 @@ static int smu7_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
return -ENOMEM;
hwmgr->backend = data;
+ smu7_set_sclk_cap(hwmgr);
smu7_patch_voltage_workaround(hwmgr);
smu7_init_dpm_defaults(hwmgr);
@@ -2983,6 +3050,10 @@ static int smu7_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
smu7_get_elb_voltages(hwmgr);
}
+ result = smu7_init_voltage_dependency_on_display_clock_table(hwmgr);
+ if (result)
+ goto fail;
+
if (hwmgr->pp_table_version == PP_TABLE_V1) {
smu7_complete_dependency_tables(hwmgr);
smu7_set_private_data_based_on_pptable_v1(hwmgr);
@@ -2991,9 +3062,6 @@ static int smu7_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
smu7_set_private_data_based_on_pptable_v0(hwmgr);
}
- /* Initalize Dynamic State Adjustment Rule Settings */
- result = phm_initializa_dynamic_state_adjustment_rule_settings(hwmgr);
-
if (result)
goto fail;
@@ -3079,13 +3147,40 @@ static int smu7_force_dpm_highest(struct pp_hwmgr *hwmgr)
return 0;
}
+static uint32_t smu7_lookup_vddc_from_dispclk(struct pp_hwmgr *hwmgr)
+{
+ const struct amd_pp_display_configuration *cfg = hwmgr->display_config;
+ const struct phm_clock_voltage_dependency_table *vddc_dep_on_dispclk =
+ hwmgr->dyn_state.vddc_dependency_on_display_clock;
+ uint32_t i;
+
+ if (!vddc_dep_on_dispclk || !vddc_dep_on_dispclk->count ||
+ !cfg || !cfg->num_display || !cfg->display_clk)
+ return 0;
+
+ /* Start from 1 because ClocksStateUltraLow should not be used according to DC. */
+ for (i = 1; i < vddc_dep_on_dispclk->count; ++i)
+ if (vddc_dep_on_dispclk->entries[i].clk >= cfg->display_clk)
+ return vddc_dep_on_dispclk->entries[i].v;
+
+ return vddc_dep_on_dispclk->entries[vddc_dep_on_dispclk->count - 1].v;
+}
+
+static void smu7_apply_minimum_dce_voltage_request(struct pp_hwmgr *hwmgr)
+{
+ uint32_t req_vddc = smu7_lookup_vddc_from_dispclk(hwmgr);
+
+ smum_send_msg_to_smc_with_parameter(hwmgr,
+ PPSMC_MSG_VddC_Request,
+ req_vddc * VOLTAGE_SCALE,
+ NULL);
+}
+
static int smu7_upload_dpm_level_enable_mask(struct pp_hwmgr *hwmgr)
{
struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
- if (hwmgr->pp_table_version == PP_TABLE_V1)
- phm_apply_dal_min_voltage_request(hwmgr);
-/* TO DO for v0 iceland and Ci*/
+ smu7_apply_minimum_dce_voltage_request(hwmgr);
if (!data->sclk_dpm_key_disabled) {
if (data->dpm_level_enable_mask.sclk_dpm_enable_mask)
@@ -3821,7 +3916,7 @@ static int smu7_get_pp_table_entry_callback_func_v0(struct pp_hwmgr *hwmgr,
/* Performance levels are arranged from low to high. */
performance_level->memory_clock = memory_clock;
- performance_level->engine_clock = engine_clock;
+ performance_level->engine_clock = min(engine_clock, data->sclk_cap);
pcie_gen_from_bios = visland_clk_info->ucPCIEGen;
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.h
index d9e8b386bd4d..66adabeab6a3 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.h
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.h
@@ -234,6 +234,7 @@ struct smu7_hwmgr {
uint32_t pcie_gen_cap;
uint32_t pcie_lane_cap;
uint32_t pcie_spc_cap;
+ uint32_t sclk_cap;
struct smu7_leakage_voltage vddc_leakage;
struct smu7_leakage_voltage vddci_leakage;
struct smu7_leakage_voltage vddcgfx_leakage;
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.c
index 40ecaac6c604..30d83e18db40 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.c
@@ -484,52 +484,6 @@ int phm_get_sclk_for_voltage_evv(struct pp_hwmgr *hwmgr,
return 0;
}
-/**
- * phm_initializa_dynamic_state_adjustment_rule_settings - Initialize Dynamic State Adjustment Rule Settings
- *
- * @hwmgr: the address of the powerplay hardware manager.
- */
-int phm_initializa_dynamic_state_adjustment_rule_settings(struct pp_hwmgr *hwmgr)
-{
- struct phm_clock_voltage_dependency_table *table_clk_vlt;
- struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
-
- /* initialize vddc_dep_on_dal_pwrl table */
- table_clk_vlt = kzalloc_flex(*table_clk_vlt, entries, 4);
-
- if (NULL == table_clk_vlt) {
- pr_err("Can not allocate space for vddc_dep_on_dal_pwrl! \n");
- return -ENOMEM;
- } else {
- table_clk_vlt->count = 4;
- table_clk_vlt->entries[0].clk = PP_DAL_POWERLEVEL_ULTRALOW;
- if (hwmgr->chip_id >= CHIP_POLARIS10 &&
- hwmgr->chip_id <= CHIP_VEGAM)
- table_clk_vlt->entries[0].v = 700;
- else
- table_clk_vlt->entries[0].v = 0;
- table_clk_vlt->entries[1].clk = PP_DAL_POWERLEVEL_LOW;
- if (hwmgr->chip_id >= CHIP_POLARIS10 &&
- hwmgr->chip_id <= CHIP_VEGAM)
- table_clk_vlt->entries[1].v = 740;
- else
- table_clk_vlt->entries[1].v = 720;
- table_clk_vlt->entries[2].clk = PP_DAL_POWERLEVEL_NOMINAL;
- if (hwmgr->chip_id >= CHIP_POLARIS10 &&
- hwmgr->chip_id <= CHIP_VEGAM)
- table_clk_vlt->entries[2].v = 800;
- else
- table_clk_vlt->entries[2].v = 810;
- table_clk_vlt->entries[3].clk = PP_DAL_POWERLEVEL_PERFORMANCE;
- table_clk_vlt->entries[3].v = 900;
- if (pptable_info != NULL)
- pptable_info->vddc_dep_on_dal_pwrl = table_clk_vlt;
- hwmgr->dyn_state.vddc_dep_on_dal_pwrl = table_clk_vlt;
- }
-
- return 0;
-}
-
uint32_t phm_get_lowest_enabled_level(struct pp_hwmgr *hwmgr, uint32_t mask)
{
uint32_t level = 0;
@@ -540,43 +494,6 @@ uint32_t phm_get_lowest_enabled_level(struct pp_hwmgr *hwmgr, uint32_t mask)
return level;
}
-void phm_apply_dal_min_voltage_request(struct pp_hwmgr *hwmgr)
-{
- struct phm_ppt_v1_information *table_info =
- (struct phm_ppt_v1_information *)hwmgr->pptable;
- struct phm_clock_voltage_dependency_table *table =
- table_info->vddc_dep_on_dal_pwrl;
- struct phm_ppt_v1_clock_voltage_dependency_table *vddc_table;
- enum PP_DAL_POWERLEVEL dal_power_level = hwmgr->dal_power_level;
- uint32_t req_vddc = 0, req_volt, i;
-
- if (!table || table->count <= 0
- || dal_power_level < PP_DAL_POWERLEVEL_ULTRALOW
- || dal_power_level > PP_DAL_POWERLEVEL_PERFORMANCE)
- return;
-
- for (i = 0; i < table->count; i++) {
- if (dal_power_level == table->entries[i].clk) {
- req_vddc = table->entries[i].v;
- break;
- }
- }
-
- vddc_table = table_info->vdd_dep_on_sclk;
- for (i = 0; i < vddc_table->count; i++) {
- if (req_vddc <= vddc_table->entries[i].vddc) {
- req_volt = (((uint32_t)vddc_table->entries[i].vddc) * VOLTAGE_SCALE);
- smum_send_msg_to_smc_with_parameter(hwmgr,
- PPSMC_MSG_VddC_Request,
- req_volt,
- NULL);
- return;
- }
- }
- pr_err("DAL requested level can not"
- " found a available voltage in VDDC DPM Table \n");
-}
-
int phm_get_voltage_evv_on_sclk(struct pp_hwmgr *hwmgr, uint8_t voltage_type,
uint32_t sclk, uint16_t id, uint16_t *voltage)
{
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.h
index 83b3c9315143..d370bfd0764d 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.h
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.h
@@ -87,9 +87,7 @@ extern uint16_t phm_find_closest_vddci(struct pp_atomctrl_voltage_table *vddci_t
extern int phm_find_boot_level(void *table, uint32_t value, uint32_t *boot_level);
extern int phm_get_sclk_for_voltage_evv(struct pp_hwmgr *hwmgr, phm_ppt_v1_voltage_lookup_table *lookup_table,
uint16_t virtual_voltage_id, int32_t *sclk);
-extern int phm_initializa_dynamic_state_adjustment_rule_settings(struct pp_hwmgr *hwmgr);
extern uint32_t phm_get_lowest_enabled_level(struct pp_hwmgr *hwmgr, uint32_t mask);
-extern void phm_apply_dal_min_voltage_request(struct pp_hwmgr *hwmgr);
extern int phm_get_voltage_evv_on_sclk(struct pp_hwmgr *hwmgr, uint8_t voltage_type,
uint32_t sclk, uint16_t id, uint16_t *voltage);
diff --git a/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h
index c661185753b4..3ae45eac0c5c 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h
+++ b/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h
@@ -631,6 +631,7 @@ struct phm_dynamic_state_info {
struct phm_clock_voltage_dependency_table *vddci_dependency_on_mclk;
struct phm_clock_voltage_dependency_table *vddc_dependency_on_mclk;
struct phm_clock_voltage_dependency_table *mvdd_dependency_on_mclk;
+ struct phm_clock_voltage_dependency_table *vddc_dependency_on_display_clock;
struct phm_clock_voltage_dependency_table *vddc_dep_on_dal_pwrl;
struct phm_clock_array *valid_sclk_values;
struct phm_clock_array *valid_mclk_values;
@@ -772,7 +773,6 @@ struct pp_hwmgr {
const struct pp_smumgr_func *smumgr_funcs;
bool is_kicker;
- enum PP_DAL_POWERLEVEL dal_power_level;
struct phm_dynamic_state_info dyn_state;
const struct pp_hwmgr_func *hwmgr_func;
const struct pp_table_func *pptable_func;
diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c
index 62ebec1c6fe3..731355bdb9bc 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c
@@ -245,7 +245,7 @@ static void ci_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr)
smu_data->power_tune_defaults = &defaults_hawaii_pro;
break;
case 0x67B8:
- case 0x66B0:
+ case 0x67B0:
smu_data->power_tune_defaults = &defaults_hawaii_xt;
break;
case 0x6640:
@@ -543,12 +543,11 @@ static int ci_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset)
{
struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend);
const struct ci_pt_defaults *defaults = smu_data->power_tune_defaults;
- uint32_t temp;
if (ci_read_smc_sram_dword(hwmgr,
fuse_table_offset +
offsetof(SMU7_Discrete_PmFuses, TdcWaterfallCtl),
- (uint32_t *)&temp, SMC_RAM_END))
+ (uint32_t *)&smu_data->power_tune_table.TdcWaterfallCtl, SMC_RAM_END))
PP_ASSERT_WITH_CODE(false,
"Attempt to read PmFuses.DW6 (SviLoadLineEn) from SMC Failed!",
return -EINVAL);
@@ -1217,7 +1216,7 @@ static int ci_populate_single_memory_level(
}
memory_level->EnabledForThrottle = 1;
- memory_level->EnabledForActivity = 1;
+ memory_level->EnabledForActivity = 0;
memory_level->UpH = data->current_profile_setting.mclk_up_hyst;
memory_level->DownH = data->current_profile_setting.mclk_down_hyst;
memory_level->VoltageDownH = 0;
@@ -1322,6 +1321,14 @@ static int ci_populate_all_memory_levels(struct pp_hwmgr *hwmgr)
return result;
}
+ if (data->mclk_dpm_key_disabled && dpm_table->mclk_table.count) {
+ /* Populate the table with the highest MCLK level when MCLK DPM is disabled */
+ for (i = 0; i < dpm_table->mclk_table.count - 1; i++) {
+ levels[i] = levels[dpm_table->mclk_table.count - 1];
+ levels[i].DisplayWatermark = PPSMC_DISPLAY_WATERMARK_HIGH;
+ }
+ }
+
smu_data->smc_state_table.MemoryLevel[0].EnabledForActivity = 1;
dev_id = adev->pdev->device;
diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
index 26b43a6276d0..8faf7de7aaa9 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
@@ -47,6 +47,7 @@
#include "smu_v14_0_0_ppt.h"
#include "smu_v14_0_2_ppt.h"
#include "smu_v15_0_0_ppt.h"
+#include "smu_v15_0_8_ppt.h"
#include "amd_pcie.h"
/*
@@ -802,6 +803,10 @@ static int smu_set_funcs(struct amdgpu_device *adev)
case IP_VERSION(15, 0, 0):
smu_v15_0_0_set_ppt_funcs(smu);
break;
+ case IP_VERSION(15, 0, 8):
+ smu_v15_0_8_set_ppt_funcs(smu);
+ smu->od_enabled = true;
+ break;
default:
return -EINVAL;
}
@@ -2965,6 +2970,7 @@ int smu_get_power_limit(void *handle,
case IP_VERSION(11, 0, 11):
case IP_VERSION(11, 0, 12):
case IP_VERSION(11, 0, 13):
+ case IP_VERSION(15, 0, 8):
ret = smu_get_asic_power_limits(smu,
&smu->current_power_limit,
NULL, NULL, NULL);
@@ -3056,6 +3062,8 @@ static enum smu_clk_type smu_convert_to_smuclk(enum pp_clock_type type)
clk_type = SMU_OD_SCLK; break;
case OD_MCLK:
clk_type = SMU_OD_MCLK; break;
+ case OD_FCLK:
+ clk_type = SMU_OD_FCLK; break;
case OD_VDDC_CURVE:
clk_type = SMU_OD_VDDC_CURVE; break;
case OD_RANGE:
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
index 90346e70a614..609f5ab07d8a 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
@@ -389,6 +389,7 @@ struct smu_table_context {
void *metrics_table;
void *clocks_table;
void *watermarks_table;
+ struct mutex metrics_lock;
void *max_sustainable_clocks;
struct smu_bios_boot_up_values boot_values;
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu15_driver_if_v15_0_8.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu15_driver_if_v15_0_8.h
new file mode 100644
index 000000000000..6993d866183d
--- /dev/null
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu15_driver_if_v15_0_8.h
@@ -0,0 +1,295 @@
+/*
+ * Copyright 2025 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#ifndef SMU_15_0_8_DRIVER_IF_H
+#define SMU_15_0_8_DRIVER_IF_H
+
+//I2C Interface
+#define NUM_I2C_CONTROLLERS 8
+#define I2C_CONTROLLER_ENABLED 1
+#define I2C_CONTROLLER_DISABLED 0
+
+#define MAX_SW_I2C_COMMANDS 24
+
+typedef enum {
+ I2C_CONTROLLER_PORT_0,
+ I2C_CONTROLLER_PORT_COUNT,
+} I2cControllerPort_e;
+
+typedef enum {
+ /* 50 Kbits/s not supported anymore! */
+ UNSUPPORTED_1,
+ /* 100 Kbits/s */
+ I2C_SPEED_STANDARD_100K,
+ /* 400 Kbits/s */
+ I2C_SPEED_FAST_400K,
+ /* 1 Mbits/s (in fast mode) */
+ I2C_SPEED_FAST_PLUS_1M,
+ /* 1 Mbits/s (in high speed mode) not supported anymore!*/
+ UNSUPPORTED_2,
+ /* 2.3 Mbits/s not supported anymore! */
+ UNSUPPORTED_3,
+ I2C_SPEED_COUNT,
+} I2cSpeed_e;
+
+typedef enum {
+ I2C_CMD_READ,
+ I2C_CMD_WRITE,
+ I2C_CMD_COUNT,
+} I2cCmdType_e;
+
+#define CMDCONFIG_STOP_BIT 0
+#define CMDCONFIG_RESTART_BIT 1
+/* bit should be 0 for read, 1 for write */
+#define CMDCONFIG_READWRITE_BIT 2
+
+#define CMDCONFIG_STOP_MASK (1 << CMDCONFIG_STOP_BIT)
+#define CMDCONFIG_RESTART_MASK (1 << CMDCONFIG_RESTART_BIT)
+#define CMDCONFIG_READWRITE_MASK (1 << CMDCONFIG_READWRITE_BIT)
+
+/* 64 Bit register offsets for PPSMC_MSG_McaBankDumpDW, PPSMC_MSG_McaBankCeDumpDW messages
+ * eg to read MCA_BANK_OFFSET_SYND for CE index, call PPSMC_MSG_McaBankCeDumpDW twice,
+ * (index << 16 + MCA_BANK_OFFSET_SYND*8) argument for 1st DWORD, and
+ * ((index << 16 ) + MCA_BANK_OFFSET_SYND*8 + 4) argument for 2nd DWORD */
+typedef enum {
+ MCA_BANK_OFFSET_CTL = 0,
+ MCA_BANK_OFFSET_STATUS = 1,
+ MCA_BANK_OFFSET_ADDR = 2,
+ MCA_BANK_OFFSET_MISC = 3,
+ MCA_BANK_OFFSET_IPID = 5,
+ MCA_BANK_OFFSET_SYND = 6,
+ MCA_BANK_OFFSET_MAX = 16,
+} MCA_BANK_OFFSET_e;
+
+/* Firmware MP1 AID MCA Error Codes stored in MCA_MP_MP1:MCMP1_SYNDT0 errorinformation */
+typedef enum {
+ /* MMHUB */
+ CODE_DAGB0 = 0,
+ CODE_DAGB1 = 1,
+ CODE_DAGB2 = 2,
+ CODE_DAGB3 = 3,
+ CODE_DAGB4 = 4,
+ CODE_EA0 = 5,
+ CODE_EA1 = 6,
+ CODE_EA2 = 7,
+ CODE_EA3 = 8,
+ CODE_EA4 = 9,
+ CODE_UTCL2_ROUTER = 10,
+ CODE_VML2 = 11,
+ CODE_VML2_WALKER = 12,
+ CODE_MMCANE = 13,
+
+ /* VCN VCPU */
+ CODE_VIDD = 14,
+ CODE_VIDV = 15,
+ /* VCN JPEG */
+ CODE_JPEG0S = 16,
+ CODE_JPEG0D = 17,
+ CODE_JPEG1S = 18,
+ CODE_JPEG1D = 19,
+ CODE_JPEG2S = 20,
+ CODE_JPEG2D = 21,
+ CODE_JPEG3S = 22,
+ CODE_JPEG3D = 23,
+ CODE_JPEG4S = 24,
+ CODE_JPEG4D = 25,
+ CODE_JPEG5S = 26,
+ CODE_JPEG5D = 27,
+ CODE_JPEG6S = 28,
+ CODE_JPEG6D = 29,
+ CODE_JPEG7S = 30,
+ CODE_JPEG7D = 31,
+ /* VCN MMSCH */
+ CODE_MMSCHD = 32,
+
+ /* SDMA */
+ CODE_SDMA0 = 33,
+ CODE_SDMA1 = 34,
+ CODE_SDMA2 = 35,
+ CODE_SDMA3 = 36,
+
+ /* SOC */
+ CODE_HDP = 37,
+ CODE_ATHUB = 38,
+ CODE_IH = 39,
+ CODE_XHUB_POISON = 40,
+ CODE_SMN_SLVERR = 41,
+ CODE_WDT = 42,
+
+ CODE_UNKNOWN = 43,
+ CODE_DMA = 44,
+ CODE_COUNT = 45,
+} ERR_CODE_e;
+
+/* Firmware MP5 XCD MCA Error Codes stored in MCA_MP_MP5:MCMP5_SYNDT0 errorinformation */
+typedef enum {
+ /* SH POISON FED */
+ SH_FED_CODE = 0,
+ /* GCEA Pin UE_ERR regs */
+ GCEA_CODE = 1,
+ SQ_CODE = 2,
+ LDS_CODE = 3,
+ GDS_CODE = 4,
+ SP0_CODE = 5,
+ SP1_CODE = 6,
+ TCC_CODE = 7,
+ TCA_CODE = 8,
+ TCX_CODE = 9,
+ CPC_CODE = 10,
+ CPF_CODE = 11,
+ CPG_CODE = 12,
+ SPI_CODE = 13,
+ RLC_CODE = 14,
+ /* GCEA Pin, UE_EDC regs */
+ SQC_CODE = 15,
+ TA_CODE = 16,
+ TD_CODE = 17,
+ TCP_CODE = 18,
+ TCI_CODE = 19,
+ /* GC Router */
+ GC_ROUTER_CODE = 20,
+ VML2_CODE = 21,
+ VML2_WALKER_CODE = 22,
+ ATCL2_CODE = 23,
+ GC_CANE_CODE = 24,
+
+ /* SOC error codes 41-43 are common with ERR_CODE_e */
+ MP5_CODE_SMN_SLVERR = CODE_SMN_SLVERR,
+ MP5_CODE_UNKNOWN = CODE_UNKNOWN,
+} GC_ERROR_CODE_e;
+
+/* SW I2C Command Table */
+typedef struct {
+ /* Return data for read. Data to send for write*/
+ uint8_t ReadWriteData;
+ /* Includes whether associated command should have a stop or restart command,
+ * and is a read or write */
+ uint8_t CmdConfig;
+} SwI2cCmd_t;
+
+/* SW I2C Request Table */
+typedef struct {
+ /* CKSVII2C0(0) or //CKSVII2C1(1) */
+ uint8_t I2CcontrollerPort;
+ /* Use I2cSpeed_e to indicate speed to select */
+ uint8_t I2CSpeed;
+ /* Slave address of device */
+ uint8_t SlaveAddress;
+ /* Number of commands */
+ uint8_t NumCmds;
+ SwI2cCmd_t SwI2cCmds[MAX_SW_I2C_COMMANDS];
+} SwI2cRequest_t;
+
+typedef struct {
+ SwI2cRequest_t SwI2cRequest;
+ uint32_t Spare[8];
+ /* SMU internal use */
+ uint32_t MmHubPadding[8];
+} SwI2cRequestExternal_t;
+
+typedef enum {
+ PPCLK_UCLK,
+ PPCLK_COUNT,
+} PPCLK_e;
+
+typedef enum {
+ GPIO_INT_POLARITY_ACTIVE_LOW,
+ GPIO_INT_POLARITY_ACTIVE_HIGH,
+} GpioIntPolarity_e;
+
+/* TODO confirm if this is used in MI300 PPSMC_MSG_SetUclkDpmMode */
+typedef enum {
+ UCLK_DPM_MODE_BANDWIDTH,
+ UCLK_DPM_MODE_LATENCY,
+} UCLK_DPM_MODE_e;
+
+typedef struct {
+ /* 2 AVFS.PSM chains */
+ uint16_t AvgPsmCount_Chain0[13];
+ uint16_t AvgPsmCount_Chain1[15];
+ uint16_t MinPsmCount_Chain0[13];
+ uint16_t MinPsmCount_Chain1[15];
+ float MaxTemperature;
+
+ /* For voltage conversions, these are the array indexes
+ * 0:SOCIO
+ * 1:065_UCIE
+ * 2:075_UCIE
+ * 3:11_GTA
+ * 4:075_GTA */
+ float MinPsmVoltage[5];
+ float AvgPsmVoltage[5];
+} AvfsDebugTableMid_t;
+
+typedef struct {
+ /* 7 AVFS.PSM chains - not including TRO */
+ uint16_t AvgPsmCount_Chain0[15];
+ uint16_t AvgPsmCount_Chain1[15];
+ uint16_t AvgPsmCount_Chain2[13];
+ uint16_t AvgPsmCount_Chain3[13];
+ uint16_t AvgPsmCount_Chain4[15];
+ uint16_t AvgPsmCount_Chain5[15];
+ uint16_t AvgPsmCount_Chain6[5];
+ uint16_t MinPsmCount_Chain0[15];
+ uint16_t MinPsmCount_Chain1[15];
+ uint16_t MinPsmCount_Chain2[13];
+ uint16_t MinPsmCount_Chain3[13];
+ uint16_t MinPsmCount_Chain4[15];
+ uint16_t MinPsmCount_Chain5[15];
+ uint16_t MinPsmCount_Chain6[5];
+ float MaxTemperature;
+
+ /* For voltage conversions, these are the array indexes
+ * 0:VDDX */
+ float MinPsmVoltage;
+ float AvgPsmVoltage;
+} AvfsDebugTableAid_t;
+
+typedef struct {
+ /* 0-27 GFX, 28-29 SOC */
+ uint16_t avgPsmCount[30];
+ uint16_t minPsmCount[30];
+ float avgPsmVoltage[30];
+ float minPsmVoltage[30];
+} AvfsDebugTableXcd_t;
+
+/* Defines used for IH-based thermal interrupts to GFX driver - A/X only */
+#define IH_INTERRUPT_ID_TO_DRIVER 0xFE
+#define IH_INTERRUPT_CONTEXT_ID_THERMAL_THROTTLING 0x7
+#define IH_INTERRUPT_VFFLR_INT 0xA
+
+/* thermal over-temp mask defines for IH interrup to host */
+#define THROTTLER_PROCHOT_BIT 0
+#define THROTTLER_RESERVED 1
+/* AID, XCD, CCD throttling */
+#define THROTTLER_THERMAL_SOCKET_BIT 2
+/* VRHOT */
+#define THROTTLER_THERMAL_VR_BIT 3
+#define THROTTLER_THERMAL_HBM_BIT 4
+/* UEs are always reported, set flag to 0 to prevent clearing of UEs */
+#define ClearMcaOnRead_UE_FLAG_MASK 0x1
+/* Enable CE logging and clearing to driver */
+#define ClearMcaOnRead_CE_POLL_MASK 0x2
+/* AID MMHUB client IP CE Logging and clearing */
+#define ClearMcaOnRead_MMHUB_POLL_MASK 0x4
+
+#endif
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v15_0_8_pmfw.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v15_0_8_pmfw.h
new file mode 100644
index 000000000000..a3401c4cc20b
--- /dev/null
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v15_0_8_pmfw.h
@@ -0,0 +1,427 @@
+/*
+ * Copyright 2025 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#ifndef SMU_15_0_8_PMFW_H
+#define SMU_15_0_8_PMFW_H
+
+#define NUM_VCLK_DPM_LEVELS 4
+#define NUM_DCLK_DPM_LEVELS 4
+#define NUM_SOCCLK_DPM_LEVELS 4
+#define NUM_LCLK_DPM_LEVELS 4
+#define NUM_UCLK_DPM_LEVELS 4
+#define NUM_FCLK_DPM_LEVELS 4
+#define NUM_XGMI_DPM_LEVELS 2
+#define NUM_PCIE_BITRATES 4
+#define NUM_XGMI_BITRATES 4
+#define NUM_XGMI_WIDTHS 3
+#define NUM_GFX_P2S_TABLES 8
+#define NUM_PSM_DIDT_THRESHOLDS 3
+#define NUM_XCD_XVMIN_VMIN_THRESHOLDS 3
+
+#define PRODUCT_MODEL_NUMBER_LEN 20
+#define PRODUCT_NAME_LEN 64
+#define PRODUCT_SERIAL_LEN 20
+#define PRODUCT_MANUFACTURER_NAME_LEN 32
+#define PRODUCT_FRU_ID_LEN 32
+
+//Feature ID list
+#define FEATURE_ID_DATA_CALCULATION 1
+#define FEATURE_ID_DPM_FCLK 2
+#define FEATURE_ID_DPM_GFXCLK 3
+#define FEATURE_ID_DPM_SPARE_4 4
+#define FEATURE_ID_DPM_SPARE_5 5
+#define FEATURE_ID_DPM_UCLK 6
+#define FEATURE_ID_DPM_SPARE_7 7
+#define FEATURE_ID_DPM_XGMI 8
+#define FEATURE_ID_DS_FCLK 9
+#define FEATURE_ID_DS_GFXCLK 10
+#define FEATURE_ID_DS_LCLK 11
+#define FEATURE_ID_DS_MP0CLK 12
+#define FEATURE_ID_DS_MP1CLK 13
+#define FEATURE_ID_DS_MPIOCLK 14
+#define FEATURE_ID_DS_SOCCLK 15
+#define FEATURE_ID_DS_VCN 16
+#define FEATURE_ID_PPT 17
+#define FEATURE_ID_TDC 18
+#define FEATURE_ID_THERMAL 19
+#define FEATURE_ID_SOC_PCC 20
+#define FEATURE_ID_PROCHOT 21
+#define FEATURE_ID_XVMIN0_VMIN_AID 22
+#define FEATURE_ID_XVMIN1_DD_AID 23
+#define FEATURE_ID_XVMIN0_VMIN_XCD 24
+#define FEATURE_ID_XVMIN1_DD_XCD 25
+#define FEATURE_ID_FW_CTF 26
+#define FEATURE_ID_MGCG 27
+#define FEATURE_ID_PSI7 28
+#define FEATURE_ID_XGMI_PER_LINK_PWR_DOWN 29
+#define FEATURE_ID_SOC_DC_RTC 30
+#define FEATURE_ID_GFX_DC_RTC 31
+#define FEATURE_ID_DVM_MIN_PSM 32
+#define FEATURE_ID_PRC 33
+#define FEATURE_ID_PSM_DIDT 34
+#define FEATURE_ID_PIT 35
+#define FEATURE_ID_DVO 36
+#define FEATURE_ID_XVMIN_CLKSTOP_DS 37
+#define FEATURE_ID_HBM_THROTTLE_CTRL 38
+#define FEATURE_ID_DPM_GL2CLK 39
+#define FEATURE_ID_GC_CAC_EDC 40
+#define FEATURE_ID_DS_DMABECLK 41
+#define FEATURE_ID_DS_MPIFOECLK 42
+#define FEATURE_ID_DS_MPRASCLK 43
+#define FEATURE_ID_DS_MPNHTCLK 44
+#define FEATURE_ID_DS_FIOCLK 45
+#define FEATURE_ID_DS_DXIOCLK 46
+#define FEATURE_ID_PCC 47
+#define FEATURE_ID_OCP 48
+#define FEATURE_ID_TRO 49
+#define FEATURE_ID_GL2_CAC_EDC 50
+#define FEATURE_ID_SPARE_51 51
+#define FEATURE_ID_GL2_CGCG 52
+#define FEATURE_ID_XCAC 53
+#define FEATURE_ID_DS_GL2CLK 54
+#define FEATURE_ID_FCS_VIN_PCC 55
+#define FEATURE_ID_FCS_VDDX_OCP_WARN 56
+#define FEATURE_ID_FCS_PWRBRK 57
+#define FEATURE_ID_DF_CSTATE 58
+#define FEATURE_ID_ARO 59
+#define FEATURE_ID_PS_PsPowerLimit 60
+#define FEATURE_ID_PS_PsPowerFloor 61
+#define FEATURE_ID_OCPWARNRC 62
+#define FEATURE_ID_XGMI_FOLDING 63
+#define FEATURE_ID_SMU_CG 64
+#define NUM_FEATURES 65
+
+//MGCG Feature ID List
+#define WAFL_CG 0
+#define SMU_FUSE_CG_DEEPSLEEP 1
+#define SMUIO_CG 2
+#define RSMU_MGCG 3
+#define SMU_CLK_MGCG 4
+#define MP5_CG 5
+#define UMC_CG 6
+#define WAFL0_CLK 7
+#define WAFL1_CLK 8
+#define VCN_MGCG 9
+#define GL2_MGCG 10
+#define MGCG_NUM_FEATURES 11
+
+/* enum for MPIO PCIe gen speed msgs */
+typedef enum {
+ PCIE_LINK_SPEED_INDEX_TABLE_GEN1,
+ PCIE_LINK_SPEED_INDEX_TABLE_GEN2,
+ PCIE_LINK_SPEED_INDEX_TABLE_GEN3,
+ PCIE_LINK_SPEED_INDEX_TABLE_GEN4,
+ PCIE_LINK_SPEED_INDEX_TABLE_GEN5,
+ PCIE_LINK_SPEED_INDEX_TABLE_GEN6,
+ PCIE_LINK_SPEED_INDEX_TABLE_GEN6_ESM,
+ PCIE_LINK_SPEED_INDEX_TABLE_COUNT
+} PCIE_LINK_SPEED_INDEX_TABLE_e;
+
+typedef enum {
+ GFX_GUARDBAND_OFFSET_0,
+ GFX_GUARDBAND_OFFSET_1,
+ GFX_GUARDBAND_OFFSET_2,
+ GFX_GUARDBAND_OFFSET_3,
+ GFX_GUARDBAND_OFFSET_4,
+ GFX_GUARDBAND_OFFSET_5,
+ GFX_GUARDBAND_OFFSET_6,
+ GFX_GUARDBAND_OFFSET_7,
+ GFX_GUARDBAND_OFFSET_COUNT
+} GFX_GUARDBAND_OFFSET_e;
+
+typedef enum {
+ GFX_DVM_MARGINHI_0,
+ GFX_DVM_MARGINHI_1,
+ GFX_DVM_MARGINHI_2,
+ GFX_DVM_MARGINHI_3,
+ GFX_DVM_MARGINHI_4,
+ GFX_DVM_MARGINHI_5,
+ GFX_DVM_MARGINHI_6,
+ GFX_DVM_MARGINHI_7,
+ GFX_DVM_MARGINLO_0,
+ GFX_DVM_MARGINLO_1,
+ GFX_DVM_MARGINLO_2,
+ GFX_DVM_MARGINLO_3,
+ GFX_DVM_MARGINLO_4,
+ GFX_DVM_MARGINLO_5,
+ GFX_DVM_MARGINLO_6,
+ GFX_DVM_MARGINLO_7,
+ GFX_DVM_MARGIN_COUNT
+} GFX_DVM_MARGIN_e;
+
+typedef enum{
+ SYSTEM_TEMP_UBB_FPGA,
+ SYSTEM_TEMP_UBB_FRONT,
+ SYSTEM_TEMP_UBB_BACK,
+ SYSTEM_TEMP_UBB_OAM7,
+ SYSTEM_TEMP_UBB_IBC,
+ SYSTEM_TEMP_UBB_UFPGA,
+ SYSTEM_TEMP_UBB_OAM1,
+ SYSTEM_TEMP_OAM_0_1_HSC,
+ SYSTEM_TEMP_OAM_2_3_HSC,
+ SYSTEM_TEMP_OAM_4_5_HSC,
+ SYSTEM_TEMP_OAM_6_7_HSC,
+ SYSTEM_TEMP_UBB_FPGA_0V72_VR,
+ SYSTEM_TEMP_UBB_FPGA_3V3_VR,
+ SYSTEM_TEMP_RETIMER_0_1_2_3_1V2_VR,
+ SYSTEM_TEMP_RETIMER_4_5_6_7_1V2_VR,
+ SYSTEM_TEMP_RETIMER_0_1_0V9_VR,
+ SYSTEM_TEMP_RETIMER_4_5_0V9_VR,
+ SYSTEM_TEMP_RETIMER_2_3_0V9_VR,
+ SYSTEM_TEMP_RETIMER_6_7_0V9_VR,
+ SYSTEM_TEMP_OAM_0_1_2_3_3V3_VR,
+ SYSTEM_TEMP_OAM_4_5_6_7_3V3_VR,
+ SYSTEM_TEMP_IBC_HSC,
+ SYSTEM_TEMP_IBC,
+ SYSTEM_TEMP_MAX_ENTRIES = 32
+} SYSTEM_TEMP_e;
+
+typedef enum{
+ NODE_TEMP_RETIMER,
+ NODE_TEMP_IBC_TEMP,
+ NODE_TEMP_IBC_2_TEMP,
+ NODE_TEMP_VDD18_VR_TEMP,
+ NODE_TEMP_04_HBM_B_VR_TEMP,
+ NODE_TEMP_04_HBM_D_VR_TEMP,
+ NODE_TEMP_MAX_TEMP_ENTRIES = 12
+} NODE_TEMP_e;
+
+typedef enum {
+ SVI_PLANE_VDDCR_X0_TEMP,
+ SVI_PLANE_VDDCR_X1_TEMP,
+
+ SVI_PLANE_VDDIO_HBM_B_TEMP,
+ SVI_PLANE_VDDIO_HBM_D_TEMP,
+ SVI_PLANE_VDDIO_04_HBM_B_TEMP,
+ SVI_PLANE_VDDIO_04_HBM_D_TEMP,
+ SVI_PLANE_VDDCR_HBM_B_TEMP,
+ SVI_PLANE_VDDCR_HBM_D_TEMP,
+ SVI_PLANE_VDDCR_075_HBM_B_TEMP,
+ SVI_PLANE_VDDCR_075_HBM_D_TEMP,
+
+ SVI_PLANE_VDDIO_11_GTA_A_TEMP,
+ SVI_PLANE_VDDIO_11_GTA_C_TEMP,
+ SVI_PLANE_VDDAN_075_GTA_A_TEMP,
+ SVI_PLANE_VDDAN_075_GTA_C_TEMP,
+
+ SVI_PLANE_VDDCR_075_UCIE_TEMP,
+ SVI_PLANE_VDDIO_065_UCIEAA_TEMP,
+ SVI_PLANE_VDDIO_065_UCIEAM_A_TEMP,
+ SVI_PLANE_VDDIO_065_UCIEAM_C_TEMP,
+
+ SVI_PLANE_VDDCR_SOCIO_A_TEMP,
+ SVI_PLANE_VDDCR_SOCIO_C_TEMP,
+
+ SVI_PLANE_VDDAN_075_TEMP,
+ SVI_MAX_TEMP_ENTRIES, //22
+} SVI_TEMP_e;
+
+typedef enum{
+ SYSTEM_POWER_UBB_POWER,
+ SYSTEM_POWER_UBB_POWER_THRESHOLD,
+ SYSTEM_POWER_MAX_ENTRIES_WO_RESERVED,
+ SYSTEM_POWER_MAX_ENTRIES = 4
+} SYSTEM_POWER_e;
+
+#define SMU_METRICS_TABLE_VERSION 0xF
+
+typedef struct __attribute__((packed, aligned(4))) {
+ uint64_t AccumulationCounter;
+
+ //TEMPERATURE
+ uint32_t MaxSocketTemperature;
+ uint32_t MaxVrTemperature;
+ uint32_t HbmTemperature[12];
+ uint64_t MaxSocketTemperatureAcc;
+ uint64_t MaxVrTemperatureAcc;
+ uint64_t HbmTemperatureAcc[12];
+ uint32_t MidTemperature[2];
+ uint32_t AidTemperature[2];
+ uint32_t XcdTemperature[8];
+
+ //POWER
+ uint32_t SocketPowerLimit;
+ uint32_t SocketPower;
+
+ //ENERGY
+ uint64_t Timestamp;
+ uint64_t SocketEnergyAcc;
+ uint64_t HbmEnergyAcc;
+
+ //FREQUENCY
+ uint32_t GfxclkFrequencyLimit;
+ uint32_t FclkFrequency[2];
+ uint32_t UclkFrequency[2];
+ uint64_t GfxclkFrequencyAcc[8];
+ uint32_t GfxclkFrequency[8];
+ uint32_t SocclkFrequency[2];
+ uint32_t VclkFrequency[4];
+ uint32_t DclkFrequency[4];
+ uint32_t LclkFrequency[2];
+
+ //XGMI:
+ uint32_t XgmiWidth;
+ uint32_t XgmiBitrate;
+ uint64_t XgmiReadBandwidthAcc;
+ uint64_t XgmiWriteBandwidthAcc;
+
+ //ACTIVITY:
+ uint32_t SocketGfxBusy;
+ uint32_t DramBandwidthUtilization;
+ uint64_t SocketGfxBusyAcc;
+ uint64_t DramBandwidthAcc;
+ uint32_t MaxDramBandwidth;
+ uint64_t DramBandwidthUtilizationAcc;
+ uint64_t PcieBandwidthAcc[2];
+
+ //THROTTLERS
+ uint64_t ProchotResidencyAcc;
+ uint64_t PptResidencyAcc;
+ uint64_t SocketThmResidencyAcc;
+ uint64_t VrThmResidencyAcc;
+ uint64_t HbmThmResidencyAcc;
+
+ //PCIE BW Data and error count
+ uint32_t PcieBandwidth[2];
+ uint64_t PCIeL0ToRecoveryCountAcc;
+ uint64_t PCIenReplayAAcc;
+ uint64_t PCIenReplayARolloverCountAcc;
+ uint64_t PCIeNAKSentCountAcc;
+ uint64_t PCIeNAKReceivedCountAcc;
+ uint64_t PCIeOtherEndRecoveryAcc; // The Pcie counter itself is accumulated
+
+ // VCN/JPEG ACTIVITY
+ uint32_t VcnBusy[4];
+ uint32_t JpegBusy[40];
+
+ // PCIE LINK Speed and width
+ uint32_t PCIeLinkSpeed;
+ uint32_t PCIeLinkWidth;
+
+ // PER XCD ACTIVITY
+ uint32_t GfxBusy[8];
+ uint64_t GfxBusyAcc[8];
+
+ //NVML-Parity: Total App Clock Counter
+ uint64_t GfxclkBelowHostLimitPptAcc[8];
+ uint64_t GfxclkBelowHostLimitThmAcc[8];
+ uint64_t GfxclkBelowHostLimitTotalAcc[8];
+ uint64_t GfxclkLowUtilizationAcc[8];
+} MetricsTable_t;
+
+#define SMU_SYSTEM_METRICS_TABLE_VERSION 0x1
+
+#pragma pack(push, 4)
+typedef struct {
+ uint64_t AccumulationCounter; // Last update timestamp
+ uint16_t LabelVersion; //Defaults to 0.
+ uint16_t NodeIdentifier;
+ int16_t SystemTemperatures[SYSTEM_TEMP_MAX_ENTRIES]; // Signed integer temperature value in Celsius, unused fields are set to 0xFFFF
+ int16_t NodeTemperatures[NODE_TEMP_MAX_TEMP_ENTRIES]; // Signed integer temperature value in Celsius, unused fields are set to 0xFFFF
+ int16_t VrTemperatures[SVI_MAX_TEMP_ENTRIES]; // Signed integer temperature value in Celsius, 13 entries,
+ int16_t spare[7];
+
+ //NPM: NODE POWER MANAGEMENT
+ uint32_t NodePowerLimit;
+ uint32_t NodePower;
+ uint32_t GlobalPPTResidencyAcc;
+
+ uint16_t SystemPower[SYSTEM_POWER_MAX_ENTRIES]; // UBB Current Power and Power Threshold
+} SystemMetricsTable_t;
+#pragma pack(pop)
+
+#define SMU_VF_METRICS_TABLE_VERSION 0x5
+
+typedef struct __attribute__((packed, aligned(4))) {
+ uint32_t AccumulationCounter;
+ uint32_t InstGfxclk_TargFreq;
+ uint64_t AccGfxclk_TargFreq;
+ uint64_t AccGfxRsmuDpm_Busy;
+ uint64_t AccGfxclkBelowHostLimit;
+} VfMetricsTable_t;
+
+/* FRU product information */
+typedef struct __attribute__((aligned(4))) {
+ uint8_t ModelNumber[PRODUCT_MODEL_NUMBER_LEN];
+ uint8_t Name[PRODUCT_NAME_LEN];
+ uint8_t Serial[PRODUCT_SERIAL_LEN];
+ uint8_t ManufacturerName[PRODUCT_MANUFACTURER_NAME_LEN];
+ uint8_t FruId[PRODUCT_FRU_ID_LEN];
+} FRUProductInfo_t;
+
+#define SMU_STATIC_METRICS_TABLE_VERSION 0x1
+
+#pragma pack(push, 4)
+typedef struct {
+ //FRU PRODUCT INFO
+ FRUProductInfo_t ProductInfo; //from i2c
+
+ //POWER
+ uint32_t MaxSocketPowerLimit;
+
+ //FREQUENCY RANGE
+ uint32_t MaxGfxclkFrequency;
+ uint32_t MinGfxclkFrequency;
+ uint32_t MaxFclkFrequency;
+ uint32_t MinFclkFrequency;
+ uint32_t MaxGl2clkFrequency;
+ uint32_t MinGl2clkFrequency;
+ uint32_t UclkFrequencyTable[4];
+ uint32_t SocclkFrequency;
+ uint32_t LclkFrequency;
+ uint32_t VclkFrequency;
+ uint32_t DclkFrequency;
+
+ //CTF limits
+ uint32_t CTFLimit_MID;
+ uint32_t CTFLimit_AID;
+ uint32_t CTFLimit_XCD;
+ uint32_t CTFLimit_HBM;
+
+ //Thermal Throttling limits
+ uint32_t ThermalLimit_MID;
+ uint32_t ThermalLimit_AID;
+ uint32_t ThermalLimit_XCD;
+ uint32_t ThermalLimit_HBM;
+
+ //PSNs
+ uint64_t PublicSerialNumber_MID[2];
+ uint64_t PublicSerialNumber_AID[2];
+ uint64_t PublicSerialNumber_XCD[8];
+
+ //XGMI
+ uint32_t MaxXgmiWidth;
+ uint32_t MaxXgmiBitrate;
+
+ // Telemetry
+ uint32_t InputTelemetryVoltageInmV;
+
+ // General info
+ uint32_t pldmVersion[2];
+
+ uint32_t PPT1Max;
+ uint32_t PPT1Min;
+ uint32_t PPT1Default;
+} StaticMetricsTable_t;
+#pragma pack(pop)
+
+#endif
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v15_0_8_ppsmc.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v15_0_8_ppsmc.h
new file mode 100644
index 000000000000..7ffb445f4c0c
--- /dev/null
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v15_0_8_ppsmc.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2025 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#ifndef SMU_15_0_8_PPSMC_H
+#define SMU_15_0_8_PPSMC_H
+
+/* SMU Response Codes */
+#define PPSMC_Result_OK 0x1
+#define PPSMC_Result_Failed 0xFF
+#define PPSMC_Result_UnknownCmd 0xFE
+#define PPSMC_Result_CmdRejectedPrereq 0xFD
+#define PPSMC_Result_CmdRejectedBusy 0xFC
+
+/* Message Definitions */
+#define PPSMC_MSG_TestMessage 0x1
+#define PPSMC_MSG_GetSmuVersion 0x2
+#define PPSMC_MSG_GfxDriverReset 0x3
+#define PPSMC_MSG_GetDriverIfVersion 0x4
+#define PPSMC_MSG_EnableAllSmuFeatures 0x5
+#define PPSMC_MSG_GetMetricsVersion 0x6
+#define PPSMC_MSG_GetMetricsTable 0x7
+#define PPSMC_MSG_GetEnabledSmuFeatures 0x8
+#define PPSMC_MSG_SetDriverDramAddr 0x9 //ARG0: low address, ARG1: high address
+#define PPSMC_MSG_SetToolsDramAddr 0xA //ARG0: low address, ARG1: high address
+//#define PPSMC_MSG_SetSystemVirtualDramAddr 0xB
+#define PPSMC_MSG_SetSoftMaxByFreq 0xC
+#define PPSMC_MSG_SetPptLimit 0xD
+#define PPSMC_MSG_GetPptLimit 0xE
+#define PPSMC_MSG_DramLogSetDramAddr 0xF //ARG0: low address, ARG1: high address, ARG2: size
+#define PPSMC_MSG_HeavySBR 0x10
+#define PPSMC_MSG_DFCstateControl 0x11
+#define PPSMC_MSG_GfxDriverResetRecovery 0x12
+#define PPSMC_MSG_TriggerVFFLR 0x13
+#define PPSMC_MSG_SetSoftMinGfxClk 0x14
+#define PPSMC_MSG_SetSoftMaxGfxClk 0x15
+#define PPSMC_MSG_PrepareForDriverUnload 0x16
+#define PPSMC_MSG_QueryValidMcaCount 0x17
+#define PPSMC_MSG_McaBankDumpDW 0x18
+#define PPSMC_MSG_ClearMcaOnRead 0x19
+#define PPSMC_MSG_QueryValidMcaCeCount 0x1A
+#define PPSMC_MSG_McaBankCeDumpDW 0x1B
+#define PPSMC_MSG_SelectPLPDMode 0x1C
+#define PPSMC_MSG_SetThrottlingPolicy 0x1D
+#define PPSMC_MSG_ResetSDMA 0x1E
+#define PPSMC_MSG_GetRasTableVersion 0x1F
+#define PPSMC_MSG_GetRmaStatus 0x20
+#define PPSMC_MSG_GetBadPageCount 0x21
+#define PPSMC_MSG_GetBadPageMcaAddress 0x22
+#define PPSMC_MSG_GetBadPagePaAddress 0x23
+#define PPSMC_MSG_SetTimestamp 0x24
+#define PPSMC_MSG_GetTimestamp 0x25
+#define PPSMC_MSG_GetRasPolicy 0x26
+#define PPSMC_MSG_GetBadPageIpIdLoHi 0x27
+#define PPSMC_MSG_EraseRasTable 0x28
+#define PPSMC_MSG_GetStaticMetricsTable 0x29
+#define PPSMC_MSG_ResetVfArbitersByIndex 0x2A
+#define PPSMC_MSG_GetBadPageSeverity 0x2B
+#define PPSMC_MSG_GetSystemMetricsTable 0x2C
+#define PPSMC_MSG_GetSystemMetricsVersion 0x2D
+#define PPSMC_MSG_ResetVCN 0x2E
+#define PPSMC_MSG_SetFastPptLimit 0x2F
+#define PPSMC_MSG_GetFastPptLimit 0x30
+#define PPSMC_MSG_SetSoftMinGl2clk 0x31
+#define PPSMC_MSG_SetSoftMaxGl2clk 0x32
+#define PPSMC_MSG_SetSoftMinFclk 0x33
+#define PPSMC_MSG_SetSoftMaxFclk 0x34
+#define PPSMC_Message_Count 0x35
+
+/* PSMC Reset Types for driver msg argument */
+#define PPSMC_RESET_TYPE_DRIVER_MODE_1_RESET 0x1
+#define PPSMC_RESET_TYPE_DRIVER_MODE_2_RESET 0x2
+#define PPSMC_RESET_TYPE_DRIVER_MODE_3_RESET 0x3
+
+/* PLPD modes */
+#define PPSMC_PLPD_MODE_DEFAULT 0x1
+#define PPSMC_PLPD_MODE_OPTIMIZED 0x2
+
+typedef uint32_t PPSMC_Result;
+typedef uint32_t PPSMC_MSG;
+
+#endif
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h
index 584c4cfd0c16..636ff90923d9 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h
@@ -42,8 +42,10 @@
__SMU_DUMMY_MAP(SetPptLimit), \
__SMU_DUMMY_MAP(SetDriverDramAddrHigh), \
__SMU_DUMMY_MAP(SetDriverDramAddrLow), \
+ __SMU_DUMMY_MAP(SetDriverDramAddr), \
__SMU_DUMMY_MAP(SetToolsDramAddrHigh), \
__SMU_DUMMY_MAP(SetToolsDramAddrLow), \
+ __SMU_DUMMY_MAP(SetToolsDramAddr), \
__SMU_DUMMY_MAP(TransferTableSmu2Dram), \
__SMU_DUMMY_MAP(TransferTableDram2Smu), \
__SMU_DUMMY_MAP(UseDefaultPPTable), \
@@ -292,7 +294,12 @@
__SMU_DUMMY_MAP(AllowZstates), \
__SMU_DUMMY_MAP(GetSmartShiftStatus), \
__SMU_DUMMY_MAP(EnableLSdma), \
- __SMU_DUMMY_MAP(DisableLSdma),
+ __SMU_DUMMY_MAP(DisableLSdma), \
+ __SMU_DUMMY_MAP(InitializeGfx), \
+ __SMU_DUMMY_MAP(SetSoftMaxFclk), \
+ __SMU_DUMMY_MAP(SetSoftMaxGl2clk), \
+ __SMU_DUMMY_MAP(SetSoftMinGl2clk), \
+ __SMU_DUMMY_MAP(GetSystemMetricsVersion),
#undef __SMU_DUMMY_MAP
#define __SMU_DUMMY_MAP(type) SMU_MSG_##type
@@ -324,6 +331,7 @@ enum smu_clk_type {
SMU_OD_CCLK,
SMU_OD_SCLK,
SMU_OD_MCLK,
+ SMU_OD_FCLK,
SMU_OD_VDDC_CURVE,
SMU_OD_RANGE,
SMU_OD_VDDGFX_OFFSET,
@@ -334,6 +342,7 @@ enum smu_clk_type {
SMU_OD_FAN_MINIMUM_PWM,
SMU_OD_FAN_ZERO_RPM_ENABLE,
SMU_OD_FAN_ZERO_RPM_STOP_TEMP,
+ SMU_GL2CLK,
SMU_CLK_COUNT,
};
@@ -472,6 +481,14 @@ enum smu_clk_type {
__SMU_DUMMY_MAP(GFX_DIDT_XVMIN), \
__SMU_DUMMY_MAP(FAN_ABNORMAL), \
__SMU_DUMMY_MAP(PIT), \
+ __SMU_DUMMY_MAP(DS_DMABECLK), \
+ __SMU_DUMMY_MAP(DS_MPIFOECLK), \
+ __SMU_DUMMY_MAP(DS_MPRASCLK), \
+ __SMU_DUMMY_MAP(DS_MPNHTCLK), \
+ __SMU_DUMMY_MAP(DS_FIOCLK), \
+ __SMU_DUMMY_MAP(DS_DXIOCLK), \
+ __SMU_DUMMY_MAP(DS_GL2CLK), \
+ __SMU_DUMMY_MAP(DPM_GL2CLK), \
__SMU_DUMMY_MAP(HROM_EN),
#undef __SMU_DUMMY_MAP
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v11_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v11_0.h
index 7c1701ed3e11..dd94e8a9e218 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v11_0.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v11_0.h
@@ -25,18 +25,6 @@
#include "amdgpu_smu.h"
-#define SMU11_DRIVER_IF_VERSION_INV 0xFFFFFFFF
-#define SMU11_DRIVER_IF_VERSION_ARCT 0x17
-#define SMU11_DRIVER_IF_VERSION_NV10 0x37
-#define SMU11_DRIVER_IF_VERSION_NV12 0x38
-#define SMU11_DRIVER_IF_VERSION_NV14 0x38
-#define SMU11_DRIVER_IF_VERSION_Sienna_Cichlid 0x40
-#define SMU11_DRIVER_IF_VERSION_Navy_Flounder 0xE
-#define SMU11_DRIVER_IF_VERSION_VANGOGH 0x03
-#define SMU11_DRIVER_IF_VERSION_Dimgrey_Cavefish 0xF
-#define SMU11_DRIVER_IF_VERSION_Beige_Goby 0xD
-#define SMU11_DRIVER_IF_VERSION_Cyan_Skillfish 0x8
-
/* MP Apertures */
#define MP0_Public 0x03800000
#define MP0_SRAM 0x03900000
@@ -148,8 +136,6 @@ int smu_v11_0_setup_pptable(struct smu_context *smu);
int smu_v11_0_get_vbios_bootup_values(struct smu_context *smu);
-int smu_v11_0_check_fw_version(struct smu_context *smu);
-
int smu_v11_0_set_driver_table_location(struct smu_context *smu);
int smu_v11_0_set_tool_table_location(struct smu_context *smu);
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v12_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v12_0.h
index fd3937b08662..2346d9c6e162 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v12_0.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v12_0.h
@@ -35,8 +35,6 @@
int smu_v12_0_check_fw_status(struct smu_context *smu);
-int smu_v12_0_check_fw_version(struct smu_context *smu);
-
int smu_v12_0_powergate_sdma(struct smu_context *smu, bool gate);
int smu_v12_0_powergate_vcn(struct smu_context *smu, bool gate);
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h
index b0d6b7b0946d..89bbda0670ef 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h
@@ -132,8 +132,6 @@ int smu_v13_0_setup_pptable(struct smu_context *smu);
int smu_v13_0_get_vbios_bootup_values(struct smu_context *smu);
-int smu_v13_0_check_fw_version(struct smu_context *smu);
-
int smu_v13_0_set_driver_table_location(struct smu_context *smu);
int smu_v13_0_set_tool_table_location(struct smu_context *smu);
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h
index b453e6efc7c9..4eb40ff8aff2 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h
@@ -25,11 +25,6 @@
#include "amdgpu_smu.h"
-#define SMU14_DRIVER_IF_VERSION_INV 0xFFFFFFFF
-#define SMU14_DRIVER_IF_VERSION_SMU_V14_0_0 0x7
-#define SMU14_DRIVER_IF_VERSION_SMU_V14_0_1 0x6
-#define SMU14_DRIVER_IF_VERSION_SMU_V14_0_2 0x2E
-
#define FEATURE_MASK(feature) (1ULL << feature)
/* MP Apertures */
@@ -124,8 +119,6 @@ int smu_v14_0_setup_pptable(struct smu_context *smu);
int smu_v14_0_get_vbios_bootup_values(struct smu_context *smu);
-int smu_v14_0_check_fw_version(struct smu_context *smu);
-
int smu_v14_0_set_driver_table_location(struct smu_context *smu);
int smu_v14_0_set_tool_table_location(struct smu_context *smu);
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v15_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v15_0.h
index ab4a64f54e79..e6fd8be2cc4a 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v15_0.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v15_0.h
@@ -41,7 +41,10 @@
#define smnMP1_FIRMWARE_FLAGS 0x3010024
#define smnMP1_PUB_CTRL 0x3010d10
-#define MAX_DPM_LEVELS 16
+#define SMU15_DRIVER_IF_VERSION_SMU_V15_0_8 0x007D0000
+
+#define FEATURE_MASK(feature) (1ULL << feature)
+
#define MAX_PCIE_CONF 3
#define SMU15_TOOL_SIZE 0x19000
@@ -65,45 +68,28 @@ struct smu_15_0_max_sustainable_clocks {
uint32_t soc_clock;
};
-struct smu_15_0_dpm_clk_level {
- bool enabled;
- uint32_t value;
-};
-
-struct smu_15_0_dpm_table {
- uint32_t min; /* MHz */
- uint32_t max; /* MHz */
- uint32_t count;
- bool is_fine_grained;
- struct smu_15_0_dpm_clk_level dpm_levels[MAX_DPM_LEVELS];
-};
-
-struct smu_15_0_pcie_table {
- uint8_t pcie_gen[MAX_PCIE_CONF];
- uint8_t pcie_lane[MAX_PCIE_CONF];
- uint16_t clk_freq[MAX_PCIE_CONF];
- uint32_t num_of_link_levels;
-};
-
struct smu_15_0_dpm_tables {
- struct smu_15_0_dpm_table soc_table;
- struct smu_15_0_dpm_table gfx_table;
- struct smu_15_0_dpm_table uclk_table;
- struct smu_15_0_dpm_table eclk_table;
- struct smu_15_0_dpm_table vclk_table;
- struct smu_15_0_dpm_table dclk_table;
- struct smu_15_0_dpm_table dcef_table;
- struct smu_15_0_dpm_table pixel_table;
- struct smu_15_0_dpm_table display_table;
- struct smu_15_0_dpm_table phy_table;
- struct smu_15_0_dpm_table fclk_table;
- struct smu_15_0_pcie_table pcie_table;
+ struct smu_dpm_table soc_table;
+ struct smu_dpm_table gfx_table;
+ struct smu_dpm_table uclk_table;
+ struct smu_dpm_table eclk_table;
+ struct smu_dpm_table vclk_table;
+ struct smu_dpm_table dclk_table;
+ struct smu_dpm_table dcef_table;
+ struct smu_dpm_table pixel_table;
+ struct smu_dpm_table display_table;
+ struct smu_dpm_table phy_table;
+ struct smu_dpm_table fclk_table;
+ struct smu_pcie_table pcie_table;
+ struct smu_dpm_table gl2_table;
};
struct smu_15_0_dpm_context {
struct smu_15_0_dpm_tables dpm_tables;
uint32_t workload_policy_mask;
uint32_t dcef_min_ds_clk;
+ uint64_t caps;
+ uint32_t board_volt;
};
enum smu_15_0_power_state {
@@ -118,6 +104,7 @@ struct smu_15_0_power_context {
uint32_t power_source;
uint8_t in_power_limit_boost_mode;
enum smu_15_0_power_state power_state;
+ atomic_t throttle_status;
};
#if defined(SWSMU_CODE_LAYER_L2) || defined(SWSMU_CODE_LAYER_L3)
@@ -142,8 +129,6 @@ int smu_v15_0_setup_pptable(struct smu_context *smu);
int smu_v15_0_get_vbios_bootup_values(struct smu_context *smu);
-int smu_v15_0_check_fw_version(struct smu_context *smu);
-
int smu_v15_0_set_driver_table_location(struct smu_context *smu);
int smu_v15_0_set_tool_table_location(struct smu_context *smu);
@@ -199,7 +184,7 @@ int smu_v15_0_set_power_source(struct smu_context *smu,
int smu_v15_0_set_single_dpm_table(struct smu_context *smu,
enum smu_clk_type clk_type,
- struct smu_15_0_dpm_table *single_dpm_table);
+ struct smu_dpm_table *single_dpm_table);
int smu_v15_0_gfx_ulv_control(struct smu_context *smu,
bool enablement);
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
index 74c818e3fbd0..54d3dba7d354 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
@@ -65,6 +65,8 @@
#define SMU_FEATURES_HIGH_MASK 0xFFFFFFFF00000000
#define SMU_FEATURES_HIGH_SHIFT 32
+#define SMU11_DRIVER_IF_VERSION_ARCT 0x17
+
static const struct smu_feature_bits arcturus_dpm_features = {
.bits = { SMU_FEATURE_BIT_INIT(FEATURE_DPM_PREFETCHER_BIT),
SMU_FEATURE_BIT_INIT(FEATURE_DPM_GFXCLK_BIT),
@@ -1905,7 +1907,7 @@ static const struct pptable_funcs arcturus_ppt_funcs = {
/* pptable related */
.setup_pptable = arcturus_setup_pptable,
.get_vbios_bootup_values = smu_v11_0_get_vbios_bootup_values,
- .check_fw_version = smu_v11_0_check_fw_version,
+ .check_fw_version = smu_cmn_check_fw_version,
.write_pptable = smu_cmn_write_pptable,
.set_driver_table_location = smu_v11_0_set_driver_table_location,
.set_tool_table_location = smu_v11_0_set_tool_table_location,
@@ -1958,5 +1960,6 @@ void arcturus_set_ppt_funcs(struct smu_context *smu)
smu->table_map = arcturus_table_map;
smu->pwr_src_map = arcturus_pwr_src_map;
smu->workload_map = arcturus_workload_map;
+ smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_ARCT;
smu_v11_0_init_msg_ctl(smu, arcturus_message_map);
}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c
index 4e70308a455e..e6e009df9840 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c
@@ -582,7 +582,7 @@ cyan_skillfish_get_enabled_mask(struct smu_context *smu,
static const struct pptable_funcs cyan_skillfish_ppt_funcs = {
.check_fw_status = smu_v11_0_check_fw_status,
- .check_fw_version = smu_v11_0_check_fw_version,
+ .check_fw_version = smu_cmn_check_fw_version,
.init_power = smu_v11_0_init_power,
.fini_power = smu_v11_0_fini_power,
.init_smc_tables = cyan_skillfish_init_smc_tables,
@@ -605,5 +605,6 @@ void cyan_skillfish_set_ppt_funcs(struct smu_context *smu)
smu->ppt_funcs = &cyan_skillfish_ppt_funcs;
smu->table_map = cyan_skillfish_table_map;
smu->is_apu = true;
+ smu->smc_driver_if_version = MP1_DRIVER_IF_VERSION;
smu_v11_0_init_msg_ctl(smu, cyan_skillfish_message_map);
}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
index 163e09ca0730..cd0457e13f54 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
@@ -73,6 +73,10 @@ static const struct smu_feature_bits navi10_dpm_features = {
#define SMU_11_0_GFX_BUSY_THRESHOLD 15
+#define SMU11_DRIVER_IF_VERSION_NV10 0x37
+#define SMU11_DRIVER_IF_VERSION_NV12 0x38
+#define SMU11_DRIVER_IF_VERSION_NV14 0x38
+
static struct cmn2asic_msg_mapping navi10_message_map[SMU_MSG_MAX_COUNT] = {
MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 1),
MSG_MAP(GetSmuVersion, PPSMC_MSG_GetSmuVersion, 1),
@@ -3308,7 +3312,7 @@ static const struct pptable_funcs navi10_ppt_funcs = {
.check_fw_status = smu_v11_0_check_fw_status,
.setup_pptable = navi10_setup_pptable,
.get_vbios_bootup_values = smu_v11_0_get_vbios_bootup_values,
- .check_fw_version = smu_v11_0_check_fw_version,
+ .check_fw_version = smu_cmn_check_fw_version,
.write_pptable = smu_cmn_write_pptable,
.set_driver_table_location = smu_v11_0_set_driver_table_location,
.set_tool_table_location = smu_v11_0_set_tool_table_location,
@@ -3361,11 +3365,26 @@ static const struct pptable_funcs navi10_ppt_funcs = {
void navi10_set_ppt_funcs(struct smu_context *smu)
{
+ struct amdgpu_device *adev = smu->adev;
+
smu->ppt_funcs = &navi10_ppt_funcs;
smu->clock_map = navi10_clk_map;
smu->feature_map = navi10_feature_mask_map;
smu->table_map = navi10_table_map;
smu->pwr_src_map = navi10_pwr_src_map;
smu->workload_map = navi10_workload_map;
+
+ switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) {
+ case IP_VERSION(11, 0, 0):
+ smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_NV10;
+ break;
+ case IP_VERSION(11, 0, 9):
+ smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_NV12;
+ break;
+ case IP_VERSION(11, 0, 5):
+ smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_NV14;
+ break;
+ }
+
smu_v11_0_init_msg_ctl(smu, navi10_message_map);
}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
index cf030af18aad..f799e489b481 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
@@ -3119,7 +3119,7 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = {
.check_fw_status = smu_v11_0_check_fw_status,
.setup_pptable = sienna_cichlid_setup_pptable,
.get_vbios_bootup_values = smu_v11_0_get_vbios_bootup_values,
- .check_fw_version = smu_v11_0_check_fw_version,
+ .check_fw_version = smu_cmn_check_fw_version,
.write_pptable = smu_cmn_write_pptable,
.set_driver_table_location = smu_v11_0_set_driver_table_location,
.set_tool_table_location = smu_v11_0_set_tool_table_location,
@@ -3176,13 +3176,36 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = {
.mode2_reset = sienna_cichlid_mode2_reset,
};
+#define SMU11_DRIVER_IF_VERSION_Sienna_Cichlid 0x40
+#define SMU11_DRIVER_IF_VERSION_Navy_Flounder 0xE
+#define SMU11_DRIVER_IF_VERSION_Dimgrey_Cavefish 0xF
+#define SMU11_DRIVER_IF_VERSION_Beige_Goby 0xD
+
void sienna_cichlid_set_ppt_funcs(struct smu_context *smu)
{
+ struct amdgpu_device *adev = smu->adev;
+
smu->ppt_funcs = &sienna_cichlid_ppt_funcs;
smu->clock_map = sienna_cichlid_clk_map;
smu->feature_map = sienna_cichlid_feature_mask_map;
smu->table_map = sienna_cichlid_table_map;
smu->pwr_src_map = sienna_cichlid_pwr_src_map;
smu->workload_map = sienna_cichlid_workload_map;
+
+ switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) {
+ case IP_VERSION(11, 0, 7):
+ smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_Sienna_Cichlid;
+ break;
+ case IP_VERSION(11, 0, 11):
+ smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_Navy_Flounder;
+ break;
+ case IP_VERSION(11, 0, 12):
+ smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_Dimgrey_Cavefish;
+ break;
+ case IP_VERSION(11, 0, 13):
+ smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_Beige_Goby;
+ break;
+ }
+
smu_v11_0_init_msg_ctl(smu, sienna_cichlid_message_map);
}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
index 12b052d920f5..d68ceee16d8f 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
@@ -192,82 +192,6 @@ int smu_v11_0_check_fw_status(struct smu_context *smu)
return -EIO;
}
-int smu_v11_0_check_fw_version(struct smu_context *smu)
-{
- struct amdgpu_device *adev = smu->adev;
- uint32_t if_version = 0xff, smu_version = 0xff;
- uint8_t smu_program, smu_major, smu_minor, smu_debug;
- int ret = 0;
-
- ret = smu_cmn_get_smc_version(smu, &if_version, &smu_version);
- if (ret)
- return ret;
-
- smu_program = (smu_version >> 24) & 0xff;
- smu_major = (smu_version >> 16) & 0xff;
- smu_minor = (smu_version >> 8) & 0xff;
- smu_debug = (smu_version >> 0) & 0xff;
- if (smu->is_apu)
- adev->pm.fw_version = smu_version;
-
- switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) {
- case IP_VERSION(11, 0, 0):
- smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_NV10;
- break;
- case IP_VERSION(11, 0, 9):
- smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_NV12;
- break;
- case IP_VERSION(11, 0, 5):
- smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_NV14;
- break;
- case IP_VERSION(11, 0, 7):
- smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_Sienna_Cichlid;
- break;
- case IP_VERSION(11, 0, 11):
- smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_Navy_Flounder;
- break;
- case IP_VERSION(11, 5, 0):
- case IP_VERSION(11, 5, 2):
- smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_VANGOGH;
- break;
- case IP_VERSION(11, 0, 12):
- smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_Dimgrey_Cavefish;
- break;
- case IP_VERSION(11, 0, 13):
- smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_Beige_Goby;
- break;
- case IP_VERSION(11, 0, 8):
- smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_Cyan_Skillfish;
- break;
- case IP_VERSION(11, 0, 2):
- smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_ARCT;
- break;
- default:
- dev_err(smu->adev->dev, "smu unsupported IP version: 0x%x.\n",
- amdgpu_ip_version(adev, MP1_HWIP, 0));
- smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_INV;
- break;
- }
-
- /*
- * 1. if_version mismatch is not critical as our fw is designed
- * to be backward compatible.
- * 2. New fw usually brings some optimizations. But that's visible
- * only on the paired driver.
- * Considering above, we just leave user a verbal message instead
- * of halt driver loading.
- */
- if (if_version != smu->smc_driver_if_version) {
- dev_info(smu->adev->dev, "smu driver if version = 0x%08x, smu fw if version = 0x%08x, "
- "smu fw program = %d, version = 0x%08x (%d.%d.%d)\n",
- smu->smc_driver_if_version, if_version,
- smu_program, smu_version, smu_major, smu_minor, smu_debug);
- dev_info(smu->adev->dev, "SMU driver if version not matched\n");
- }
-
- return ret;
-}
-
static int smu_v11_0_set_pptable_v2_0(struct smu_context *smu, void **table, uint32_t *size)
{
struct amdgpu_device *adev = smu->adev;
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c
index 5eabaf55dfc5..d269b505aefb 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c
@@ -2511,7 +2511,7 @@ static u32 vangogh_get_gfxoff_entrycount(struct smu_context *smu, uint64_t *entr
static const struct pptable_funcs vangogh_ppt_funcs = {
.check_fw_status = smu_v11_0_check_fw_status,
- .check_fw_version = smu_v11_0_check_fw_version,
+ .check_fw_version = smu_cmn_check_fw_version,
.init_smc_tables = vangogh_init_smc_tables,
.fini_smc_tables = smu_v11_0_fini_smc_tables,
.init_power = smu_v11_0_init_power,
@@ -2561,5 +2561,6 @@ void vangogh_set_ppt_funcs(struct smu_context *smu)
smu->table_map = vangogh_table_map;
smu->workload_map = vangogh_workload_map;
smu->is_apu = true;
+ smu->smc_driver_if_version = SMU13_DRIVER_IF_VERSION;
smu_v11_0_init_msg_ctl(smu, vangogh_message_map);
}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c
index 186020ed6708..75335da224c7 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c
@@ -1457,7 +1457,7 @@ static const struct pptable_funcs renoir_ppt_funcs = {
.get_power_profile_mode = renoir_get_power_profile_mode,
.read_sensor = renoir_read_sensor,
.check_fw_status = smu_v12_0_check_fw_status,
- .check_fw_version = smu_v12_0_check_fw_version,
+ .check_fw_version = smu_cmn_check_fw_version,
.powergate_sdma = smu_v12_0_powergate_sdma,
.set_gfx_cgpg = smu_v12_0_set_gfx_cgpg,
.gfx_off_control = smu_v12_0_gfx_off_control,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c
index 2c20624caca4..f09da4d14510 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c
@@ -70,43 +70,6 @@ int smu_v12_0_check_fw_status(struct smu_context *smu)
return -EIO;
}
-int smu_v12_0_check_fw_version(struct smu_context *smu)
-{
- struct amdgpu_device *adev = smu->adev;
- uint32_t if_version = 0xff, smu_version = 0xff;
- uint8_t smu_program, smu_major, smu_minor, smu_debug;
- int ret = 0;
-
- ret = smu_cmn_get_smc_version(smu, &if_version, &smu_version);
- if (ret)
- return ret;
-
- smu_program = (smu_version >> 24) & 0xff;
- smu_major = (smu_version >> 16) & 0xff;
- smu_minor = (smu_version >> 8) & 0xff;
- smu_debug = (smu_version >> 0) & 0xff;
- if (smu->is_apu)
- adev->pm.fw_version = smu_version;
-
- /*
- * 1. if_version mismatch is not critical as our fw is designed
- * to be backward compatible.
- * 2. New fw usually brings some optimizations. But that's visible
- * only on the paired driver.
- * Considering above, we just leave user a verbal message instead
- * of halt driver loading.
- */
- if (if_version != smu->smc_driver_if_version) {
- dev_info(smu->adev->dev, "smu driver if version = 0x%08x, smu fw if version = 0x%08x, "
- "smu fw program = %d, smu fw version = 0x%08x (%d.%d.%d)\n",
- smu->smc_driver_if_version, if_version,
- smu_program, smu_version, smu_major, smu_minor, smu_debug);
- dev_info(smu->adev->dev, "SMU driver if version not matched\n");
- }
-
- return ret;
-}
-
int smu_v12_0_powergate_sdma(struct smu_context *smu, bool gate)
{
if (!smu->is_apu)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c
index 2b4faab37693..dc056f1e4b64 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c
@@ -1988,7 +1988,7 @@ static const struct pptable_funcs aldebaran_ppt_funcs = {
/* pptable related */
.setup_pptable = aldebaran_setup_pptable,
.get_vbios_bootup_values = smu_v13_0_get_vbios_bootup_values,
- .check_fw_version = smu_v13_0_check_fw_version,
+ .check_fw_version = smu_cmn_check_fw_version,
.write_pptable = smu_cmn_write_pptable,
.set_driver_table_location = smu_v13_0_set_driver_table_location,
.set_tool_table_location = smu_v13_0_set_tool_table_location,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c
index 4e09eda77d8b..be9a7a32de99 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c
@@ -258,49 +258,6 @@ int smu_v13_0_check_fw_status(struct smu_context *smu)
return -EIO;
}
-int smu_v13_0_check_fw_version(struct smu_context *smu)
-{
- struct amdgpu_device *adev = smu->adev;
- uint32_t if_version = 0xff, smu_version = 0xff;
- uint8_t smu_program, smu_major, smu_minor, smu_debug;
- int ret = 0;
-
- ret = smu_cmn_get_smc_version(smu, &if_version, &smu_version);
- if (ret)
- return ret;
-
- smu_program = (smu_version >> 24) & 0xff;
- smu_major = (smu_version >> 16) & 0xff;
- smu_minor = (smu_version >> 8) & 0xff;
- smu_debug = (smu_version >> 0) & 0xff;
- adev->pm.fw_version = smu_version;
-
- /* only for dGPU w/ SMU13*/
- if (adev->pm.fw)
- dev_dbg(smu->adev->dev, "smu fw reported program %d, version = 0x%08x (%d.%d.%d)\n",
- smu_program, smu_version, smu_major, smu_minor, smu_debug);
-
- /*
- * 1. if_version mismatch is not critical as our fw is designed
- * to be backward compatible.
- * 2. New fw usually brings some optimizations. But that's visible
- * only on the paired driver.
- * Considering above, we just leave user a verbal message instead
- * of halt driver loading.
- */
- dev_info_once(adev->dev, "smu driver if version = 0x%08x, smu fw if version = 0x%08x, "
- "smu fw program = %d, smu fw version = 0x%08x (%d.%d.%d)\n",
- smu->smc_driver_if_version, if_version,
- smu_program, smu_version, smu_major, smu_minor, smu_debug);
-
- if (smu->smc_driver_if_version != SMU_IGNORE_IF_VERSION &&
- if_version != smu->smc_driver_if_version) {
- dev_info(adev->dev, "SMU driver if version not matched\n");
- }
-
- return ret;
-}
-
static int smu_v13_0_set_pptable_v2_0(struct smu_context *smu, void **table, uint32_t *size)
{
struct amdgpu_device *adev = smu->adev;
@@ -2509,4 +2466,6 @@ void smu_v13_0_reset_custom_level(struct smu_context *smu)
pstate_table->uclk_pstate.custom.max = 0;
pstate_table->gfxclk_pstate.custom.min = 0;
pstate_table->gfxclk_pstate.custom.max = 0;
+ pstate_table->fclk_pstate.custom.min = 0;
+ pstate_table->fclk_pstate.custom.max = 0;
}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
index a8d63d4d1f6e..b414a74d29fd 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
@@ -59,6 +59,10 @@
#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c))
+static void smu_v13_0_0_get_od_setting_limits(struct smu_context *smu,
+ int od_feature_bit,
+ int32_t *min, int32_t *max);
+
static const struct smu_feature_bits smu_v13_0_0_dpm_features = {
.bits = {
SMU_FEATURE_BIT_INIT(FEATURE_DPM_GFXCLK_BIT),
@@ -1043,8 +1047,35 @@ static bool smu_v13_0_0_is_od_feature_supported(struct smu_context *smu,
PPTable_t *pptable = smu->smu_table.driver_pptable;
const OverDriveLimits_t * const overdrive_upperlimits =
&pptable->SkuTable.OverDriveLimitsBasicMax;
+ int32_t min_value, max_value;
+ bool feature_enabled;
- return overdrive_upperlimits->FeatureCtrlMask & (1U << od_feature_bit);
+ switch (od_feature_bit) {
+ case PP_OD_FEATURE_FAN_CURVE_BIT:
+ feature_enabled = !!(overdrive_upperlimits->FeatureCtrlMask & (1U << od_feature_bit));
+ if (feature_enabled) {
+ smu_v13_0_0_get_od_setting_limits(smu, PP_OD_FEATURE_FAN_CURVE_TEMP,
+ &min_value, &max_value);
+ if (!min_value && !max_value) {
+ feature_enabled = false;
+ goto out;
+ }
+
+ smu_v13_0_0_get_od_setting_limits(smu, PP_OD_FEATURE_FAN_CURVE_PWM,
+ &min_value, &max_value);
+ if (!min_value && !max_value) {
+ feature_enabled = false;
+ goto out;
+ }
+ }
+ break;
+ default:
+ feature_enabled = !!(overdrive_upperlimits->FeatureCtrlMask & (1U << od_feature_bit));
+ break;
+ }
+
+out:
+ return feature_enabled;
}
static void smu_v13_0_0_get_od_setting_limits(struct smu_context *smu,
@@ -3133,7 +3164,7 @@ static const struct pptable_funcs smu_v13_0_0_ppt_funcs = {
.fini_power = smu_v13_0_fini_power,
.check_fw_status = smu_v13_0_check_fw_status,
.setup_pptable = smu_v13_0_0_setup_pptable,
- .check_fw_version = smu_v13_0_check_fw_version,
+ .check_fw_version = smu_cmn_check_fw_version,
.write_pptable = smu_cmn_write_pptable,
.set_driver_table_location = smu_v13_0_set_driver_table_location,
.system_features_control = smu_v13_0_0_system_features_control,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c
index 5b1a038d6a19..ba91bf590eed 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c
@@ -1098,7 +1098,7 @@ static int smu_v13_0_4_set_fine_grain_gfx_freq_parameters(struct smu_context *sm
static const struct pptable_funcs smu_v13_0_4_ppt_funcs = {
.check_fw_status = smu_v13_0_check_fw_status,
- .check_fw_version = smu_v13_0_check_fw_version,
+ .check_fw_version = smu_cmn_check_fw_version,
.init_smc_tables = smu_v13_0_4_init_smc_tables,
.fini_smc_tables = smu_v13_0_4_fini_smc_tables,
.get_vbios_bootup_values = smu_v13_0_get_vbios_bootup_values,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_5_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_5_ppt.c
index d534723fef91..27372a60e83d 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_5_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_5_ppt.c
@@ -1102,7 +1102,7 @@ static int smu_v13_0_5_set_fine_grain_gfx_freq_parameters(struct smu_context *sm
static const struct pptable_funcs smu_v13_0_5_ppt_funcs = {
.check_fw_status = smu_v13_0_check_fw_status,
- .check_fw_version = smu_v13_0_check_fw_version,
+ .check_fw_version = smu_cmn_check_fw_version,
.init_smc_tables = smu_v13_0_5_init_smc_tables,
.fini_smc_tables = smu_v13_0_5_fini_smc_tables,
.get_vbios_bootup_values = smu_v13_0_get_vbios_bootup_values,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
index 8dc8674b7ce1..475541189782 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
@@ -461,6 +461,7 @@ static void smu_v13_0_6_init_caps(struct smu_context *smu)
smu_v13_0_6_cap_set(smu, SMU_CAP(SDMA_RESET));
if ((pgm == 0 && fw_ver >= 0x00558200) ||
+ (pgm == 4 && fw_ver >= 0x04557100) ||
(pgm == 7 && fw_ver >= 0x07551400))
smu_v13_0_6_cap_set(smu, SMU_CAP(VCN_RESET));
}
@@ -481,7 +482,7 @@ static int smu_v13_0_6_check_fw_version(struct smu_context *smu)
{
int r;
- r = smu_v13_0_check_fw_version(smu);
+ r = smu_cmn_check_fw_version(smu);
/* Initialize caps flags once fw version is fetched */
if (!r)
smu_v13_0_x_init_caps(smu);
@@ -1199,6 +1200,7 @@ static int smu_v13_0_6_populate_umd_state_clk(struct smu_context *smu)
struct smu_dpm_table *gfx_table = &dpm_context->dpm_tables.gfx_table;
struct smu_dpm_table *mem_table = &dpm_context->dpm_tables.uclk_table;
struct smu_dpm_table *soc_table = &dpm_context->dpm_tables.soc_table;
+ struct smu_dpm_table *fclk_table = &dpm_context->dpm_tables.fclk_table;
struct smu_umd_pstate_table *pstate_table = &smu->pstate_table;
pstate_table->gfxclk_pstate.min = SMU_DPM_TABLE_MIN(gfx_table);
@@ -1216,6 +1218,12 @@ static int smu_v13_0_6_populate_umd_state_clk(struct smu_context *smu)
pstate_table->socclk_pstate.curr.min = SMU_DPM_TABLE_MIN(soc_table);
pstate_table->socclk_pstate.curr.max = SMU_DPM_TABLE_MAX(soc_table);
+ pstate_table->fclk_pstate.min = SMU_DPM_TABLE_MIN(fclk_table);
+ pstate_table->fclk_pstate.peak = SMU_DPM_TABLE_MAX(fclk_table);
+ pstate_table->fclk_pstate.curr.min = SMU_DPM_TABLE_MIN(fclk_table);
+ pstate_table->fclk_pstate.curr.max = SMU_DPM_TABLE_MAX(fclk_table);
+ pstate_table->fclk_pstate.standard = SMU_DPM_TABLE_MIN(fclk_table);
+
if (gfx_table->count > SMU_13_0_6_UMD_PSTATE_GFXCLK_LEVEL &&
mem_table->count > SMU_13_0_6_UMD_PSTATE_MCLK_LEVEL &&
soc_table->count > SMU_13_0_6_UMD_PSTATE_SOCCLK_LEVEL) {
@@ -1394,14 +1402,22 @@ static int smu_v13_0_6_emit_clk_levels(struct smu_context *smu,
break;
case SMU_OD_MCLK:
if (!smu_v13_0_6_cap_supported(smu, SMU_CAP(SET_UCLK_MAX)))
- return 0;
+ return -EOPNOTSUPP;
size += sysfs_emit_at(buf, size, "%s:\n", "OD_MCLK");
size += sysfs_emit_at(buf, size, "0: %uMhz\n1: %uMhz\n",
pstate_table->uclk_pstate.curr.min,
pstate_table->uclk_pstate.curr.max);
break;
+ case SMU_OD_FCLK:
+ if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_FCLK_BIT))
+ return -EOPNOTSUPP;
+ size += sysfs_emit_at(buf, size, "%s:\n", "OD_FCLK");
+ size += sysfs_emit_at(buf, size, "0: %uMhz\n1: %uMhz\n",
+ pstate_table->fclk_pstate.curr.min,
+ pstate_table->fclk_pstate.curr.max);
+ break;
case SMU_SCLK:
case SMU_GFXCLK:
single_dpm_table = &(dpm_context->dpm_tables.gfx_table);
@@ -2043,7 +2059,7 @@ static int smu_v13_0_6_set_soft_freq_limited_range(struct smu_context *smu,
int ret = 0;
if (clk_type != SMU_GFXCLK && clk_type != SMU_SCLK &&
- clk_type != SMU_UCLK)
+ clk_type != SMU_UCLK && clk_type != SMU_FCLK)
return -EINVAL;
if ((smu_dpm->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) &&
@@ -2084,6 +2100,15 @@ static int smu_v13_0_6_set_soft_freq_limited_range(struct smu_context *smu,
pstate_table->uclk_pstate.curr.max = max;
}
+ if (clk_type == SMU_FCLK) {
+ if (max == pstate_table->fclk_pstate.curr.max)
+ return 0;
+
+ ret = smu_v13_0_set_soft_freq_limited_range(smu, SMU_FCLK, 0, max, false);
+ if (!ret)
+ pstate_table->fclk_pstate.curr.max = max;
+ }
+
return ret;
}
@@ -2125,6 +2150,8 @@ static int smu_v13_0_6_usr_edit_dpm_table(struct smu_context *smu,
{
struct smu_dpm_context *smu_dpm = &(smu->smu_dpm);
struct smu_13_0_dpm_context *dpm_context = smu_dpm->dpm_context;
+ struct smu_dpm_table *uclk_table = &dpm_context->dpm_tables.uclk_table;
+ struct smu_dpm_table *fclk_table = &dpm_context->dpm_tables.fclk_table;
struct smu_umd_pstate_table *pstate_table = &smu->pstate_table;
uint32_t min_clk;
uint32_t max_clk;
@@ -2205,6 +2232,40 @@ static int smu_v13_0_6_usr_edit_dpm_table(struct smu_context *smu,
pstate_table->uclk_pstate.custom.max = input[1];
}
break;
+ case PP_OD_EDIT_FCLK_TABLE:
+ if (size != 2) {
+ dev_err(smu->adev->dev,
+ "Input parameter number not correct\n");
+ return -EINVAL;
+ }
+
+ if (!smu_cmn_feature_is_enabled(smu,
+ SMU_FEATURE_DPM_FCLK_BIT)) {
+ dev_warn(smu->adev->dev,
+ "FCLK limits setting not supported!\n");
+ return -EOPNOTSUPP;
+ }
+
+ max_clk = SMU_DPM_TABLE_MAX(&dpm_context->dpm_tables.fclk_table);
+ if (input[0] == 0) {
+ dev_info(smu->adev->dev,
+ "Setting min FCLK level is not supported\n");
+ return -EOPNOTSUPP;
+ } else if (input[0] == 1) {
+ if (input[1] > max_clk) {
+ dev_warn(smu->adev->dev,
+ "Maximum FCLK (%ld) MHz specified is greater than the maximum allowed (%d) MHz\n",
+ input[1], max_clk);
+ pstate_table->fclk_pstate.custom.max =
+ pstate_table->fclk_pstate.curr.max;
+ return -EINVAL;
+ }
+
+ pstate_table->fclk_pstate.custom.max = input[1];
+ } else {
+ return -EINVAL;
+ }
+ break;
case PP_OD_RESTORE_DEFAULT_TABLE:
if (size != 0) {
@@ -2224,14 +2285,27 @@ static int smu_v13_0_6_usr_edit_dpm_table(struct smu_context *smu,
if (ret)
return ret;
- min_clk = SMU_DPM_TABLE_MIN(
- &dpm_context->dpm_tables.uclk_table);
- max_clk = SMU_DPM_TABLE_MAX(
- &dpm_context->dpm_tables.uclk_table);
- ret = smu_v13_0_6_set_soft_freq_limited_range(
- smu, SMU_UCLK, min_clk, max_clk, false);
- if (ret)
- return ret;
+ if (SMU_DPM_TABLE_MAX(uclk_table) !=
+ pstate_table->uclk_pstate.curr.max) {
+ min_clk = SMU_DPM_TABLE_MIN(&dpm_context->dpm_tables.uclk_table);
+ max_clk = SMU_DPM_TABLE_MAX(&dpm_context->dpm_tables.uclk_table);
+ ret = smu_v13_0_6_set_soft_freq_limited_range(smu,
+ SMU_UCLK, min_clk,
+ max_clk, false);
+ if (ret)
+ return ret;
+ }
+
+ if (SMU_DPM_TABLE_MAX(fclk_table) !=
+ pstate_table->fclk_pstate.curr.max) {
+ max_clk = SMU_DPM_TABLE_MAX(&dpm_context->dpm_tables.fclk_table);
+ min_clk = SMU_DPM_TABLE_MIN(&dpm_context->dpm_tables.fclk_table);
+ ret = smu_v13_0_6_set_soft_freq_limited_range(smu,
+ SMU_FCLK, min_clk,
+ max_clk, false);
+ if (ret)
+ return ret;
+ }
smu_v13_0_reset_custom_level(smu);
}
break;
@@ -2258,6 +2332,16 @@ static int smu_v13_0_6_usr_edit_dpm_table(struct smu_context *smu,
if (ret)
return ret;
+ if (pstate_table->fclk_pstate.custom.max) {
+ min_clk = pstate_table->fclk_pstate.curr.min;
+ max_clk = pstate_table->fclk_pstate.custom.max;
+ ret = smu_v13_0_6_set_soft_freq_limited_range(smu,
+ SMU_FCLK, min_clk,
+ max_clk, false);
+ if (ret)
+ return ret;
+ }
+
if (!pstate_table->uclk_pstate.custom.max)
return 0;
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
index 5500a0f12f0e..fd0b6215364f 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
@@ -59,6 +59,10 @@
#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c))
+static void smu_v13_0_7_get_od_setting_limits(struct smu_context *smu,
+ int od_feature_bit,
+ int32_t *min, int32_t *max);
+
static const struct smu_feature_bits smu_v13_0_7_dpm_features = {
.bits = {
SMU_FEATURE_BIT_INIT(FEATURE_DPM_GFXCLK_BIT),
@@ -1053,8 +1057,35 @@ static bool smu_v13_0_7_is_od_feature_supported(struct smu_context *smu,
PPTable_t *pptable = smu->smu_table.driver_pptable;
const OverDriveLimits_t * const overdrive_upperlimits =
&pptable->SkuTable.OverDriveLimitsBasicMax;
+ int32_t min_value, max_value;
+ bool feature_enabled;
- return overdrive_upperlimits->FeatureCtrlMask & (1U << od_feature_bit);
+ switch (od_feature_bit) {
+ case PP_OD_FEATURE_FAN_CURVE_BIT:
+ feature_enabled = !!(overdrive_upperlimits->FeatureCtrlMask & (1U << od_feature_bit));
+ if (feature_enabled) {
+ smu_v13_0_7_get_od_setting_limits(smu, PP_OD_FEATURE_FAN_CURVE_TEMP,
+ &min_value, &max_value);
+ if (!min_value && !max_value) {
+ feature_enabled = false;
+ goto out;
+ }
+
+ smu_v13_0_7_get_od_setting_limits(smu, PP_OD_FEATURE_FAN_CURVE_PWM,
+ &min_value, &max_value);
+ if (!min_value && !max_value) {
+ feature_enabled = false;
+ goto out;
+ }
+ }
+ break;
+ default:
+ feature_enabled = !!(overdrive_upperlimits->FeatureCtrlMask & (1U << od_feature_bit));
+ break;
+ }
+
+out:
+ return feature_enabled;
}
static void smu_v13_0_7_get_od_setting_limits(struct smu_context *smu,
@@ -2788,7 +2819,7 @@ static const struct pptable_funcs smu_v13_0_7_ppt_funcs = {
.fini_power = smu_v13_0_fini_power,
.check_fw_status = smu_v13_0_7_check_fw_status,
.setup_pptable = smu_v13_0_7_setup_pptable,
- .check_fw_version = smu_v13_0_check_fw_version,
+ .check_fw_version = smu_cmn_check_fw_version,
.write_pptable = smu_cmn_write_pptable,
.set_driver_table_location = smu_v13_0_set_driver_table_location,
.system_features_control = smu_v13_0_system_features_control,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c
index f43a91ac6970..7bf88ffd311b 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c
@@ -1331,7 +1331,7 @@ static int yellow_carp_set_fine_grain_gfx_freq_parameters(struct smu_context *sm
static const struct pptable_funcs yellow_carp_ppt_funcs = {
.check_fw_status = smu_v13_0_check_fw_status,
- .check_fw_version = smu_v13_0_check_fw_version,
+ .check_fw_version = smu_cmn_check_fw_version,
.init_smc_tables = yellow_carp_init_smc_tables,
.fini_smc_tables = yellow_carp_fini_smc_tables,
.get_vbios_bootup_values = smu_v13_0_get_vbios_bootup_values,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c
index cec2df1ad0af..d0a8df1aa6b6 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c
@@ -229,67 +229,6 @@ int smu_v14_0_check_fw_status(struct smu_context *smu)
return -EIO;
}
-int smu_v14_0_check_fw_version(struct smu_context *smu)
-{
- struct amdgpu_device *adev = smu->adev;
- uint32_t if_version = 0xff, smu_version = 0xff;
- uint8_t smu_program, smu_major, smu_minor, smu_debug;
- int ret = 0;
-
- ret = smu_cmn_get_smc_version(smu, &if_version, &smu_version);
- if (ret)
- return ret;
-
- smu_program = (smu_version >> 24) & 0xff;
- smu_major = (smu_version >> 16) & 0xff;
- smu_minor = (smu_version >> 8) & 0xff;
- smu_debug = (smu_version >> 0) & 0xff;
- if (smu->is_apu)
- adev->pm.fw_version = smu_version;
-
- switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) {
- case IP_VERSION(14, 0, 0):
- case IP_VERSION(14, 0, 4):
- case IP_VERSION(14, 0, 5):
- smu->smc_driver_if_version = SMU14_DRIVER_IF_VERSION_SMU_V14_0_0;
- break;
- case IP_VERSION(14, 0, 1):
- smu->smc_driver_if_version = SMU14_DRIVER_IF_VERSION_SMU_V14_0_1;
- break;
- case IP_VERSION(14, 0, 2):
- case IP_VERSION(14, 0, 3):
- smu->smc_driver_if_version = SMU14_DRIVER_IF_VERSION_SMU_V14_0_2;
- break;
- default:
- dev_err(adev->dev, "smu unsupported IP version: 0x%x.\n",
- amdgpu_ip_version(adev, MP1_HWIP, 0));
- smu->smc_driver_if_version = SMU14_DRIVER_IF_VERSION_INV;
- break;
- }
-
- if (adev->pm.fw)
- dev_dbg(smu->adev->dev, "smu fw reported program %d, version = 0x%08x (%d.%d.%d)\n",
- smu_program, smu_version, smu_major, smu_minor, smu_debug);
-
- /*
- * 1. if_version mismatch is not critical as our fw is designed
- * to be backward compatible.
- * 2. New fw usually brings some optimizations. But that's visible
- * only on the paired driver.
- * Considering above, we just leave user a verbal message instead
- * of halt driver loading.
- */
- if (if_version != smu->smc_driver_if_version) {
- dev_info(adev->dev, "smu driver if version = 0x%08x, smu fw if version = 0x%08x, "
- "smu fw program = %d, smu fw version = 0x%08x (%d.%d.%d)\n",
- smu->smc_driver_if_version, if_version,
- smu_program, smu_version, smu_major, smu_minor, smu_debug);
- dev_info(adev->dev, "SMU driver if version not matched\n");
- }
-
- return ret;
-}
-
static int smu_v14_0_set_pptable_v2_0(struct smu_context *smu, void **table, uint32_t *size)
{
struct amdgpu_device *adev = smu->adev;
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c
index 2353524b8821..a28624d4847a 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c
@@ -65,6 +65,9 @@
#define SMU_MALL_PG_CONFIG_DEFAULT SMU_MALL_PG_CONFIG_DRIVER_CONTROL_ALWAYS_ON
+#define SMU14_DRIVER_IF_VERSION_SMU_V14_0_0 0x7
+#define SMU14_DRIVER_IF_VERSION_SMU_V14_0_1 0x6
+
#define SMU_14_0_0_UMD_PSTATE_GFXCLK 700
#define SMU_14_0_0_UMD_PSTATE_SOCCLK 678
#define SMU_14_0_0_UMD_PSTATE_FCLK 1800
@@ -1699,7 +1702,7 @@ static int smu_v14_0_0_restore_user_od_settings(struct smu_context *smu)
static const struct pptable_funcs smu_v14_0_0_ppt_funcs = {
.check_fw_status = smu_v14_0_check_fw_status,
- .check_fw_version = smu_v14_0_check_fw_version,
+ .check_fw_version = smu_cmn_check_fw_version,
.init_smc_tables = smu_v14_0_0_init_smc_tables,
.fini_smc_tables = smu_v14_0_0_fini_smc_tables,
.get_vbios_bootup_values = smu_v14_0_get_vbios_bootup_values,
@@ -1750,10 +1753,23 @@ static void smu_v14_0_0_init_msg_ctl(struct smu_context *smu)
void smu_v14_0_0_set_ppt_funcs(struct smu_context *smu)
{
+ struct amdgpu_device *adev = smu->adev;
+
smu->ppt_funcs = &smu_v14_0_0_ppt_funcs;
smu->feature_map = smu_v14_0_0_feature_mask_map;
smu->table_map = smu_v14_0_0_table_map;
smu->is_apu = true;
+ switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) {
+ case IP_VERSION(14, 0, 0):
+ case IP_VERSION(14, 0, 4):
+ case IP_VERSION(14, 0, 5):
+ smu->smc_driver_if_version = SMU14_DRIVER_IF_VERSION_SMU_V14_0_0;
+ break;
+ case IP_VERSION(14, 0, 1):
+ smu->smc_driver_if_version = SMU14_DRIVER_IF_VERSION_SMU_V14_0_1;
+ break;
+ }
+
smu_v14_0_0_init_msg_ctl(smu);
}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c
index 73762d9b5969..31f9566f7979 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c
@@ -56,6 +56,10 @@
#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c))
+static void smu_v14_0_2_get_od_setting_limits(struct smu_context *smu,
+ int od_feature_bit,
+ int32_t *min, int32_t *max);
+
static const struct smu_feature_bits smu_v14_0_2_dpm_features = {
.bits = { SMU_FEATURE_BIT_INIT(FEATURE_DPM_GFXCLK_BIT),
SMU_FEATURE_BIT_INIT(FEATURE_DPM_UCLK_BIT),
@@ -64,6 +68,8 @@ static const struct smu_feature_bits smu_v14_0_2_dpm_features = {
SMU_FEATURE_BIT_INIT(FEATURE_DPM_FCLK_BIT) }
};
+#define SMU14_DRIVER_IF_VERSION_SMU_V14_0_2 0x2E
+
#define MP0_MP1_DATA_REGION_SIZE_COMBOPPTABLE 0x4000
#define DEBUGSMC_MSG_Mode1Reset 2
#define LINK_SPEED_MAX 3
@@ -922,8 +928,35 @@ static bool smu_v14_0_2_is_od_feature_supported(struct smu_context *smu,
PPTable_t *pptable = smu->smu_table.driver_pptable;
const OverDriveLimits_t * const overdrive_upperlimits =
&pptable->SkuTable.OverDriveLimitsBasicMax;
+ int32_t min_value, max_value;
+ bool feature_enabled;
+
+ switch (od_feature_bit) {
+ case PP_OD_FEATURE_FAN_CURVE_BIT:
+ feature_enabled = !!(overdrive_upperlimits->FeatureCtrlMask & (1U << od_feature_bit));
+ if (feature_enabled) {
+ smu_v14_0_2_get_od_setting_limits(smu, PP_OD_FEATURE_FAN_CURVE_TEMP,
+ &min_value, &max_value);
+ if (!min_value && !max_value) {
+ feature_enabled = false;
+ goto out;
+ }
- return overdrive_upperlimits->FeatureCtrlMask & (1U << od_feature_bit);
+ smu_v14_0_2_get_od_setting_limits(smu, PP_OD_FEATURE_FAN_CURVE_PWM,
+ &min_value, &max_value);
+ if (!min_value && !max_value) {
+ feature_enabled = false;
+ goto out;
+ }
+ }
+ break;
+ default:
+ feature_enabled = !!(overdrive_upperlimits->FeatureCtrlMask & (1U << od_feature_bit));
+ break;
+ }
+
+out:
+ return feature_enabled;
}
static void smu_v14_0_2_get_od_setting_limits(struct smu_context *smu,
@@ -2767,7 +2800,7 @@ static const struct pptable_funcs smu_v14_0_2_ppt_funcs = {
.fini_power = smu_v14_0_fini_power,
.check_fw_status = smu_v14_0_check_fw_status,
.setup_pptable = smu_v14_0_2_setup_pptable,
- .check_fw_version = smu_v14_0_check_fw_version,
+ .check_fw_version = smu_cmn_check_fw_version,
.set_driver_table_location = smu_v14_0_set_driver_table_location,
.system_features_control = smu_v14_0_system_features_control,
.set_allowed_mask = smu_v14_0_set_allowed_mask,
@@ -2832,5 +2865,6 @@ void smu_v14_0_2_set_ppt_funcs(struct smu_context *smu)
smu->table_map = smu_v14_0_2_table_map;
smu->pwr_src_map = smu_v14_0_2_pwr_src_map;
smu->workload_map = smu_v14_0_2_workload_map;
+ smu->smc_driver_if_version = SMU14_DRIVER_IF_VERSION_SMU_V14_0_2;
smu_v14_0_2_init_msg_ctl(smu);
}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/Makefile b/drivers/gpu/drm/amd/pm/swsmu/smu15/Makefile
index 7f59a0aabdeb..fa083ad46c0f 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu15/Makefile
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/Makefile
@@ -23,7 +23,7 @@
# Makefile for the 'smu manager' sub-component of powerplay.
# It provides the smu management services for the driver.
-SMU15_MGR = smu_v15_0.o smu_v15_0_0_ppt.o
+SMU15_MGR = smu_v15_0.o smu_v15_0_0_ppt.o smu_v15_0_8_ppt.o
AMD_SWSMU_SMU15MGR = $(addprefix $(AMD_SWSMU_PATH)/smu15/,$(SMU15_MGR))
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0.c
index 3fd84dd85e9b..c3cb36813806 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0.c
@@ -207,58 +207,6 @@ int smu_v15_0_check_fw_status(struct smu_context *smu)
return -EIO;
}
-int smu_v15_0_check_fw_version(struct smu_context *smu)
-{
- struct amdgpu_device *adev = smu->adev;
- uint32_t if_version = 0xff, smu_version = 0xff;
- uint8_t smu_program, smu_major, smu_minor, smu_debug;
- int ret = 0;
-
- ret = smu_cmn_get_smc_version(smu, &if_version, &smu_version);
- if (ret)
- return ret;
-
- smu_program = (smu_version >> 24) & 0xff;
- smu_major = (smu_version >> 16) & 0xff;
- smu_minor = (smu_version >> 8) & 0xff;
- smu_debug = (smu_version >> 0) & 0xff;
- if (smu->is_apu)
- adev->pm.fw_version = smu_version;
-
- switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) {
- case IP_VERSION(15, 0, 0):
- smu->smc_driver_if_version = SMU15_DRIVER_IF_VERSION_SMU_V15_0;
- break;
- default:
- dev_err(adev->dev, "smu unsupported IP version: 0x%x.\n",
- amdgpu_ip_version(adev, MP1_HWIP, 0));
- smu->smc_driver_if_version = SMU15_DRIVER_IF_VERSION_INV;
- break;
- }
-
- if (adev->pm.fw)
- dev_dbg(smu->adev->dev, "smu fw reported program %d, version = 0x%08x (%d.%d.%d)\n",
- smu_program, smu_version, smu_major, smu_minor, smu_debug);
-
- /*
- * 1. if_version mismatch is not critical as our fw is designed
- * to be backward compatible.
- * 2. New fw usually brings some optimizations. But that's visible
- * only on the paired driver.
- * Considering above, we just leave user a verbal message instead
- * of halt driver loading.
- */
- if (if_version != smu->smc_driver_if_version) {
- dev_info(adev->dev, "smu driver if version = 0x%08x, smu fw if version = 0x%08x, "
- "smu fw program = %d, smu fw version = 0x%08x (%d.%d.%d)\n",
- smu->smc_driver_if_version, if_version,
- smu_program, smu_version, smu_major, smu_minor, smu_debug);
- dev_info(adev->dev, "SMU driver if version not matched\n");
- }
-
- return ret;
-}
-
static int smu_v15_0_set_pptable_v2_0(struct smu_context *smu, void **table, uint32_t *size)
{
struct amdgpu_device *adev = smu->adev;
@@ -641,71 +589,52 @@ int smu_v15_0_notify_memory_pool_location(struct smu_context *smu)
{
struct smu_table_context *smu_table = &smu->smu_table;
struct smu_table *memory_pool = &smu_table->memory_pool;
- int ret = 0;
- uint64_t address;
- uint32_t address_low, address_high;
+ struct smu_msg_args args = {
+ .msg = SMU_MSG_DramLogSetDramAddr,
+ .num_args = 3,
+ .num_out_args = 0,
+ };
if (memory_pool->size == 0 || memory_pool->cpu_addr == NULL)
- return ret;
-
- address = memory_pool->mc_address;
- address_high = (uint32_t)upper_32_bits(address);
- address_low = (uint32_t)lower_32_bits(address);
+ return 0;
- ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_DramLogSetDramAddrHigh,
- address_high, NULL);
- if (ret)
- return ret;
- ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_DramLogSetDramAddrLow,
- address_low, NULL);
- if (ret)
- return ret;
- ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_DramLogSetDramSize,
- (uint32_t)memory_pool->size, NULL);
- if (ret)
- return ret;
+ /* SMU_MSG_DramLogSetDramAddr: ARG0=low, ARG1=high, ARG2=size */
+ args.args[0] = lower_32_bits(memory_pool->mc_address);
+ args.args[1] = upper_32_bits(memory_pool->mc_address);
+ args.args[2] = (u32)memory_pool->size;
- return ret;
+ return smu->msg_ctl.ops->send_msg(&smu->msg_ctl, &args);
}
int smu_v15_0_set_driver_table_location(struct smu_context *smu)
{
struct smu_table *driver_table = &smu->smu_table.driver_table;
- int ret = 0;
+ struct smu_msg_args args = {
+ .msg = SMU_MSG_SetDriverDramAddr,
+ .num_args = 2,
+ .num_out_args = 0,
+ };
- if (driver_table->mc_address) {
- ret = smu_cmn_send_smc_msg_with_param(smu,
- SMU_MSG_SetDriverDramAddrHigh,
- upper_32_bits(driver_table->mc_address),
- NULL);
- if (!ret)
- ret = smu_cmn_send_smc_msg_with_param(smu,
- SMU_MSG_SetDriverDramAddrLow,
- lower_32_bits(driver_table->mc_address),
- NULL);
- }
+ args.args[0] = lower_32_bits(driver_table->mc_address);
+ args.args[1] = upper_32_bits(driver_table->mc_address);
- return ret;
+ return smu->msg_ctl.ops->send_msg(&smu->msg_ctl, &args);
}
int smu_v15_0_set_tool_table_location(struct smu_context *smu)
{
- int ret = 0;
struct smu_table *tool_table = &smu->smu_table.tables[SMU_TABLE_PMSTATUSLOG];
+ struct smu_msg_args args = {
+ .msg = SMU_MSG_SetToolsDramAddr,
+ .num_args = 2,
+ .num_out_args = 0,
+ };
- if (tool_table->mc_address) {
- ret = smu_cmn_send_smc_msg_with_param(smu,
- SMU_MSG_SetToolsDramAddrHigh,
- upper_32_bits(tool_table->mc_address),
- NULL);
- if (!ret)
- ret = smu_cmn_send_smc_msg_with_param(smu,
- SMU_MSG_SetToolsDramAddrLow,
- lower_32_bits(tool_table->mc_address),
- NULL);
- }
+ /* SMU_MSG_SetToolsDramAddr: ARG0=low, ARG1=high */
+ args.args[0] = lower_32_bits(tool_table->mc_address);
+ args.args[1] = upper_32_bits(tool_table->mc_address);
- return ret;
+ return smu->msg_ctl.ops->send_msg(&smu->msg_ctl, &args);
}
int smu_v15_0_set_allowed_mask(struct smu_context *smu)
@@ -752,8 +681,7 @@ int smu_v15_0_gfx_off_control(struct smu_context *smu, bool enable)
return ret;
}
-int smu_v15_0_system_features_control(struct smu_context *smu,
- bool en)
+int smu_v15_0_system_features_control(struct smu_context *smu, bool en)
{
return smu_cmn_send_smc_msg(smu, (en ? SMU_MSG_EnableAllSmuFeatures :
SMU_MSG_DisableAllSmuFeatures), NULL);
@@ -957,7 +885,8 @@ static int smu_v15_0_wait_for_reset_complete(struct smu_context *smu,
return ret;
}
-int smu_v15_0_wait_for_event(struct smu_context *smu, enum smu_event_type event,
+int smu_v15_0_wait_for_event(struct smu_context *smu,
+ enum smu_event_type event,
uint64_t event_arg)
{
int ret = -EINVAL;
@@ -1129,18 +1058,12 @@ int smu_v15_0_set_performance_level(struct smu_context *smu,
{
struct smu_15_0_dpm_context *dpm_context =
smu->smu_dpm.dpm_context;
- struct smu_15_0_dpm_table *gfx_table =
- &dpm_context->dpm_tables.gfx_table;
- struct smu_15_0_dpm_table *mem_table =
- &dpm_context->dpm_tables.uclk_table;
- struct smu_15_0_dpm_table *soc_table =
- &dpm_context->dpm_tables.soc_table;
- struct smu_15_0_dpm_table *vclk_table =
- &dpm_context->dpm_tables.vclk_table;
- struct smu_15_0_dpm_table *dclk_table =
- &dpm_context->dpm_tables.dclk_table;
- struct smu_15_0_dpm_table *fclk_table =
- &dpm_context->dpm_tables.fclk_table;
+ struct smu_dpm_table *gfx_table = &dpm_context->dpm_tables.gfx_table;
+ struct smu_dpm_table *mem_table = &dpm_context->dpm_tables.uclk_table;
+ struct smu_dpm_table *soc_table = &dpm_context->dpm_tables.soc_table;
+ struct smu_dpm_table *vclk_table = &dpm_context->dpm_tables.vclk_table;
+ struct smu_dpm_table *dclk_table = &dpm_context->dpm_tables.dclk_table;
+ struct smu_dpm_table *fclk_table = &dpm_context->dpm_tables.fclk_table;
struct smu_umd_pstate_table *pstate_table =
&smu->pstate_table;
struct amdgpu_device *adev = smu->adev;
@@ -1155,34 +1078,34 @@ int smu_v15_0_set_performance_level(struct smu_context *smu,
switch (level) {
case AMD_DPM_FORCED_LEVEL_HIGH:
- sclk_min = sclk_max = gfx_table->max;
- mclk_min = mclk_max = mem_table->max;
- socclk_min = socclk_max = soc_table->max;
- vclk_min = vclk_max = vclk_table->max;
- dclk_min = dclk_max = dclk_table->max;
- fclk_min = fclk_max = fclk_table->max;
+ sclk_min = sclk_max = SMU_DPM_TABLE_MAX(gfx_table);
+ mclk_min = mclk_max = SMU_DPM_TABLE_MAX(mem_table);
+ socclk_min = socclk_max = SMU_DPM_TABLE_MAX(soc_table);
+ vclk_min = vclk_max = SMU_DPM_TABLE_MAX(vclk_table);
+ dclk_min = dclk_max = SMU_DPM_TABLE_MAX(dclk_table);
+ fclk_min = fclk_max = SMU_DPM_TABLE_MAX(fclk_table);
break;
case AMD_DPM_FORCED_LEVEL_LOW:
- sclk_min = sclk_max = gfx_table->min;
- mclk_min = mclk_max = mem_table->min;
- socclk_min = socclk_max = soc_table->min;
- vclk_min = vclk_max = vclk_table->min;
- dclk_min = dclk_max = dclk_table->min;
- fclk_min = fclk_max = fclk_table->min;
+ sclk_min = sclk_max = SMU_DPM_TABLE_MIN(gfx_table);
+ mclk_min = mclk_max = SMU_DPM_TABLE_MIN(mem_table);
+ socclk_min = socclk_max = SMU_DPM_TABLE_MIN(soc_table);
+ vclk_min = vclk_max = SMU_DPM_TABLE_MIN(vclk_table);
+ dclk_min = dclk_max = SMU_DPM_TABLE_MIN(dclk_table);
+ fclk_min = fclk_max = SMU_DPM_TABLE_MIN(fclk_table);
break;
case AMD_DPM_FORCED_LEVEL_AUTO:
- sclk_min = gfx_table->min;
- sclk_max = gfx_table->max;
- mclk_min = mem_table->min;
- mclk_max = mem_table->max;
- socclk_min = soc_table->min;
- socclk_max = soc_table->max;
- vclk_min = vclk_table->min;
- vclk_max = vclk_table->max;
- dclk_min = dclk_table->min;
- dclk_max = dclk_table->max;
- fclk_min = fclk_table->min;
- fclk_max = fclk_table->max;
+ sclk_min = SMU_DPM_TABLE_MIN(gfx_table);
+ sclk_max = SMU_DPM_TABLE_MAX(gfx_table);
+ mclk_min = SMU_DPM_TABLE_MIN(mem_table);
+ mclk_max = SMU_DPM_TABLE_MAX(mem_table);
+ socclk_min = SMU_DPM_TABLE_MIN(soc_table);
+ socclk_max = SMU_DPM_TABLE_MAX(soc_table);
+ vclk_min = SMU_DPM_TABLE_MIN(vclk_table);
+ vclk_max = SMU_DPM_TABLE_MAX(vclk_table);
+ dclk_min = SMU_DPM_TABLE_MIN(dclk_table);
+ dclk_max = SMU_DPM_TABLE_MAX(dclk_table);
+ fclk_min = SMU_DPM_TABLE_MIN(fclk_table);
+ fclk_max = SMU_DPM_TABLE_MAX(fclk_table);
auto_level = true;
break;
case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
@@ -1404,10 +1327,11 @@ static int smu_v15_0_get_fine_grained_status(struct smu_context *smu,
int smu_v15_0_set_single_dpm_table(struct smu_context *smu,
enum smu_clk_type clk_type,
- struct smu_15_0_dpm_table *single_dpm_table)
+ struct smu_dpm_table *single_dpm_table)
{
int ret = 0;
uint32_t clk;
+ bool is_fine_grained;
int i;
ret = smu_v15_0_get_dpm_level_count(smu,
@@ -1420,12 +1344,15 @@ int smu_v15_0_set_single_dpm_table(struct smu_context *smu,
ret = smu_v15_0_get_fine_grained_status(smu,
clk_type,
- &single_dpm_table->is_fine_grained);
+ &is_fine_grained);
if (ret) {
dev_err(smu->adev->dev, "[%s] failed to get fine grained status!\n", __func__);
return ret;
}
+ if (is_fine_grained)
+ single_dpm_table->flags |= SMU_DPM_TABLE_FINE_GRAINED;
+
for (i = 0; i < single_dpm_table->count; i++) {
ret = smu_v15_0_get_dpm_freq_by_index(smu,
clk_type,
@@ -1438,11 +1365,6 @@ int smu_v15_0_set_single_dpm_table(struct smu_context *smu,
single_dpm_table->dpm_levels[i].value = clk;
single_dpm_table->dpm_levels[i].enabled = true;
-
- if (i == 0)
- single_dpm_table->min = clk;
- else if (i == single_dpm_table->count - 1)
- single_dpm_table->max = clk;
}
return 0;
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_0_ppt.c
index 49cf2b9d931e..8d092c347076 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_0_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_0_ppt.c
@@ -1416,7 +1416,7 @@ static int smu_v15_0_common_get_dpm_table(struct smu_context *smu, struct dpm_cl
static const struct pptable_funcs smu_v15_0_0_ppt_funcs = {
.check_fw_status = smu_v15_0_check_fw_status,
- .check_fw_version = smu_v15_0_check_fw_version,
+ .check_fw_version = smu_cmn_check_fw_version,
.init_smc_tables = smu_v15_0_0_init_smc_tables,
.fini_smc_tables = smu_v15_0_0_fini_smc_tables,
.get_vbios_bootup_values = smu_v15_0_get_vbios_bootup_values,
@@ -1468,6 +1468,7 @@ void smu_v15_0_0_set_ppt_funcs(struct smu_context *smu)
smu->feature_map = smu_v15_0_0_feature_mask_map;
smu->table_map = smu_v15_0_0_table_map;
smu->is_apu = true;
+ smu->smc_driver_if_version = SMU15_DRIVER_IF_VERSION_SMU_V15_0;
smu_v15_0_0_init_msg_ctl(smu);
}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
new file mode 100644
index 000000000000..cc2babc6a341
--- /dev/null
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
@@ -0,0 +1,2270 @@
+/*
+ * Copyright 2025 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#define SWSMU_CODE_LAYER_L2
+
+#include <linux/firmware.h>
+#include "amdgpu.h"
+#include "amdgpu_smu.h"
+#include "smu_v15_0_8_pmfw.h"
+#include "smu15_driver_if_v15_0_8.h"
+#include "smu_v15_0_8_ppsmc.h"
+#include "smu_v15_0_8_ppt.h"
+#include <linux/pci.h>
+#include "smu_cmn.h"
+#include "mp/mp_15_0_8_offset.h"
+#include "mp/mp_15_0_8_sh_mask.h"
+#include "smu_v15_0.h"
+#include "amdgpu_fru_eeprom.h"
+
+#undef MP1_Public
+
+/* address block */
+#define MP1_Public 0x03b00000
+#define smnMP1_FIRMWARE_FLAGS_15_0_8 0x3010024
+/*
+ * DO NOT use these for err/warn/info/debug messages.
+ * Use dev_err, dev_warn, dev_info and dev_dbg instead.
+ * They are more MGPU friendly.
+ */
+#undef pr_err
+#undef pr_warn
+#undef pr_info
+#undef pr_debug
+
+#define SMUQ10_TO_UINT(x) ((x) >> 10)
+#define SMUQ10_FRAC(x) ((x) & 0x3ff)
+#define SMUQ10_ROUND(x) ((SMUQ10_TO_UINT(x)) + ((SMUQ10_FRAC(x)) >= 0x200))
+
+#define hbm_stack_mask_valid(umc_mask) \
+ (((umc_mask) & 0xF) == 0xF)
+
+#define for_each_hbm_stack(stack_idx, umc_mask) \
+ for ((stack_idx) = 0; (umc_mask); \
+ (umc_mask) >>= 4, (stack_idx)++) \
+
+#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c))
+
+#define SMU_15_0_8_FEA_MAP(smu_feature, smu_15_0_8_feature) \
+ [smu_feature] = { 1, (smu_15_0_8_feature) }
+
+#define FEATURE_MASK(feature) (1ULL << feature)
+
+static const struct smu_feature_bits smu_v15_0_8_dpm_features = {
+ .bits = { SMU_FEATURE_BIT_INIT(FEATURE_ID_DATA_CALCULATION),
+ SMU_FEATURE_BIT_INIT(FEATURE_ID_DPM_GFXCLK),
+ SMU_FEATURE_BIT_INIT(FEATURE_ID_DPM_UCLK),
+ SMU_FEATURE_BIT_INIT(FEATURE_ID_DPM_FCLK),
+ SMU_FEATURE_BIT_INIT(FEATURE_ID_DPM_GL2CLK) }
+};
+
+static const struct cmn2asic_msg_mapping smu_v15_0_8_message_map[SMU_MSG_MAX_COUNT] = {
+ MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 0),
+ MSG_MAP(GetSmuVersion, PPSMC_MSG_GetSmuVersion, 1),
+ MSG_MAP(GfxDeviceDriverReset, PPSMC_MSG_GfxDriverReset, SMU_MSG_RAS_PRI | SMU_MSG_NO_PRECHECK),
+ MSG_MAP(GetDriverIfVersion, PPSMC_MSG_GetDriverIfVersion, 1),
+ MSG_MAP(EnableAllSmuFeatures, PPSMC_MSG_EnableAllSmuFeatures, 0),
+ MSG_MAP(GetMetricsVersion, PPSMC_MSG_GetMetricsVersion, 1),
+ MSG_MAP(GetMetricsTable, PPSMC_MSG_GetMetricsTable, 1),
+ MSG_MAP(GetEnabledSmuFeatures, PPSMC_MSG_GetEnabledSmuFeatures, 1),
+ MSG_MAP(SetDriverDramAddr, PPSMC_MSG_SetDriverDramAddr, 1),
+ MSG_MAP(SetToolsDramAddr, PPSMC_MSG_SetToolsDramAddr, 0),
+ MSG_MAP(SetSoftMaxByFreq, PPSMC_MSG_SetSoftMaxByFreq, 1),
+ MSG_MAP(SetPptLimit, PPSMC_MSG_SetPptLimit, 0),
+ MSG_MAP(GetPptLimit, PPSMC_MSG_GetPptLimit, 1),
+ MSG_MAP(DramLogSetDramAddr, PPSMC_MSG_DramLogSetDramAddr, 0),
+ MSG_MAP(HeavySBR, PPSMC_MSG_HeavySBR, 0),
+ MSG_MAP(DFCstateControl, PPSMC_MSG_DFCstateControl, 0),
+ MSG_MAP(GfxDriverResetRecovery, PPSMC_MSG_GfxDriverResetRecovery, 0),
+ MSG_MAP(SetSoftMinGfxclk, PPSMC_MSG_SetSoftMinGfxClk, 1),
+ MSG_MAP(SetSoftMaxGfxClk, PPSMC_MSG_SetSoftMaxGfxClk, 1),
+ MSG_MAP(PrepareMp1ForUnload, PPSMC_MSG_PrepareForDriverUnload, 0),
+ MSG_MAP(QueryValidMcaCount, PPSMC_MSG_QueryValidMcaCount, SMU_MSG_RAS_PRI),
+ MSG_MAP(McaBankDumpDW, PPSMC_MSG_McaBankDumpDW, SMU_MSG_RAS_PRI),
+ MSG_MAP(ClearMcaOnRead, PPSMC_MSG_ClearMcaOnRead, 0),
+ MSG_MAP(QueryValidMcaCeCount, PPSMC_MSG_QueryValidMcaCeCount, SMU_MSG_RAS_PRI),
+ MSG_MAP(McaBankCeDumpDW, PPSMC_MSG_McaBankCeDumpDW, SMU_MSG_RAS_PRI),
+ MSG_MAP(SelectPLPDMode, PPSMC_MSG_SelectPLPDMode, 0),
+ MSG_MAP(SetThrottlingPolicy, PPSMC_MSG_SetThrottlingPolicy, 0),
+ MSG_MAP(ResetSDMA, PPSMC_MSG_ResetSDMA, 0),
+ MSG_MAP(GetRASTableVersion, PPSMC_MSG_GetRasTableVersion, 0),
+ MSG_MAP(SetTimestamp, PPSMC_MSG_SetTimestamp, 0),
+ MSG_MAP(GetTimestamp, PPSMC_MSG_GetTimestamp, 0),
+ MSG_MAP(GetBadPageIpid, PPSMC_MSG_GetBadPageIpIdLoHi, 0),
+ MSG_MAP(EraseRasTable, PPSMC_MSG_EraseRasTable, 0),
+ MSG_MAP(GetStaticMetricsTable, PPSMC_MSG_GetStaticMetricsTable, 1),
+ MSG_MAP(GetSystemMetricsTable, PPSMC_MSG_GetSystemMetricsTable, 1),
+ MSG_MAP(GetSystemMetricsVersion, PPSMC_MSG_GetSystemMetricsVersion, 0),
+ MSG_MAP(ResetVCN, PPSMC_MSG_ResetVCN, 0),
+ MSG_MAP(SetFastPptLimit, PPSMC_MSG_SetFastPptLimit, 0),
+ MSG_MAP(GetFastPptLimit, PPSMC_MSG_GetFastPptLimit, 0),
+ MSG_MAP(SetSoftMinGl2clk, PPSMC_MSG_SetSoftMinGl2clk, 0),
+ MSG_MAP(SetSoftMaxGl2clk, PPSMC_MSG_SetSoftMaxGl2clk, 0),
+ MSG_MAP(SetSoftMinFclk, PPSMC_MSG_SetSoftMinFclk, 0),
+ MSG_MAP(SetSoftMaxFclk, PPSMC_MSG_SetSoftMaxFclk, 0),
+};
+
+/* TODO: Update the clk map once enum PPCLK is updated in smu15_driver_if_v15_0_8.h */
+static struct cmn2asic_mapping smu_v15_0_8_clk_map[SMU_CLK_COUNT] = {
+ CLK_MAP(UCLK, PPCLK_UCLK),
+};
+
+static const struct cmn2asic_mapping smu_v15_0_8_feature_mask_map[SMU_FEATURE_COUNT] = {
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_DATA_CALCULATIONS_BIT, FEATURE_ID_DATA_CALCULATION),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_DPM_GFXCLK_BIT, FEATURE_ID_DPM_GFXCLK),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_DPM_UCLK_BIT, FEATURE_ID_DPM_UCLK),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_DPM_FCLK_BIT, FEATURE_ID_DPM_FCLK),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_DPM_GL2CLK_BIT, FEATURE_ID_DPM_GL2CLK),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_DS_GFXCLK_BIT, FEATURE_ID_DS_GFXCLK),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_DS_SOCCLK_BIT, FEATURE_ID_DS_SOCCLK),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_DS_LCLK_BIT, FEATURE_ID_DS_LCLK),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_DS_FCLK_BIT, FEATURE_ID_DS_FCLK),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_DS_DMABECLK_BIT, FEATURE_ID_DS_DMABECLK),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_DS_MPIFOECLK_BIT, FEATURE_ID_DS_MPIFOECLK),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_DS_MPRASCLK_BIT, FEATURE_ID_DS_MPRASCLK),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_DS_MPNHTCLK_BIT, FEATURE_ID_DS_MPNHTCLK),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_DS_FIOCLK_BIT, FEATURE_ID_DS_FIOCLK),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_DS_DXIOCLK_BIT, FEATURE_ID_DS_DXIOCLK),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_DS_GL2CLK_BIT, FEATURE_ID_DS_GL2CLK),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_PPT_BIT, FEATURE_ID_PPT),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_TDC_BIT, FEATURE_ID_TDC),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_MP1_CG_BIT, FEATURE_ID_SMU_CG),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_FW_CTF_BIT, FEATURE_ID_FW_CTF),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_THERMAL_BIT, FEATURE_ID_THERMAL),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_SOC_PCC_BIT, FEATURE_ID_SOC_PCC),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_XGMI_PER_LINK_PWR_DWN_BIT, FEATURE_ID_XGMI_PER_LINK_PWR_DOWN),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_DS_VCN_BIT, FEATURE_ID_DS_VCN),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_DS_MP1CLK_BIT, FEATURE_ID_DS_MP1CLK),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_DS_MPIOCLK_BIT, FEATURE_ID_DS_MPIOCLK),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_DS_MP0CLK_BIT, FEATURE_ID_DS_MP0CLK),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_PIT_BIT, FEATURE_ID_PIT),
+};
+
+#define TABLE_PMSTATUSLOG 0
+#define TABLE_SMU_METRICS 1
+#define TABLE_I2C_COMMANDS 2
+#define TABLE_COUNT 3
+
+static const struct cmn2asic_mapping smu_v15_0_8_table_map[SMU_TABLE_COUNT] = {
+ TAB_MAP(PMSTATUSLOG),
+ TAB_MAP(SMU_METRICS),
+ TAB_MAP(I2C_COMMANDS),
+};
+
+static size_t smu_v15_0_8_get_system_metrics_size(void)
+{
+ return sizeof(SystemMetricsTable_t);
+}
+
+static int smu_v15_0_8_tables_init(struct smu_context *smu)
+{
+ struct smu_v15_0_8_baseboard_temp_metrics *baseboard_temp_metrics;
+ struct smu_v15_0_8_gpuboard_temp_metrics *gpuboard_temp_metrics;
+ struct smu_table_context *smu_table = &smu->smu_table;
+ int ret, gpu_metrcs_size = sizeof(MetricsTable_t);
+ struct smu_table *tables = smu_table->tables;
+ struct smu_v15_0_8_gpu_metrics *gpu_metrics;
+ void *driver_pptable __free(kfree) = NULL;
+ void *metrics_table __free(kfree) = NULL;
+
+ SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU15_TOOL_SIZE,
+ PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
+
+ SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS,
+ gpu_metrcs_size,
+ PAGE_SIZE,
+ AMDGPU_GEM_DOMAIN_VRAM | AMDGPU_GEM_DOMAIN_GTT);
+ SMU_TABLE_INIT(tables, SMU_TABLE_PMFW_SYSTEM_METRICS,
+ smu_v15_0_8_get_system_metrics_size(), PAGE_SIZE,
+ AMDGPU_GEM_DOMAIN_VRAM | AMDGPU_GEM_DOMAIN_GTT);
+
+ metrics_table = kzalloc(gpu_metrcs_size, GFP_KERNEL);
+ if (!metrics_table)
+ return -ENOMEM;
+
+ smu_table->metrics_time = 0;
+
+ driver_pptable = kzalloc(sizeof(PPTable_t), GFP_KERNEL);
+ if (!driver_pptable)
+ return -ENOMEM;
+
+ ret = smu_driver_table_init(smu, SMU_DRIVER_TABLE_GPU_METRICS,
+ sizeof(struct smu_v15_0_8_gpu_metrics),
+ SMU_GPU_METRICS_CACHE_INTERVAL);
+ if (ret)
+ return ret;
+
+ gpu_metrics = (struct smu_v15_0_8_gpu_metrics *)smu_driver_table_ptr(smu,
+ SMU_DRIVER_TABLE_GPU_METRICS);
+ smu_v15_0_8_gpu_metrics_init(gpu_metrics, 1, 9);
+
+ ret = smu_table_cache_init(smu, SMU_TABLE_PMFW_SYSTEM_METRICS,
+ smu_v15_0_8_get_system_metrics_size(), 5);
+
+ if (ret)
+ return ret;
+
+ /* Initialize base board temperature metrics */
+ ret = smu_driver_table_init(smu,
+ SMU_DRIVER_TABLE_BASEBOARD_TEMP_METRICS,
+ sizeof(*baseboard_temp_metrics), 50);
+ if (ret)
+ return ret;
+ baseboard_temp_metrics = (struct smu_v15_0_8_baseboard_temp_metrics *)
+ smu_driver_table_ptr(smu,
+ SMU_DRIVER_TABLE_BASEBOARD_TEMP_METRICS);
+ smu_v15_0_8_baseboard_temp_metrics_init(baseboard_temp_metrics, 1, 1);
+ /* Initialize GPU board temperature metrics */
+ ret = smu_driver_table_init(smu, SMU_DRIVER_TABLE_GPUBOARD_TEMP_METRICS,
+ sizeof(*gpuboard_temp_metrics), 50);
+ if (ret) {
+ smu_table_cache_fini(smu, SMU_TABLE_PMFW_SYSTEM_METRICS);
+ smu_driver_table_fini(smu,
+ SMU_DRIVER_TABLE_BASEBOARD_TEMP_METRICS);
+ return ret;
+ }
+ gpuboard_temp_metrics = (struct smu_v15_0_8_gpuboard_temp_metrics *)
+ smu_driver_table_ptr(smu,
+ SMU_DRIVER_TABLE_GPUBOARD_TEMP_METRICS);
+ smu_v15_0_8_gpuboard_temp_metrics_init(gpuboard_temp_metrics, 1, 1);
+
+ smu_table->metrics_table = no_free_ptr(metrics_table);
+ smu_table->driver_pptable = no_free_ptr(driver_pptable);
+
+ mutex_init(&smu_table->metrics_lock);
+
+ return 0;
+}
+
+static int smu_v15_0_8_allocate_dpm_context(struct smu_context *smu)
+{
+ struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
+
+ smu_dpm->dpm_context =
+ kzalloc(sizeof(struct smu_15_0_dpm_context), GFP_KERNEL);
+ if (!smu_dpm->dpm_context)
+ return -ENOMEM;
+ smu_dpm->dpm_context_size = sizeof(struct smu_15_0_dpm_context);
+
+ smu_dpm->dpm_policies =
+ kzalloc(sizeof(struct smu_dpm_policy_ctxt), GFP_KERNEL);
+ if (!smu_dpm->dpm_policies) {
+ kfree(smu_dpm->dpm_context);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static int smu_v15_0_8_init_smc_tables(struct smu_context *smu)
+{
+ int ret = 0;
+
+ ret = smu_v15_0_8_tables_init(smu);
+ if (ret)
+ return ret;
+
+ ret = smu_v15_0_8_allocate_dpm_context(smu);
+
+ return ret;
+}
+
+static int smu_v15_0_8_tables_fini(struct smu_context *smu)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+
+ smu_driver_table_fini(smu, SMU_DRIVER_TABLE_BASEBOARD_TEMP_METRICS);
+ smu_driver_table_fini(smu, SMU_DRIVER_TABLE_GPUBOARD_TEMP_METRICS);
+ smu_table_cache_fini(smu, SMU_TABLE_PMFW_SYSTEM_METRICS);
+ mutex_destroy(&smu_table->metrics_lock);
+
+ return 0;
+}
+
+static int smu_v15_0_8_fini_smc_tables(struct smu_context *smu)
+{
+ int ret;
+
+ ret = smu_v15_0_8_tables_fini(smu);
+ if (ret)
+ return ret;
+
+ ret = smu_v15_0_fini_smc_tables(smu);
+ if (ret)
+ return ret;
+
+ return ret;
+}
+
+static int smu_v15_0_8_init_allowed_features(struct smu_context *smu)
+{
+ /* pptable will handle the features to enable */
+ smu_feature_list_set_all(smu, SMU_FEATURE_LIST_ALLOWED);
+
+ return 0;
+}
+
+static int smu_v15_0_8_get_metrics_table_internal(struct smu_context *smu, uint32_t tmo, void *data)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+ uint32_t table_size = smu_table->tables[SMU_TABLE_SMU_METRICS].size;
+ struct smu_table *table = &smu_table->driver_table;
+ struct amdgpu_device *adev = smu->adev;
+
+ mutex_lock(&smu_table->metrics_lock);
+
+ if (!tmo || !smu_table->metrics_time ||
+ time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(tmo))) {
+ int ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetMetricsTable, NULL);
+ if (ret) {
+ dev_info(adev->dev,
+ "Failed to export SMU metrics table!\n");
+ mutex_unlock(&smu_table->metrics_lock);
+ return ret;
+ }
+
+ amdgpu_device_invalidate_hdp(smu->adev, NULL);
+ memcpy(smu_table->metrics_table, table->cpu_addr, table_size);
+
+ smu_table->metrics_time = jiffies;
+ }
+
+ if (data)
+ memcpy(data, smu_table->metrics_table, table_size);
+ mutex_unlock(&smu_table->metrics_lock);
+ return 0;
+}
+
+static int smu_v15_0_8_get_smu_metrics_data(struct smu_context *smu,
+ MetricsMember_t member, uint32_t *value)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+ MetricsTable_t *metrics = (MetricsTable_t *)smu_table->metrics_table;
+ struct amdgpu_device *adev = smu->adev;
+ int ret, xcc_id;
+
+ ret = smu_v15_0_8_get_metrics_table_internal(smu, 10, NULL);
+ if (ret)
+ return ret;
+
+ switch (member) {
+ case METRICS_CURR_GFXCLK:
+ case METRICS_AVERAGE_GFXCLK:
+ xcc_id = GET_INST(GC, 0);
+ *value = SMUQ10_ROUND(metrics->GfxclkFrequency[xcc_id]);
+ break;
+ case METRICS_CURR_SOCCLK:
+ case METRICS_AVERAGE_SOCCLK:
+ *value = SMUQ10_ROUND(metrics->SocclkFrequency[0]);
+ break;
+ case METRICS_CURR_UCLK:
+ case METRICS_AVERAGE_UCLK:
+ *value = SMUQ10_ROUND(metrics->UclkFrequency[0]);
+ break;
+ case METRICS_CURR_VCLK:
+ *value = SMUQ10_ROUND(metrics->VclkFrequency[0]);
+ break;
+ case METRICS_CURR_DCLK:
+ *value = SMUQ10_ROUND(metrics->DclkFrequency[0]);
+ break;
+ case METRICS_CURR_FCLK:
+ *value = SMUQ10_ROUND(metrics->FclkFrequency[0]);
+ break;
+ case METRICS_AVERAGE_GFXACTIVITY:
+ *value = SMUQ10_ROUND(metrics->SocketGfxBusy);
+ break;
+ case METRICS_AVERAGE_MEMACTIVITY:
+ *value = SMUQ10_ROUND(metrics->DramBandwidthUtilization);
+ break;
+ case METRICS_CURR_SOCKETPOWER:
+ *value = SMUQ10_ROUND(metrics->SocketPower) << 8;
+ break;
+ case METRICS_TEMPERATURE_HOTSPOT:
+ *value = SMUQ10_ROUND(metrics->MaxSocketTemperature) *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ break;
+ case METRICS_TEMPERATURE_MEM:
+ {
+ struct amdgpu_device *adev = smu->adev;
+ u32 max_hbm_temp = 0;
+
+ /* Find max temperature across all HBM stacks */
+ if (adev->umc.active_mask) {
+ u64 mask = adev->umc.active_mask;
+ int stack_idx;
+
+ for_each_hbm_stack(stack_idx, mask) {
+ u32 temp;
+
+ if (!hbm_stack_mask_valid(mask))
+ continue;
+
+ temp = SMUQ10_ROUND(metrics->HbmTemperature[stack_idx]);
+ if (temp > max_hbm_temp)
+ max_hbm_temp = temp;
+ }
+ }
+ *value = max_hbm_temp * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ break;
+ }
+ /* This is the max of all VRs and not just SOC VR.
+ */
+ case METRICS_TEMPERATURE_VRSOC:
+ *value = SMUQ10_ROUND(metrics->MaxVrTemperature) *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ break;
+ default:
+ *value = UINT_MAX;
+ break;
+ }
+
+ return 0;
+}
+
+static int smu_v15_0_8_get_current_clk_freq_by_table(struct smu_context *smu,
+ enum smu_clk_type clk_type,
+ uint32_t *value)
+{
+ MetricsMember_t member_type;
+
+ if (!value)
+ return -EINVAL;
+
+ switch (clk_type) {
+ case SMU_GFXCLK:
+ case SMU_SCLK:
+ member_type = METRICS_CURR_GFXCLK;
+ break;
+ case SMU_UCLK:
+ case SMU_MCLK:
+ member_type = METRICS_CURR_UCLK;
+ break;
+ case SMU_SOCCLK:
+ member_type = METRICS_CURR_SOCCLK;
+ break;
+ case SMU_VCLK:
+ member_type = METRICS_CURR_VCLK;
+ break;
+ case SMU_DCLK:
+ member_type = METRICS_CURR_DCLK;
+ break;
+ case SMU_FCLK:
+ member_type = METRICS_CURR_FCLK;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return smu_v15_0_8_get_smu_metrics_data(smu, member_type, value);
+}
+
+static int smu_v15_0_8_get_current_activity_percent(struct smu_context *smu,
+ enum amd_pp_sensors sensor,
+ uint32_t *value)
+{
+ int ret = 0;
+
+ if (!value)
+ return -EINVAL;
+
+ switch (sensor) {
+ case AMDGPU_PP_SENSOR_GPU_LOAD:
+ ret = smu_v15_0_8_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_GFXACTIVITY, value);
+ break;
+ case AMDGPU_PP_SENSOR_MEM_LOAD:
+ ret = smu_v15_0_8_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_MEMACTIVITY, value);
+ break;
+ default:
+ dev_err(smu->adev->dev,
+ "Invalid sensor for retrieving clock activity\n");
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+static int smu_v15_0_8_thermal_get_temperature(struct smu_context *smu,
+ enum amd_pp_sensors sensor,
+ uint32_t *value)
+{
+ int ret = 0;
+
+ if (!value)
+ return -EINVAL;
+
+ switch (sensor) {
+ case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
+ ret = smu_v15_0_8_get_smu_metrics_data(smu,
+ METRICS_TEMPERATURE_HOTSPOT, value);
+ break;
+ case AMDGPU_PP_SENSOR_MEM_TEMP:
+ ret = smu_v15_0_8_get_smu_metrics_data(smu,
+ METRICS_TEMPERATURE_MEM, value);
+ break;
+ default:
+ dev_err(smu->adev->dev, "Invalid sensor for retrieving temp\n");
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+static int smu_v15_0_8_get_system_metrics_table(struct smu_context *smu)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+ struct smu_table *table = &smu_table->driver_table;
+ struct smu_table *tables = smu_table->tables;
+ struct smu_table *sys_table;
+ int ret;
+
+ sys_table = &tables[SMU_TABLE_PMFW_SYSTEM_METRICS];
+ if (smu_table_cache_is_valid(sys_table))
+ return 0;
+
+ ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetSystemMetricsTable, NULL);
+ if (ret) {
+ dev_info(smu->adev->dev,
+ "Failed to export system metrics table!\n");
+ return ret;
+ }
+
+ amdgpu_hdp_invalidate(smu->adev, NULL);
+ smu_table_cache_update_time(sys_table, jiffies);
+ memcpy(sys_table->cache.buffer, table->cpu_addr,
+ sizeof(SystemMetricsTable_t));
+
+ return 0;
+}
+
+static int smu_v15_0_8_get_npm_data(struct smu_context *smu,
+ enum amd_pp_sensors sensor,
+ uint32_t *value)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+ struct smu_table *tables = smu_table->tables;
+ SystemMetricsTable_t *metrics;
+ struct smu_table *sys_table;
+ int ret;
+
+ if (sensor == AMDGPU_PP_SENSOR_MAXNODEPOWERLIMIT) {
+ /*TBD as of now put 0 */
+ *value = 0;
+ return 0;
+ }
+
+ ret = smu_v15_0_8_get_system_metrics_table(smu);
+ if (ret)
+ return ret;
+
+ sys_table = &tables[SMU_TABLE_PMFW_SYSTEM_METRICS];
+ metrics = (SystemMetricsTable_t *)sys_table->cache.buffer;
+
+ switch (sensor) {
+ case AMDGPU_PP_SENSOR_NODEPOWERLIMIT:
+ *value = SMUQ10_ROUND(metrics->NodePowerLimit);
+ break;
+ case AMDGPU_PP_SENSOR_NODEPOWER:
+ *value = SMUQ10_ROUND(metrics->NodePower);
+ break;
+ case AMDGPU_PP_SENSOR_GPPTRESIDENCY:
+ *value = SMUQ10_ROUND(metrics->GlobalPPTResidencyAcc);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int smu_v15_0_8_read_sensor(struct smu_context *smu,
+ enum amd_pp_sensors sensor, void *data,
+ uint32_t *size)
+{
+ struct smu_15_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
+ int ret = 0;
+
+ if (amdgpu_ras_intr_triggered())
+ return 0;
+
+ if (!data || !size)
+ return -EINVAL;
+
+ switch (sensor) {
+ case AMDGPU_PP_SENSOR_MEM_LOAD:
+ case AMDGPU_PP_SENSOR_GPU_LOAD:
+ ret = smu_v15_0_8_get_current_activity_percent(smu, sensor,
+ (uint32_t *)data);
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_GPU_INPUT_POWER:
+ ret = smu_v15_0_8_get_smu_metrics_data(smu,
+ METRICS_CURR_SOCKETPOWER,
+ (uint32_t *)data);
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
+ case AMDGPU_PP_SENSOR_MEM_TEMP:
+ ret = smu_v15_0_8_thermal_get_temperature(smu, sensor,
+ (uint32_t *)data);
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_GFX_MCLK:
+ ret = smu_v15_0_8_get_current_clk_freq_by_table(smu,
+ SMU_UCLK, (uint32_t *)data);
+ /* the output clock frequency in 10K unit */
+ *(uint32_t *)data *= 100;
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_GFX_SCLK:
+ ret = smu_v15_0_8_get_current_clk_freq_by_table(smu,
+ SMU_GFXCLK, (uint32_t *)data);
+ *(uint32_t *)data *= 100;
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_VDDBOARD:
+ *(uint32_t *)data = dpm_context->board_volt;
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_NODEPOWERLIMIT:
+ case AMDGPU_PP_SENSOR_NODEPOWER:
+ case AMDGPU_PP_SENSOR_GPPTRESIDENCY:
+ case AMDGPU_PP_SENSOR_MAXNODEPOWERLIMIT:
+ ret = smu_v15_0_8_get_npm_data(smu, sensor, (uint32_t *)data);
+ if (ret)
+ return ret;
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_GPU_AVG_POWER:
+ default:
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ return ret;
+}
+
+static int smu_v15_0_8_emit_clk_levels(struct smu_context *smu,
+ enum smu_clk_type type, char *buf,
+ int *offset)
+{
+ struct smu_umd_pstate_table *pstate_table = &smu->pstate_table;
+ struct smu_15_0_dpm_context *dpm_context;
+ struct smu_dpm_table *single_dpm_table = NULL;
+ struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
+ int ret, now, size = *offset;
+
+ if (amdgpu_ras_intr_triggered()) {
+ sysfs_emit_at(buf, size, "unavailable\n");
+ return -EBUSY;
+ }
+
+ dpm_context = smu_dpm->dpm_context;
+
+ switch (type) {
+ case SMU_OD_SCLK:
+ size += sysfs_emit_at(buf, size, "%s:\n", "OD_SCLK");
+ size += sysfs_emit_at(buf, size, "0: %uMhz\n1: %uMhz\n",
+ pstate_table->gfxclk_pstate.curr.min,
+ pstate_table->gfxclk_pstate.curr.max);
+ break;
+ case SMU_OD_MCLK:
+ size += sysfs_emit_at(buf, size, "%s:\n", "OD_MCLK");
+ size += sysfs_emit_at(buf, size, "0: %uMhz\n1: %uMhz\n",
+ pstate_table->uclk_pstate.curr.min,
+ pstate_table->uclk_pstate.curr.max);
+ break;
+ case SMU_SCLK:
+ case SMU_GFXCLK:
+ single_dpm_table = &dpm_context->dpm_tables.gfx_table;
+ break;
+ case SMU_MCLK:
+ case SMU_UCLK:
+ single_dpm_table = &dpm_context->dpm_tables.uclk_table;
+ break;
+ case SMU_SOCCLK:
+ single_dpm_table = &dpm_context->dpm_tables.soc_table;
+ break;
+ case SMU_FCLK:
+ single_dpm_table = &dpm_context->dpm_tables.fclk_table;
+ break;
+ case SMU_VCLK:
+ single_dpm_table = &dpm_context->dpm_tables.vclk_table;
+ break;
+ case SMU_DCLK:
+ single_dpm_table = &dpm_context->dpm_tables.dclk_table;
+ break;
+ default:
+ break;
+ }
+
+ if (single_dpm_table) {
+ ret = smu_v15_0_8_get_current_clk_freq_by_table(smu, type, &now);
+ if (ret) {
+ dev_err(smu->adev->dev,
+ "Attempt to get current clk Failed!");
+ return ret;
+ }
+ ret = smu_cmn_print_dpm_clk_levels(smu, single_dpm_table, now,
+ buf, offset);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+ }
+
+ *offset = size;
+
+ return 0;
+}
+
+static int smu_v15_0_8_get_dpm_ultimate_freq(struct smu_context *smu,
+ enum smu_clk_type clk_type,
+ uint32_t *min, uint32_t *max)
+{
+ struct smu_15_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
+ struct smu_table_context *smu_table = &smu->smu_table;
+ PPTable_t *pptable = (PPTable_t *)smu_table->driver_pptable;
+ struct smu_dpm_table *dpm_table;
+ uint32_t min_clk = 0, max_clk = 0;
+
+ if (!pptable->init)
+ return -EINVAL;
+
+ /* Try cached DPM tables first */
+ if (dpm_context) {
+ switch (clk_type) {
+ case SMU_MCLK:
+ case SMU_UCLK:
+ dpm_table = &dpm_context->dpm_tables.uclk_table;
+ break;
+ case SMU_GFXCLK:
+ case SMU_SCLK:
+ dpm_table = &dpm_context->dpm_tables.gfx_table;
+ break;
+ case SMU_SOCCLK:
+ dpm_table = &dpm_context->dpm_tables.soc_table;
+ break;
+ case SMU_FCLK:
+ dpm_table = &dpm_context->dpm_tables.fclk_table;
+ break;
+ case SMU_GL2CLK:
+ dpm_table = &dpm_context->dpm_tables.gl2_table;
+ break;
+ case SMU_VCLK:
+ dpm_table = &dpm_context->dpm_tables.vclk_table;
+ break;
+ case SMU_DCLK:
+ dpm_table = &dpm_context->dpm_tables.dclk_table;
+ break;
+ default:
+ dpm_table = NULL;
+ break;
+ }
+
+ if (dpm_table && dpm_table->count > 0) {
+ min_clk = SMU_DPM_TABLE_MIN(dpm_table);
+ max_clk = SMU_DPM_TABLE_MAX(dpm_table);
+
+ if (min_clk && max_clk) {
+ if (min)
+ *min = min_clk;
+ if (max)
+ *max = max_clk;
+ return 0;
+ }
+ }
+ }
+
+ /* Fall back to pptable */
+ switch (clk_type) {
+ case SMU_GFXCLK:
+ case SMU_SCLK:
+ min_clk = pptable->MinGfxclkFrequency;
+ max_clk = pptable->MaxGfxclkFrequency;
+ break;
+ case SMU_FCLK:
+ min_clk = pptable->MinFclkFrequency;
+ max_clk = pptable->MaxFclkFrequency;
+ break;
+ case SMU_GL2CLK:
+ min_clk = pptable->MinGl2clkFrequency;
+ max_clk = pptable->MaxGl2clkFrequency;
+ break;
+ case SMU_MCLK:
+ case SMU_UCLK:
+ min_clk = pptable->UclkFrequencyTable[0];
+ max_clk = pptable->UclkFrequencyTable[ARRAY_SIZE(pptable->UclkFrequencyTable) - 1];
+ break;
+ case SMU_SOCCLK:
+ min_clk = pptable->SocclkFrequency;
+ max_clk = pptable->SocclkFrequency;
+ break;
+ case SMU_VCLK:
+ min_clk = pptable->VclkFrequency;
+ max_clk = pptable->VclkFrequency;
+ break;
+ case SMU_DCLK:
+ min_clk = pptable->DclkFrequency;
+ max_clk = pptable->DclkFrequency;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (min)
+ *min = min_clk;
+ if (max)
+ *max = max_clk;
+
+ return 0;
+}
+
+static int smu_v15_0_8_set_dpm_table(struct smu_context *smu)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+ struct smu_15_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
+ struct smu_dpm_table *dpm_table;
+ PPTable_t *pptable = (PPTable_t *)smu_table->driver_pptable;
+ int i, ret;
+ uint32_t gfxclkmin, gfxclkmax;
+
+ /* gfxclk dpm table setup - fine-grained */
+ dpm_table = &dpm_context->dpm_tables.gfx_table;
+ dpm_table->clk_type = SMU_GFXCLK;
+ dpm_table->flags = SMU_DPM_TABLE_FINE_GRAINED;
+ if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) {
+ ret = smu_v15_0_8_get_dpm_ultimate_freq(smu, SMU_GFXCLK,
+ &gfxclkmin, &gfxclkmax);
+ if (ret)
+ return ret;
+
+ dpm_table->count = 2;
+ dpm_table->dpm_levels[0].value = gfxclkmin;
+ dpm_table->dpm_levels[0].enabled = true;
+ dpm_table->dpm_levels[1].value = gfxclkmax;
+ dpm_table->dpm_levels[1].enabled = true;
+ } else {
+ dpm_table->count = 1;
+ dpm_table->dpm_levels[0].value = pptable->MinGfxclkFrequency;
+ dpm_table->dpm_levels[0].enabled = true;
+ }
+
+ /* fclk dpm table setup - fine-grained */
+ dpm_table = &dpm_context->dpm_tables.fclk_table;
+ dpm_table->clk_type = SMU_FCLK;
+ dpm_table->flags = SMU_DPM_TABLE_FINE_GRAINED;
+ if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_FCLK_BIT)) {
+ dpm_table->count = 2;
+ dpm_table->dpm_levels[0].value = pptable->MinFclkFrequency;
+ dpm_table->dpm_levels[0].enabled = true;
+ dpm_table->dpm_levels[1].value = pptable->MaxFclkFrequency;
+ dpm_table->dpm_levels[1].enabled = true;
+ } else {
+ dpm_table->count = 1;
+ dpm_table->dpm_levels[0].value = pptable->MinFclkFrequency;
+ dpm_table->dpm_levels[0].enabled = true;
+ }
+
+ /* gl2clk dpm table setup - fine-grained */
+ dpm_table = &dpm_context->dpm_tables.gl2_table;
+ dpm_table->flags = SMU_DPM_TABLE_FINE_GRAINED;
+ if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_GL2CLK_BIT)) {
+ dpm_table->count = 2;
+ dpm_table->dpm_levels[0].value = pptable->MinGl2clkFrequency;
+ dpm_table->dpm_levels[0].enabled = true;
+ dpm_table->dpm_levels[1].value = pptable->MaxGl2clkFrequency;
+ dpm_table->dpm_levels[1].enabled = true;
+ } else {
+ dpm_table->count = 1;
+ dpm_table->dpm_levels[0].value = pptable->MinGl2clkFrequency;
+ dpm_table->dpm_levels[0].enabled = true;
+ }
+
+ /* uclk dpm table setup - discrete levels */
+ dpm_table = &dpm_context->dpm_tables.uclk_table;
+ dpm_table->clk_type = SMU_UCLK;
+ dpm_table->flags = 0;
+ if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
+ dpm_table->count = ARRAY_SIZE(pptable->UclkFrequencyTable);
+ for (i = 0; i < dpm_table->count; ++i) {
+ dpm_table->dpm_levels[i].value = pptable->UclkFrequencyTable[i];
+ dpm_table->dpm_levels[i].enabled = true;
+ }
+ } else {
+ dpm_table->count = 1;
+ dpm_table->dpm_levels[0].value = pptable->UclkFrequencyTable[0];
+ dpm_table->dpm_levels[0].enabled = true;
+ }
+
+ /* socclk dpm table setup - single boot-time value */
+ dpm_table = &dpm_context->dpm_tables.soc_table;
+ dpm_table->clk_type = SMU_SOCCLK;
+ dpm_table->flags = 0;
+ dpm_table->count = 1;
+ dpm_table->dpm_levels[0].value = pptable->SocclkFrequency;
+ dpm_table->dpm_levels[0].enabled = true;
+
+ /* vclk dpm table setup - single boot-time value */
+ dpm_table = &dpm_context->dpm_tables.vclk_table;
+ dpm_table->clk_type = SMU_VCLK;
+ dpm_table->flags = 0;
+ dpm_table->count = 1;
+ dpm_table->dpm_levels[0].value = pptable->VclkFrequency;
+ dpm_table->dpm_levels[0].enabled = true;
+
+ /* dclk dpm table setup - single boot-time value */
+ dpm_table = &dpm_context->dpm_tables.dclk_table;
+ dpm_table->clk_type = SMU_DCLK;
+ dpm_table->flags = 0;
+ dpm_table->count = 1;
+ dpm_table->dpm_levels[0].value = pptable->DclkFrequency;
+ dpm_table->dpm_levels[0].enabled = true;
+
+ return 0;
+}
+
+static int smu_v15_0_8_setup_pptable(struct smu_context *smu)
+{
+ struct smu_table_context *table_context = &smu->smu_table;
+
+ /* TODO: PPTable is not available.
+ * 1) Find an alternate way to get 'PPTable values' here.
+ * 2) Check if there is SW CTF
+ */
+ table_context->thermal_controller_type = 0;
+
+ return 0;
+}
+
+static int smu_v15_0_8_check_fw_status(struct smu_context *smu)
+{
+ struct amdgpu_device *adev = smu->adev;
+ uint32_t mp1_fw_flags;
+
+ mp1_fw_flags = RREG32_PCIE(MP1_Public |
+ (smnMP1_FIRMWARE_FLAGS_15_0_8 & 0xffffffff));
+
+ if ((mp1_fw_flags & MP1_CRU1_MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED_MASK) >>
+ MP1_CRU1_MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED__SHIFT)
+ return 0;
+
+ return -EIO;
+}
+
+static int smu_v15_0_8_get_static_metrics_table(struct smu_context *smu)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+ uint32_t table_size = smu_table->tables[SMU_TABLE_SMU_METRICS].size;
+ struct smu_table *table = &smu_table->driver_table;
+ int ret;
+
+ ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetStaticMetricsTable, NULL);
+ if (ret) {
+ dev_err(smu->adev->dev,
+ "Failed to export static metrics table!\n");
+ return ret;
+ }
+
+ amdgpu_hdp_invalidate(smu->adev, NULL);
+ memcpy(smu_table->metrics_table, table->cpu_addr, table_size);
+
+ return 0;
+}
+
+static int smu_v15_0_8_fru_get_product_info(struct smu_context *smu,
+ StaticMetricsTable_t *static_metrics)
+{
+ struct amdgpu_fru_info *fru_info;
+ struct amdgpu_device *adev = smu->adev;
+
+ if (!adev->fru_info) {
+ adev->fru_info = kzalloc(sizeof(*adev->fru_info), GFP_KERNEL);
+ if (!adev->fru_info)
+ return -ENOMEM;
+ }
+
+ fru_info = adev->fru_info;
+ strscpy(fru_info->product_number, static_metrics->ProductInfo.ModelNumber,
+ sizeof(fru_info->product_number));
+ strscpy(fru_info->product_name, static_metrics->ProductInfo.Name,
+ sizeof(fru_info->product_name));
+ strscpy(fru_info->serial, static_metrics->ProductInfo.Serial,
+ sizeof(fru_info->serial));
+ strscpy(fru_info->manufacturer_name, static_metrics->ProductInfo.ManufacturerName,
+ sizeof(fru_info->manufacturer_name));
+ strscpy(fru_info->fru_id, static_metrics->ProductInfo.FruId,
+ sizeof(fru_info->fru_id));
+
+ return 0;
+}
+
+static void smu_v15_0_8_init_xgmi_data(struct smu_context *smu,
+ StaticMetricsTable_t *static_metrics)
+{
+ uint16_t max_speed;
+ uint8_t max_width;
+
+ max_width = (uint8_t)static_metrics->MaxXgmiWidth;
+ max_speed = (uint16_t)static_metrics->MaxXgmiBitrate;
+ amgpu_xgmi_set_max_speed_width(smu->adev, max_speed, max_width);
+}
+
+static int smu_v15_0_8_set_driver_pptable(struct smu_context *smu)
+{
+ struct smu_15_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
+ struct smu_table_context *smu_table = &smu->smu_table;
+ StaticMetricsTable_t *static_metrics = (StaticMetricsTable_t *)smu_table->metrics_table;
+ PPTable_t *pptable = (PPTable_t *)smu_table->driver_pptable;
+ int ret, i, n;
+ uint32_t table_version;
+
+ if (!pptable->init) {
+ ret = smu_v15_0_8_get_static_metrics_table(smu);
+ if (ret)
+ return ret;
+
+ ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetMetricsVersion,
+ &table_version);
+ if (ret)
+ return ret;
+ smu_table->tables[SMU_TABLE_SMU_METRICS].version =
+ table_version;
+
+ pptable->MaxSocketPowerLimit =
+ SMUQ10_ROUND(static_metrics->MaxSocketPowerLimit);
+ pptable->MaxGfxclkFrequency =
+ SMUQ10_ROUND(static_metrics->MaxGfxclkFrequency);
+ pptable->MinGfxclkFrequency =
+ SMUQ10_ROUND(static_metrics->MinGfxclkFrequency);
+ pptable->MaxFclkFrequency =
+ SMUQ10_ROUND(static_metrics->MaxFclkFrequency);
+ pptable->MinFclkFrequency =
+ SMUQ10_ROUND(static_metrics->MinFclkFrequency);
+ pptable->MaxGl2clkFrequency =
+ SMUQ10_ROUND(static_metrics->MaxGl2clkFrequency);
+ pptable->MinGl2clkFrequency =
+ SMUQ10_ROUND(static_metrics->MinGl2clkFrequency);
+
+ for (i = 0; i < ARRAY_SIZE(static_metrics->UclkFrequencyTable); ++i)
+ pptable->UclkFrequencyTable[i] =
+ SMUQ10_ROUND(static_metrics->UclkFrequencyTable[i]);
+
+ pptable->SocclkFrequency = SMUQ10_ROUND(static_metrics->SocclkFrequency);
+ pptable->LclkFrequency = SMUQ10_ROUND(static_metrics->LclkFrequency);
+ pptable->VclkFrequency = SMUQ10_ROUND(static_metrics->VclkFrequency);
+ pptable->DclkFrequency = SMUQ10_ROUND(static_metrics->DclkFrequency);
+
+ pptable->CTFLimitMID = SMUQ10_ROUND(static_metrics->CTFLimit_MID);
+ pptable->CTFLimitAID = SMUQ10_ROUND(static_metrics->CTFLimit_AID);
+ pptable->CTFLimitXCD = SMUQ10_ROUND(static_metrics->CTFLimit_XCD);
+ pptable->CTFLimitHBM = SMUQ10_ROUND(static_metrics->CTFLimit_HBM);
+ pptable->ThermalLimitMID = SMUQ10_ROUND(static_metrics->ThermalLimit_MID);
+ pptable->ThermalLimitAID = SMUQ10_ROUND(static_metrics->ThermalLimit_AID);
+ pptable->ThermalLimitXCD = SMUQ10_ROUND(static_metrics->ThermalLimit_XCD);
+ pptable->ThermalLimitHBM = SMUQ10_ROUND(static_metrics->ThermalLimit_HBM);
+
+ /* use MID0 serial number by default */
+ pptable->PublicSerialNumberMID =
+ static_metrics->PublicSerialNumber_MID[0];
+
+ amdgpu_device_set_uid(smu->adev->uid_info, AMDGPU_UID_TYPE_SOC,
+ 0, pptable->PublicSerialNumberMID);
+ pptable->PublicSerialNumberAID =
+ static_metrics->PublicSerialNumber_AID[0];
+ pptable->PublicSerialNumberXCD =
+ static_metrics->PublicSerialNumber_XCD[0];
+ n = ARRAY_SIZE(static_metrics->PublicSerialNumber_MID);
+ for (i = 0; i < n; i++) {
+ amdgpu_device_set_uid(smu->adev->uid_info, AMDGPU_UID_TYPE_MID, i,
+ static_metrics->PublicSerialNumber_MID[i]);
+ }
+ n = ARRAY_SIZE(static_metrics->PublicSerialNumber_AID);
+ for (i = 0; i < n; i++) {
+ amdgpu_device_set_uid(smu->adev->uid_info, AMDGPU_UID_TYPE_AID, i,
+ static_metrics->PublicSerialNumber_AID[i]);
+ }
+ n = ARRAY_SIZE(static_metrics->PublicSerialNumber_XCD);
+ for (i = 0; i < n; i++) {
+ amdgpu_device_set_uid(smu->adev->uid_info, AMDGPU_UID_TYPE_XCD, i,
+ static_metrics->PublicSerialNumber_XCD[i]);
+ }
+
+ ret = smu_v15_0_8_fru_get_product_info(smu, static_metrics);
+ if (ret)
+ return ret;
+ pptable->PPT1Max = static_metrics->PPT1Max;
+ pptable->PPT1Min = static_metrics->PPT1Min;
+ pptable->PPT1Default = static_metrics->PPT1Default;
+
+ if (static_metrics->pldmVersion[0] != 0xFFFFFFFF)
+ smu->adev->firmware.pldm_version =
+ static_metrics->pldmVersion[0];
+ dpm_context->board_volt = static_metrics->InputTelemetryVoltageInmV;
+ smu_v15_0_8_init_xgmi_data(smu, static_metrics);
+ pptable->init = true;
+ }
+
+ return 0;
+}
+
+static int smu_v15_0_8_set_default_dpm_table(struct smu_context *smu)
+{
+ int ret;
+
+ ret = smu_v15_0_8_set_driver_pptable(smu);
+ if (ret)
+ return ret;
+
+ ret = smu_v15_0_8_set_dpm_table(smu);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int smu_v15_0_8_irq_process(struct amdgpu_device *adev,
+ struct amdgpu_irq_src *source,
+ struct amdgpu_iv_entry *entry)
+{
+ struct smu_context *smu = adev->powerplay.pp_handle;
+ struct smu_power_context *smu_power = &smu->smu_power;
+ struct smu_15_0_power_context *power_context = smu_power->power_context;
+ uint32_t client_id = entry->client_id;
+ uint32_t ctxid = entry->src_data[0];
+ uint32_t src_id = entry->src_id;
+ uint32_t data;
+
+ if (client_id == SOC_V1_0_IH_CLIENTID_MP1) {
+ if (src_id == IH_INTERRUPT_ID_TO_DRIVER) {
+ /* ACK SMUToHost interrupt */
+ data = RREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_CTRL);
+ data = REG_SET_FIELD(data, MP1_SMN_IH_SW_INT_CTRL, INT_ACK, 1);
+ WREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_CTRL, data);
+ /*
+ * ctxid is used to distinguish different events for SMCToHost
+ * interrupt.
+ */
+ switch (ctxid) {
+ case IH_INTERRUPT_CONTEXT_ID_THERMAL_THROTTLING:
+ /*
+ * Increment the throttle interrupt counter
+ */
+ atomic64_inc(&smu->throttle_int_counter);
+
+ if (!atomic_read(&adev->throttling_logging_enabled))
+ return 0;
+
+ /* This uses the new method which fixes the
+ * incorrect throttling status reporting
+ * through metrics table. For older FWs,
+ * it will be ignored.
+ */
+ if (__ratelimit(&adev->throttling_logging_rs)) {
+ atomic_set(
+ &power_context->throttle_status,
+ entry->src_data[1]);
+ schedule_work(&smu->throttling_logging_work);
+ }
+ break;
+ default:
+ dev_dbg(adev->dev, "Unhandled context id %d from client:%d!\n",
+ ctxid, client_id);
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int smu_v15_0_8_set_irq_state(struct amdgpu_device *adev,
+ struct amdgpu_irq_src *source,
+ unsigned type,
+ enum amdgpu_interrupt_state state)
+{
+ uint32_t val = 0;
+
+ switch (state) {
+ case AMDGPU_IRQ_STATE_DISABLE:
+ /* For MP1 SW irqs */
+ val = RREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_CTRL);
+ val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT_CTRL, INT_MASK, 1);
+ WREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_CTRL, val);
+
+ break;
+ case AMDGPU_IRQ_STATE_ENABLE:
+ /* For MP1 SW irqs */
+ val = RREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT);
+ val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT, ID, 0xFE);
+ val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT, VALID, 0);
+ WREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT, val);
+
+ val = RREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_CTRL);
+ val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT_CTRL, INT_MASK, 0);
+ WREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_CTRL, val);
+
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static const struct amdgpu_irq_src_funcs smu_v15_0_8_irq_funcs = {
+ .set = smu_v15_0_8_set_irq_state,
+ .process = smu_v15_0_8_irq_process,
+};
+
+static int smu_v15_0_8_register_irq_handler(struct smu_context *smu)
+{
+ struct amdgpu_device *adev = smu->adev;
+ struct amdgpu_irq_src *irq_src = &smu->irq_source;
+ int ret = 0;
+
+ if (amdgpu_sriov_vf(adev))
+ return 0;
+
+ irq_src->num_types = 1;
+ irq_src->funcs = &smu_v15_0_8_irq_funcs;
+
+ ret = amdgpu_irq_add_id(adev, SOC_V1_0_IH_CLIENTID_MP1,
+ IH_INTERRUPT_ID_TO_DRIVER,
+ irq_src);
+ if (ret)
+ return ret;
+
+ return ret;
+}
+
+static int smu_v15_0_8_notify_unload(struct smu_context *smu)
+{
+ if (amdgpu_in_reset(smu->adev))
+ return 0;
+
+ dev_dbg(smu->adev->dev, "Notify PMFW about driver unload");
+ /* Ignore return, just intimate FW that driver is not going to be there */
+ smu_cmn_send_smc_msg(smu, SMU_MSG_PrepareMp1ForUnload, NULL);
+
+ return 0;
+}
+
+
+static int smu_v15_0_8_system_features_control(struct smu_context *smu,
+ bool enable)
+{
+ struct amdgpu_device *adev = smu->adev;
+ int ret = 0;
+
+ if (amdgpu_sriov_vf(adev))
+ return 0;
+
+ if (enable)
+ ret = smu_v15_0_system_features_control(smu, enable);
+ else
+ smu_v15_0_8_notify_unload(smu);
+
+ return ret;
+}
+
+/**
+ * smu_v15_0_8_get_enabled_mask - Get enabled SMU features (128-bit)
+ * @smu: SMU context
+ * @feature_mask: feature mask structure
+ *
+ * SMU 15 returns all 128 feature bits in a single message via out_args[0..3].
+ * For backward compatibility, this function returns only the first 64 bits.
+ *
+ * Return: 0 on success, negative errno on failure
+ */
+static int smu_v15_0_8_get_enabled_mask(struct smu_context *smu,
+ struct smu_feature_bits *feature_mask)
+{
+ struct smu_msg_args args = {
+ .msg = SMU_MSG_GetEnabledSmuFeatures,
+ .num_args = 0,
+ .num_out_args = 2,
+ };
+ int ret;
+
+ if (!feature_mask)
+ return -EINVAL;
+
+ ret = smu->msg_ctl.ops->send_msg(&smu->msg_ctl, &args);
+
+ if (ret)
+ return ret;
+
+ smu_feature_bits_from_arr32(feature_mask, args.out_args,
+ SMU_FEATURE_NUM_DEFAULT);
+
+ return 0;
+}
+
+static bool smu_v15_0_8_is_dpm_running(struct smu_context *smu)
+{
+ int ret = 0;
+ struct smu_feature_bits feature_enabled;
+
+ ret = smu_v15_0_8_get_enabled_mask(smu, &feature_enabled);
+ if (ret)
+ return false;
+
+ return smu_feature_bits_test_mask(&feature_enabled,
+ smu_v15_0_8_dpm_features.bits);
+}
+
+static ssize_t smu_v15_0_8_get_pm_metrics(struct smu_context *smu,
+ void *metrics, size_t max_size)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+ struct amdgpu_pm_metrics *pm_metrics = (struct amdgpu_pm_metrics *)metrics;
+ uint32_t table_version = smu_table->tables[SMU_TABLE_SMU_METRICS].version;
+ uint32_t table_size = smu_table->tables[SMU_TABLE_SMU_METRICS].size;
+ uint32_t pmfw_version;
+ int ret;
+
+ if (!pm_metrics || !max_size)
+ return -EINVAL;
+
+ if (max_size < (table_size + sizeof(pm_metrics->common_header)))
+ return -EOVERFLOW;
+
+ /* Don't use cached metrics data */
+ ret = smu_v15_0_8_get_metrics_table_internal(smu, 0, pm_metrics->data);
+ if (ret)
+ return ret;
+
+ smu_cmn_get_smc_version(smu, NULL, &pmfw_version);
+ memset(&pm_metrics->common_header, 0, sizeof(pm_metrics->common_header));
+ pm_metrics->common_header.mp1_ip_discovery_version =
+ amdgpu_ip_version(smu->adev, MP1_HWIP, 0);
+ pm_metrics->common_header.pmfw_version = pmfw_version;
+ pm_metrics->common_header.pmmetrics_version = table_version;
+ pm_metrics->common_header.structure_size =
+ sizeof(pm_metrics->common_header) + table_size;
+
+ return pm_metrics->common_header.structure_size;
+}
+
+static int smu_v15_0_8_mode2_reset(struct smu_context *smu)
+{
+ struct smu_msg_ctl *ctl = &smu->msg_ctl;
+ struct amdgpu_device *adev = smu->adev;
+ int timeout = 10;
+ int ret = 0;
+
+ mutex_lock(&ctl->lock);
+
+ ret = smu_msg_send_async_locked(ctl, SMU_MSG_GfxDeviceDriverReset,
+ SMU_RESET_MODE_2);
+
+ if (ret)
+ goto out;
+
+ /* Reset takes a bit longer, wait for 200ms. */
+ msleep(200);
+
+ dev_dbg(adev->dev, "wait for reset ack\n");
+ do {
+ ret = smu_msg_wait_response(ctl, 0);
+ /* Wait a bit more time for getting ACK */
+ if (ret == -ETIME) {
+ --timeout;
+ usleep_range(500, 1000);
+ continue;
+ }
+
+ if (ret)
+ goto out;
+
+ } while (ret == -ETIME && timeout);
+
+out:
+ mutex_unlock(&ctl->lock);
+
+ if (ret)
+ dev_err(adev->dev, "failed to send mode2 reset, error code %d",
+ ret);
+
+ return ret;
+}
+
+static bool smu_v15_0_8_is_temp_metrics_supported(struct smu_context *smu,
+ enum smu_temp_metric_type type)
+{
+ switch (type) {
+ case SMU_TEMP_METRIC_BASEBOARD:
+ if (smu->adev->gmc.xgmi.physical_node_id == 0)
+ return true;
+ return false;
+ case SMU_TEMP_METRIC_GPUBOARD:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static void smu_v15_0_8_fill_baseboard_temp_metrics(
+ struct smu_v15_0_8_baseboard_temp_metrics *baseboard_temp_metrics,
+ const SystemMetricsTable_t *metrics)
+{
+ baseboard_temp_metrics->accumulation_counter = metrics->AccumulationCounter;
+ baseboard_temp_metrics->label_version = metrics->LabelVersion;
+ baseboard_temp_metrics->node_id = metrics->NodeIdentifier;
+
+ baseboard_temp_metrics->system_temp_ubb_fpga =
+ metrics->SystemTemperatures[SYSTEM_TEMP_UBB_FPGA];
+ baseboard_temp_metrics->system_temp_ubb_front =
+ metrics->SystemTemperatures[SYSTEM_TEMP_UBB_FRONT];
+ baseboard_temp_metrics->system_temp_ubb_back =
+ metrics->SystemTemperatures[SYSTEM_TEMP_UBB_BACK];
+ baseboard_temp_metrics->system_temp_ubb_oam7 =
+ metrics->SystemTemperatures[SYSTEM_TEMP_UBB_OAM7];
+ baseboard_temp_metrics->system_temp_ubb_ibc =
+ metrics->SystemTemperatures[SYSTEM_TEMP_UBB_IBC];
+ baseboard_temp_metrics->system_temp_ubb_ufpga =
+ metrics->SystemTemperatures[SYSTEM_TEMP_UBB_UFPGA];
+ baseboard_temp_metrics->system_temp_ubb_oam1 =
+ metrics->SystemTemperatures[SYSTEM_TEMP_UBB_OAM1];
+ baseboard_temp_metrics->system_temp_oam_0_1_hsc =
+ metrics->SystemTemperatures[SYSTEM_TEMP_OAM_0_1_HSC];
+ baseboard_temp_metrics->system_temp_oam_2_3_hsc =
+ metrics->SystemTemperatures[SYSTEM_TEMP_OAM_2_3_HSC];
+ baseboard_temp_metrics->system_temp_oam_4_5_hsc =
+ metrics->SystemTemperatures[SYSTEM_TEMP_OAM_4_5_HSC];
+ baseboard_temp_metrics->system_temp_oam_6_7_hsc =
+ metrics->SystemTemperatures[SYSTEM_TEMP_OAM_6_7_HSC];
+ baseboard_temp_metrics->system_temp_ubb_fpga_0v72_vr =
+ metrics->SystemTemperatures[SYSTEM_TEMP_UBB_FPGA_0V72_VR];
+ baseboard_temp_metrics->system_temp_ubb_fpga_3v3_vr =
+ metrics->SystemTemperatures[SYSTEM_TEMP_UBB_FPGA_3V3_VR];
+ baseboard_temp_metrics->system_temp_retimer_0_1_2_3_1v2_vr =
+ metrics->SystemTemperatures[SYSTEM_TEMP_RETIMER_0_1_2_3_1V2_VR];
+ baseboard_temp_metrics->system_temp_retimer_4_5_6_7_1v2_vr =
+ metrics->SystemTemperatures[SYSTEM_TEMP_RETIMER_4_5_6_7_1V2_VR];
+ baseboard_temp_metrics->system_temp_retimer_0_1_0v9_vr =
+ metrics->SystemTemperatures[SYSTEM_TEMP_RETIMER_0_1_0V9_VR];
+ baseboard_temp_metrics->system_temp_retimer_4_5_0v9_vr =
+ metrics->SystemTemperatures[SYSTEM_TEMP_RETIMER_4_5_0V9_VR];
+ baseboard_temp_metrics->system_temp_retimer_2_3_0v9_vr =
+ metrics->SystemTemperatures[SYSTEM_TEMP_RETIMER_2_3_0V9_VR];
+ baseboard_temp_metrics->system_temp_retimer_6_7_0v9_vr =
+ metrics->SystemTemperatures[SYSTEM_TEMP_RETIMER_6_7_0V9_VR];
+ baseboard_temp_metrics->system_temp_oam_0_1_2_3_3v3_vr =
+ metrics->SystemTemperatures[SYSTEM_TEMP_OAM_0_1_2_3_3V3_VR];
+ baseboard_temp_metrics->system_temp_oam_4_5_6_7_3v3_vr =
+ metrics->SystemTemperatures[SYSTEM_TEMP_OAM_4_5_6_7_3V3_VR];
+ baseboard_temp_metrics->system_temp_ibc_hsc =
+ metrics->SystemTemperatures[SYSTEM_TEMP_IBC_HSC];
+ baseboard_temp_metrics->system_temp_ibc =
+ metrics->SystemTemperatures[SYSTEM_TEMP_IBC];
+}
+
+static void smu_v15_0_8_fill_gpuboard_temp_metrics(
+ struct smu_v15_0_8_gpuboard_temp_metrics *gpuboard_temp_metrics,
+ const SystemMetricsTable_t *metrics)
+{
+ gpuboard_temp_metrics->accumulation_counter = metrics->AccumulationCounter;
+ gpuboard_temp_metrics->label_version = metrics->LabelVersion;
+ gpuboard_temp_metrics->node_id = metrics->NodeIdentifier;
+
+ gpuboard_temp_metrics->node_temp_retimer =
+ metrics->NodeTemperatures[NODE_TEMP_RETIMER];
+ gpuboard_temp_metrics->node_temp_ibc =
+ metrics->NodeTemperatures[NODE_TEMP_IBC_TEMP];
+ gpuboard_temp_metrics->node_temp_ibc_2 =
+ metrics->NodeTemperatures[NODE_TEMP_IBC_2_TEMP];
+ gpuboard_temp_metrics->node_temp_vdd18_vr =
+ metrics->NodeTemperatures[NODE_TEMP_VDD18_VR_TEMP];
+ gpuboard_temp_metrics->node_temp_04_hbm_b_vr =
+ metrics->NodeTemperatures[NODE_TEMP_04_HBM_B_VR_TEMP];
+ gpuboard_temp_metrics->node_temp_04_hbm_d_vr =
+ metrics->NodeTemperatures[NODE_TEMP_04_HBM_D_VR_TEMP];
+
+ gpuboard_temp_metrics->vr_temp_vddcr_socio_a =
+ metrics->VrTemperatures[SVI_PLANE_VDDCR_SOCIO_A_TEMP];
+ gpuboard_temp_metrics->vr_temp_vddcr_socio_c =
+ metrics->VrTemperatures[SVI_PLANE_VDDCR_SOCIO_C_TEMP];
+ gpuboard_temp_metrics->vr_temp_vddcr_x0 =
+ metrics->VrTemperatures[SVI_PLANE_VDDCR_X0_TEMP];
+ gpuboard_temp_metrics->vr_temp_vddcr_x1 =
+ metrics->VrTemperatures[SVI_PLANE_VDDCR_X1_TEMP];
+ gpuboard_temp_metrics->vr_temp_vddio_hbm_b =
+ metrics->VrTemperatures[SVI_PLANE_VDDIO_HBM_B_TEMP];
+ gpuboard_temp_metrics->vr_temp_vddio_hbm_d =
+ metrics->VrTemperatures[SVI_PLANE_VDDIO_HBM_D_TEMP];
+ gpuboard_temp_metrics->vr_temp_vddio_04_hbm_b =
+ metrics->VrTemperatures[SVI_PLANE_VDDIO_04_HBM_B_TEMP];
+ gpuboard_temp_metrics->vr_temp_vddio_04_hbm_d =
+ metrics->VrTemperatures[SVI_PLANE_VDDIO_04_HBM_D_TEMP];
+ gpuboard_temp_metrics->vr_temp_vddcr_hbm_b =
+ metrics->VrTemperatures[SVI_PLANE_VDDCR_HBM_B_TEMP];
+ gpuboard_temp_metrics->vr_temp_vddcr_hbm_d =
+ metrics->VrTemperatures[SVI_PLANE_VDDCR_HBM_D_TEMP];
+ gpuboard_temp_metrics->vr_temp_vddcr_075_hbm_b =
+ metrics->VrTemperatures[SVI_PLANE_VDDCR_075_HBM_B_TEMP];
+ gpuboard_temp_metrics->vr_temp_vddcr_075_hbm_d =
+ metrics->VrTemperatures[SVI_PLANE_VDDCR_075_HBM_D_TEMP];
+ gpuboard_temp_metrics->vr_temp_vddio_11_gta_a =
+ metrics->VrTemperatures[SVI_PLANE_VDDIO_11_GTA_A_TEMP];
+ gpuboard_temp_metrics->vr_temp_vddio_11_gta_c =
+ metrics->VrTemperatures[SVI_PLANE_VDDIO_11_GTA_C_TEMP];
+ gpuboard_temp_metrics->vr_temp_vddan_075_gta_a =
+ metrics->VrTemperatures[SVI_PLANE_VDDAN_075_GTA_A_TEMP];
+ gpuboard_temp_metrics->vr_temp_vddan_075_gta_c =
+ metrics->VrTemperatures[SVI_PLANE_VDDAN_075_GTA_C_TEMP];
+ gpuboard_temp_metrics->vr_temp_vddcr_075_ucie =
+ metrics->VrTemperatures[SVI_PLANE_VDDCR_075_UCIE_TEMP];
+ gpuboard_temp_metrics->vr_temp_vddio_065_ucieaa =
+ metrics->VrTemperatures[SVI_PLANE_VDDIO_065_UCIEAA_TEMP];
+ gpuboard_temp_metrics->vr_temp_vddio_065_ucieam_a =
+ metrics->VrTemperatures[SVI_PLANE_VDDIO_065_UCIEAM_A_TEMP];
+ gpuboard_temp_metrics->vr_temp_vddio_065_ucieam_c =
+ metrics->VrTemperatures[SVI_PLANE_VDDIO_065_UCIEAM_C_TEMP];
+ gpuboard_temp_metrics->vr_temp_vddan_075 =
+ metrics->VrTemperatures[SVI_PLANE_VDDAN_075_TEMP];
+}
+
+static ssize_t smu_v15_0_8_get_temp_metrics(struct smu_context *smu,
+ enum smu_temp_metric_type type,
+ void *table)
+{
+ struct smu_v15_0_8_baseboard_temp_metrics *baseboard_temp_metrics;
+ struct smu_v15_0_8_gpuboard_temp_metrics *gpuboard_temp_metrics;
+ struct smu_table_context *smu_table = &smu->smu_table;
+ struct smu_table *tables = smu_table->tables;
+ SystemMetricsTable_t *metrics;
+ struct smu_table *sys_table;
+ int ret;
+
+ ret = smu_v15_0_8_get_system_metrics_table(smu);
+ if (ret)
+ return ret;
+
+ sys_table = &tables[SMU_TABLE_PMFW_SYSTEM_METRICS];
+ metrics = (SystemMetricsTable_t *)sys_table->cache.buffer;
+
+ switch (type) {
+ case SMU_TEMP_METRIC_GPUBOARD:
+ gpuboard_temp_metrics =
+ (struct smu_v15_0_8_gpuboard_temp_metrics *)
+ smu_driver_table_ptr(smu, SMU_DRIVER_TABLE_GPUBOARD_TEMP_METRICS);
+ smu_driver_table_update_cache_time(smu, SMU_DRIVER_TABLE_GPUBOARD_TEMP_METRICS);
+ smu_v15_0_8_fill_gpuboard_temp_metrics(gpuboard_temp_metrics,
+ metrics);
+ memcpy(table, gpuboard_temp_metrics, sizeof(*gpuboard_temp_metrics));
+ return sizeof(*gpuboard_temp_metrics);
+ case SMU_TEMP_METRIC_BASEBOARD:
+ baseboard_temp_metrics =
+ (struct smu_v15_0_8_baseboard_temp_metrics *)
+ smu_driver_table_ptr(smu, SMU_DRIVER_TABLE_BASEBOARD_TEMP_METRICS);
+ smu_driver_table_update_cache_time(smu, SMU_DRIVER_TABLE_BASEBOARD_TEMP_METRICS);
+ smu_v15_0_8_fill_baseboard_temp_metrics(baseboard_temp_metrics,
+ metrics);
+ memcpy(table, baseboard_temp_metrics, sizeof(*baseboard_temp_metrics));
+ return sizeof(*baseboard_temp_metrics);
+ default:
+ return -EINVAL;
+ }
+}
+
+static ssize_t smu_v15_0_8_get_gpu_metrics(struct smu_context *smu, void **table)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+ struct smu_v15_0_8_gpu_metrics *gpu_metrics;
+ struct amdgpu_device *adev = smu->adev;
+ int ret = 0, xcc_id, inst, i, j, idx;
+ uint32_t aid_mask = adev->aid_mask;
+ uint32_t mid_mask = adev->aid_mask;
+ MetricsTable_t *metrics;
+
+ metrics = kzalloc(sizeof(MetricsTable_t), GFP_KERNEL);
+
+ ret = smu_v15_0_8_get_metrics_table_internal(smu, 1, NULL);
+ if (ret)
+ return ret;
+
+ metrics = (MetricsTable_t *)smu_table->metrics_table;
+ gpu_metrics = (struct smu_v15_0_8_gpu_metrics *)smu_driver_table_ptr(smu,
+ SMU_DRIVER_TABLE_GPU_METRICS);
+
+ gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
+
+ gpu_metrics->temperature_hotspot = SMUQ10_ROUND(metrics->MaxSocketTemperature);
+
+ /* Per-HBM stack temperatures */
+ if (adev->umc.active_mask) {
+ u64 mask = adev->umc.active_mask;
+ int out_idx = 0;
+ int stack_idx;
+
+ if (unlikely(hweight64(mask)/4 > SMU_15_0_8_MAX_HBM_STACKS))
+ dev_warn(adev->dev, "Invalid umc mask %lld\n", mask);
+ else {
+ for_each_hbm_stack(stack_idx, mask) {
+ if (!hbm_stack_mask_valid(mask))
+ continue;
+ gpu_metrics->temperature_hbm[out_idx++] =
+ SMUQ10_ROUND(metrics->HbmTemperature[stack_idx]);
+ }
+ }
+ }
+
+ /* Reports max temperature of all voltage rails */
+ gpu_metrics->temperature_vrsoc = SMUQ10_ROUND(metrics->MaxVrTemperature);
+ /* MID, AID, XCD temperatures */
+ idx = 0;
+ for_each_inst(i, mid_mask) {
+ gpu_metrics->temperature_mid[idx] = SMUQ10_ROUND(metrics->MidTemperature[i]);
+ idx++;
+ }
+
+ idx = 0;
+ for_each_inst(i, aid_mask) {
+ gpu_metrics->temperature_aid[idx] = SMUQ10_ROUND(metrics->AidTemperature[i]);
+ idx++;
+ }
+
+ for (i = 0; i < NUM_XCC(adev->gfx.xcc_mask); ++i) {
+ xcc_id = GET_INST(GC, i);
+ if (xcc_id >= 0)
+ gpu_metrics->temperature_xcd[i] = SMUQ10_ROUND(metrics->XcdTemperature[xcc_id]);
+ }
+ /* Power */
+ gpu_metrics->curr_socket_power = SMUQ10_ROUND(metrics->SocketPower);
+
+ gpu_metrics->average_gfx_activity = SMUQ10_ROUND(metrics->SocketGfxBusy);
+ gpu_metrics->average_umc_activity = SMUQ10_ROUND(metrics->DramBandwidthUtilization);
+ gpu_metrics->mem_max_bandwidth = SMUQ10_ROUND(metrics->MaxDramBandwidth);
+
+ /* Energy counter reported in 15.259uJ (2^-16) units */
+ gpu_metrics->energy_accumulator = metrics->SocketEnergyAcc;
+
+ for (i = 0; i < NUM_XCC(adev->gfx.xcc_mask); ++i) {
+ xcc_id = GET_INST(GC, i);
+ if (xcc_id >= 0) {
+ gpu_metrics->current_gfxclk[i] =
+ SMUQ10_ROUND(metrics->GfxclkFrequency[xcc_id]);
+ }
+ }
+
+ /* Per-MID clocks */
+ idx = 0;
+ for_each_inst(i, mid_mask) {
+ gpu_metrics->current_socclk[idx] = SMUQ10_ROUND(metrics->SocclkFrequency[i]);
+ idx++;
+ }
+
+ /* Per-VCN clocks */
+ for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+ inst = GET_INST(VCN, i);
+ if (inst >= 0) {
+ gpu_metrics->current_vclk0[i] = SMUQ10_ROUND(metrics->VclkFrequency[inst]);
+ gpu_metrics->current_dclk0[i] = SMUQ10_ROUND(metrics->DclkFrequency[inst]);
+ }
+ }
+
+ /* Per-AID clocks */
+ idx = 0;
+ for_each_inst(i, aid_mask) {
+ gpu_metrics->current_uclk[idx] = SMUQ10_ROUND(metrics->UclkFrequency[i]);
+ idx++;
+ }
+
+ /* Total accumulated cycle counter */
+ gpu_metrics->accumulation_counter = metrics->AccumulationCounter;
+
+ /* Accumulated throttler residencies */
+ gpu_metrics->prochot_residency_acc = metrics->ProchotResidencyAcc;
+ gpu_metrics->ppt_residency_acc = metrics->PptResidencyAcc;
+ gpu_metrics->socket_thm_residency_acc = metrics->SocketThmResidencyAcc;
+ gpu_metrics->vr_thm_residency_acc = metrics->VrThmResidencyAcc;
+ gpu_metrics->hbm_thm_residency_acc = metrics->HbmThmResidencyAcc;
+
+ gpu_metrics->gfx_activity_acc = SMUQ10_ROUND(metrics->SocketGfxBusyAcc);
+ gpu_metrics->mem_activity_acc = SMUQ10_ROUND(metrics->DramBandwidthUtilizationAcc);
+
+ for (i = 0; i < NUM_XGMI_LINKS; i++) {
+ j = amdgpu_xgmi_get_ext_link(adev, i);
+ if (j < 0 || j >= NUM_XGMI_LINKS)
+ continue;
+ ret = amdgpu_get_xgmi_link_status(adev, i);
+ if (ret >= 0)
+ gpu_metrics->xgmi_link_status[j] = ret;
+ }
+
+ gpu_metrics->xgmi_read_data_acc = SMUQ10_ROUND(metrics->XgmiReadBandwidthAcc);
+ gpu_metrics->xgmi_write_data_acc = SMUQ10_ROUND(metrics->XgmiWriteBandwidthAcc);
+
+ for (i = 0; i < NUM_XCC(adev->gfx.xcc_mask); ++i) {
+ inst = GET_INST(GC, i);
+ gpu_metrics->gfx_busy_inst[i] = SMUQ10_ROUND(metrics->GfxBusy[inst]);
+ gpu_metrics->gfx_busy_acc[i] = SMUQ10_ROUND(metrics->GfxBusyAcc[inst]);
+ gpu_metrics->gfx_below_host_limit_ppt_acc[i] =
+ SMUQ10_ROUND(metrics->GfxclkBelowHostLimitPptAcc[inst]);
+ gpu_metrics->gfx_below_host_limit_thm_acc[i] =
+ SMUQ10_ROUND(metrics->GfxclkBelowHostLimitThmAcc[inst]);
+ gpu_metrics->gfx_low_utilization_acc[i] =
+ SMUQ10_ROUND(metrics->GfxclkLowUtilizationAcc[inst]);
+ gpu_metrics->gfx_below_host_limit_total_acc[i] =
+ SMUQ10_ROUND(metrics->GfxclkBelowHostLimitTotalAcc[inst]);
+ }
+
+ gpu_metrics->xgmi_link_width = metrics->XgmiWidth;
+ gpu_metrics->xgmi_link_speed = metrics->XgmiBitrate;
+
+ gpu_metrics->firmware_timestamp = metrics->Timestamp;
+
+ *table = gpu_metrics;
+
+ smu_driver_table_update_cache_time(smu, SMU_DRIVER_TABLE_GPU_METRICS);
+
+ return sizeof(*gpu_metrics);
+}
+
+static void smu_v15_0_8_get_unique_id(struct smu_context *smu)
+{
+ struct amdgpu_device *adev = smu->adev;
+ struct smu_table_context *smu_table = &smu->smu_table;
+ PPTable_t *pptable = (PPTable_t *)smu_table->driver_pptable;
+
+ adev->unique_id = pptable->PublicSerialNumberMID;
+}
+
+static int smu_v15_0_8_get_power_limit(struct smu_context *smu,
+ uint32_t *current_power_limit,
+ uint32_t *default_power_limit,
+ uint32_t *max_power_limit,
+ uint32_t *min_power_limit)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+ PPTable_t *pptable = (PPTable_t *)smu_table->driver_pptable;
+ uint32_t power_limit = 0;
+ int ret;
+
+ ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetPptLimit, &power_limit);
+ if (ret) {
+ dev_err(smu->adev->dev, "Couldn't get PPT limit");
+ return -EINVAL;
+ }
+
+ if (current_power_limit)
+ *current_power_limit = power_limit;
+
+ if (default_power_limit)
+ *max_power_limit = pptable->MaxSocketPowerLimit;
+
+ if (max_power_limit)
+ *max_power_limit = pptable->MaxSocketPowerLimit;
+
+ if (min_power_limit)
+ *min_power_limit = 0;
+
+ return 0;
+}
+
+static int smu_v15_0_8_populate_umd_state_clk(struct smu_context *smu)
+{
+ struct smu_15_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
+ struct smu_dpm_table *gfx_table = &dpm_context->dpm_tables.gfx_table;
+ struct smu_dpm_table *mem_table = &dpm_context->dpm_tables.uclk_table;
+ struct smu_umd_pstate_table *pstate_table = &smu->pstate_table;
+
+ pstate_table->gfxclk_pstate.curr.min = SMU_DPM_TABLE_MIN(gfx_table);
+ pstate_table->gfxclk_pstate.curr.max = SMU_DPM_TABLE_MAX(gfx_table);
+
+ pstate_table->uclk_pstate.curr.min = SMU_DPM_TABLE_MIN(mem_table);
+ pstate_table->uclk_pstate.curr.max = SMU_DPM_TABLE_MAX(mem_table);
+ return 0;
+}
+
+static int smu_v15_0_8_set_gfx_soft_freq_limited_range(struct smu_context *smu,
+ uint32_t min,
+ uint32_t max)
+{
+ int ret;
+
+ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk,
+ max & 0xffff, NULL);
+ if (ret)
+ return ret;
+
+ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMinGfxclk,
+ min & 0xffff, NULL);
+
+ return ret;
+}
+
+static int smu_v15_0_8_set_performance_level(struct smu_context *smu,
+ enum amd_dpm_forced_level level)
+{
+ struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
+ struct smu_15_0_dpm_context *dpm_context = smu_dpm->dpm_context;
+ struct smu_dpm_table *gfx_table = &dpm_context->dpm_tables.gfx_table;
+ struct smu_dpm_table *uclk_table = &dpm_context->dpm_tables.uclk_table;
+ struct smu_umd_pstate_table *pstate_table = &smu->pstate_table;
+ int ret;
+
+ switch (level) {
+ case AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM:
+ /* Determinism not supported on SMU v15.0.8 */
+ ret = -EOPNOTSUPP;
+ break;
+
+ case AMD_DPM_FORCED_LEVEL_AUTO:
+ /* Restore GFXCLK to default range */
+ if ((SMU_DPM_TABLE_MIN(gfx_table) !=
+ pstate_table->gfxclk_pstate.curr.min) ||
+ (SMU_DPM_TABLE_MAX(gfx_table) !=
+ pstate_table->gfxclk_pstate.curr.max)) {
+ ret = smu_v15_0_8_set_gfx_soft_freq_limited_range(
+ smu, SMU_DPM_TABLE_MIN(gfx_table),
+ SMU_DPM_TABLE_MAX(gfx_table));
+ if (ret)
+ goto out;
+
+ pstate_table->gfxclk_pstate.curr.min =
+ SMU_DPM_TABLE_MIN(gfx_table);
+ pstate_table->gfxclk_pstate.curr.max =
+ SMU_DPM_TABLE_MAX(gfx_table);
+ }
+
+ /* Restore UCLK to default max */
+ if (SMU_DPM_TABLE_MAX(uclk_table) !=
+ pstate_table->uclk_pstate.curr.max) {
+ /* Min UCLK is not expected to be changed */
+ ret = smu_v15_0_set_soft_freq_limited_range(smu,
+ SMU_UCLK, 0,
+ SMU_DPM_TABLE_MAX(uclk_table),
+ false);
+ if (ret)
+ goto out;
+
+ pstate_table->uclk_pstate.curr.max =
+ SMU_DPM_TABLE_MAX(uclk_table);
+ }
+
+ if (ret)
+ goto out;
+
+ smu_cmn_reset_custom_level(smu);
+
+ break;
+ case AMD_DPM_FORCED_LEVEL_MANUAL:
+ ret = 0;
+ break;
+ default:
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+out:
+ return ret;
+}
+
+static int smu_v15_0_8_set_soft_freq_limited_range(struct smu_context *smu,
+ enum smu_clk_type clk_type,
+ uint32_t min, uint32_t max,
+ bool automatic)
+{
+ struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
+ struct smu_umd_pstate_table *pstate_table = &smu->pstate_table;
+ int ret = 0;
+
+ if (clk_type != SMU_GFXCLK && clk_type != SMU_SCLK &&
+ clk_type != SMU_UCLK)
+ return -EINVAL;
+
+ if (smu_dpm->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL)
+ return -EINVAL;
+
+ if (smu_dpm->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) {
+ if (min >= max) {
+ dev_err(smu->adev->dev,
+ "Minimum clk should be less than the maximum allowed clock\n");
+ return -EINVAL;
+ }
+
+ if (clk_type == SMU_GFXCLK || clk_type == SMU_SCLK) {
+ if ((min == pstate_table->gfxclk_pstate.curr.min) &&
+ (max == pstate_table->gfxclk_pstate.curr.max))
+ return 0;
+
+ ret = smu_v15_0_8_set_gfx_soft_freq_limited_range(smu,
+ min, max);
+ if (!ret) {
+ pstate_table->gfxclk_pstate.curr.min = min;
+ pstate_table->gfxclk_pstate.curr.max = max;
+ }
+ }
+
+ if (clk_type == SMU_UCLK) {
+ if (max == pstate_table->uclk_pstate.curr.max)
+ return 0;
+
+ ret = smu_v15_0_set_soft_freq_limited_range(smu,
+ SMU_UCLK,
+ 0, max,
+ false);
+ if (!ret)
+ pstate_table->uclk_pstate.curr.max = max;
+ }
+
+ return ret;
+ }
+
+ return 0;
+}
+
+static int smu_v15_0_8_od_edit_dpm_table(struct smu_context *smu,
+ enum PP_OD_DPM_TABLE_COMMAND type,
+ long input[], uint32_t size)
+{
+ struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
+ struct smu_umd_pstate_table *pstate_table = &smu->pstate_table;
+ struct smu_15_0_dpm_context *dpm_context = smu_dpm->dpm_context;
+ uint32_t min_clk, max_clk;
+ int ret;
+
+ /* Only allowed in manual mode */
+ if (smu_dpm->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL)
+ return -EINVAL;
+
+ switch (type) {
+ case PP_OD_EDIT_SCLK_VDDC_TABLE:
+ if (size != 2) {
+ dev_err(smu->adev->dev,
+ "Input parameter number not correct\n");
+ return -EINVAL;
+ }
+ min_clk = SMU_DPM_TABLE_MIN(&dpm_context->dpm_tables.gfx_table);
+ max_clk = SMU_DPM_TABLE_MAX(&dpm_context->dpm_tables.gfx_table);
+ if (input[0] == 0) {
+ if (input[1] < min_clk) {
+ dev_warn(smu->adev->dev,
+ "Minimum GFX clk (%ld) MHz specified is less than the minimum allowed (%d) MHz\n",
+ input[1], min_clk);
+ pstate_table->gfxclk_pstate.custom.min =
+ pstate_table->gfxclk_pstate.curr.min;
+ return -EINVAL;
+ }
+
+ pstate_table->gfxclk_pstate.custom.min = input[1];
+ } else if (input[0] == 1) {
+ if (input[1] > max_clk) {
+ dev_warn(smu->adev->dev,
+ "Maximum GFX clk (%ld) MHz specified is greater than the maximum allowed (%d) MHz\n",
+ input[1], max_clk);
+ pstate_table->gfxclk_pstate.custom.max =
+ pstate_table->gfxclk_pstate.curr.max;
+ return -EINVAL;
+ }
+
+ pstate_table->gfxclk_pstate.custom.max = input[1];
+ } else {
+ return -EINVAL;
+ }
+ break;
+ case PP_OD_EDIT_MCLK_VDDC_TABLE:
+ if (size != 2) {
+ dev_err(smu->adev->dev,
+ "Input parameter number not correct\n");
+ return -EINVAL;
+ }
+
+ if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
+ dev_warn(smu->adev->dev,
+ "UCLK_LIMITS setting not supported!\n");
+ return -EOPNOTSUPP;
+ }
+ max_clk = SMU_DPM_TABLE_MAX(&dpm_context->dpm_tables.uclk_table);
+ if (input[0] == 0) {
+ dev_info(smu->adev->dev,
+ "Setting min UCLK level is not supported");
+ return -EINVAL;
+ } else if (input[0] == 1) {
+ if (input[1] > max_clk) {
+ dev_warn(smu->adev->dev,
+ "Maximum UCLK (%ld) MHz specified is greater than the maximum allowed (%d) MHz\n",
+ input[1], max_clk);
+ pstate_table->uclk_pstate.custom.max =
+ pstate_table->uclk_pstate.curr.max;
+
+ return -EINVAL;
+ }
+
+ pstate_table->uclk_pstate.custom.max = input[1];
+ }
+ break;
+ case PP_OD_RESTORE_DEFAULT_TABLE:
+ if (size != 0) {
+ dev_err(smu->adev->dev,
+ "Input parameter number not correct\n");
+ return -EINVAL;
+ }
+
+ /* Use the default frequencies for manual mode */
+ min_clk = SMU_DPM_TABLE_MIN(&dpm_context->dpm_tables.gfx_table);
+ max_clk = SMU_DPM_TABLE_MAX(&dpm_context->dpm_tables.gfx_table);
+
+ ret = smu_v15_0_8_set_soft_freq_limited_range(smu,
+ SMU_GFXCLK,
+ min_clk, max_clk,
+ false);
+ if (ret)
+ return ret;
+
+ min_clk = SMU_DPM_TABLE_MIN(&dpm_context->dpm_tables.uclk_table);
+ max_clk = SMU_DPM_TABLE_MAX(&dpm_context->dpm_tables.uclk_table);
+ ret = smu_v15_0_8_set_soft_freq_limited_range(smu,
+ SMU_UCLK,
+ min_clk, max_clk,
+ false);
+ if (ret)
+ return ret;
+
+ smu_cmn_reset_custom_level(smu);
+ break;
+ case PP_OD_COMMIT_DPM_TABLE:
+ if (size != 0) {
+ dev_err(smu->adev->dev,
+ "Input parameter number not correct\n");
+ return -EINVAL;
+ }
+
+ if (!pstate_table->gfxclk_pstate.custom.min)
+ pstate_table->gfxclk_pstate.custom.min =
+ pstate_table->gfxclk_pstate.curr.min;
+
+ if (!pstate_table->gfxclk_pstate.custom.max)
+ pstate_table->gfxclk_pstate.custom.max =
+ pstate_table->gfxclk_pstate.curr.max;
+
+ min_clk = pstate_table->gfxclk_pstate.custom.min;
+ max_clk = pstate_table->gfxclk_pstate.custom.max;
+
+ ret = smu_v15_0_8_set_soft_freq_limited_range(smu,
+ SMU_GFXCLK,
+ min_clk, max_clk,
+ false);
+ if (ret)
+ return ret;
+
+ /* Commit UCLK custom range (only max supported) */
+ if (pstate_table->uclk_pstate.custom.max) {
+ min_clk = pstate_table->uclk_pstate.curr.min;
+ max_clk = pstate_table->uclk_pstate.custom.max;
+ ret = smu_v15_0_8_set_soft_freq_limited_range(smu,
+ SMU_UCLK,
+ min_clk, max_clk,
+ false);
+ if (ret)
+ return ret;
+ }
+
+ break;
+ default:
+ return -ENOSYS;
+ }
+
+ return 0;
+}
+
+static int smu_v15_0_8_get_thermal_temperature_range(struct smu_context *smu,
+ struct smu_temperature_range *range)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+ PPTable_t *pptable = (PPTable_t *)smu_table->driver_pptable;
+ uint32_t max_ctf, max_thm;
+
+ if (amdgpu_sriov_multi_vf_mode(smu->adev))
+ return 0;
+
+ if (!range)
+ return -EINVAL;
+
+ /* CTF (Critical Temperature Fault) limits */
+ max_ctf = max3(pptable->CTFLimitMID, pptable->CTFLimitXCD,
+ pptable->CTFLimitAID);
+ range->hotspot_emergency_max = max_ctf * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+
+ range->mem_emergency_max = pptable->CTFLimitHBM *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+
+ /* Thermal throttling limits */
+ max_thm = max3(pptable->ThermalLimitMID, pptable->ThermalLimitXCD,
+ pptable->ThermalLimitAID);
+ range->hotspot_crit_max = max_thm * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+
+ range->mem_crit_max = pptable->ThermalLimitHBM *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+
+ return 0;
+}
+
+static int smu_v15_0_8_set_power_limit(struct smu_context *smu,
+ enum smu_ppt_limit_type limit_type,
+ uint32_t limit)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+ PPTable_t *pptable = (PPTable_t *)smu_table->driver_pptable;
+ int ret;
+
+ if (limit_type == SMU_FAST_PPT_LIMIT) {
+ if (!pptable->PPT1Max)
+ return -EOPNOTSUPP;
+
+ if (limit > pptable->PPT1Max || limit < pptable->PPT1Min) {
+ dev_err(smu->adev->dev,
+ "New PPT1 limit (%d) should be between min %d and max %d\n",
+ limit, pptable->PPT1Min, pptable->PPT1Max);
+ return -EINVAL;
+ }
+
+ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetFastPptLimit,
+ limit, NULL);
+ if (ret)
+ dev_err(smu->adev->dev, "Set fast PPT limit failed!\n");
+
+ return ret;
+ }
+
+ return smu_v15_0_set_power_limit(smu, limit_type, limit);
+}
+
+static int smu_v15_0_8_get_ppt_limit(struct smu_context *smu,
+ uint32_t *ppt_limit,
+ enum smu_ppt_limit_type type,
+ enum smu_ppt_limit_level level)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+ PPTable_t *pptable = (PPTable_t *)smu_table->driver_pptable;
+ int ret = 0;
+
+ if (!ppt_limit)
+ return -EINVAL;
+
+ if (type == SMU_FAST_PPT_LIMIT) {
+ if (!pptable->PPT1Max)
+ return -EOPNOTSUPP;
+
+ switch (level) {
+ case SMU_PPT_LIMIT_MAX:
+ *ppt_limit = pptable->PPT1Max;
+ break;
+ case SMU_PPT_LIMIT_CURRENT:
+ ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetFastPptLimit,
+ ppt_limit);
+ if (ret)
+ dev_err(smu->adev->dev,
+ "Get fast PPT limit failed!\n");
+ break;
+ case SMU_PPT_LIMIT_DEFAULT:
+ *ppt_limit = pptable->PPT1Default;
+ break;
+ case SMU_PPT_LIMIT_MIN:
+ *ppt_limit = pptable->PPT1Min;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+ return ret;
+ }
+
+ return -EOPNOTSUPP;
+}
+
+static const struct pptable_funcs smu_v15_0_8_ppt_funcs = {
+ .init_allowed_features = smu_v15_0_8_init_allowed_features,
+ .set_default_dpm_table = smu_v15_0_8_set_default_dpm_table,
+ .is_dpm_running = smu_v15_0_8_is_dpm_running,
+ .init_smc_tables = smu_v15_0_8_init_smc_tables,
+ .fini_smc_tables = smu_v15_0_8_fini_smc_tables,
+ .init_power = smu_v15_0_init_power,
+ .fini_power = smu_v15_0_fini_power,
+ .check_fw_status = smu_v15_0_8_check_fw_status,
+ .check_fw_version = smu_cmn_check_fw_version,
+ .set_driver_table_location = smu_v15_0_set_driver_table_location,
+ .set_tool_table_location = smu_v15_0_set_tool_table_location,
+ .notify_memory_pool_location = smu_v15_0_notify_memory_pool_location,
+ .system_features_control = smu_v15_0_8_system_features_control,
+ .get_enabled_mask = smu_v15_0_8_get_enabled_mask,
+ .feature_is_enabled = smu_cmn_feature_is_enabled,
+ .register_irq_handler = smu_v15_0_8_register_irq_handler,
+ .setup_pptable = smu_v15_0_8_setup_pptable,
+ .get_pp_feature_mask = smu_cmn_get_pp_feature_mask,
+ .wait_for_event = smu_v15_0_wait_for_event,
+ .get_pm_metrics = smu_v15_0_8_get_pm_metrics,
+ .mode2_reset = smu_v15_0_8_mode2_reset,
+ .get_dpm_ultimate_freq = smu_v15_0_8_get_dpm_ultimate_freq,
+ .get_gpu_metrics = smu_v15_0_8_get_gpu_metrics,
+ .get_unique_id = smu_v15_0_8_get_unique_id,
+ .get_power_limit = smu_v15_0_8_get_power_limit,
+ .set_power_limit = smu_v15_0_8_set_power_limit,
+ .get_ppt_limit = smu_v15_0_8_get_ppt_limit,
+ .emit_clk_levels = smu_v15_0_8_emit_clk_levels,
+ .read_sensor = smu_v15_0_8_read_sensor,
+ .populate_umd_state_clk = smu_v15_0_8_populate_umd_state_clk,
+ .set_performance_level = smu_v15_0_8_set_performance_level,
+ .od_edit_dpm_table = smu_v15_0_8_od_edit_dpm_table,
+ .get_thermal_temperature_range = smu_v15_0_8_get_thermal_temperature_range,
+};
+
+static void smu_v15_0_8_init_msg_ctl(struct smu_context *smu,
+ const struct cmn2asic_msg_mapping *message_map)
+{
+ struct amdgpu_device *adev = smu->adev;
+ struct smu_msg_ctl *ctl = &smu->msg_ctl;
+
+ ctl->smu = smu;
+ mutex_init(&ctl->lock);
+ ctl->config.msg_reg = SOC15_REG_OFFSET(MP1, 0, regMP1_SMN_C2PMSG_40);
+ ctl->config.resp_reg = SOC15_REG_OFFSET(MP1, 0, regMP1_SMN_C2PMSG_41);
+ ctl->config.arg_regs[0] = SOC15_REG_OFFSET(MP1, 0, regMP1_SMN_C2PMSG_42);
+ ctl->config.arg_regs[1] = SOC15_REG_OFFSET(MP1, 0, regMP1_SMN_C2PMSG_43);
+ ctl->config.arg_regs[2] = SOC15_REG_OFFSET(MP1, 0, regMP1_SMN_C2PMSG_44);
+ ctl->config.arg_regs[3] = SOC15_REG_OFFSET(MP1, 0, regMP1_SMN_C2PMSG_45);
+ ctl->config.num_arg_regs = 4;
+ ctl->ops = &smu_msg_v1_ops;
+ ctl->default_timeout = adev->usec_timeout * 20;
+ ctl->message_map = message_map;
+}
+
+static const struct smu_temp_funcs smu_v15_0_8_temp_funcs = {
+ .temp_metrics_is_supported = smu_v15_0_8_is_temp_metrics_supported,
+ .get_temp_metrics = smu_v15_0_8_get_temp_metrics,
+};
+
+void smu_v15_0_8_set_ppt_funcs(struct smu_context *smu)
+{
+ smu->ppt_funcs = &smu_v15_0_8_ppt_funcs;
+ smu->clock_map = smu_v15_0_8_clk_map;
+ smu->feature_map = smu_v15_0_8_feature_mask_map;
+ smu->table_map = smu_v15_0_8_table_map;
+ smu_v15_0_8_init_msg_ctl(smu, smu_v15_0_8_message_map);
+ smu->smu_temp.temp_funcs = &smu_v15_0_8_temp_funcs;
+ smu->smc_driver_if_version = SMU15_DRIVER_IF_VERSION_SMU_V15_0_8;
+}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.h b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.h
new file mode 100644
index 000000000000..398ce4482174
--- /dev/null
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.h
@@ -0,0 +1,313 @@
+/*
+ * Copyright 2025 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#ifndef __SMU_15_0_8_PPT_H__
+#define __SMU_15_0_8_PPT_H__
+
+#define SMU_15_0_8_NUM_XGMI_LINKS 8
+#define SMU_15_0_8_MAX_GFX_CLKS 8
+#define SMU_15_0_8_MAX_CLKS 4
+#define SMU_15_0_8_MAX_XCC 8
+#define SMU_15_0_8_MAX_VCN 4
+#define SMU_15_0_8_MAX_JPEG 40
+#define SMU_15_0_8_MAX_AID 2
+#define SMU_15_0_8_MAX_MID 2
+#define SMU_15_0_8_MAX_HBM_STACKS 12
+extern void smu_v15_0_8_set_ppt_funcs(struct smu_context *smu);
+
+typedef struct {
+ uint32_t MaxSocketPowerLimit;
+ uint32_t MaxGfxclkFrequency;
+ uint32_t MinGfxclkFrequency;
+ uint32_t MaxFclkFrequency;
+ uint32_t MinFclkFrequency;
+ uint32_t MaxGl2clkFrequency;
+ uint32_t MinGl2clkFrequency;
+ uint32_t UclkFrequencyTable[4];
+ uint32_t SocclkFrequency;
+ uint32_t LclkFrequency;
+ uint32_t VclkFrequency;
+ uint32_t DclkFrequency;
+ uint32_t CTFLimitMID;
+ uint32_t CTFLimitAID;
+ uint32_t CTFLimitXCD;
+ uint32_t CTFLimitHBM;
+ uint32_t ThermalLimitMID;
+ uint32_t ThermalLimitAID;
+ uint32_t ThermalLimitXCD;
+ uint32_t ThermalLimitHBM;
+ uint64_t PublicSerialNumberMID;
+ uint64_t PublicSerialNumberAID;
+ uint64_t PublicSerialNumberXCD;
+ uint32_t PPT1Max;
+ uint32_t PPT1Min;
+ uint32_t PPT1Default;
+ bool init;
+} PPTable_t;
+
+#if defined(SWSMU_CODE_LAYER_L2)
+#include "smu_cmn.h"
+
+/* SMUv 15.0.8 GPU metrics*/
+#define SMU_15_0_8_METRICS_FIELDS(SMU_SCALAR, SMU_ARRAY) \
+ SMU_SCALAR(SMU_MATTR(TEMPERATURE_HOTSPOT), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(U16), temperature_hotspot); \
+ SMU_SCALAR(SMU_MATTR(TEMPERATURE_MEM), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(U16), temperature_mem); \
+ SMU_SCALAR(SMU_MATTR(TEMPERATURE_VRSOC), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(U16), temperature_vrsoc); \
+ SMU_ARRAY(SMU_MATTR(TEMPERATURE_HBM), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(U16), temperature_hbm, \
+ SMU_15_0_8_MAX_HBM_STACKS); \
+ SMU_ARRAY(SMU_MATTR(TEMPERATURE_MID), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(U16), temperature_mid, SMU_15_0_8_MAX_MID); \
+ SMU_ARRAY(SMU_MATTR(TEMPERATURE_AID), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(U16), temperature_aid, SMU_15_0_8_MAX_AID); \
+ SMU_ARRAY(SMU_MATTR(TEMPERATURE_XCD), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(U16), temperature_xcd, SMU_15_0_8_MAX_XCC); \
+ SMU_SCALAR(SMU_MATTR(CURR_SOCKET_POWER), SMU_MUNIT(POWER_1), \
+ SMU_MTYPE(U16), curr_socket_power); \
+ SMU_SCALAR(SMU_MATTR(AVERAGE_GFX_ACTIVITY), SMU_MUNIT(PERCENT), \
+ SMU_MTYPE(U16), average_gfx_activity); \
+ SMU_SCALAR(SMU_MATTR(AVERAGE_UMC_ACTIVITY), SMU_MUNIT(PERCENT), \
+ SMU_MTYPE(U16), average_umc_activity); \
+ SMU_SCALAR(SMU_MATTR(MEM_MAX_BANDWIDTH), SMU_MUNIT(BW_1), \
+ SMU_MTYPE(U64), mem_max_bandwidth); \
+ SMU_SCALAR(SMU_MATTR(ENERGY_ACCUMULATOR), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U64), energy_accumulator); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_CLOCK_COUNTER), SMU_MUNIT(TIME_1), \
+ SMU_MTYPE(U64), system_clock_counter); \
+ SMU_SCALAR(SMU_MATTR(ACCUMULATION_COUNTER), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U64), accumulation_counter); \
+ SMU_SCALAR(SMU_MATTR(PROCHOT_RESIDENCY_ACC), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U64), prochot_residency_acc); \
+ SMU_SCALAR(SMU_MATTR(PPT_RESIDENCY_ACC), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U64), ppt_residency_acc); \
+ SMU_SCALAR(SMU_MATTR(SOCKET_THM_RESIDENCY_ACC), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U64), socket_thm_residency_acc); \
+ SMU_SCALAR(SMU_MATTR(VR_THM_RESIDENCY_ACC), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U64), vr_thm_residency_acc); \
+ SMU_SCALAR(SMU_MATTR(HBM_THM_RESIDENCY_ACC), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U64), hbm_thm_residency_acc); \
+ SMU_SCALAR(SMU_MATTR(GFXCLK_LOCK_STATUS), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U32), gfxclk_lock_status); \
+ SMU_SCALAR(SMU_MATTR(PCIE_LINK_WIDTH), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U16), pcie_link_width); \
+ SMU_SCALAR(SMU_MATTR(PCIE_LINK_SPEED), SMU_MUNIT(SPEED_2), \
+ SMU_MTYPE(U16), pcie_link_speed); \
+ SMU_SCALAR(SMU_MATTR(XGMI_LINK_WIDTH), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U16), xgmi_link_width); \
+ SMU_SCALAR(SMU_MATTR(XGMI_LINK_SPEED), SMU_MUNIT(SPEED_1), \
+ SMU_MTYPE(U16), xgmi_link_speed); \
+ SMU_SCALAR(SMU_MATTR(GFX_ACTIVITY_ACC), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U64), gfx_activity_acc); \
+ SMU_SCALAR(SMU_MATTR(MEM_ACTIVITY_ACC), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U64), mem_activity_acc); \
+ SMU_ARRAY(SMU_MATTR(PCIE_BANDWIDTH_ACC), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U64), pcie_bandwidth_acc, SMU_15_0_8_MAX_MID); \
+ SMU_ARRAY(SMU_MATTR(PCIE_BANDWIDTH_INST), SMU_MUNIT(BW_1), \
+ SMU_MTYPE(U32), pcie_bandwidth_inst, SMU_15_0_8_MAX_MID); \
+ SMU_SCALAR(SMU_MATTR(PCIE_L0_TO_RECOV_COUNT_ACC), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U64), pcie_l0_to_recov_count_acc); \
+ SMU_SCALAR(SMU_MATTR(PCIE_REPLAY_COUNT_ACC), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U64), pcie_replay_count_acc); \
+ SMU_SCALAR(SMU_MATTR(PCIE_REPLAY_ROVER_COUNT_ACC), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U64), pcie_replay_rover_count_acc); \
+ SMU_SCALAR(SMU_MATTR(PCIE_NAK_SENT_COUNT_ACC), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U64), pcie_nak_sent_count_acc); \
+ SMU_SCALAR(SMU_MATTR(PCIE_NAK_RCVD_COUNT_ACC), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U64), pcie_nak_rcvd_count_acc); \
+ SMU_ARRAY(SMU_MATTR(XGMI_LINK_STATUS), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U16), xgmi_link_status, \
+ SMU_15_0_8_NUM_XGMI_LINKS); \
+ SMU_SCALAR(SMU_MATTR(XGMI_READ_DATA_ACC), SMU_MUNIT(DATA_1), \
+ SMU_MTYPE(U64), xgmi_read_data_acc); \
+ SMU_SCALAR(SMU_MATTR(XGMI_WRITE_DATA_ACC), SMU_MUNIT(DATA_1), \
+ SMU_MTYPE(U64), xgmi_write_data_acc); \
+ SMU_SCALAR(SMU_MATTR(FIRMWARE_TIMESTAMP), SMU_MUNIT(TIME_2), \
+ SMU_MTYPE(U64), firmware_timestamp); \
+ SMU_ARRAY(SMU_MATTR(CURRENT_GFXCLK), SMU_MUNIT(CLOCK_1), \
+ SMU_MTYPE(U16), current_gfxclk, SMU_15_0_8_MAX_GFX_CLKS); \
+ SMU_ARRAY(SMU_MATTR(CURRENT_SOCCLK), SMU_MUNIT(CLOCK_1), \
+ SMU_MTYPE(U16), current_socclk, SMU_15_0_8_MAX_MID); \
+ SMU_ARRAY(SMU_MATTR(CURRENT_VCLK0), SMU_MUNIT(CLOCK_1), \
+ SMU_MTYPE(U16), current_vclk0, SMU_15_0_8_MAX_VCN); \
+ SMU_ARRAY(SMU_MATTR(CURRENT_DCLK0), SMU_MUNIT(CLOCK_1), \
+ SMU_MTYPE(U16), current_dclk0, SMU_15_0_8_MAX_VCN); \
+ SMU_ARRAY(SMU_MATTR(CURRENT_UCLK), SMU_MUNIT(CLOCK_1), \
+ SMU_MTYPE(U16), current_uclk, SMU_15_0_8_MAX_AID); \
+ SMU_SCALAR(SMU_MATTR(PCIE_LC_PERF_OTHER_END_RECOVERY), \
+ SMU_MUNIT(NONE), SMU_MTYPE(U64), \
+ pcie_lc_perf_other_end_recovery); \
+ SMU_ARRAY(SMU_MATTR(GFX_BUSY_INST), SMU_MUNIT(PERCENT), \
+ SMU_MTYPE(U32), gfx_busy_inst, SMU_15_0_8_MAX_XCC); \
+ SMU_ARRAY(SMU_MATTR(JPEG_BUSY), SMU_MUNIT(PERCENT), SMU_MTYPE(U16), \
+ jpeg_busy, SMU_15_0_8_MAX_JPEG); \
+ SMU_ARRAY(SMU_MATTR(VCN_BUSY), SMU_MUNIT(PERCENT), SMU_MTYPE(U16), \
+ vcn_busy, SMU_15_0_8_MAX_VCN); \
+ SMU_ARRAY(SMU_MATTR(GFX_BUSY_ACC), SMU_MUNIT(NONE), SMU_MTYPE(U64), \
+ gfx_busy_acc, SMU_15_0_8_MAX_XCC); \
+ SMU_ARRAY(SMU_MATTR(GFX_BELOW_HOST_LIMIT_PPT_ACC), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U64), gfx_below_host_limit_ppt_acc, \
+ SMU_15_0_8_MAX_XCC); \
+ SMU_ARRAY(SMU_MATTR(GFX_BELOW_HOST_LIMIT_THM_ACC), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U64), gfx_below_host_limit_thm_acc, \
+ SMU_15_0_8_MAX_XCC); \
+ SMU_ARRAY(SMU_MATTR(GFX_LOW_UTILIZATION_ACC), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U64), gfx_low_utilization_acc, \
+ SMU_15_0_8_MAX_XCC); \
+ SMU_ARRAY(SMU_MATTR(GFX_BELOW_HOST_LIMIT_TOTAL_ACC), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U64), gfx_below_host_limit_total_acc, \
+ SMU_15_0_8_MAX_XCC);
+
+DECLARE_SMU_METRICS_CLASS(smu_v15_0_8_gpu_metrics, SMU_15_0_8_METRICS_FIELDS);
+
+/* Maximum temperature sensor counts for system metrics */
+#define SMU_15_0_8_MAX_SYSTEM_TEMP_ENTRIES 32
+#define SMU_15_0_8_MAX_NODE_TEMP_ENTRIES 12
+#define SMU_15_0_8_MAX_VR_TEMP_ENTRIES 22
+
+/* SMUv 15.0.8 GPU board temperature metrics */
+#define SMU_15_0_8_GPUBOARD_TEMP_METRICS_FIELDS(SMU_SCALAR, SMU_ARRAY) \
+ SMU_SCALAR(SMU_MATTR(ACCUMULATION_COUNTER), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U64), accumulation_counter); \
+ SMU_SCALAR(SMU_MATTR(LABEL_VERSION), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U16), label_version); \
+ SMU_SCALAR(SMU_MATTR(NODE_ID), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U16), node_id); \
+ SMU_SCALAR(SMU_MATTR(NODE_TEMP_RETIMER), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), node_temp_retimer); \
+ SMU_SCALAR(SMU_MATTR(NODE_TEMP_IBC), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), node_temp_ibc); \
+ SMU_SCALAR(SMU_MATTR(NODE_TEMP_IBC_2), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), node_temp_ibc_2); \
+ SMU_SCALAR(SMU_MATTR(NODE_TEMP_VDD18_VR), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), node_temp_vdd18_vr); \
+ SMU_SCALAR(SMU_MATTR(NODE_TEMP_04_HBM_B_VR), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), node_temp_04_hbm_b_vr); \
+ SMU_SCALAR(SMU_MATTR(NODE_TEMP_04_HBM_D_VR), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), node_temp_04_hbm_d_vr); \
+ SMU_SCALAR(SMU_MATTR(VR_TEMP_VDDCR_SOCIO_A), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), vr_temp_vddcr_socio_a); \
+ SMU_SCALAR(SMU_MATTR(VR_TEMP_VDDCR_SOCIO_C), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), vr_temp_vddcr_socio_c); \
+ SMU_SCALAR(SMU_MATTR(VR_TEMP_VDDCR_X0), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), vr_temp_vddcr_x0); \
+ SMU_SCALAR(SMU_MATTR(VR_TEMP_VDDCR_X1), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), vr_temp_vddcr_x1); \
+ SMU_SCALAR(SMU_MATTR(VR_TEMP_VDDIO_HBM_B), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), vr_temp_vddio_hbm_b); \
+ SMU_SCALAR(SMU_MATTR(VR_TEMP_VDDIO_HBM_D), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), vr_temp_vddio_hbm_d); \
+ SMU_SCALAR(SMU_MATTR(VR_TEMP_VDDIO_04_HBM_B), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), vr_temp_vddio_04_hbm_b); \
+ SMU_SCALAR(SMU_MATTR(VR_TEMP_VDDIO_04_HBM_D), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), vr_temp_vddio_04_hbm_d); \
+ SMU_SCALAR(SMU_MATTR(VR_TEMP_VDDCR_HBM_B), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), vr_temp_vddcr_hbm_b); \
+ SMU_SCALAR(SMU_MATTR(VR_TEMP_VDDCR_HBM_D), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), vr_temp_vddcr_hbm_d); \
+ SMU_SCALAR(SMU_MATTR(VR_TEMP_VDDCR_075_HBM_B), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), vr_temp_vddcr_075_hbm_b); \
+ SMU_SCALAR(SMU_MATTR(VR_TEMP_VDDCR_075_HBM_D), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), vr_temp_vddcr_075_hbm_d); \
+ SMU_SCALAR(SMU_MATTR(VR_TEMP_VDDIO_11_GTA_A), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), vr_temp_vddio_11_gta_a); \
+ SMU_SCALAR(SMU_MATTR(VR_TEMP_VDDIO_11_GTA_C), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), vr_temp_vddio_11_gta_c); \
+ SMU_SCALAR(SMU_MATTR(VR_TEMP_VDDAN_075_GTA_A), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), vr_temp_vddan_075_gta_a); \
+ SMU_SCALAR(SMU_MATTR(VR_TEMP_VDDAN_075_GTA_C), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), vr_temp_vddan_075_gta_c); \
+ SMU_SCALAR(SMU_MATTR(VR_TEMP_VDDCR_075_UCIE), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), vr_temp_vddcr_075_ucie); \
+ SMU_SCALAR(SMU_MATTR(VR_TEMP_VDDIO_065_UCIEAA), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), vr_temp_vddio_065_ucieaa); \
+ SMU_SCALAR(SMU_MATTR(VR_TEMP_VDDIO_065_UCIEAM_A), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), vr_temp_vddio_065_ucieam_a); \
+ SMU_SCALAR(SMU_MATTR(VR_TEMP_VDDIO_065_UCIEAM_C), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), vr_temp_vddio_065_ucieam_c); \
+ SMU_SCALAR(SMU_MATTR(VR_TEMP_VDDAN_075), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), vr_temp_vddan_075);
+
+DECLARE_SMU_METRICS_CLASS(smu_v15_0_8_gpuboard_temp_metrics,
+ SMU_15_0_8_GPUBOARD_TEMP_METRICS_FIELDS);
+
+/* SMUv 15.0.8 Baseboard temperature metrics - ID-based approach */
+#define SMU_15_0_8_BASEBOARD_TEMP_METRICS_FIELDS(SMU_SCALAR, SMU_ARRAY) \
+ SMU_SCALAR(SMU_MATTR(ACCUMULATION_COUNTER), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U64), accumulation_counter); \
+ SMU_SCALAR(SMU_MATTR(LABEL_VERSION), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U16), label_version); \
+ SMU_SCALAR(SMU_MATTR(NODE_ID), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U16), node_id); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_UBB_FPGA), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_ubb_fpga); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_UBB_FRONT), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_ubb_front); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_UBB_BACK), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_ubb_back); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_UBB_OAM7), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_ubb_oam7); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_UBB_IBC), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_ubb_ibc); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_UBB_UFPGA), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_ubb_ufpga); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_UBB_OAM1), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_ubb_oam1); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_OAM_0_1_HSC), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_oam_0_1_hsc); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_OAM_2_3_HSC), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_oam_2_3_hsc); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_OAM_4_5_HSC), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_oam_4_5_hsc); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_OAM_6_7_HSC), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_oam_6_7_hsc); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_UBB_FPGA_0V72_VR), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_ubb_fpga_0v72_vr); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_UBB_FPGA_3V3_VR), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_ubb_fpga_3v3_vr); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_RETIMER_0_1_2_3_1V2_VR), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_retimer_0_1_2_3_1v2_vr); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_RETIMER_4_5_6_7_1V2_VR), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_retimer_4_5_6_7_1v2_vr); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_RETIMER_0_1_0V9_VR), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_retimer_0_1_0v9_vr); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_RETIMER_4_5_0V9_VR), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_retimer_4_5_0v9_vr); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_RETIMER_2_3_0V9_VR), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_retimer_2_3_0v9_vr); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_RETIMER_6_7_0V9_VR), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_retimer_6_7_0v9_vr); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_OAM_0_1_2_3_3V3_VR), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_oam_0_1_2_3_3v3_vr); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_OAM_4_5_6_7_3V3_VR), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_oam_4_5_6_7_3v3_vr); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_IBC_HSC), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_ibc_hsc); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_IBC), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_ibc);
+
+DECLARE_SMU_METRICS_CLASS(smu_v15_0_8_baseboard_temp_metrics,
+ SMU_15_0_8_BASEBOARD_TEMP_METRICS_FIELDS);
+#endif
+#endif
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
index 326c86b920a2..7bd8c435466a 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
@@ -1035,6 +1035,31 @@ int smu_cmn_get_smc_version(struct smu_context *smu,
return ret;
}
+int smu_cmn_check_fw_version(struct smu_context *smu)
+{
+ struct amdgpu_device *adev = smu->adev;
+ uint32_t if_version = 0xff, smu_version = 0xff;
+ uint8_t smu_program, smu_major, smu_minor, smu_debug;
+ int ret;
+
+ ret = smu_cmn_get_smc_version(smu, &if_version, &smu_version);
+ if (ret)
+ return ret;
+
+ smu_program = (smu_version >> 24) & 0xff;
+ smu_major = (smu_version >> 16) & 0xff;
+ smu_minor = (smu_version >> 8) & 0xff;
+ smu_debug = (smu_version >> 0) & 0xff;
+ adev->pm.fw_version = smu_version;
+
+ dev_info_once(adev->dev, "smu driver if version = 0x%08x, smu fw if version = 0x%08x, "
+ "smu fw program = %d, smu fw version = 0x%08x (%d.%d.%d)\n",
+ smu->smc_driver_if_version, if_version,
+ smu_program, smu_version, smu_major, smu_minor, smu_debug);
+
+ return 0;
+}
+
int smu_cmn_update_table(struct smu_context *smu,
enum smu_table_id table_index,
int argument,
@@ -1276,6 +1301,16 @@ void smu_cmn_get_backend_workload_mask(struct smu_context *smu,
}
}
+void smu_cmn_reset_custom_level(struct smu_context *smu)
+{
+ struct smu_umd_pstate_table *pstate_table = &smu->pstate_table;
+
+ pstate_table->gfxclk_pstate.custom.min = 0;
+ pstate_table->gfxclk_pstate.custom.max = 0;
+ pstate_table->uclk_pstate.custom.min = 0;
+ pstate_table->uclk_pstate.custom.max = 0;
+}
+
static inline bool smu_cmn_freqs_match(uint32_t freq1, uint32_t freq2)
{
/* Frequencies within 25 MHz are considered equal */
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
index b7bfddc65fb2..b76e86df5da7 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
@@ -204,9 +204,11 @@ int smu_cmn_print_pcie_levels(struct smu_context *smu,
struct smu_pcie_table *pcie_table,
uint32_t cur_gen, uint32_t cur_lane,
char *buf, int *offset);
+void smu_cmn_reset_custom_level(struct smu_context *smu);
int smu_cmn_dpm_pcie_gen_idx(int gen);
int smu_cmn_dpm_pcie_width_idx(int width);
+int smu_cmn_check_fw_version(struct smu_context *smu);
/*SMU gpu metrics */
diff --git a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.c b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.c
index 4b86a58e8149..d213eea71cff 100644
--- a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.c
+++ b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.c
@@ -535,6 +535,37 @@ int amdgpu_ras_mgr_handle_controller_interrupt(struct amdgpu_device *adev, void
return ret;
}
+int amdgpu_ras_mgr_dispatch_interrupt(struct amdgpu_device *adev, struct ras_ih_info *ih_info)
+{
+ struct amdgpu_ras_mgr *ras_mgr = amdgpu_ras_mgr_get_context(adev);
+ uint64_t seq_no = 0;
+ int ret = 0;
+
+ if (!amdgpu_ras_mgr_is_ready(adev))
+ return -EPERM;
+
+ if (!ih_info)
+ return 0;
+
+ if (ih_info->block == RAS_BLOCK_ID__UMC) {
+ if (ras_mgr->ras_core->poison_supported) {
+ seq_no = amdgpu_ras_mgr_gen_ras_event_seqno(adev, RAS_SEQNO_TYPE_DE);
+ RAS_DEV_INFO(adev,
+ "{%llu} RAS poison is created, no user action is needed.\n",
+ seq_no);
+ }
+
+ ret = amdgpu_ras_process_handle_umc_interrupt(adev, ih_info);
+ } else if (ras_mgr->ras_core->poison_supported) {
+ ret = amdgpu_ras_process_handle_consumption_interrupt(adev, ih_info);
+ } else {
+ RAS_DEV_WARN(adev,
+ "No RAS interrupt handler for non-UMC block with poison disabled.\n");
+ }
+
+ return ret;
+}
+
int amdgpu_ras_mgr_handle_consumer_interrupt(struct amdgpu_device *adev, void *data)
{
if (!amdgpu_ras_mgr_is_ready(adev))
diff --git a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.h b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.h
index 23c411c98231..4f44a917d48b 100644
--- a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.h
+++ b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.h
@@ -67,6 +67,7 @@ bool amdgpu_uniras_enabled(struct amdgpu_device *adev);
int amdgpu_ras_mgr_handle_fatal_interrupt(struct amdgpu_device *adev, void *data);
int amdgpu_ras_mgr_handle_controller_interrupt(struct amdgpu_device *adev, void *data);
int amdgpu_ras_mgr_handle_consumer_interrupt(struct amdgpu_device *adev, void *data);
+int amdgpu_ras_mgr_dispatch_interrupt(struct amdgpu_device *adev, struct ras_ih_info *ih_info);
int amdgpu_ras_mgr_update_ras_ecc(struct amdgpu_device *adev);
int amdgpu_ras_mgr_reset_gpu(struct amdgpu_device *adev, uint32_t flags);
uint64_t amdgpu_ras_mgr_gen_ras_event_seqno(struct amdgpu_device *adev,
diff --git a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_process.c b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_process.c
index 5782c007de71..285d81a85a99 100644
--- a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_process.c
+++ b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_process.c
@@ -103,6 +103,16 @@ int amdgpu_ras_process_handle_consumption_interrupt(struct amdgpu_device *adev,
if (!ih_info)
return -EINVAL;
+ if (amdgpu_sriov_vf(adev)) {
+ if (adev->virt.ops && adev->virt.ops->ras_poison_handler)
+ adev->virt.ops->ras_poison_handler(adev, ih_info->block);
+ else
+ dev_warn(adev->dev,
+ "No ras_poison_handler interface in SRIOV for block[%d]!\n",
+ ih_info->block);
+ return 0;
+ }
+
memset(&req, 0, sizeof(req));
req.block = ih_info->block;
req.data = ih_info->data;
diff --git a/drivers/gpu/drm/amd/ras/rascore/ras_core.c b/drivers/gpu/drm/amd/ras/rascore/ras_core.c
index bbf13c076a94..49b3aa7489ff 100644
--- a/drivers/gpu/drm/amd/ras/rascore/ras_core.c
+++ b/drivers/gpu/drm/amd/ras/rascore/ras_core.c
@@ -69,6 +69,9 @@ int ras_core_convert_timestamp_to_time(struct ras_core_context *ras_core,
int seconds_per_minute = 60;
int days, remaining_seconds;
+ if (!tm)
+ return -EINVAL;
+
days = div64_u64_rem(timestamp, seconds_per_day, &remainder);
/* remainder will always be less than seconds_per_day. */
remaining_seconds = remainder;
@@ -116,6 +119,9 @@ bool ras_core_gpu_in_reset(struct ras_core_context *ras_core)
{
uint32_t status = 0;
+ if (!ras_core)
+ return false;
+
if (ras_core->sys_fn &&
ras_core->sys_fn->check_gpu_status)
ras_core->sys_fn->check_gpu_status(ras_core, &status);
@@ -127,6 +133,9 @@ bool ras_core_gpu_is_vf(struct ras_core_context *ras_core)
{
uint32_t status = 0;
+ if (!ras_core)
+ return false;
+
if (ras_core->sys_fn &&
ras_core->sys_fn->check_gpu_status)
ras_core->sys_fn->check_gpu_status(ras_core, &status);
@@ -271,6 +280,9 @@ struct ras_core_context *ras_core_create(struct ras_core_config *init_config)
struct ras_core_context *ras_core;
struct ras_core_config *config;
+ if (!init_config)
+ return NULL;
+
ras_core = kzalloc_obj(*ras_core);
if (!ras_core)
return NULL;
@@ -479,6 +491,9 @@ int ras_core_handle_fatal_error(struct ras_core_context *ras_core)
uint32_t ras_core_get_curr_nps_mode(struct ras_core_context *ras_core)
{
+ if (!ras_core)
+ return 0;
+
if (ras_core->ras_nbio.ip_func &&
ras_core->ras_nbio.ip_func->get_memory_partition_mode)
return ras_core->ras_nbio.ip_func->get_memory_partition_mode(ras_core);
@@ -527,8 +542,11 @@ bool ras_core_is_enabled(struct ras_core_context *ras_core)
uint64_t ras_core_get_utc_second_timestamp(struct ras_core_context *ras_core)
{
- if (ras_core && ras_core->sys_fn &&
- ras_core->sys_fn->get_utc_second_timestamp)
+ if (!ras_core)
+ return 0;
+
+ if (ras_core->sys_fn &&
+ ras_core->sys_fn->get_utc_second_timestamp)
return ras_core->sys_fn->get_utc_second_timestamp(ras_core);
RAS_DEV_ERR(ras_core->dev, "Failed to get system timestamp!\n");
@@ -550,13 +568,17 @@ bool ras_core_ras_interrupt_detected(struct ras_core_context *ras_core)
ras_core->sys_fn->detect_ras_interrupt)
return ras_core->sys_fn->detect_ras_interrupt(ras_core);
- RAS_DEV_ERR(ras_core->dev, "Failed to detect ras interrupt!\n");
+ if (ras_core && ras_core->dev)
+ RAS_DEV_ERR(ras_core->dev, "Failed to detect ras interrupt!\n");
+
return false;
}
int ras_core_get_gpu_mem(struct ras_core_context *ras_core,
enum gpu_mem_type mem_type, struct gpu_mem_block *gpu_mem)
{
+ if (!ras_core || !gpu_mem)
+ return -EINVAL;
if (ras_core->sys_fn && ras_core->sys_fn->get_gpu_mem)
return ras_core->sys_fn->get_gpu_mem(ras_core, mem_type, gpu_mem);
@@ -567,6 +589,8 @@ int ras_core_get_gpu_mem(struct ras_core_context *ras_core,
int ras_core_put_gpu_mem(struct ras_core_context *ras_core,
enum gpu_mem_type mem_type, struct gpu_mem_block *gpu_mem)
{
+ if (!ras_core || !gpu_mem)
+ return -EINVAL;
if (ras_core->sys_fn && ras_core->sys_fn->put_gpu_mem)
return ras_core->sys_fn->put_gpu_mem(ras_core, mem_type, gpu_mem);
@@ -620,6 +644,9 @@ int ras_core_event_notify(struct ras_core_context *ras_core,
int ras_core_get_device_system_info(struct ras_core_context *ras_core,
struct device_system_info *dev_info)
{
+ if (!dev_info)
+ return -EINVAL;
+
if (ras_core && ras_core->sys_fn &&
ras_core->sys_fn->get_device_system_info)
return ras_core->sys_fn->get_device_system_info(ras_core, dev_info);
diff --git a/drivers/gpu/drm/amd/ras/rascore/ras_umc.c b/drivers/gpu/drm/amd/ras/rascore/ras_umc.c
index 23118f41eb96..c7ae005ea705 100644
--- a/drivers/gpu/drm/amd/ras/rascore/ras_umc.c
+++ b/drivers/gpu/drm/amd/ras/rascore/ras_umc.c
@@ -222,7 +222,7 @@ int ras_umc_log_pending_bad_bank(struct ras_core_context *ras_core)
mutex_lock(&ras_umc->pending_ecc_lock);
list_for_each_entry_safe(ecc_node,
tmp, &ras_umc->pending_ecc_list, node){
- if (ecc_node && !ras_umc_log_bad_bank(ras_core, &ecc_node->ecc)) {
+ if (!ras_umc_log_bad_bank(ras_core, &ecc_node->ecc)) {
list_del(&ecc_node->node);
kfree(ecc_node);
}
diff --git a/drivers/gpu/drm/arm/display/include/malidp_product.h b/drivers/gpu/drm/arm/display/include/malidp_product.h
index 16a8a2c22c42..6f954bcdf40e 100644
--- a/drivers/gpu/drm/arm/display/include/malidp_product.h
+++ b/drivers/gpu/drm/arm/display/include/malidp_product.h
@@ -20,6 +20,7 @@
/* Mali-display product IDs */
#define MALIDP_D71_PRODUCT_ID 0x0071
#define MALIDP_D32_PRODUCT_ID 0x0032
+#define LINLONDP_D6_PRODUCT_ID 0x0060
union komeda_config_id {
struct {
diff --git a/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c b/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
index 67e5d3b4190f..27ca2930cdac 100644
--- a/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
+++ b/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
@@ -1080,11 +1080,11 @@ static void d71_improc_update(struct komeda_component *c,
mask |= IPS_CTRL_YUV | IPS_CTRL_CHD422 | IPS_CTRL_CHD420;
/* config color format */
- if (st->color_format == DRM_COLOR_FORMAT_YCBCR420)
+ if (st->color_format == DRM_OUTPUT_COLOR_FORMAT_YCBCR420)
ctrl |= IPS_CTRL_YUV | IPS_CTRL_CHD422 | IPS_CTRL_CHD420;
- else if (st->color_format == DRM_COLOR_FORMAT_YCBCR422)
+ else if (st->color_format == DRM_OUTPUT_COLOR_FORMAT_YCBCR422)
ctrl |= IPS_CTRL_YUV | IPS_CTRL_CHD422;
- else if (st->color_format == DRM_COLOR_FORMAT_YCBCR444)
+ else if (st->color_format == DRM_OUTPUT_COLOR_FORMAT_YCBCR444)
ctrl |= IPS_CTRL_YUV;
malidp_write32_mask(reg, BLK_CONTROL, mask, ctrl);
@@ -1145,12 +1145,12 @@ static int d71_improc_init(struct d71_dev *d71,
improc = to_improc(c);
improc->supported_color_depths = BIT(8) | BIT(10);
- improc->supported_color_formats = DRM_COLOR_FORMAT_RGB444 |
- DRM_COLOR_FORMAT_YCBCR444 |
- DRM_COLOR_FORMAT_YCBCR422;
+ improc->supported_color_formats = BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444) |
+ BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444) |
+ BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422);
value = malidp_read32(reg, BLK_INFO);
if (value & IPS_INFO_CHD420)
- improc->supported_color_formats |= DRM_COLOR_FORMAT_YCBCR420;
+ improc->supported_color_formats |= BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420);
improc->supports_csc = true;
improc->supports_gamma = true;
diff --git a/drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c b/drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c
index 80973975bfdb..f105e3a2dce2 100644
--- a/drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c
+++ b/drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c
@@ -628,6 +628,7 @@ d71_identify(u32 __iomem *reg_base, struct komeda_chip_info *chip)
switch (product_id) {
case MALIDP_D71_PRODUCT_ID:
case MALIDP_D32_PRODUCT_ID:
+ case LINLONDP_D6_PRODUCT_ID:
funcs = &d71_chip_funcs;
break;
default:
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
index 9c8b8da531a7..714af5c889d7 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
@@ -40,7 +40,7 @@ void komeda_crtc_get_color_config(struct drm_crtc_state *crtc_st,
/* connector doesn't config any color_format, use RGB444 as default */
if (!conn_color_formats)
- conn_color_formats = DRM_COLOR_FORMAT_RGB444;
+ conn_color_formats = BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444);
*color_depths = GENMASK(min_bpc, 0);
*color_formats = conn_color_formats;
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_drv.c b/drivers/gpu/drm/arm/display/komeda/komeda_drv.c
index 358c1512b087..4bb5f250e95e 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_drv.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_drv.c
@@ -104,6 +104,7 @@ free_mdrv:
static const struct of_device_id komeda_of_match[] = {
{ .compatible = "arm,mali-d71", .data = d71_identify, },
{ .compatible = "arm,mali-d32", .data = d71_identify, },
+ { .compatible = "armchina,linlon-d6", .data = d71_identify, },
{},
};
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h
index 37b9e9220244..bbee6da43164 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h
@@ -319,7 +319,7 @@ struct komeda_splitter_state {
struct komeda_improc {
struct komeda_component base;
- u32 supported_color_formats; /* DRM_RGB/YUV444/YUV420*/
+ u32 supported_color_formats; /* BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444/YUV444/YUV420) */
u32 supported_color_depths; /* BIT(8) | BIT(10)*/
u8 supports_degamma : 1;
u8 supports_csc : 1;
@@ -328,7 +328,8 @@ struct komeda_improc {
struct komeda_improc_state {
struct komeda_component_state base;
- u8 color_format, color_depth;
+ enum drm_output_color_format color_format;
+ u8 color_depth;
u16 hsize, vsize;
u32 fgamma_coeffs[KOMEDA_N_GAMMA_COEFFS];
u32 ctm_coeffs[KOMEDA_N_CTM_COEFFS];
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c
index f4e76b46ca32..6f9b10cc831f 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c
@@ -799,7 +799,7 @@ komeda_improc_validate(struct komeda_improc *improc,
}
st->color_depth = __fls(avail_depths);
- st->color_format = BIT(__ffs(avail_formats));
+ st->color_format = __ffs(avail_formats);
}
if (kcrtc_st->base.color_mgmt_changed) {
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_private_obj.c b/drivers/gpu/drm/arm/display/komeda/komeda_private_obj.c
index 49b934c6dbdf..77b3f361091f 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_private_obj.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_private_obj.c
@@ -65,7 +65,7 @@ static const struct drm_private_state_funcs komeda_layer_obj_funcs = {
static int komeda_layer_obj_add(struct komeda_kms_dev *kms,
struct komeda_layer *layer)
{
- drm_atomic_private_obj_init(&kms->base, &layer->base.obj, NULL,
+ drm_atomic_private_obj_init(&kms->base, &layer->base.obj,
&komeda_layer_obj_funcs);
return 0;
}
@@ -118,7 +118,7 @@ static int komeda_scaler_obj_add(struct komeda_kms_dev *kms,
struct komeda_scaler *scaler)
{
drm_atomic_private_obj_init(&kms->base,
- &scaler->base.obj, NULL,
+ &scaler->base.obj,
&komeda_scaler_obj_funcs);
return 0;
}
@@ -170,7 +170,7 @@ static const struct drm_private_state_funcs komeda_compiz_obj_funcs = {
static int komeda_compiz_obj_add(struct komeda_kms_dev *kms,
struct komeda_compiz *compiz)
{
- drm_atomic_private_obj_init(&kms->base, &compiz->base.obj, NULL,
+ drm_atomic_private_obj_init(&kms->base, &compiz->base.obj,
&komeda_compiz_obj_funcs);
return 0;
@@ -224,7 +224,7 @@ static int komeda_splitter_obj_add(struct komeda_kms_dev *kms,
struct komeda_splitter *splitter)
{
drm_atomic_private_obj_init(&kms->base,
- &splitter->base.obj, NULL,
+ &splitter->base.obj,
&komeda_splitter_obj_funcs);
return 0;
@@ -277,7 +277,7 @@ static int komeda_merger_obj_add(struct komeda_kms_dev *kms,
struct komeda_merger *merger)
{
drm_atomic_private_obj_init(&kms->base,
- &merger->base.obj, NULL,
+ &merger->base.obj,
&komeda_merger_obj_funcs);
return 0;
@@ -330,7 +330,7 @@ static const struct drm_private_state_funcs komeda_improc_obj_funcs = {
static int komeda_improc_obj_add(struct komeda_kms_dev *kms,
struct komeda_improc *improc)
{
- drm_atomic_private_obj_init(&kms->base, &improc->base.obj, NULL,
+ drm_atomic_private_obj_init(&kms->base, &improc->base.obj,
&komeda_improc_obj_funcs);
return 0;
@@ -383,7 +383,7 @@ static const struct drm_private_state_funcs komeda_timing_ctrlr_obj_funcs = {
static int komeda_timing_ctrlr_obj_add(struct komeda_kms_dev *kms,
struct komeda_timing_ctrlr *ctrlr)
{
- drm_atomic_private_obj_init(&kms->base, &ctrlr->base.obj, NULL,
+ drm_atomic_private_obj_init(&kms->base, &ctrlr->base.obj,
&komeda_timing_ctrlr_obj_funcs);
return 0;
@@ -437,7 +437,7 @@ static const struct drm_private_state_funcs komeda_pipeline_obj_funcs = {
static int komeda_pipeline_obj_add(struct komeda_kms_dev *kms,
struct komeda_pipeline *pipe)
{
- drm_atomic_private_obj_init(&kms->base, &pipe->obj, NULL,
+ drm_atomic_private_obj_init(&kms->base, &pipe->obj,
&komeda_pipeline_obj_funcs);
return 0;
diff --git a/drivers/gpu/drm/ast/ast_dp501.c b/drivers/gpu/drm/ast/ast_dp501.c
index 9e19d8c17730..677c52c0d99a 100644
--- a/drivers/gpu/drm/ast/ast_dp501.c
+++ b/drivers/gpu/drm/ast/ast_dp501.c
@@ -436,7 +436,7 @@ static void ast_init_analog(struct ast_device *ast)
/* Finally, clear bits [17:16] of SCU2c */
data = ast_read32(ast, 0x1202c);
data &= 0xfffcffff;
- ast_write32(ast, 0, data);
+ ast_write32(ast, 0x1202c, data);
/* Disable DVO */
ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xa3, 0xcf, 0x00);
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index 1cabfa1d2b2e..c3209b0f4678 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -191,6 +191,17 @@ config DRM_LONTIUM_LT9611UXC
HDMI signals
Please say Y if you have such hardware.
+config DRM_LONTIUM_LT8713SX
+ tristate "Lontium LT8713SX DP MST bridge"
+ depends on OF
+ select CRC8
+ select REGMAP_I2C
+ help
+ Driver for Lontium LT8713SX DP MST bridge
+ chip firmware upgrade, which converts Type-C/DP1.4
+ to 3 configurable Type-C/DP1.4/HDMI2.0 outputs
+ Please say Y if you have such hardware.
+
config DRM_ITE_IT66121
tristate "ITE IT66121 HDMI bridge"
depends on OF
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index fb0cf0bf8875..beab5b695a6e 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_DRM_LONTIUM_LT8912B) += lontium-lt8912b.o
obj-$(CONFIG_DRM_LONTIUM_LT9211) += lontium-lt9211.o
obj-$(CONFIG_DRM_LONTIUM_LT9611) += lontium-lt9611.o
obj-$(CONFIG_DRM_LONTIUM_LT9611UXC) += lontium-lt9611uxc.o
+obj-$(CONFIG_DRM_LONTIUM_LT8713SX) += lontium-lt8713sx.o
obj-$(CONFIG_DRM_LVDS_CODEC) += lvds-codec.o
obj-$(CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW) += megachips-stdpxxxx-ge-b850v3-fw.o
obj-$(CONFIG_DRM_MICROCHIP_LVDS_SERIALIZER) += microchip-lvds.o
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
index 1050bb62280b..6bd76c1fb007 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
@@ -228,7 +228,7 @@ static void adv7511_set_config_csc(struct adv7511 *adv7511,
config.csc_coefficents = adv7511_csc_ycbcr_to_rgb;
if ((connector->display_info.color_formats &
- DRM_COLOR_FORMAT_YCBCR422) &&
+ BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422)) &&
connector->display_info.is_hdmi) {
config.csc_enable = false;
output_format_422 = true;
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index b1687a4aa047..8dee5f2fbde5 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -281,77 +281,14 @@ static int analogix_dp_link_start(struct analogix_dp_device *dp)
if (retval < 0)
return retval;
- for (lane = 0; lane < lane_count; lane++)
- buf[lane] = DP_TRAIN_PRE_EMPH_LEVEL_0 |
- DP_TRAIN_VOLTAGE_SWING_LEVEL_0;
-
- retval = drm_dp_dpcd_write(&dp->aux, DP_TRAINING_LANE0_SET, buf,
- lane_count);
+ retval = drm_dp_dpcd_write(&dp->aux, DP_TRAINING_LANE0_SET,
+ dp->link_train.training_lane, lane_count);
if (retval < 0)
return retval;
return 0;
}
-static unsigned char analogix_dp_get_lane_status(u8 link_status[2], int lane)
-{
- int shift = (lane & 1) * 4;
- u8 link_value = link_status[lane >> 1];
-
- return (link_value >> shift) & 0xf;
-}
-
-static int analogix_dp_clock_recovery_ok(u8 link_status[2], int lane_count)
-{
- int lane;
- u8 lane_status;
-
- for (lane = 0; lane < lane_count; lane++) {
- lane_status = analogix_dp_get_lane_status(link_status, lane);
- if ((lane_status & DP_LANE_CR_DONE) == 0)
- return -EINVAL;
- }
- return 0;
-}
-
-static int analogix_dp_channel_eq_ok(u8 link_status[2], u8 link_align,
- int lane_count)
-{
- int lane;
- u8 lane_status;
-
- if ((link_align & DP_INTERLANE_ALIGN_DONE) == 0)
- return -EINVAL;
-
- for (lane = 0; lane < lane_count; lane++) {
- lane_status = analogix_dp_get_lane_status(link_status, lane);
- lane_status &= DP_CHANNEL_EQ_BITS;
- if (lane_status != DP_CHANNEL_EQ_BITS)
- return -EINVAL;
- }
-
- return 0;
-}
-
-static unsigned char
-analogix_dp_get_adjust_request_voltage(u8 adjust_request[2], int lane)
-{
- int shift = (lane & 1) * 4;
- u8 link_value = adjust_request[lane >> 1];
-
- return (link_value >> shift) & 0x3;
-}
-
-static unsigned char analogix_dp_get_adjust_request_pre_emphasis(
- u8 adjust_request[2],
- int lane)
-{
- int shift = (lane & 1) * 4;
- u8 link_value = adjust_request[lane >> 1];
-
- return ((link_value >> shift) & 0xc) >> 2;
-}
-
static void analogix_dp_reduce_link_rate(struct analogix_dp_device *dp)
{
analogix_dp_training_pattern_dis(dp);
@@ -361,17 +298,15 @@ static void analogix_dp_reduce_link_rate(struct analogix_dp_device *dp)
}
static void analogix_dp_get_adjust_training_lane(struct analogix_dp_device *dp,
- u8 adjust_request[2])
+ u8 link_status[DP_LINK_STATUS_SIZE])
{
int lane, lane_count;
u8 voltage_swing, pre_emphasis, training_lane;
lane_count = dp->link_train.lane_count;
for (lane = 0; lane < lane_count; lane++) {
- voltage_swing = analogix_dp_get_adjust_request_voltage(
- adjust_request, lane);
- pre_emphasis = analogix_dp_get_adjust_request_pre_emphasis(
- adjust_request, lane);
+ voltage_swing = drm_dp_get_adjust_request_voltage(link_status, lane);
+ pre_emphasis = drm_dp_get_adjust_request_pre_emphasis(link_status, lane);
training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
DPCD_PRE_EMPHASIS_SET(pre_emphasis);
@@ -388,17 +323,17 @@ static int analogix_dp_process_clock_recovery(struct analogix_dp_device *dp)
{
int lane, lane_count, retval;
u8 voltage_swing, pre_emphasis, training_lane;
- u8 link_status[2], adjust_request[2];
+ u8 link_status[DP_LINK_STATUS_SIZE];
usleep_range(100, 101);
lane_count = dp->link_train.lane_count;
- retval = drm_dp_dpcd_read(&dp->aux, DP_LANE0_1_STATUS, link_status, 2);
+ retval = drm_dp_dpcd_read_link_status(&dp->aux, link_status);
if (retval < 0)
return retval;
- if (analogix_dp_clock_recovery_ok(link_status, lane_count) == 0) {
+ if (drm_dp_clock_recovery_ok(link_status, lane_count)) {
/* set training pattern 2 for EQ */
analogix_dp_set_training_pattern(dp, TRAINING_PTN2);
@@ -414,15 +349,10 @@ static int analogix_dp_process_clock_recovery(struct analogix_dp_device *dp)
return 0;
}
- retval = drm_dp_dpcd_read(&dp->aux, DP_ADJUST_REQUEST_LANE0_1,
- adjust_request, 2);
- if (retval < 0)
- return retval;
-
for (lane = 0; lane < lane_count; lane++) {
training_lane = analogix_dp_get_lane_link_training(dp, lane);
- voltage_swing = analogix_dp_get_adjust_request_voltage(adjust_request, lane);
- pre_emphasis = analogix_dp_get_adjust_request_pre_emphasis(adjust_request, lane);
+ voltage_swing = drm_dp_get_adjust_request_voltage(link_status, lane);
+ pre_emphasis = drm_dp_get_adjust_request_pre_emphasis(link_status, lane);
if (DPCD_VOLTAGE_SWING_GET(training_lane) == voltage_swing &&
DPCD_PRE_EMPHASIS_GET(training_lane) == pre_emphasis)
@@ -439,7 +369,7 @@ static int analogix_dp_process_clock_recovery(struct analogix_dp_device *dp)
}
}
- analogix_dp_get_adjust_training_lane(dp, adjust_request);
+ analogix_dp_get_adjust_training_lane(dp, link_status);
analogix_dp_set_lane_link_training(dp);
retval = drm_dp_dpcd_write(&dp->aux, DP_TRAINING_LANE0_SET,
@@ -454,34 +384,24 @@ static int analogix_dp_process_equalizer_training(struct analogix_dp_device *dp)
{
int lane_count, retval;
u32 reg;
- u8 link_align, link_status[2], adjust_request[2];
+ u8 link_status[DP_LINK_STATUS_SIZE];
usleep_range(400, 401);
lane_count = dp->link_train.lane_count;
- retval = drm_dp_dpcd_read(&dp->aux, DP_LANE0_1_STATUS, link_status, 2);
+ retval = drm_dp_dpcd_read_link_status(&dp->aux, link_status);
if (retval < 0)
return retval;
- if (analogix_dp_clock_recovery_ok(link_status, lane_count)) {
+ if (!drm_dp_clock_recovery_ok(link_status, lane_count)) {
analogix_dp_reduce_link_rate(dp);
return -EIO;
}
- retval = drm_dp_dpcd_read(&dp->aux, DP_ADJUST_REQUEST_LANE0_1,
- adjust_request, 2);
- if (retval < 0)
- return retval;
-
- retval = drm_dp_dpcd_readb(&dp->aux, DP_LANE_ALIGN_STATUS_UPDATED,
- &link_align);
- if (retval < 0)
- return retval;
-
- analogix_dp_get_adjust_training_lane(dp, adjust_request);
+ analogix_dp_get_adjust_training_lane(dp, link_status);
- if (!analogix_dp_channel_eq_ok(link_status, link_align, lane_count)) {
+ if (drm_dp_channel_eq_ok(link_status, lane_count)) {
/* traing pattern Set to Normal */
retval = analogix_dp_training_pattern_dis(dp);
if (retval < 0)
@@ -619,7 +539,7 @@ static int analogix_dp_full_link_train(struct analogix_dp_device *dp,
static int analogix_dp_fast_link_train(struct analogix_dp_device *dp)
{
int ret;
- u8 link_align, link_status[2];
+ u8 link_status[DP_LINK_STATUS_SIZE];
analogix_dp_set_link_bandwidth(dp, dp->link_train.link_rate);
ret = analogix_dp_wait_pll_locked(dp);
@@ -653,31 +573,20 @@ static int analogix_dp_fast_link_train(struct analogix_dp_device *dp)
* speed
*/
if (verify_fast_training) {
- ret = drm_dp_dpcd_readb(&dp->aux, DP_LANE_ALIGN_STATUS_UPDATED,
- &link_align);
- if (ret < 0) {
- DRM_DEV_ERROR(dp->dev, "Read align status failed %d\n",
- ret);
- return ret;
- }
-
- ret = drm_dp_dpcd_read(&dp->aux, DP_LANE0_1_STATUS, link_status,
- 2);
+ ret = drm_dp_dpcd_read_link_status(&dp->aux, link_status);
if (ret < 0) {
DRM_DEV_ERROR(dp->dev, "Read link status failed %d\n",
ret);
return ret;
}
- if (analogix_dp_clock_recovery_ok(link_status,
- dp->link_train.lane_count)) {
+ if (!drm_dp_clock_recovery_ok(link_status, dp->link_train.lane_count)) {
DRM_DEV_ERROR(dp->dev, "Clock recovery failed\n");
analogix_dp_reduce_link_rate(dp);
return -EIO;
}
- if (analogix_dp_channel_eq_ok(link_status, link_align,
- dp->link_train.lane_count)) {
+ if (!drm_dp_channel_eq_ok(link_status, dp->link_train.lane_count)) {
DRM_DEV_ERROR(dp->dev, "Channel EQ failed\n");
analogix_dp_reduce_link_rate(dp);
return -EIO;
@@ -1223,9 +1132,9 @@ static void analogix_dp_bridge_mode_set(struct drm_bridge *bridge,
video->color_depth = COLOR_8;
break;
}
- if (display_info->color_formats & DRM_COLOR_FORMAT_YCBCR444)
+ if (display_info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444))
video->color_space = COLOR_YCBCR444;
- else if (display_info->color_formats & DRM_COLOR_FORMAT_YCBCR422)
+ else if (display_info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422))
video->color_space = COLOR_YCBCR422;
else
video->color_space = COLOR_RGB;
diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
index 945bb47c172b..064c6915c896 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
@@ -1448,14 +1448,14 @@ static u32 cdns_mhdp_get_bpp(struct cdns_mhdp_display_fmt *fmt)
return fmt->bpc;
switch (fmt->color_format) {
- case DRM_COLOR_FORMAT_RGB444:
- case DRM_COLOR_FORMAT_YCBCR444:
+ case DRM_OUTPUT_COLOR_FORMAT_RGB444:
+ case DRM_OUTPUT_COLOR_FORMAT_YCBCR444:
bpp = fmt->bpc * 3;
break;
- case DRM_COLOR_FORMAT_YCBCR422:
+ case DRM_OUTPUT_COLOR_FORMAT_YCBCR422:
bpp = fmt->bpc * 2;
break;
- case DRM_COLOR_FORMAT_YCBCR420:
+ case DRM_OUTPUT_COLOR_FORMAT_YCBCR420:
bpp = fmt->bpc * 3 / 2;
break;
default:
@@ -1552,26 +1552,26 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp,
* If YCBCR supported and stream not SD, use ITU709
* Need to handle ITU version with YCBCR420 when supported
*/
- if ((pxlfmt == DRM_COLOR_FORMAT_YCBCR444 ||
- pxlfmt == DRM_COLOR_FORMAT_YCBCR422) && mode->crtc_vdisplay >= 720)
+ if ((pxlfmt == DRM_OUTPUT_COLOR_FORMAT_YCBCR444 ||
+ pxlfmt == DRM_OUTPUT_COLOR_FORMAT_YCBCR422) && mode->crtc_vdisplay >= 720)
misc0 = DP_YCBCR_COEFFICIENTS_ITU709;
bpp = cdns_mhdp_get_bpp(&mhdp->display_fmt);
switch (pxlfmt) {
- case DRM_COLOR_FORMAT_RGB444:
+ case DRM_OUTPUT_COLOR_FORMAT_RGB444:
pxl_repr = CDNS_DP_FRAMER_RGB << CDNS_DP_FRAMER_PXL_FORMAT;
misc0 |= DP_COLOR_FORMAT_RGB;
break;
- case DRM_COLOR_FORMAT_YCBCR444:
+ case DRM_OUTPUT_COLOR_FORMAT_YCBCR444:
pxl_repr = CDNS_DP_FRAMER_YCBCR444 << CDNS_DP_FRAMER_PXL_FORMAT;
misc0 |= DP_COLOR_FORMAT_YCbCr444 | DP_TEST_DYNAMIC_RANGE_CEA;
break;
- case DRM_COLOR_FORMAT_YCBCR422:
+ case DRM_OUTPUT_COLOR_FORMAT_YCBCR422:
pxl_repr = CDNS_DP_FRAMER_YCBCR422 << CDNS_DP_FRAMER_PXL_FORMAT;
misc0 |= DP_COLOR_FORMAT_YCbCr422 | DP_TEST_DYNAMIC_RANGE_CEA;
break;
- case DRM_COLOR_FORMAT_YCBCR420:
+ case DRM_OUTPUT_COLOR_FORMAT_YCBCR420:
pxl_repr = CDNS_DP_FRAMER_YCBCR420 << CDNS_DP_FRAMER_PXL_FORMAT;
break;
default:
@@ -1667,7 +1667,7 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp,
if (mhdp->display_fmt.y_only)
misc1 |= CDNS_DP_TEST_COLOR_FORMAT_RAW_Y_ONLY;
/* Use VSC SDP for Y420 */
- if (pxlfmt == DRM_COLOR_FORMAT_YCBCR420)
+ if (pxlfmt == DRM_OUTPUT_COLOR_FORMAT_YCBCR420)
misc1 = CDNS_DP_TEST_VSC_SDP;
cdns_mhdp_reg_write(mhdp, CDNS_DP_MSA_MISC(stream_id),
@@ -2356,7 +2356,7 @@ static int cdns_mhdp_probe(struct platform_device *pdev)
/* The only currently supported format */
mhdp->display_fmt.y_only = false;
- mhdp->display_fmt.color_format = DRM_COLOR_FORMAT_RGB444;
+ mhdp->display_fmt.color_format = DRM_OUTPUT_COLOR_FORMAT_RGB444;
mhdp->display_fmt.bpc = 8;
mhdp->bridge.of_node = pdev->dev.of_node;
diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h
index b297db53ba28..b53335b0d22c 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h
+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h
@@ -306,7 +306,7 @@ struct cdns_mhdp_sink {
};
struct cdns_mhdp_display_fmt {
- u32 color_format;
+ enum drm_output_color_format color_format;
u32 bpc;
bool y_only;
};
diff --git a/drivers/gpu/drm/bridge/inno-hdmi.c b/drivers/gpu/drm/bridge/inno-hdmi.c
index a26b99b101c4..87422d15d9a2 100644
--- a/drivers/gpu/drm/bridge/inno-hdmi.c
+++ b/drivers/gpu/drm/bridge/inno-hdmi.c
@@ -653,7 +653,7 @@ static int inno_hdmi_config_video_csc(struct inno_hdmi *hdmi,
v_VIDEO_INPUT_CSP(0);
hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL2, value);
- if (conn_state->hdmi.output_format == HDMI_COLORSPACE_RGB) {
+ if (conn_state->hdmi.output_format == DRM_OUTPUT_COLOR_FORMAT_RGB444) {
if (conn_state->hdmi.is_limited_range) {
csc_mode = CSC_RGB_0_255_TO_RGB_16_235_8BIT;
auto_csc = AUTO_CSC_DISABLE;
@@ -672,14 +672,14 @@ static int inno_hdmi_config_video_csc(struct inno_hdmi *hdmi,
}
} else {
if (colorimetry == HDMI_COLORIMETRY_ITU_601) {
- if (conn_state->hdmi.output_format == HDMI_COLORSPACE_YUV444) {
+ if (conn_state->hdmi.output_format == DRM_OUTPUT_COLOR_FORMAT_YCBCR444) {
csc_mode = CSC_RGB_0_255_TO_ITU601_16_235_8BIT;
auto_csc = AUTO_CSC_DISABLE;
c0_c2_change = C0_C2_CHANGE_DISABLE;
csc_enable = v_CSC_ENABLE;
}
} else {
- if (conn_state->hdmi.output_format == HDMI_COLORSPACE_YUV444) {
+ if (conn_state->hdmi.output_format == DRM_OUTPUT_COLOR_FORMAT_YCBCR444) {
csc_mode = CSC_RGB_0_255_TO_ITU709_16_235_8BIT;
auto_csc = AUTO_CSC_DISABLE;
c0_c2_change = C0_C2_CHANGE_DISABLE;
diff --git a/drivers/gpu/drm/bridge/ite-it6263.c b/drivers/gpu/drm/bridge/ite-it6263.c
index e77681047bb2..4f3ebb7af4d4 100644
--- a/drivers/gpu/drm/bridge/ite-it6263.c
+++ b/drivers/gpu/drm/bridge/ite-it6263.c
@@ -666,7 +666,7 @@ it6263_bridge_mode_valid(struct drm_bridge *bridge,
{
unsigned long long rate;
- rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_RGB);
+ rate = drm_hdmi_compute_mode_clock(mode, 8, DRM_OUTPUT_COLOR_FORMAT_RGB444);
if (rate == 0)
return MODE_NOCLOCK;
diff --git a/drivers/gpu/drm/bridge/lontium-lt8713sx.c b/drivers/gpu/drm/bridge/lontium-lt8713sx.c
new file mode 100644
index 000000000000..18fac6a46db4
--- /dev/null
+++ b/drivers/gpu/drm/bridge/lontium-lt8713sx.c
@@ -0,0 +1,598 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#include <linux/crc8.h>
+#include <linux/firmware.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of_graph.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/sizes.h>
+#include <linux/wait.h>
+#include <linux/workqueue.h>
+
+#include <drm/drm_bridge.h>
+#include <drm/drm_of.h>
+
+#define FW_FILE "lt8713sx_fw.bin"
+
+#define REG_PAGE_CONTROL 0xff
+
+#define LT8713SX_PAGE_SIZE 256
+
+DECLARE_CRC8_TABLE(lt8713sx_crc_table);
+
+struct lt8713sx {
+ struct device *dev;
+ struct drm_bridge bridge;
+ struct drm_bridge *next_bridge;
+
+ struct regmap *regmap;
+ /* Protects all accesses to registers by stopping the on-chip MCU */
+ struct mutex ocm_lock;
+
+ struct gpio_desc *reset_gpio;
+ struct gpio_desc *enable_gpio;
+
+ struct i2c_client *client;
+ const struct firmware *fw;
+
+ u8 *fw_buffer;
+
+ u32 main_crc_value;
+ u32 bank_crc_value[17];
+
+ int bank_num;
+};
+
+static void lt8713sx_reset(struct lt8713sx *lt8713sx);
+
+static const struct regmap_range lt8713sx_ranges[] = {
+ {
+ .range_min = 0x0000,
+ .range_max = 0xffff
+ },
+};
+
+static const struct regmap_access_table lt8713sx_table = {
+ .yes_ranges = lt8713sx_ranges,
+ .n_yes_ranges = ARRAY_SIZE(lt8713sx_ranges),
+};
+
+static const struct regmap_range_cfg lt8713sx_range_cfg = {
+ .name = "lt8713sx",
+ .range_min = 0x0000,
+ .range_max = 0xffff,
+ .selector_reg = REG_PAGE_CONTROL,
+ .selector_mask = 0xff,
+ .selector_shift = 0,
+ .window_start = 0,
+ .window_len = 0x100,
+};
+
+static const struct regmap_config lt8713sx_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .volatile_table = &lt8713sx_table,
+ .ranges = &lt8713sx_range_cfg,
+ .num_ranges = 1,
+ .cache_type = REGCACHE_NONE,
+ .max_register = 0xffff,
+};
+
+static void lt8713sx_i2c_enable(struct lt8713sx *lt8713sx)
+{
+ regmap_write(lt8713sx->regmap, 0xe0ee, 0x01);
+}
+
+static void lt8713sx_i2c_disable(struct lt8713sx *lt8713sx)
+{
+ regmap_write(lt8713sx->regmap, 0xe0ee, 0x00);
+}
+
+static int lt8713sx_prepare_firmware_data(struct lt8713sx *lt8713sx)
+{
+ int ret = 0;
+ size_t sz_12k = 12 * SZ_1K;
+
+ ret = request_firmware(&lt8713sx->fw, FW_FILE, lt8713sx->dev);
+ if (ret < 0) {
+ dev_err(lt8713sx->dev, "request firmware failed\n");
+ return ret;
+ }
+
+ dev_dbg(lt8713sx->dev, "Firmware size: %zu bytes\n", lt8713sx->fw->size);
+
+ if (lt8713sx->fw->size > SZ_256K - 1) {
+ dev_err(lt8713sx->dev, "Firmware size exceeds 256KB limit\n");
+ release_firmware(lt8713sx->fw);
+ return -EINVAL;
+ }
+
+ lt8713sx->fw_buffer = kvmalloc(SZ_256K, GFP_KERNEL);
+ if (!lt8713sx->fw_buffer) {
+ release_firmware(lt8713sx->fw);
+ return -ENOMEM;
+ }
+
+ memset(lt8713sx->fw_buffer, 0xff, SZ_256K);
+
+ /* main firmware */
+ memcpy(lt8713sx->fw_buffer, lt8713sx->fw->data, SZ_64K - 1);
+
+ lt8713sx->fw_buffer[SZ_64K - 1] =
+ crc8(lt8713sx_crc_table, lt8713sx->fw_buffer, SZ_64K - 1, 0);
+ lt8713sx->main_crc_value = lt8713sx->fw_buffer[SZ_64K - 1];
+ dev_dbg(lt8713sx->dev,
+ "Main Firmware Data Crc = 0x%02X\n", lt8713sx->main_crc_value);
+
+ /* bank firmware */
+ memcpy(lt8713sx->fw_buffer + SZ_64K,
+ lt8713sx->fw->data + SZ_64K,
+ lt8713sx->fw->size - SZ_64K);
+
+ lt8713sx->bank_num = (lt8713sx->fw->size - SZ_64K + sz_12k - 1) / sz_12k;
+ dev_dbg(lt8713sx->dev, "Bank Number Total is %d.\n", lt8713sx->bank_num);
+
+ for (int i = 0; i < lt8713sx->bank_num; i++) {
+ lt8713sx->bank_crc_value[i] =
+ crc8(lt8713sx_crc_table, lt8713sx->fw_buffer + SZ_64K + i * sz_12k,
+ sz_12k, 0);
+ dev_dbg(lt8713sx->dev, "Bank number:%d; Firmware Data Crc:0x%02X\n",
+ i, lt8713sx->bank_crc_value[i]);
+ }
+ return 0;
+}
+
+static void lt8713sx_config_parameters(struct lt8713sx *lt8713sx)
+{
+ regmap_write(lt8713sx->regmap, 0xe05e, 0xc1);
+ regmap_write(lt8713sx->regmap, 0xe058, 0x00);
+ regmap_write(lt8713sx->regmap, 0xe059, 0x50);
+ regmap_write(lt8713sx->regmap, 0xe05a, 0x10);
+ regmap_write(lt8713sx->regmap, 0xe05a, 0x00);
+ regmap_write(lt8713sx->regmap, 0xe058, 0x21);
+}
+
+static void lt8713sx_wren(struct lt8713sx *lt8713sx)
+{
+ regmap_write(lt8713sx->regmap, 0xe103, 0xbf);
+ regmap_write(lt8713sx->regmap, 0xe103, 0xff);
+ regmap_write(lt8713sx->regmap, 0xe05a, 0x04);
+ regmap_write(lt8713sx->regmap, 0xe05a, 0x00);
+}
+
+static void lt8713sx_wrdi(struct lt8713sx *lt8713sx)
+{
+ regmap_write(lt8713sx->regmap, 0xe05a, 0x08);
+ regmap_write(lt8713sx->regmap, 0xe05a, 0x00);
+}
+
+static void lt8713sx_fifo_reset(struct lt8713sx *lt8713sx)
+{
+ regmap_write(lt8713sx->regmap, 0xe103, 0xbf);
+ regmap_write(lt8713sx->regmap, 0xe103, 0xff);
+}
+
+static void lt8713sx_disable_sram_write(struct lt8713sx *lt8713sx)
+{
+ regmap_write(lt8713sx->regmap, 0xe055, 0x00);
+}
+
+static void lt8713sx_sram_to_flash(struct lt8713sx *lt8713sx)
+{
+ regmap_write(lt8713sx->regmap, 0xe05a, 0x30);
+ regmap_write(lt8713sx->regmap, 0xe05a, 0x00);
+}
+
+static void lt8713sx_i2c_to_sram(struct lt8713sx *lt8713sx)
+{
+ regmap_write(lt8713sx->regmap, 0xe055, 0x80);
+ regmap_write(lt8713sx->regmap, 0xe05e, 0xc0);
+ regmap_write(lt8713sx->regmap, 0xe058, 0x21);
+}
+
+static u8 lt8713sx_read_flash_status(struct lt8713sx *lt8713sx)
+{
+ u32 flash_status = 0;
+
+ regmap_write(lt8713sx->regmap, 0xe103, 0x3f);
+ regmap_write(lt8713sx->regmap, 0xe103, 0xff);
+
+ regmap_write(lt8713sx->regmap, 0xe05e, 0x40);
+ regmap_write(lt8713sx->regmap, 0xe056, 0x05); /* opcode=read status register */
+ regmap_write(lt8713sx->regmap, 0xe055, 0x25);
+ regmap_write(lt8713sx->regmap, 0xe055, 0x01);
+ regmap_write(lt8713sx->regmap, 0xe058, 0x21);
+
+ regmap_read(lt8713sx->regmap, 0xe05f, &flash_status);
+ dev_dbg(lt8713sx->dev, "flash_status:%x\n", flash_status);
+
+ return flash_status;
+}
+
+static void lt8713sx_block_erase(struct lt8713sx *lt8713sx)
+{
+ u32 i = 0;
+ u8 flash_status = 0;
+ u8 blocknum = 0x00;
+ u32 flashaddr = 0x00;
+
+ for (blocknum = 0; blocknum < 8; blocknum++) {
+ flashaddr = blocknum * SZ_32K;
+ regmap_write(lt8713sx->regmap, 0xe05a, 0x04);
+ regmap_write(lt8713sx->regmap, 0xe05a, 0x00);
+ regmap_write(lt8713sx->regmap, 0xe05b, flashaddr >> 16);
+ regmap_write(lt8713sx->regmap, 0xe05c, flashaddr >> 8);
+ regmap_write(lt8713sx->regmap, 0xe05d, flashaddr);
+ regmap_write(lt8713sx->regmap, 0xe05a, 0x01);
+ regmap_write(lt8713sx->regmap, 0xe05a, 0x00);
+ msleep(100);
+ i = 0;
+ while (1) {
+ flash_status = lt8713sx_read_flash_status(lt8713sx);
+ if ((flash_status & 0x01) == 0)
+ break;
+
+ if (i > 50)
+ break;
+
+ i++;
+ msleep(50);
+ }
+ }
+ dev_dbg(lt8713sx->dev, "erase flash done.\n");
+}
+
+static void lt8713sx_load_main_fw_to_sram(struct lt8713sx *lt8713sx)
+{
+ regmap_write(lt8713sx->regmap, 0xe068, 0x00);
+ regmap_write(lt8713sx->regmap, 0xe069, 0x00);
+ regmap_write(lt8713sx->regmap, 0xe06a, 0x00);
+ regmap_write(lt8713sx->regmap, 0xe065, 0x00);
+ regmap_write(lt8713sx->regmap, 0xe066, 0xff);
+ regmap_write(lt8713sx->regmap, 0xe067, 0xff);
+ regmap_write(lt8713sx->regmap, 0xe06b, 0x00);
+ regmap_write(lt8713sx->regmap, 0xe06c, 0x00);
+ regmap_write(lt8713sx->regmap, 0xe060, 0x01);
+ msleep(200);
+ regmap_write(lt8713sx->regmap, 0xe060, 0x00);
+}
+
+static void lt8713sx_load_bank_fw_to_sram(struct lt8713sx *lt8713sx, u64 addr)
+{
+ regmap_write(lt8713sx->regmap, 0xe068, ((addr & 0xff0000) >> 16));
+ regmap_write(lt8713sx->regmap, 0xe069, ((addr & 0x00ff00) >> 8));
+ regmap_write(lt8713sx->regmap, 0xe06a, (addr & 0x0000ff));
+ regmap_write(lt8713sx->regmap, 0xe065, 0x00);
+ regmap_write(lt8713sx->regmap, 0xe066, 0x30);
+ regmap_write(lt8713sx->regmap, 0xe067, 0x00);
+ regmap_write(lt8713sx->regmap, 0xe06b, 0x00);
+ regmap_write(lt8713sx->regmap, 0xe06c, 0x00);
+ regmap_write(lt8713sx->regmap, 0xe060, 0x01);
+ msleep(50);
+ regmap_write(lt8713sx->regmap, 0xe060, 0x00);
+}
+
+static int lt8713sx_write_data(struct lt8713sx *lt8713sx, const u8 *data, u64 filesize)
+{
+ int page = 0, num = 0, i = 0, val;
+
+ page = (filesize % LT8713SX_PAGE_SIZE) ?
+ ((filesize / LT8713SX_PAGE_SIZE) + 1) : (filesize / LT8713SX_PAGE_SIZE);
+
+ dev_dbg(lt8713sx->dev,
+ "Writing to Sram=%u pages, total size = %llu bytes\n", page, filesize);
+
+ for (num = 0; num < page; num++) {
+ dev_dbg(lt8713sx->dev, "page[%d]\n", num);
+ lt8713sx_i2c_to_sram(lt8713sx);
+
+ for (i = 0; i < LT8713SX_PAGE_SIZE; i++) {
+ if ((num * LT8713SX_PAGE_SIZE + i) < filesize)
+ val = *(data + (num * LT8713SX_PAGE_SIZE + i));
+ else
+ val = 0xff;
+ regmap_write(lt8713sx->regmap, 0xe059, val);
+ }
+
+ lt8713sx_wren(lt8713sx);
+ lt8713sx_sram_to_flash(lt8713sx);
+ }
+
+ lt8713sx_wrdi(lt8713sx);
+ lt8713sx_disable_sram_write(lt8713sx);
+
+ return 0;
+}
+
+static void lt8713sx_main_upgrade_result(struct lt8713sx *lt8713sx)
+{
+ u32 main_crc_result;
+
+ regmap_read(lt8713sx->regmap, 0xe023, &main_crc_result);
+
+ dev_dbg(lt8713sx->dev, "Main CRC HW: 0x%02X\n", main_crc_result);
+ dev_dbg(lt8713sx->dev, "Main CRC FW: 0x%02X\n", lt8713sx->main_crc_value);
+
+ if (main_crc_result == lt8713sx->main_crc_value)
+ dev_info(lt8713sx->dev, "Main Firmware Upgrade Success.\n");
+ else
+ dev_err(lt8713sx->dev, "Main Firmware Upgrade Failed.\n");
+}
+
+static void lt8713sx_bank_upgrade_result(struct lt8713sx *lt8713sx, u8 banknum)
+{
+ u32 bank_crc_result;
+
+ regmap_read(lt8713sx->regmap, 0xe023, &bank_crc_result);
+
+ dev_dbg(lt8713sx->dev, "Bank %d CRC Result: 0x%02X\n", banknum, bank_crc_result);
+
+ if (bank_crc_result == lt8713sx->bank_crc_value[banknum])
+ dev_info(lt8713sx->dev, "Bank %d Firmware Upgrade Success.\n", banknum);
+ else
+ dev_err(lt8713sx->dev, "Bank %d Firmware Upgrade Failed.\n", banknum);
+}
+
+static void lt8713sx_bank_result_check(struct lt8713sx *lt8713sx)
+{
+ int i;
+ u64 addr = 0x010000;
+
+ for (i = 0; i < lt8713sx->bank_num; i++) {
+ lt8713sx_load_bank_fw_to_sram(lt8713sx, addr);
+ lt8713sx_bank_upgrade_result(lt8713sx, i);
+ addr += 0x3000;
+ }
+}
+
+static int lt8713sx_firmware_upgrade(struct lt8713sx *lt8713sx)
+{
+ int ret;
+
+ lt8713sx_config_parameters(lt8713sx);
+
+ lt8713sx_block_erase(lt8713sx);
+
+ if (lt8713sx->fw->size < SZ_64K) {
+ ret = lt8713sx_write_data(lt8713sx, lt8713sx->fw_buffer, SZ_64K);
+ if (ret < 0) {
+ dev_err(lt8713sx->dev, "Failed to write firmware data: %d\n", ret);
+ return ret;
+ }
+ } else {
+ ret = lt8713sx_write_data(lt8713sx, lt8713sx->fw_buffer, lt8713sx->fw->size);
+ if (ret < 0) {
+ dev_err(lt8713sx->dev, "Failed to write firmware data: %d\n", ret);
+ return ret;
+ }
+ }
+ dev_dbg(lt8713sx->dev, "Write Data done.\n");
+
+ return 0;
+}
+
+static int lt8713sx_firmware_update(struct lt8713sx *lt8713sx)
+{
+ int ret = 0;
+
+ guard(mutex)(&lt8713sx->ocm_lock);
+ lt8713sx_i2c_enable(lt8713sx);
+
+ ret = lt8713sx_prepare_firmware_data(lt8713sx);
+ if (ret < 0) {
+ dev_err(lt8713sx->dev, "Failed to prepare firmware data: %d\n", ret);
+ goto error;
+ }
+
+ ret = lt8713sx_firmware_upgrade(lt8713sx);
+ if (ret < 0) {
+ dev_err(lt8713sx->dev, "Upgrade failure.\n");
+ goto error;
+ }
+
+ /* Validate CRC */
+ lt8713sx_load_main_fw_to_sram(lt8713sx);
+ lt8713sx_main_upgrade_result(lt8713sx);
+ lt8713sx_wrdi(lt8713sx);
+ lt8713sx_fifo_reset(lt8713sx);
+ lt8713sx_bank_result_check(lt8713sx);
+ lt8713sx_wrdi(lt8713sx);
+
+error:
+ lt8713sx_i2c_disable(lt8713sx);
+ if (!ret)
+ lt8713sx_reset(lt8713sx);
+
+ kvfree(lt8713sx->fw_buffer);
+ lt8713sx->fw_buffer = NULL;
+
+ if (lt8713sx->fw) {
+ release_firmware(lt8713sx->fw);
+ lt8713sx->fw = NULL;
+ }
+
+ return ret;
+}
+
+static void lt8713sx_reset(struct lt8713sx *lt8713sx)
+{
+ dev_dbg(lt8713sx->dev, "reset bridge.\n");
+ gpiod_set_value_cansleep(lt8713sx->reset_gpio, 1);
+ msleep(20);
+
+ gpiod_set_value_cansleep(lt8713sx->reset_gpio, 0);
+ msleep(20);
+
+ dev_dbg(lt8713sx->dev, "reset done.\n");
+}
+
+static int lt8713sx_regulator_enable(struct lt8713sx *lt8713sx)
+{
+ int ret;
+
+ ret = devm_regulator_get_enable(lt8713sx->dev, "vdd");
+ if (ret < 0)
+ return dev_err_probe(lt8713sx->dev, ret, "failed to enable vdd regulator\n");
+
+ usleep_range(1000, 10000);
+
+ ret = devm_regulator_get_enable(lt8713sx->dev, "vcc");
+ if (ret < 0)
+ return dev_err_probe(lt8713sx->dev, ret, "failed to enable vcc regulator\n");
+ return 0;
+}
+
+static int lt8713sx_bridge_attach(struct drm_bridge *bridge,
+ struct drm_encoder *encoder,
+ enum drm_bridge_attach_flags flags)
+{
+ struct lt8713sx *lt8713sx = container_of(bridge, struct lt8713sx, bridge);
+
+ return drm_bridge_attach(encoder,
+ lt8713sx->next_bridge,
+ bridge, flags);
+}
+
+static int lt8713sx_gpio_init(struct lt8713sx *lt8713sx)
+{
+ struct device *dev = lt8713sx->dev;
+
+ lt8713sx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(lt8713sx->reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(lt8713sx->reset_gpio),
+ "failed to acquire reset gpio\n");
+
+ /* power enable gpio */
+ lt8713sx->enable_gpio = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_HIGH);
+ if (IS_ERR(lt8713sx->enable_gpio))
+ return dev_err_probe(dev, PTR_ERR(lt8713sx->enable_gpio),
+ "failed to acquire enable gpio\n");
+ return 0;
+}
+
+static ssize_t lt8713sx_firmware_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct lt8713sx *lt8713sx = dev_get_drvdata(dev);
+ int ret;
+
+ ret = lt8713sx_firmware_update(lt8713sx);
+ if (ret < 0)
+ return ret;
+ return len;
+}
+
+static DEVICE_ATTR_WO(lt8713sx_firmware);
+
+static struct attribute *lt8713sx_attrs[] = {
+ &dev_attr_lt8713sx_firmware.attr,
+ NULL,
+};
+
+static const struct attribute_group lt8713sx_attr_group = {
+ .attrs = lt8713sx_attrs,
+};
+
+static const struct attribute_group *lt8713sx_attr_groups[] = {
+ &lt8713sx_attr_group,
+ NULL,
+};
+
+static const struct drm_bridge_funcs lt8713sx_bridge_funcs = {
+ .attach = lt8713sx_bridge_attach,
+};
+
+static int lt8713sx_probe(struct i2c_client *client)
+{
+ struct lt8713sx *lt8713sx;
+ struct device *dev = &client->dev;
+ int ret;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+ return dev_err_probe(dev, -ENODEV, "device doesn't support I2C\n");
+
+ lt8713sx = devm_drm_bridge_alloc(dev, struct lt8713sx, bridge, &lt8713sx_bridge_funcs);
+ if (IS_ERR(lt8713sx))
+ return PTR_ERR(lt8713sx);
+
+ lt8713sx->dev = dev;
+ lt8713sx->client = client;
+ i2c_set_clientdata(client, lt8713sx);
+
+ ret = devm_mutex_init(lt8713sx->dev, &lt8713sx->ocm_lock);
+ if (ret)
+ return ret;
+
+ lt8713sx->regmap = devm_regmap_init_i2c(client, &lt8713sx_regmap_config);
+ if (IS_ERR(lt8713sx->regmap))
+ return dev_err_probe(dev, PTR_ERR(lt8713sx->regmap), "regmap i2c init failed\n");
+
+ ret = drm_of_find_panel_or_bridge(lt8713sx->dev->of_node, 1, -1, NULL,
+ &lt8713sx->next_bridge);
+ if (ret < 0)
+ return ret;
+
+ ret = lt8713sx_gpio_init(lt8713sx);
+ if (ret < 0)
+ return ret;
+
+ ret = lt8713sx_regulator_enable(lt8713sx);
+ if (ret)
+ return ret;
+
+ lt8713sx_reset(lt8713sx);
+
+ lt8713sx->bridge.funcs = &lt8713sx_bridge_funcs;
+ lt8713sx->bridge.of_node = dev->of_node;
+ lt8713sx->bridge.type = DRM_MODE_CONNECTOR_DisplayPort;
+ drm_bridge_add(&lt8713sx->bridge);
+
+ crc8_populate_msb(lt8713sx_crc_table, 0x31);
+
+ return 0;
+}
+
+static void lt8713sx_remove(struct i2c_client *client)
+{
+ struct lt8713sx *lt8713sx = i2c_get_clientdata(client);
+
+ drm_bridge_remove(&lt8713sx->bridge);
+}
+
+static struct i2c_device_id lt8713sx_id[] = {
+ { "lontium,lt8713sx", 0 },
+ { /* sentinel */ }
+};
+
+static const struct of_device_id lt8713sx_match_table[] = {
+ { .compatible = "lontium,lt8713sx" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, lt8713sx_match_table);
+
+static struct i2c_driver lt8713sx_driver = {
+ .driver = {
+ .name = "lt8713sx",
+ .of_match_table = lt8713sx_match_table,
+ .dev_groups = lt8713sx_attr_groups,
+ },
+ .probe = lt8713sx_probe,
+ .remove = lt8713sx_remove,
+ .id_table = lt8713sx_id,
+};
+
+module_i2c_driver(lt8713sx_driver);
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("lt8713sx drm bridge driver");
+MODULE_AUTHOR("Vishnu Saini <vishnu.saini@oss.qualcomm.com>");
+MODULE_FIRMWARE(FW_FILE);
diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c
index ec632f268644..c3eb437ef1b0 100644
--- a/drivers/gpu/drm/bridge/samsung-dsim.c
+++ b/drivers/gpu/drm/bridge/samsung-dsim.c
@@ -1988,9 +1988,7 @@ of_find_panel_or_bridge:
return 0;
err_release_next_bridge:
- drm_bridge_put(dsi->bridge.next_bridge);
- dsi->bridge.next_bridge = NULL;
-
+ drm_bridge_clear_and_put(&dsi->bridge.next_bridge);
if (!(device->mode_flags & MIPI_DSI_MODE_VIDEO))
samsung_dsim_unregister_te_irq(dsi);
err_remove_bridge:
@@ -2007,8 +2005,7 @@ static int samsung_dsim_host_detach(struct mipi_dsi_host *host,
if (pdata->host_ops && pdata->host_ops->detach)
pdata->host_ops->detach(dsi, device);
- drm_bridge_put(dsi->bridge.next_bridge);
- dsi->bridge.next_bridge = NULL;
+ drm_bridge_clear_and_put(&dsi->bridge.next_bridge);
samsung_dsim_unregister_te_irq(dsi);
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-dp.c b/drivers/gpu/drm/bridge/synopsys/dw-dp.c
index e7bef9150f6a..45b37885d719 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-dp.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-dp.c
@@ -379,7 +379,7 @@ enum {
struct dw_dp_output_format {
u32 bus_format;
- u32 color_format;
+ enum drm_output_color_format color_format;
u8 video_mapping;
u8 bpc;
u8 bpp;
@@ -388,15 +388,15 @@ struct dw_dp_output_format {
#define to_dw_dp_bridge_state(s) container_of(s, struct dw_dp_bridge_state, base)
static const struct dw_dp_output_format dw_dp_output_formats[] = {
- { MEDIA_BUS_FMT_RGB101010_1X30, DRM_COLOR_FORMAT_RGB444, DW_DP_RGB_10BIT, 10, 30 },
- { MEDIA_BUS_FMT_RGB888_1X24, DRM_COLOR_FORMAT_RGB444, DW_DP_RGB_8BIT, 8, 24 },
- { MEDIA_BUS_FMT_YUV10_1X30, DRM_COLOR_FORMAT_YCBCR444, DW_DP_YCBCR444_10BIT, 10, 30 },
- { MEDIA_BUS_FMT_YUV8_1X24, DRM_COLOR_FORMAT_YCBCR444, DW_DP_YCBCR444_8BIT, 8, 24},
- { MEDIA_BUS_FMT_YUYV10_1X20, DRM_COLOR_FORMAT_YCBCR422, DW_DP_YCBCR422_10BIT, 10, 20 },
- { MEDIA_BUS_FMT_YUYV8_1X16, DRM_COLOR_FORMAT_YCBCR422, DW_DP_YCBCR422_8BIT, 8, 16 },
- { MEDIA_BUS_FMT_UYYVYY10_0_5X30, DRM_COLOR_FORMAT_YCBCR420, DW_DP_YCBCR420_10BIT, 10, 15 },
- { MEDIA_BUS_FMT_UYYVYY8_0_5X24, DRM_COLOR_FORMAT_YCBCR420, DW_DP_YCBCR420_8BIT, 8, 12 },
- { MEDIA_BUS_FMT_RGB666_1X24_CPADHI, DRM_COLOR_FORMAT_RGB444, DW_DP_RGB_6BIT, 6, 18 },
+ { MEDIA_BUS_FMT_RGB101010_1X30, DRM_OUTPUT_COLOR_FORMAT_RGB444, DW_DP_RGB_10BIT, 10, 30 },
+ { MEDIA_BUS_FMT_RGB888_1X24, DRM_OUTPUT_COLOR_FORMAT_RGB444, DW_DP_RGB_8BIT, 8, 24 },
+ { MEDIA_BUS_FMT_YUV10_1X30, DRM_OUTPUT_COLOR_FORMAT_YCBCR444, DW_DP_YCBCR444_10BIT, 10, 30 },
+ { MEDIA_BUS_FMT_YUV8_1X24, DRM_OUTPUT_COLOR_FORMAT_YCBCR444, DW_DP_YCBCR444_8BIT, 8, 24},
+ { MEDIA_BUS_FMT_YUYV10_1X20, DRM_OUTPUT_COLOR_FORMAT_YCBCR422, DW_DP_YCBCR422_10BIT, 10, 20 },
+ { MEDIA_BUS_FMT_YUYV8_1X16, DRM_OUTPUT_COLOR_FORMAT_YCBCR422, DW_DP_YCBCR422_8BIT, 8, 16 },
+ { MEDIA_BUS_FMT_UYYVYY10_0_5X30, DRM_OUTPUT_COLOR_FORMAT_YCBCR420, DW_DP_YCBCR420_10BIT, 10, 15 },
+ { MEDIA_BUS_FMT_UYYVYY8_0_5X24, DRM_OUTPUT_COLOR_FORMAT_YCBCR420, DW_DP_YCBCR420_8BIT, 8, 12 },
+ { MEDIA_BUS_FMT_RGB666_1X24_CPADHI, DRM_OUTPUT_COLOR_FORMAT_RGB444, DW_DP_RGB_6BIT, 6, 18 },
};
static const struct dw_dp_output_format *dw_dp_get_output_format(u32 bus_format)
@@ -1091,22 +1091,22 @@ static int dw_dp_send_vsc_sdp(struct dw_dp *dp)
sdp.flags = DW_DP_SDP_VERTICAL_INTERVAL;
switch (state->color_format) {
- case DRM_COLOR_FORMAT_YCBCR444:
+ case DRM_OUTPUT_COLOR_FORMAT_YCBCR444:
vsc.pixelformat = DP_PIXELFORMAT_YUV444;
break;
- case DRM_COLOR_FORMAT_YCBCR420:
+ case DRM_OUTPUT_COLOR_FORMAT_YCBCR420:
vsc.pixelformat = DP_PIXELFORMAT_YUV420;
break;
- case DRM_COLOR_FORMAT_YCBCR422:
+ case DRM_OUTPUT_COLOR_FORMAT_YCBCR422:
vsc.pixelformat = DP_PIXELFORMAT_YUV422;
break;
- case DRM_COLOR_FORMAT_RGB444:
+ case DRM_OUTPUT_COLOR_FORMAT_RGB444:
default:
vsc.pixelformat = DP_PIXELFORMAT_RGB;
break;
}
- if (state->color_format == DRM_COLOR_FORMAT_RGB444) {
+ if (state->color_format == DRM_OUTPUT_COLOR_FORMAT_RGB444) {
vsc.colorimetry = DP_COLORIMETRY_DEFAULT;
vsc.dynamic_range = DP_DYNAMIC_RANGE_VESA;
} else {
@@ -1148,14 +1148,15 @@ static bool dw_dp_video_need_vsc_sdp(struct dw_dp *dp)
if (!link->vsc_sdp_supported)
return false;
- if (state->color_format == DRM_COLOR_FORMAT_YCBCR420)
+ if (state->color_format == DRM_OUTPUT_COLOR_FORMAT_YCBCR420)
return true;
return false;
}
-static int dw_dp_video_set_msa(struct dw_dp *dp, u8 color_format, u8 bpc,
- u16 vstart, u16 hstart)
+static int dw_dp_video_set_msa(struct dw_dp *dp,
+ enum drm_output_color_format color_format,
+ u8 bpc, u16 vstart, u16 hstart)
{
u16 misc = 0;
@@ -1163,16 +1164,16 @@ static int dw_dp_video_set_msa(struct dw_dp *dp, u8 color_format, u8 bpc,
misc |= DP_MSA_MISC_COLOR_VSC_SDP;
switch (color_format) {
- case DRM_COLOR_FORMAT_RGB444:
+ case DRM_OUTPUT_COLOR_FORMAT_RGB444:
misc |= DP_MSA_MISC_COLOR_RGB;
break;
- case DRM_COLOR_FORMAT_YCBCR444:
+ case DRM_OUTPUT_COLOR_FORMAT_YCBCR444:
misc |= DP_MSA_MISC_COLOR_YCBCR_444_BT709;
break;
- case DRM_COLOR_FORMAT_YCBCR422:
+ case DRM_OUTPUT_COLOR_FORMAT_YCBCR422:
misc |= DP_MSA_MISC_COLOR_YCBCR_422_BT709;
break;
- case DRM_COLOR_FORMAT_YCBCR420:
+ case DRM_OUTPUT_COLOR_FORMAT_YCBCR420:
break;
default:
return -EINVAL;
@@ -1304,9 +1305,9 @@ static int dw_dp_video_enable(struct dw_dp *dp)
if (dp->pixel_mode == DW_DP_MP_SINGLE_PIXEL) {
if (average_bytes_per_tu < 6)
init_threshold = 32;
- else if (hblank <= 80 && color_format != DRM_COLOR_FORMAT_YCBCR420)
+ else if (hblank <= 80 && color_format != DRM_OUTPUT_COLOR_FORMAT_YCBCR420)
init_threshold = 12;
- else if (hblank <= 40 && color_format == DRM_COLOR_FORMAT_YCBCR420)
+ else if (hblank <= 40 && color_format == DRM_OUTPUT_COLOR_FORMAT_YCBCR420)
init_threshold = 3;
else
init_threshold = 16;
@@ -1318,7 +1319,7 @@ static int dw_dp_video_enable(struct dw_dp *dp)
t1 = (4 * 1000 / 9) * link->lanes;
break;
case 8:
- if (color_format == DRM_COLOR_FORMAT_YCBCR422) {
+ if (color_format == DRM_OUTPUT_COLOR_FORMAT_YCBCR422) {
t1 = (1000 / 2) * link->lanes;
} else {
if (dp->pixel_mode == DW_DP_MP_DUAL_PIXEL)
@@ -1328,13 +1329,13 @@ static int dw_dp_video_enable(struct dw_dp *dp)
}
break;
case 10:
- if (color_format == DRM_COLOR_FORMAT_YCBCR422)
+ if (color_format == DRM_OUTPUT_COLOR_FORMAT_YCBCR422)
t1 = (2000 / 5) * link->lanes;
else
t1 = (4000 / 15) * link->lanes;
break;
case 12:
- if (color_format == DRM_COLOR_FORMAT_YCBCR422) {
+ if (color_format == DRM_OUTPUT_COLOR_FORMAT_YCBCR422) {
if (dp->pixel_mode == DW_DP_MP_DUAL_PIXEL)
t1 = (1000 / 6) * link->lanes;
else
@@ -1344,7 +1345,7 @@ static int dw_dp_video_enable(struct dw_dp *dp)
}
break;
case 16:
- if (color_format != DRM_COLOR_FORMAT_YCBCR422 &&
+ if (color_format != DRM_OUTPUT_COLOR_FORMAT_YCBCR422 &&
dp->pixel_mode == DW_DP_MP_DUAL_PIXEL)
t1 = (1000 / 6) * link->lanes;
else
@@ -1354,7 +1355,7 @@ static int dw_dp_video_enable(struct dw_dp *dp)
return -EINVAL;
}
- if (color_format == DRM_COLOR_FORMAT_YCBCR420)
+ if (color_format == DRM_OUTPUT_COLOR_FORMAT_YCBCR420)
t2 = (link->rate / 4) * 1000 / (mode->clock / 2);
else
t2 = (link->rate / 4) * 1000 / mode->clock;
@@ -1574,13 +1575,13 @@ static enum drm_mode_status dw_dp_bridge_mode_valid(struct drm_bridge *bridge,
struct dw_dp_link *link = &dp->link;
u32 min_bpp;
- if (info->color_formats & DRM_COLOR_FORMAT_YCBCR420 &&
+ if (info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420) &&
link->vsc_sdp_supported &&
(drm_mode_is_420_only(info, mode) || drm_mode_is_420_also(info, mode)))
min_bpp = 12;
- else if (info->color_formats & DRM_COLOR_FORMAT_YCBCR422)
+ else if (info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422))
min_bpp = 16;
- else if (info->color_formats & DRM_COLOR_FORMAT_RGB444)
+ else if (info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444))
min_bpp = 18;
else
min_bpp = 24;
@@ -1777,14 +1778,14 @@ static u32 *dw_dp_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge,
if (fmt->bpc > conn_state->max_bpc)
continue;
- if (!(fmt->color_format & di->color_formats))
+ if (!(BIT(fmt->color_format) & di->color_formats))
continue;
- if (fmt->color_format == DRM_COLOR_FORMAT_YCBCR420 &&
+ if (fmt->color_format == DRM_OUTPUT_COLOR_FORMAT_YCBCR420 &&
!link->vsc_sdp_supported)
continue;
- if (fmt->color_format != DRM_COLOR_FORMAT_YCBCR420 &&
+ if (fmt->color_format != DRM_OUTPUT_COLOR_FORMAT_YCBCR420 &&
drm_mode_is_420_only(di, &mode))
continue;
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index ee88c0e793b0..0296e110ce65 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -2664,7 +2664,7 @@ static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge,
struct drm_display_mode *mode = &crtc_state->mode;
u8 max_bpc = conn_state->max_requested_bpc;
bool is_hdmi2_sink = info->hdmi.scdc.supported ||
- (info->color_formats & DRM_COLOR_FORMAT_YCBCR420);
+ (info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420));
u32 *output_fmts;
unsigned int i = 0;
@@ -2723,36 +2723,36 @@ static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge,
output_fmts[i++] = MEDIA_BUS_FMT_RGB888_1X24;
if (max_bpc >= 16 && info->bpc == 16) {
- if (info->color_formats & DRM_COLOR_FORMAT_YCBCR444)
+ if (info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444))
output_fmts[i++] = MEDIA_BUS_FMT_YUV16_1X48;
output_fmts[i++] = MEDIA_BUS_FMT_RGB161616_1X48;
}
if (max_bpc >= 12 && info->bpc >= 12) {
- if (info->color_formats & DRM_COLOR_FORMAT_YCBCR422)
+ if (info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422))
output_fmts[i++] = MEDIA_BUS_FMT_UYVY12_1X24;
- if (info->color_formats & DRM_COLOR_FORMAT_YCBCR444)
+ if (info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444))
output_fmts[i++] = MEDIA_BUS_FMT_YUV12_1X36;
output_fmts[i++] = MEDIA_BUS_FMT_RGB121212_1X36;
}
if (max_bpc >= 10 && info->bpc >= 10) {
- if (info->color_formats & DRM_COLOR_FORMAT_YCBCR422)
+ if (info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422))
output_fmts[i++] = MEDIA_BUS_FMT_UYVY10_1X20;
- if (info->color_formats & DRM_COLOR_FORMAT_YCBCR444)
+ if (info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444))
output_fmts[i++] = MEDIA_BUS_FMT_YUV10_1X30;
output_fmts[i++] = MEDIA_BUS_FMT_RGB101010_1X30;
}
- if (info->color_formats & DRM_COLOR_FORMAT_YCBCR422)
+ if (info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422))
output_fmts[i++] = MEDIA_BUS_FMT_UYVY8_1X16;
- if (info->color_formats & DRM_COLOR_FORMAT_YCBCR444)
+ if (info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444))
output_fmts[i++] = MEDIA_BUS_FMT_YUV8_1X24;
*num_output_fmts = i;
diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi83.c b/drivers/gpu/drm/bridge/ti-sn65dsi83.c
index f6736b4457bb..17a885244e1e 100644
--- a/drivers/gpu/drm/bridge/ti-sn65dsi83.c
+++ b/drivers/gpu/drm/bridge/ti-sn65dsi83.c
@@ -351,9 +351,9 @@ static u8 sn65dsi83_get_dsi_range(struct sn65dsi83 *ctx,
* DSI_CLK = mode clock * bpp / dsi_data_lanes / 2
* the 2 is there because the bus is DDR.
*/
- return DIV_ROUND_UP(clamp((unsigned int)mode->clock *
- mipi_dsi_pixel_format_to_bpp(ctx->dsi->format) /
- ctx->dsi->lanes / 2, 40000U, 500000U), 5000U);
+ return clamp((unsigned int)mode->clock *
+ mipi_dsi_pixel_format_to_bpp(ctx->dsi->format) /
+ ctx->dsi->lanes / 2, 40000U, 500000U) / 5000U;
}
static u8 sn65dsi83_get_dsi_div(struct sn65dsi83 *ctx)
@@ -517,6 +517,7 @@ static void sn65dsi83_atomic_pre_enable(struct drm_bridge *bridge,
struct drm_atomic_state *state)
{
struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge);
+ const unsigned int dual_factor = ctx->lvds_dual_link ? 2 : 1;
const struct drm_bridge_state *bridge_state;
const struct drm_crtc_state *crtc_state;
const struct drm_display_mode *mode;
@@ -653,18 +654,18 @@ static void sn65dsi83_atomic_pre_enable(struct drm_bridge *bridge,
/* 32 + 1 pixel clock to ensure proper operation */
le16val = cpu_to_le16(32 + 1);
regmap_bulk_write(ctx->regmap, REG_VID_CHA_SYNC_DELAY_LOW, &le16val, 2);
- le16val = cpu_to_le16(mode->hsync_end - mode->hsync_start);
+ le16val = cpu_to_le16((mode->hsync_end - mode->hsync_start) / dual_factor);
regmap_bulk_write(ctx->regmap, REG_VID_CHA_HSYNC_PULSE_WIDTH_LOW,
&le16val, 2);
le16val = cpu_to_le16(mode->vsync_end - mode->vsync_start);
regmap_bulk_write(ctx->regmap, REG_VID_CHA_VSYNC_PULSE_WIDTH_LOW,
&le16val, 2);
regmap_write(ctx->regmap, REG_VID_CHA_HORIZONTAL_BACK_PORCH,
- mode->htotal - mode->hsync_end);
+ (mode->htotal - mode->hsync_end) / dual_factor);
regmap_write(ctx->regmap, REG_VID_CHA_VERTICAL_BACK_PORCH,
mode->vtotal - mode->vsync_end);
regmap_write(ctx->regmap, REG_VID_CHA_HORIZONTAL_FRONT_PORCH,
- mode->hsync_start - mode->hdisplay);
+ (mode->hsync_start - mode->hdisplay) / dual_factor);
regmap_write(ctx->regmap, REG_VID_CHA_VERTICAL_FRONT_PORCH,
mode->vsync_start - mode->vdisplay);
regmap_write(ctx->regmap, REG_VID_CHA_TEST_PATTERN, 0x00);
diff --git a/drivers/gpu/drm/bridge/waveshare-dsi.c b/drivers/gpu/drm/bridge/waveshare-dsi.c
index 0497c7ecbc7a..32d40414adb9 100644
--- a/drivers/gpu/drm/bridge/waveshare-dsi.c
+++ b/drivers/gpu/drm/bridge/waveshare-dsi.c
@@ -66,11 +66,13 @@ static int ws_bridge_attach_dsi(struct ws_bridge *ws)
dsi->mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO |
MIPI_DSI_CLOCK_NON_CONTINUOUS;
dsi->format = MIPI_DSI_FMT_RGB888;
- dsi->lanes = drm_of_get_data_lanes_count_ep(dev->of_node, 0, 0, 1, 4);
- if (dsi->lanes < 0) {
+ ret = drm_of_get_data_lanes_count_ep(dev->of_node, 0, 0, 1, 4);
+ if (ret < 0) {
dev_warn(dev, "Invalid or missing DSI lane count %d, falling back to 2 lanes\n",
- dsi->lanes);
+ ret);
dsi->lanes = 2; /* Old DT backward compatibility */
+ } else {
+ dsi->lanes = ret;
}
ret = devm_mipi_dsi_attach(dev, dsi);
diff --git a/drivers/gpu/drm/ci/arm64.config b/drivers/gpu/drm/ci/arm64.config
index ea0e30737c4d..563a69669a7b 100644
--- a/drivers/gpu/drm/ci/arm64.config
+++ b/drivers/gpu/drm/ci/arm64.config
@@ -83,6 +83,7 @@ CONFIG_SC_DISPCC_7180=y
CONFIG_SC_GPUCC_7180=y
CONFIG_SM_GPUCC_8350=y
CONFIG_QCOM_SPMI_ADC5=y
+CONFIG_QCOM_SPMI_VADC=y
CONFIG_DRM_PARADE_PS8640=y
CONFIG_DRM_LONTIUM_LT9611UXC=y
CONFIG_PHY_QCOM_USB_HS=y
@@ -208,3 +209,8 @@ CONFIG_ARM_TEGRA_DEVFREQ=y
CONFIG_TEGRA_SOCTHERM=y
CONFIG_DRM_TEGRA_DEBUG=y
CONFIG_PWM_TEGRA=y
+
+# For Rockchip rk3588
+CONFIG_DRM_PANTHOR=m
+CONFIG_PHY_ROCKCHIP_NANENG_COMBO_PHY=y
+CONFIG_PHY_ROCKCHIP_SAMSUNG_HDPTX=y
diff --git a/drivers/gpu/drm/ci/build.sh b/drivers/gpu/drm/ci/build.sh
index ac5e7ed195cf..d00d549cbd9c 100644
--- a/drivers/gpu/drm/ci/build.sh
+++ b/drivers/gpu/drm/ci/build.sh
@@ -3,9 +3,6 @@
set -ex
-# Clean up stale rebases that GitLab might not have removed when reusing a checkout dir
-rm -rf .git/rebase-apply
-
. .gitlab-ci/container/container_pre_build.sh
# libssl-dev was uninstalled because it was considered an ephemeral package
@@ -19,6 +16,7 @@ if [[ "$KERNEL_ARCH" = "arm64" ]]; then
GCC_ARCH="aarch64-linux-gnu"
DEBIAN_ARCH="arm64"
DEVICE_TREES="arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dtb"
+ DEVICE_TREES+=" arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dtb"
DEVICE_TREES+=" arch/arm64/boot/dts/amlogic/meson-gxl-s805x-libretech-ac.dtb"
DEVICE_TREES+=" arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dtb"
DEVICE_TREES+=" arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dtb"
@@ -61,25 +59,24 @@ export PATH=$NEWPATH:$PATH
git config --global user.email "fdo@example.com"
git config --global user.name "freedesktop.org CI"
-git config --global pull.rebase true
# cleanup git state on the worker
-rm -rf .git/rebase-merge
+rm -rf .git/rebase-merge .git/rebase-apply
# Try to merge fixes from target repo
if [ "$(git ls-remote --exit-code --heads ${UPSTREAM_REPO} ${TARGET_BRANCH}-external-fixes)" ]; then
- git pull ${UPSTREAM_REPO} ${TARGET_BRANCH}-external-fixes
+ git pull --no-rebase ${UPSTREAM_REPO} ${TARGET_BRANCH}-external-fixes
fi
# Try to merge fixes from local repo if this isn't a merge request
# otherwise try merging the fixes from the merge target
if [ -z "$CI_MERGE_REQUEST_PROJECT_PATH" ]; then
if [ "$(git ls-remote --exit-code --heads origin ${TARGET_BRANCH}-external-fixes)" ]; then
- git pull origin ${TARGET_BRANCH}-external-fixes
+ git pull --no-rebase origin ${TARGET_BRANCH}-external-fixes
fi
else
if [ "$(git ls-remote --exit-code --heads ${CI_MERGE_REQUEST_PROJECT_URL} ${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}-external-fixes)" ]; then
- git pull ${CI_MERGE_REQUEST_PROJECT_URL} ${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}-external-fixes
+ git pull --no-rebase ${CI_MERGE_REQUEST_PROJECT_URL} ${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}-external-fixes
fi
fi
diff --git a/drivers/gpu/drm/ci/build.yml b/drivers/gpu/drm/ci/build.yml
index af27ff5de369..efbcaae49807 100644
--- a/drivers/gpu/drm/ci/build.yml
+++ b/drivers/gpu/drm/ci/build.yml
@@ -1,6 +1,6 @@
.build:
extends:
- - .container+build-rules
+ - .build-rules
stage: build-only
artifacts:
paths:
@@ -133,6 +133,10 @@ debian-arm32-asan:
rules:
- when: never
+debian-x86_64-msan:
+ rules:
+ - when: never
+
debian-arm64:
rules:
- when: never
@@ -153,7 +157,7 @@ debian-arm64-ubsan:
rules:
- when: never
-debian-build-testing:
+debian-build-x86_64:
rules:
- when: never
@@ -177,31 +181,31 @@ debian-release:
rules:
- when: never
-debian-s390x:
+debian-riscv64:
rules:
- when: never
-debian-testing:
+debian-s390x:
rules:
- when: never
-debian-testing-asan:
+debian-vulkan:
rules:
- when: never
-debian-testing-msan:
+debian-x86_32:
rules:
- when: never
-debian-testing-ubsan:
+debian-x86_64:
rules:
- when: never
-debian-vulkan:
+debian-x86_64-asan:
rules:
- when: never
-debian-x86_32:
+debian-x86_64-ubsan:
rules:
- when: never
diff --git a/drivers/gpu/drm/ci/container.yml b/drivers/gpu/drm/ci/container.yml
index 5f90508578a3..ce6007a45a07 100644
--- a/drivers/gpu/drm/ci/container.yml
+++ b/drivers/gpu/drm/ci/container.yml
@@ -5,21 +5,29 @@
debian/x86_64_build-base:
variables:
- EXTRA_LOCAL_PACKAGES: "libcairo-dev libdw-dev libjson-c-dev libkmod2 libkmod-dev libpciaccess-dev libproc2-dev libudev-dev libunwind-dev python3-docutils bc python3-ply libssl-dev bc"
+ EXTRA_LOCAL_PACKAGES: "libcairo-dev libdw-dev libjson-c-dev libkmod-dev libpciaccess-dev libproc2-dev libudev-dev libunwind-dev python3-docutils bc python3-ply libssl-dev bc"
+
+debian/arm64_build:
+ variables:
+ EXTRA_LOCAL_PACKAGES: "libcairo-dev libdw-dev libjson-c-dev libproc2-dev libkmod-dev libpciaccess-dev libudev-dev libunwind-dev python3-docutils libssl-dev crossbuild-essential-armhf libkmod-dev:armhf libproc2-dev:armhf libunwind-dev:armhf libdw-dev:armhf libpixman-1-dev:armhf libcairo-dev:armhf libudev-dev:armhf libjson-c-dev:armhf"
debian/x86_64_test-gl:
variables:
- EXTRA_LOCAL_PACKAGES: "jq libasound2 libcairo2 libdw1 libglib2.0-0 libjson-c5 libkmod-dev libkmod2 libgles2 libproc2-dev"
+ EXTRA_LOCAL_PACKAGES: "jq libasound2t64 libcairo2 libdw1t64 libglib2.0-0t64 libjson-c5 libkmod2 libgles2 libdrm-nouveau2 libdrm-amdgpu1"
-debian/arm64_build:
+debian/arm64_test-gl:
variables:
- EXTRA_LOCAL_PACKAGES: "libcairo-dev libdw-dev libjson-c-dev libproc2-dev libkmod2 libkmod-dev libpciaccess-dev libudev-dev libunwind-dev python3-docutils libssl-dev crossbuild-essential-armhf libkmod-dev:armhf libproc2-dev:armhf libunwind-dev:armhf libdw-dev:armhf libpixman-1-dev:armhf libcairo-dev:armhf libudev-dev:armhf libjson-c-dev:armhf"
+ EXTRA_LOCAL_PACKAGES: "jq libasound2t64 libcairo2 libdw1t64 libglib2.0-0t64 libjson-c5 libkmod2 libgles2 libdrm-nouveau2 libdrm-amdgpu1"
-.kernel+rootfs:
+debian/arm32_test-gl:
variables:
- EXTRA_LOCAL_PACKAGES: "jq libasound2 libcairo2 libdw1 libglib2.0-0 libjson-c5"
+ EXTRA_LOCAL_PACKAGES: "jq libasound2t64 libcairo2 libdw1t64 libglib2.0-0t64 libjson-c5 libkmod2 libgles2 libdrm-nouveau2 libdrm-amdgpu1 libunwind8"
# Disable container jobs that we won't use
+alpine/x86_64_build:
+ rules:
+ - when: never
+
debian/arm64_test-vk:
rules:
- when: never
@@ -28,6 +36,10 @@ debian/baremetal_arm32_test-gl:
rules:
- when: never
+debian/baremetal_arm64_test-gl:
+ rules:
+ - when: never
+
debian/baremetal_arm64_test-vk:
rules:
- when: never
@@ -36,6 +48,10 @@ debian/ppc64el_build:
rules:
- when: never
+debian/riscv64_build:
+ rules:
+ - when: never
+
debian/s390x_build:
rules:
- when: never
diff --git a/drivers/gpu/drm/ci/gitlab-ci.yml b/drivers/gpu/drm/ci/gitlab-ci.yml
index 56638814bb28..56088c5393cd 100644
--- a/drivers/gpu/drm/ci/gitlab-ci.yml
+++ b/drivers/gpu/drm/ci/gitlab-ci.yml
@@ -1,6 +1,6 @@
variables:
DRM_CI_PROJECT_PATH: &drm-ci-project-path mesa/mesa
- DRM_CI_COMMIT_SHA: &drm-ci-commit-sha 02337aec715c25dae7ff2479d986f831c77fe536
+ DRM_CI_COMMIT_SHA: &drm-ci-commit-sha 25881c701a56233dd8fc7f92db6884a73949d63d
UPSTREAM_REPO: https://gitlab.freedesktop.org/drm/kernel.git
TARGET_BRANCH: drm-next
@@ -11,7 +11,7 @@ variables:
DEQP_RUNNER_GIT_TAG: v0.20.0
FDO_UPSTREAM_REPO: helen.fornazier/linux # The repo where the git-archive daily runs
- MESA_TEMPLATES_COMMIT: &ci-templates-commit c6aeb16f86e32525fa630fb99c66c4f3e62fc3cb
+ MESA_TEMPLATES_COMMIT: &ci-templates-commit aec7a6ce7bb38902c70641526f6611e27141784a
DRM_CI_PROJECT_URL: https://gitlab.freedesktop.org/${DRM_CI_PROJECT_PATH}
CI_PRE_CLONE_SCRIPT: |-
set -o xtrace
@@ -30,6 +30,8 @@ variables:
S3_GITCACHE_BUCKET: git-cache
# Bucket for the pipeline artifacts pushed to S3
S3_ARTIFACTS_BUCKET: artifacts
+ # Base path used for various artifacts
+ S3_BASE_PATH: "${S3_HOST}/${S3_KERNEL_BUCKET}"
# per-pipeline artifact storage on MinIO
PIPELINE_ARTIFACTS_BASE: ${S3_HOST}/${S3_ARTIFACTS_BUCKET}/${CI_PROJECT_PATH}/${CI_PIPELINE_ID}
# per-job artifact storage on MinIO
@@ -44,6 +46,8 @@ variables:
ARTIFACTS_BASE_URL: https://${CI_PROJECT_ROOT_NAMESPACE}.${CI_PAGES_DOMAIN}/-/${CI_PROJECT_NAME}/-/jobs/${CI_JOB_ID}/artifacts
# Python scripts for structured logger
PYTHONPATH: "$PYTHONPATH:$CI_PROJECT_DIR/install"
+ # Mesa-specific variables that shouldn't be forwarded to DUTs and crosvm
+ CI_EXCLUDE_ENV_VAR_REGEX: 'SCRIPTS_DIR|RESULTS_DIR'
default:
@@ -84,10 +88,11 @@ include:
- project: *drm-ci-project-path
ref: *drm-ci-commit-sha
file:
+ - '/.gitlab-ci/bare-metal/gitlab-ci.yml'
- '/.gitlab-ci/build/gitlab-ci.yml'
- '/.gitlab-ci/container/gitlab-ci.yml'
- '/.gitlab-ci/farm-rules.yml'
- - '/.gitlab-ci/lava/lava-gitlab-ci.yml'
+ - '/.gitlab-ci/lava/gitlab-ci.yml'
- '/.gitlab-ci/test-source-dep.yml'
- '/.gitlab-ci/test/gitlab-ci.yml'
- '/src/amd/ci/gitlab-ci-inc.yml'
@@ -131,6 +136,7 @@ stages:
- meson
- msm
- panfrost
+ - panthor
- powervr
- rockchip
- software-driver
@@ -147,10 +153,10 @@ stages:
- if: &is-merge-attempt $GITLAB_USER_LOGIN == "marge-bot" && $CI_PIPELINE_SOURCE == "merge_request_event"
# post-merge pipeline
- if: &is-post-merge $GITLAB_USER_LOGIN == "marge-bot" && $CI_PIPELINE_SOURCE == "push"
- # Pre-merge pipeline
- - if: &is-pre-merge $CI_PIPELINE_SOURCE == "merge_request_event"
+ # Pre-merge pipeline (because merge pipelines are already caught above)
+ - if: &is-merge-request $CI_PIPELINE_SOURCE == "merge_request_event"
# Push to a branch on a fork
- - if: &is-fork-push $CI_PIPELINE_SOURCE == "push"
+ - if: &is-push-to-fork $CI_PIPELINE_SOURCE == "push"
# nightly pipeline
- if: &is-scheduled-pipeline $CI_PIPELINE_SOURCE == "schedule"
# pipeline for direct pushes that bypassed the CI
@@ -160,17 +166,59 @@ stages:
# Rules applied to every job in the pipeline
.common-rules:
rules:
- - if: *is-fork-push
+ - if: *is-push-to-fork
when: manual
-
.never-post-merge-rules:
rules:
- if: *is-post-merge
when: never
-.container+build-rules:
+# Note: make sure the branches in this list are the same as in
+# `.build-only-delayed-rules` below.
+.container-rules:
+ rules:
+ - !reference [.common-rules, rules]
+ # Run when re-enabling a disabled farm, but not when disabling it
+ - !reference [.disable-farm-mr-rules, rules]
+ # Never run immediately after merging, as we just ran everything
+ - !reference [.never-post-merge-rules, rules]
+ # Only rebuild containers in merge pipelines if any tags have been
+ # changed, else we'll just use the already-built containers
+ - if: *is-merge-attempt
+ changes: &image_tags_path
+ - drivers/gpu/drm/ci/image-tags.yml
+ when: on_success
+ # Skip everything for pre-merge and merge pipelines which don't change
+ # anything in the build; we only do this for marge-bot and not user
+ # pipelines in a MR, because we might still need to run it to copy the
+ # container into the user's namespace.
+ - if: *is-merge-attempt
+ when: never
+ # Any MR pipeline which changes image-tags.yml needs to be able to
+ # rebuild the containers
+ - if: *is-merge-request
+ changes: *image_tags_path
+ when: manual
+ # ... however for MRs running inside the user namespace, we may need to
+ # run these jobs to copy the container images from upstream
+ - if: *is-merge-request
+ when: manual
+ # Build everything after someone bypassed the CI
+ - if: *is-direct-push
+ when: manual
+ # Scheduled pipelines reuse already-built containers
+ - if: *is-scheduled-pipeline
+ when: never
+ # Allow building everything in fork pipelines, but build nothing unless
+ # manually triggered
+ - when: manual
+
+
+# Note: make sure the branches in this list are the same as in
+# `.build-only-delayed-rules` below.
+.build-rules:
rules:
- !reference [.common-rules, rules]
# Run when re-enabling a disabled farm, but not when disabling it
@@ -181,7 +229,7 @@ stages:
- if: *is-merge-attempt
when: on_success
# Same as above, but for pre-merge pipelines
- - if: *is-pre-merge
+ - if: *is-merge-request
when: manual
# Build everything after someone bypassed the CI
- if: *is-direct-push
@@ -197,7 +245,7 @@ stages:
# Repeat of the above but with `when: on_success` replaced with
# `when: delayed` + `start_in:`, for build-only jobs.
# Note: make sure the branches in this list are the same as in
-# `.container+build-rules` above.
+# `.build-rules` above.
.build-only-delayed-rules:
rules:
- !reference [.common-rules, rules]
@@ -210,7 +258,7 @@ stages:
when: delayed
start_in: &build-delay 5 minutes
# Same as above, but for pre-merge pipelines
- - if: *is-pre-merge
+ - if: *is-merge-request
when: manual
# Build everything after someone bypassed the CI
- if: *is-direct-push
@@ -237,11 +285,6 @@ stages:
- _build/meson-logs/strace
-python-artifacts:
- variables:
- GIT_DEPTH: 10
-
-
# Git archive
make-git-archive:
extends:
@@ -273,7 +316,7 @@ sanity:
tags:
- $FDO_RUNNER_JOB_PRIORITY_TAG_X86_64
rules:
- - if: *is-pre-merge
+ - if: *is-merge-request
when: on_success
- when: never
variables:
@@ -284,7 +327,6 @@ sanity:
- |
set -eu
image_tags=(
- ALPINE_X86_64_LAVA_SSH_TAG
CONTAINER_TAG
DEBIAN_BASE_TAG
DEBIAN_BUILD_TAG
@@ -347,3 +389,19 @@ linkcheck-docs:
test-docs:
rules:
- when: never
+
+.ci-tron-x86_64-test-vk:
+ rules:
+ - when: never
+
+.ci-tron-x86_64-test-gl-manual:
+ rules:
+ - when: never
+
+.ci-tron-arm64-test-gl:
+ rules:
+ - when: never
+
+.ci-tron-x86_64-test-gl:
+ rules:
+ - when: never
diff --git a/drivers/gpu/drm/ci/igt_runner.sh b/drivers/gpu/drm/ci/igt_runner.sh
index b24d4bc53cda..741d30655ab5 100755
--- a/drivers/gpu/drm/ci/igt_runner.sh
+++ b/drivers/gpu/drm/ci/igt_runner.sh
@@ -1,6 +1,8 @@
-#!/bin/sh
+#!/usr/bin/env bash
# SPDX-License-Identifier: MIT
+. "${SCRIPTS_DIR}/setup-test-env.sh"
+
set -ex
export IGT_FORCE_DRIVER=${DRIVER_NAME}
@@ -21,7 +23,7 @@ set -e
mkdir -p /lib/modules
case "$DRIVER_NAME" in
- amdgpu|vkms)
+ amdgpu|vkms|panthor)
# Cannot use HWCI_KERNEL_MODULES as at that point we don't have the module in /lib
mv /install/modules/lib/modules/* /lib/modules/. || true
modprobe --first-time $DRIVER_NAME
diff --git a/drivers/gpu/drm/ci/image-tags.yml b/drivers/gpu/drm/ci/image-tags.yml
index 7acc2e2a8eaa..7c43ae22bfd3 100644
--- a/drivers/gpu/drm/ci/image-tags.yml
+++ b/drivers/gpu/drm/ci/image-tags.yml
@@ -1,18 +1,22 @@
variables:
- CONTAINER_TAG: "20250502-mesa-uprev"
- DEBIAN_BASE_TAG: "${CONTAINER_TAG}"
+ CONTAINER_TAG: "20260108-mesa-igt"
+
+ DEBIAN_BUILD_BASE_TAG: "${CONTAINER_TAG}"
DEBIAN_BUILD_TAG: "${CONTAINER_TAG}"
+ DEBIAN_TEST_BASE_TAG: "${CONTAINER_TAG}"
DEBIAN_TEST_GL_TAG: "${CONTAINER_TAG}"
# default kernel for rootfs before injecting the current kernel tree
- KERNEL_TAG: "v6.14-mesa-0bdd"
+ KERNEL_TAG: "v6.16-mesa-9d85"
KERNEL_REPO: "gfx-ci/linux"
- PKG_REPO_REV: "95bf62c"
-
- DEBIAN_PYUTILS_TAG: "${CONTAINER_TAG}"
+ PKG_REPO_REV: "0d2527f6"
+ FIRMWARE_TAG: "8fc31b97"
+ FIRMWARE_REPO: "gfx-ci/firmware"
ALPINE_X86_64_BUILD_TAG: "${CONTAINER_TAG}"
- ALPINE_X86_64_LAVA_SSH_TAG: "${CONTAINER_TAG}"
- CONDITIONAL_BUILD_ANGLE_TAG: 384145a4023315dae658259bee07c43a
- CONDITIONAL_BUILD_PIGLIT_TAG: a19e424b8a3f020dbf1b9dd29f220a4f
+ CONDITIONAL_BUILD_ANGLE_TAG: efd57e99d51361944f87b9466356b0ce
+ CONDITIONAL_BUILD_CROSVM_TAG: 4079babd375b09761d59eacb25a0598a
+ CONDITIONAL_BUILD_PIGLIT_TAG: 21ab2c66f54777163dd038dc4cfcfde6
+
+ CROSVM_TAG: ${CONDITIONAL_BUILD_CROSVM_TAG}
diff --git a/drivers/gpu/drm/ci/lava-submit.sh b/drivers/gpu/drm/ci/lava-submit.sh
index a295102c3468..405055aa9cc4 100755
--- a/drivers/gpu/drm/ci/lava-submit.sh
+++ b/drivers/gpu/drm/ci/lava-submit.sh
@@ -3,27 +3,18 @@
# shellcheck disable=SC2086 # we want word splitting
# shellcheck disable=SC1091 # paths only become valid at runtime
-# If we run in the fork (not from mesa or Marge-bot), reuse mainline kernel and rootfs, if exist.
-_check_artifact_path() {
- _url="https://${1}/${2}"
- if curl -s -o /dev/null -I -L -f --retry 4 --retry-delay 15 "${_url}"; then
- echo -n "${_url}"
- fi
-}
+# shellcheck disable=SC1090
+source "${FDO_CI_BASH_HELPERS}"
-get_path_to_artifact() {
- _mainline_artifact="$(_check_artifact_path ${BASE_SYSTEM_MAINLINE_HOST_PATH} ${1})"
- if [ -n "${_mainline_artifact}" ]; then
- echo -n "${_mainline_artifact}"
- return
- fi
- _fork_artifact="$(_check_artifact_path ${BASE_SYSTEM_FORK_HOST_PATH} ${1})"
- if [ -n "${_fork_artifact}" ]; then
- echo -n "${_fork_artifact}"
- return
- fi
+fdo_log_section_start_collapsed prepare_rootfs "Preparing root filesystem"
+
+set -ex
+
+# If we run in the fork (not from mesa or Marge-bot), reuse mainline kernel and rootfs, if exist.
+ROOTFS_URL="$(fdo_find_s3_path "$LAVA_ROOTFS_PATH")" ||
+{
set +x
- error "Sorry, I couldn't find a viable built path for ${1} in either mainline or a fork." >&2
+ fdo_log_section_error "Sorry, I couldn't find a viable built path for ${LAVA_ROOTFS_PATH} in either mainline or a fork." >&2
echo "" >&2
echo "If you're working on CI, this probably means that you're missing a dependency:" >&2
echo "this job ran ahead of the job which was supposed to upload that artifact." >&2
@@ -35,38 +26,51 @@ get_path_to_artifact() {
exit 1
}
-. "${SCRIPTS_DIR}/setup-test-env.sh"
-
-section_start prepare_rootfs "Preparing root filesystem"
-
-set -ex
-
-ROOTFS_URL="$(get_path_to_artifact lava-rootfs.tar.zst)"
-[ $? != 1 ] || exit 1
-
rm -rf results
-mkdir -p results/job-rootfs-overlay/
+mkdir results
-artifacts/ci-common/export-gitlab-job-env-for-dut.sh \
- > results/job-rootfs-overlay/set-job-env-vars.sh
-cp artifacts/ci-common/init-*.sh results/job-rootfs-overlay/
-cp "$SCRIPTS_DIR"/setup-test-env.sh results/job-rootfs-overlay/
+fdo_filter_env_vars > dut-env-vars.sh
+# Set SCRIPTS_DIR to point to the Mesa install we download for the DUT
+echo "export SCRIPTS_DIR='$CI_PROJECT_DIR/install'" >> dut-env-vars.sh
-tar zcf job-rootfs-overlay.tar.gz -C results/job-rootfs-overlay/ .
-ci-fairy s3cp --token-file "${S3_JWT_FILE}" job-rootfs-overlay.tar.gz "https://${JOB_ROOTFS_OVERLAY_PATH}"
+fdo_log_section_end prepare_rootfs
# Prepare env vars for upload.
-section_switch variables "Environment variables passed through to device:"
-cat results/job-rootfs-overlay/set-job-env-vars.sh
+fdo_log_section_start_collapsed variables "Environment variables passed through to device:"
+cat dut-env-vars.sh
+fdo_log_section_end variables
-section_switch lava_submit "Submitting job for scheduling"
+fdo_log_section_start_collapsed lava_submit "Submitting job for scheduling"
touch results/lava.log
tail -f results/lava.log &
# Ensure that we are printing the commands that are being executed,
# making it easier to debug the job in case it fails.
set -x
-PYTHONPATH=artifacts/ artifacts/lava/lava_job_submitter.py \
+
+# List of optional overlays
+LAVA_EXTRA_OVERLAYS=()
+if [ -n "${LAVA_FIRMWARE:-}" ]; then
+ for fw in $LAVA_FIRMWARE; do
+ LAVA_EXTRA_OVERLAYS+=(
+ - append-overlay
+ --name=linux-firmware
+ --url="https://${S3_BASE_PATH}/${FIRMWARE_REPO}/${fw}-${FIRMWARE_TAG}.tar"
+ --path="/"
+ --format=tar
+ )
+ done
+fi
+LAVA_EXTRA_OVERLAYS+=(
+ - append-overlay \
+ --name=kernel-build \
+ --url="${FDO_HTTP_CACHE_URI:-}https://${PIPELINE_ARTIFACTS_BASE}/${DEBIAN_ARCH}/kernel-files.tar.zst" \
+ --compression=zstd \
+ --path="${CI_PROJECT_DIR}" \
+ --format=tar \
+)
+
+lava-job-submitter \
--farm "${FARM}" \
--device-type "${DEVICE_TYPE}" \
--boot-method "${BOOT_METHOD}" \
@@ -75,9 +79,8 @@ PYTHONPATH=artifacts/ artifacts/lava/lava_job_submitter.py \
--pipeline-info "$CI_JOB_NAME: $CI_PIPELINE_URL on $CI_COMMIT_REF_NAME ${CI_NODE_INDEX}/${CI_NODE_TOTAL}" \
--rootfs-url "${ROOTFS_URL}" \
--kernel-url-prefix "https://${PIPELINE_ARTIFACTS_BASE}/${DEBIAN_ARCH}" \
- --kernel-external "${EXTERNAL_KERNEL_TAG}" \
- --first-stage-init artifacts/ci-common/init-stage1.sh \
--dtb-filename "${DTB}" \
+ --env-file dut-env-vars.sh \
--jwt-file "${S3_JWT_FILE}" \
--kernel-image-name "${KERNEL_IMAGE_NAME}" \
--kernel-image-type "${KERNEL_IMAGE_TYPE}" \
@@ -86,20 +89,10 @@ PYTHONPATH=artifacts/ artifacts/lava/lava_job_submitter.py \
--mesa-job-name "$CI_JOB_NAME" \
--structured-log-file "results/lava_job_detail.json" \
--ssh-client-image "${LAVA_SSH_CLIENT_IMAGE}" \
+ --project-dir "${CI_PROJECT_DIR}" \
--project-name "${CI_PROJECT_NAME}" \
- --starting-section "${CURRENT_SECTION}" \
+ --starting-section lava_submit \
--job-submitted-at "${CI_JOB_STARTED_AT}" \
- - append-overlay \
- --name=kernel-build \
- --url="${FDO_HTTP_CACHE_URI:-}https://${PIPELINE_ARTIFACTS_BASE}/${DEBIAN_ARCH}/kernel-files.tar.zst" \
- --compression=zstd \
- --path="${CI_PROJECT_DIR}" \
- --format=tar \
- - append-overlay \
- --name=job-overlay \
- --url="https://${JOB_ROOTFS_OVERLAY_PATH}" \
- --compression=gz \
- --path="/" \
- --format=tar \
+ "${LAVA_EXTRA_OVERLAYS[@]}" \
- submit \
>> results/lava.log
diff --git a/drivers/gpu/drm/ci/static-checks.yml b/drivers/gpu/drm/ci/static-checks.yml
index 13ffa827b7fa..712d3efe99c6 100644
--- a/drivers/gpu/drm/ci/static-checks.yml
+++ b/drivers/gpu/drm/ci/static-checks.yml
@@ -1,4 +1,5 @@
check-patch:
+ stage: static-checks
extends:
- .build
- .use-debian/x86_64_build
diff --git a/drivers/gpu/drm/ci/test.yml b/drivers/gpu/drm/ci/test.yml
index 81147e86bfd0..f6bee5b67931 100644
--- a/drivers/gpu/drm/ci/test.yml
+++ b/drivers/gpu/drm/ci/test.yml
@@ -7,13 +7,16 @@
.lava-test:
extends:
- - .container+build-rules
+ - .build-rules
- .allow_failure_lockdep
timeout: "1h30m"
rules:
- !reference [.scheduled_pipeline-rules, rules]
- !reference [.collabora-farm-rules, rules]
- when: on_success
+ before_script:
+ # lava-submit.sh is a part of the archive, unlike Mesa CI
+ - eval "$S3_JWT_FILE_SCRIPT"
script:
# Note: Build dir (and thus install) may be dirty due to GIT_STRATEGY
- rm -rf install
@@ -32,9 +35,7 @@
dependencies:
- testing:arm32
needs:
- - alpine/x86_64_lava_ssh_client
- debian/arm32_test-gl
- - python-artifacts
- testing:arm32
- igt:arm32
@@ -48,9 +49,7 @@
dependencies:
- testing:arm64
needs:
- - alpine/x86_64_lava_ssh_client
- debian/arm64_test-gl
- - python-artifacts
- testing:arm64
- igt:arm64
@@ -64,37 +63,10 @@
dependencies:
- testing:x86_64
needs:
- - alpine/x86_64_lava_ssh_client
- debian/x86_64_test-gl
- - python-artifacts
- testing:x86_64
- igt:x86_64
-.baremetal-igt-arm64:
- extends:
- - .baremetal-test-arm64-gl
- - .use-debian/baremetal_arm64_test-gl
- - .allow_failure_lockdep
- timeout: "1h30m"
- rules:
- - !reference [.scheduled_pipeline-rules, rules]
- - !reference [.google-freedreno-farm-rules, rules]
- - when: on_success
- variables:
- FDO_CI_CONCURRENT: 10
- HWCI_TEST_SCRIPT: "/install/igt_runner.sh"
- S3_ARTIFACT_NAME: "arm64/kernel-files"
- BM_KERNEL: https://${PIPELINE_ARTIFACTS_BASE}/arm64/Image.gz
- BM_CMDLINE: "ip=dhcp console=ttyMSM0,115200n8 $BM_KERNEL_EXTRA_ARGS root=/dev/nfs rw nfsrootdebug nfsroot=,tcp,nfsvers=4.2 init=/init $BM_KERNELARGS"
- FARM: google
- needs:
- - debian/baremetal_arm64_test-gl
- - job: testing:arm64
- artifacts: false
- - igt:arm64
- tags:
- - $RUNNER_TAG
-
.software-driver:
stage: software-driver
extends:
@@ -110,6 +82,7 @@
- !reference [default, before_script]
- rm -rf install
- tar -xf artifacts/install.tar
+ - mkdir -p /kernel
script:
- ln -sf $CI_PROJECT_DIR/install /install
- mv install/bzImage /kernel/bzImage
@@ -127,6 +100,7 @@
DRIVER_NAME: msm
BOOT_METHOD: depthcharge
KERNEL_IMAGE_TYPE: ""
+ LAVA_FIRMWARE: qcom-lava
msm:sc7180-trogdor-lazor-limozeen:
extends:
@@ -150,40 +124,43 @@ msm:sc7180-trogdor-kingoftown:
msm:apq8016:
extends:
- - .baremetal-igt-arm64
+ - .lava-igt:arm64
stage: msm
+ parallel: 3
variables:
- DEVICE_TYPE: apq8016-sbc-usb-host
+ BOOT_METHOD: fastboot
+ DEVICE_TYPE: dragonboard-410c
DRIVER_NAME: msm
- BM_DTB: https://${PIPELINE_ARTIFACTS_BASE}/arm64/${DEVICE_TYPE}.dtb
+ DTB: apq8016-sbc-usb-host
+ FARM: collabora
GPU_VERSION: apq8016
- # disabling unused clocks congests with the MDSS runtime PM trying to
- # disable those clocks and causes boot to fail.
- # Reproducer: DRM_MSM=y, DRM_I2C_ADV7511=m
- BM_KERNEL_EXTRA_ARGS: clk_ignore_unused
- RUNNER_TAG: google-freedreno-db410c
- script:
- - ./install/bare-metal/fastboot.sh || exit $?
+ KERNEL_IMAGE_NAME: "Image.gz"
+ KERNEL_IMAGE_TYPE: ""
+ RUNNER_TAG: mesa-ci-x86-64-lava-dragonboard-410c
+ LAVA_FIRMWARE: qcom-lava
msm:apq8096:
extends:
- - .baremetal-igt-arm64
+ - .lava-igt:arm64
stage: msm
+ parallel: 3
variables:
- DEVICE_TYPE: apq8096-db820c
+ BOOT_METHOD: fastboot
+ DEVICE_TYPE: dragonboard-820c
DRIVER_NAME: msm
- BM_KERNEL_EXTRA_ARGS: maxcpus=2
- BM_DTB: https://${PIPELINE_ARTIFACTS_BASE}/arm64/${DEVICE_TYPE}.dtb
+ DTB: apq8096-db820c
+ FARM: collabora
GPU_VERSION: apq8096
- RUNNER_TAG: google-freedreno-db820c
- script:
- - ./install/bare-metal/fastboot.sh || exit $?
+ KERNEL_IMAGE_NAME: "Image.gz"
+ KERNEL_IMAGE_TYPE: ""
+ RUNNER_TAG: mesa-ci-x86-64-lava-dragonboard-820c
+ LAVA_FIRMWARE: qcom-lava
msm:sm8350-hdk:
extends:
- .lava-igt:arm64
stage: msm
- parallel: 4
+ parallel: 2
variables:
BOOT_METHOD: fastboot
DEVICE_TYPE: sm8350-hdk
@@ -194,11 +171,14 @@ msm:sm8350-hdk:
KERNEL_IMAGE_NAME: "Image.gz"
KERNEL_IMAGE_TYPE: ""
RUNNER_TAG: mesa-ci-x86-64-lava-sm8350-hdk
+ LAVA_FIRMWARE: qcom-lava
+ LAVA_FASTBOOT_CMD: "set_active a"
.rockchip-device:
variables:
DTB: ${DEVICE_TYPE}
BOOT_METHOD: depthcharge
+ LAVA_FIRMWARE: arm
.rockchip-display:
stage: rockchip
@@ -226,6 +206,19 @@ msm:sm8350-hdk:
KERNEL_IMAGE_TYPE: ""
RUNNER_TAG: mesa-ci-x86-64-lava-rk3399-gru-kevin
+.rk3588:
+ extends:
+ - .lava-igt:arm64
+ - .rockchip-device
+ parallel: 2
+ variables:
+ DEVICE_TYPE: rk3588-rock-5b
+ GPU_VERSION: rk3588
+ BOOT_METHOD: u-boot
+ KERNEL_IMAGE_NAME: Image
+ KERNEL_IMAGE_TYPE: "image"
+ RUNNER_TAG: mesa-ci-x86-64-lava-rk3588-rock-5b
+
rockchip:rk3288:
extends:
- .rk3288
@@ -246,6 +239,16 @@ panfrost:rk3399:
- .rk3399
- .panfrost-gpu
+rockchip:rk3588:
+ extends:
+ - .rk3588
+ - .rockchip-display
+
+panthor:rk3588:
+ extends:
+ - .rk3588
+ - .panthor-gpu
+
.i915:
extends:
- .lava-igt:x86_64
@@ -255,6 +258,7 @@ panfrost:rk3399:
DTB: ""
BOOT_METHOD: depthcharge
KERNEL_IMAGE_TYPE: ""
+ LAVA_FIRMWARE: i915
i915:apl:
extends:
@@ -277,7 +281,7 @@ i915:glk:
i915:amly:
extends:
- .i915
- parallel: 2
+ parallel: 3
variables:
DEVICE_TYPE: asus-C433TA-AJ0005-rammus
GPU_VERSION: amly
@@ -304,11 +308,11 @@ i915:whl:
i915:cml:
extends:
- .i915
- parallel: 2
+ parallel: 5
variables:
- DEVICE_TYPE: asus-C436FA-Flip-hatch
+ DEVICE_TYPE: acer-chromebox-cxi4-puff
GPU_VERSION: cml
- RUNNER_TAG: mesa-ci-x86-64-lava-asus-C436FA-Flip-hatch
+ RUNNER_TAG: mesa-ci-x86-64-lava-acer-chromebox-cxi4-puff
i915:tgl:
extends:
@@ -337,6 +341,7 @@ i915:jsl:
DTB: ""
BOOT_METHOD: depthcharge
KERNEL_IMAGE_TYPE: ""
+ LAVA_FIRMWARE: amdgpu-lava
amdgpu:stoney:
extends:
@@ -355,6 +360,7 @@ amdgpu:stoney:
DTB: ${DEVICE_TYPE}
BOOT_METHOD: depthcharge
KERNEL_IMAGE_TYPE: ""
+ LAVA_FIRMWARE: arm
.mediatek-display:
stage: mediatek
@@ -371,6 +377,11 @@ amdgpu:stoney:
variables:
DRIVER_NAME: panfrost
+.panthor-gpu:
+ stage: panthor
+ variables:
+ DRIVER_NAME: panthor
+
.mt8173:
extends:
- .mediatek-device
diff --git a/drivers/gpu/drm/ci/xfails/amdgpu-stoney-fails.txt b/drivers/gpu/drm/ci/xfails/amdgpu-stoney-fails.txt
index f44dbce3151a..442d3bc3d90b 100644
--- a/drivers/gpu/drm/ci/xfails/amdgpu-stoney-fails.txt
+++ b/drivers/gpu/drm/ci/xfails/amdgpu-stoney-fails.txt
@@ -3,9 +3,10 @@ amdgpu/amd_abm@abm_gradual,Fail
amdgpu/amd_abm@backlight_monotonic_abm,Fail
amdgpu/amd_abm@backlight_monotonic_basic,Fail
amdgpu/amd_abm@dpms_cycle,Fail
-amdgpu/amd_assr@assr-links,Fail
amdgpu/amd_assr@assr-links-dpms,Fail
-amdgpu/amd_mall@static-screen,Crash
+amdgpu/amd_assr@assr-links,Fail
+amdgpu/amd_basic@cs-gfx-with-IP-GFX,Fail
+amdgpu/amd_basic@cs-multi-fence-with-IP-GFX,Fail
amdgpu/amd_mode_switch@mode-switch-first-last-pipe-2,Crash
amdgpu/amd_plane@mpo-pan-nv12,Fail
amdgpu/amd_plane@mpo-pan-p010,Fail
@@ -13,11 +14,13 @@ amdgpu/amd_plane@mpo-pan-rgb,Crash
amdgpu/amd_plane@mpo-scale-nv12,Fail
amdgpu/amd_plane@mpo-scale-p010,Fail
amdgpu/amd_plane@mpo-scale-rgb,Crash
-amdgpu/amd_plane@mpo-swizzle-toggle,Fail
+amdgpu/amd_plane@mpo-swizzle-toggle,Crash
amdgpu/amd_uvd_dec@amdgpu_uvd_decode,Fail
+core_setmaster@master-drop-set-user,Fail
kms_addfb_basic@bad-pitch-65536,Fail
kms_addfb_basic@bo-too-small,Fail
kms_addfb_basic@too-high,Fail
+kms_async_flips@basic-modeset-with-all-modifiers-formats,Crash
kms_atomic_transition@plane-all-modeset-transition-internal-panels,Fail
kms_atomic_transition@plane-all-transition,Fail
kms_atomic_transition@plane-all-transition-nonblocking,Fail
@@ -33,8 +36,10 @@ kms_cursor_crc@cursor-sliding-64x64,Fail
kms_cursor_edge_walk@64x64-left-edge,Fail
kms_flip@flip-vs-modeset-vs-hang,Fail
kms_flip@flip-vs-panning-vs-hang,Fail
+kms_invalid_mode@int-max-clock,Fail
+kms_invalid_mode@overflow-vrefresh,Fail
kms_lease@lease-uevent,Fail
-kms_plane@pixel-format,Fail
kms_plane_cursor@primary,Fail
+kms_plane@pixel-format,Fail
kms_rotation_crc@primary-rotation-180,Fail
perf@i915-ref-count,Fail
diff --git a/drivers/gpu/drm/ci/xfails/amdgpu-stoney-flakes.txt b/drivers/gpu/drm/ci/xfails/amdgpu-stoney-flakes.txt
index adffb011298a..8b81af104b30 100644
--- a/drivers/gpu/drm/ci/xfails/amdgpu-stoney-flakes.txt
+++ b/drivers/gpu/drm/ci/xfails/amdgpu-stoney-flakes.txt
@@ -32,3 +32,10 @@ kms_async_flips@async-flip-with-page-flip-events-atomic
# IGT Version: 1.29-g33adea9eb
# Linux Version: 6.13.0-rc2
kms_async_flips@crc-atomic
+
+# Board Name: hp-11A-G6-EE-grunt
+# Bug Report: https://gitlab.freedesktop.org/drm/amd/-/issues/4406
+# Failure Rate: 20
+# IGT Version: 2.1-g26ddb59c1
+# Linux Version: 6.16.0-rc2
+kms_async_flips@alternate-sync-async-flip
diff --git a/drivers/gpu/drm/ci/xfails/i915-amly-fails.txt b/drivers/gpu/drm/ci/xfails/i915-amly-fails.txt
index 8e2b5504004e..ff0c10626004 100644
--- a/drivers/gpu/drm/ci/xfails/i915-amly-fails.txt
+++ b/drivers/gpu/drm/ci/xfails/i915-amly-fails.txt
@@ -1,43 +1,18 @@
-core_setmaster_vs_auth,Fail
i915_module_load@load,Fail
i915_module_load@reload,Fail
i915_module_load@reload-no-display,Fail
i915_module_load@resize-bar,Fail
i915_pm_rpm@gem-execbuf-stress,Timeout
i915_pm_rpm@module-reload,Fail
-kms_ccs@ccs-on-another-bo-y-tiled-gen12-rc-ccs-cc,Timeout
-kms_fb_coherency@memset-crc,Crash
-kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-downscaling,Fail
-kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-upscaling,Fail
-kms_flip_scaled_crc@flip-32bpp-xtile-to-64bpp-xtile-upscaling,Fail
-kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-downscaling,Fail
kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-upscaling,Fail
-kms_flip_scaled_crc@flip-32bpp-ytileccs-to-64bpp-ytile-downscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-linear-to-16bpp-linear-downscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-linear-to-16bpp-linear-upscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-linear-to-32bpp-linear-downscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-linear-to-32bpp-linear-upscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-xtile-to-16bpp-xtile-downscaling,Fail
kms_flip_scaled_crc@flip-64bpp-xtile-to-16bpp-xtile-upscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-xtile-to-32bpp-xtile-downscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-xtile-to-32bpp-xtile-upscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-ytile-to-16bpp-ytile-downscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-ytile-to-16bpp-ytile-upscaling,Fail
kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-downscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-upscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilegen12rcccs-upscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilercccs-downscaling,Fail
-kms_frontbuffer_tracking@fbc-rgb101010-draw-mmap-cpu,Timeout
kms_lease@lease-uevent,Fail
kms_plane_alpha_blend@alpha-basic,Fail
kms_plane_alpha_blend@alpha-opaque-fb,Fail
kms_plane_alpha_blend@alpha-transparent-fb,Fail
kms_plane_alpha_blend@constant-alpha-max,Fail
-kms_plane_scaling@planes-upscale-factor-0-25,Timeout
-kms_pm_backlight@brightness-with-dpms,Crash
-kms_pm_backlight@fade,Crash
-kms_prop_blob@invalid-set-prop-any,Fail
-kms_properties@connector-properties-legacy,Timeout
+kms_pm_rpm@modeset-stress-extra-wait,Timeout
kms_universal_plane@disable-primary-vs-flip,Timeout
perf@i915-ref-count,Fail
perf_pmu@module-unload,Fail
diff --git a/drivers/gpu/drm/ci/xfails/i915-apl-fails.txt b/drivers/gpu/drm/ci/xfails/i915-apl-fails.txt
index 7353ab11e940..032f7adeeff2 100644
--- a/drivers/gpu/drm/ci/xfails/i915-apl-fails.txt
+++ b/drivers/gpu/drm/ci/xfails/i915-apl-fails.txt
@@ -1,29 +1,9 @@
+core_setmaster@master-drop-set-user,Fail
i915_module_load@load,Fail
i915_module_load@reload,Fail
i915_module_load@reload-no-display,Fail
i915_module_load@resize-bar,Fail
-kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-downscaling,Fail
-kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-upscaling,Fail
-kms_flip_scaled_crc@flip-32bpp-xtile-to-64bpp-xtile-downscaling,Fail
-kms_flip_scaled_crc@flip-32bpp-xtile-to-64bpp-xtile-upscaling,Fail
-kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-downscaling,Fail
-kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-upscaling,Fail
-kms_flip_scaled_crc@flip-32bpp-ytileccs-to-64bpp-ytile-downscaling,Fail
-kms_flip_scaled_crc@flip-32bpp-ytileccs-to-64bpp-ytile-upscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-linear-to-16bpp-linear-downscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-linear-to-16bpp-linear-upscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-linear-to-32bpp-linear-downscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-linear-to-32bpp-linear-upscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-xtile-to-16bpp-xtile-downscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-xtile-to-16bpp-xtile-upscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-xtile-to-32bpp-xtile-downscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-xtile-to-32bpp-xtile-upscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-ytile-to-16bpp-ytile-downscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-ytile-to-16bpp-ytile-upscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-downscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-upscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilegen12rcccs-upscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilercccs-downscaling,Fail
+kms_flip@flip-vs-wf_vblank-interruptible,Fail
kms_lease@lease-uevent,Fail
kms_plane_alpha_blend@alpha-basic,Fail
kms_plane_alpha_blend@alpha-opaque-fb,Fail
diff --git a/drivers/gpu/drm/ci/xfails/i915-cml-fails.txt b/drivers/gpu/drm/ci/xfails/i915-cml-fails.txt
index 6fef7c1e56ea..351cb06228ff 100644
--- a/drivers/gpu/drm/ci/xfails/i915-cml-fails.txt
+++ b/drivers/gpu/drm/ci/xfails/i915-cml-fails.txt
@@ -1,4 +1,5 @@
-core_setmaster_vs_auth,Fail
+api_intel_bb@intel-bb-blit-none,Timeout
+core_setmaster@master-drop-set-user,Fail
i915_module_load@load,Fail
i915_module_load@reload,Fail
i915_module_load@reload-no-display,Fail
@@ -8,18 +9,15 @@ i915_pipe_stress@stress-xrgb8888-ytiled,Fail
i915_pm_rpm@gem-execbuf-stress,Timeout
i915_pm_rpm@module-reload,Fail
i915_pm_rpm@system-suspend-execbuf,Timeout
-kms_ccs@ccs-on-another-bo-y-tiled-gen12-rc-ccs-cc,Timeout
-kms_cursor_crc@cursor-suspend,Timeout
-kms_fb_coherency@memset-crc,Crash
kms_flip@busy-flip,Timeout
kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-downscaling,Fail
kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-upscaling,Fail
kms_flip_scaled_crc@flip-32bpp-xtile-to-64bpp-xtile-downscaling,Fail
kms_flip_scaled_crc@flip-32bpp-xtile-to-64bpp-xtile-upscaling,Fail
-kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-downscaling,Fail
-kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-upscaling,Fail
kms_flip_scaled_crc@flip-32bpp-ytileccs-to-64bpp-ytile-downscaling,Fail
kms_flip_scaled_crc@flip-32bpp-ytileccs-to-64bpp-ytile-upscaling,Fail
+kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-downscaling,Fail
+kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-upscaling,Fail
kms_flip_scaled_crc@flip-64bpp-linear-to-16bpp-linear-downscaling,Fail
kms_flip_scaled_crc@flip-64bpp-linear-to-16bpp-linear-upscaling,Fail
kms_flip_scaled_crc@flip-64bpp-linear-to-32bpp-linear-downscaling,Fail
@@ -31,39 +29,18 @@ kms_flip_scaled_crc@flip-64bpp-xtile-to-32bpp-xtile-upscaling,Fail
kms_flip_scaled_crc@flip-64bpp-ytile-to-16bpp-ytile-downscaling,Fail
kms_flip_scaled_crc@flip-64bpp-ytile-to-16bpp-ytile-upscaling,Fail
kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-downscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-upscaling,Fail
kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilegen12rcccs-upscaling,Fail
kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilercccs-downscaling,Fail
+kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-upscaling,Fail
kms_lease@lease-uevent,Fail
-kms_pipe_stress@stress-xrgb8888-untiled,Fail
-kms_pipe_stress@stress-xrgb8888-ytiled,Fail
-kms_plane_alpha_blend@alpha-basic,Fail
-kms_plane_alpha_blend@alpha-opaque-fb,Fail
-kms_plane_alpha_blend@alpha-transparent-fb,Fail
-kms_plane_alpha_blend@constant-alpha-max,Fail
-kms_plane_scaling@planes-upscale-factor-0-25,Timeout
-kms_pm_backlight@brightness-with-dpms,Crash
-kms_pm_backlight@fade,Crash
-kms_prop_blob@invalid-set-prop-any,Fail
-kms_properties@connector-properties-legacy,Timeout
+kms_pm_rpm@basic-rte,Fail
kms_psr2_sf@cursor-plane-update-sf,Fail
kms_psr2_sf@overlay-plane-update-continuous-sf,Fail
kms_psr2_sf@overlay-plane-update-sf-dmg-area,Fail
kms_psr2_sf@overlay-primary-update-sf-dmg-area,Fail
kms_psr2_sf@plane-move-sf-dmg-area,Fail
-kms_psr2_sf@primary-plane-update-sf-dmg-area,Fail
kms_psr2_sf@primary-plane-update-sf-dmg-area-big-fb,Fail
-kms_psr2_sf@psr2-cursor-plane-update-sf,Fail
-kms_psr2_sf@psr2-overlay-plane-update-continuous-sf,Fail
-kms_psr2_sf@psr2-overlay-plane-update-sf-dmg-area,Fail
-kms_psr2_sf@psr2-overlay-primary-update-sf-dmg-area,Fail
-kms_psr2_sf@psr2-plane-move-sf-dmg-area,Fail
-kms_psr2_sf@psr2-primary-plane-update-sf-dmg-area,Fail
-kms_psr2_sf@psr2-primary-plane-update-sf-dmg-area-big-fb,Fail
-kms_psr2_su@page_flip-NV12,Fail
-kms_psr2_su@page_flip-P010,Fail
-kms_setmode@basic,Fail
-kms_universal_plane@disable-primary-vs-flip,Timeout
+kms_psr2_sf@primary-plane-update-sf-dmg-area,Fail
perf@i915-ref-count,Fail
perf_pmu@module-unload,Fail
perf_pmu@rc6,Crash
diff --git a/drivers/gpu/drm/ci/xfails/i915-cml-flakes.txt b/drivers/gpu/drm/ci/xfails/i915-cml-flakes.txt
index 5343cc1c8696..5e5b9901a08e 100644
--- a/drivers/gpu/drm/ci/xfails/i915-cml-flakes.txt
+++ b/drivers/gpu/drm/ci/xfails/i915-cml-flakes.txt
@@ -32,3 +32,10 @@ kms_async_flips@crc
# IGT Version: 1.29-g33adea9eb
# Linux Version: 6.13.0-rc2
gen9_exec_parse@unaligned-access
+
+# Board Name: asus-C436FA-Flip-hatch
+# Bug Report: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14625
+# Failure Rate: 100
+# IGT Version: 2.1-g26ddb59c1
+# Linux Version: 6.16.0-rc2
+perf_pmu@most-busy-check-all
diff --git a/drivers/gpu/drm/ci/xfails/i915-glk-fails.txt b/drivers/gpu/drm/ci/xfails/i915-glk-fails.txt
index 8adf5f0a6e80..5d79b65cd354 100644
--- a/drivers/gpu/drm/ci/xfails/i915-glk-fails.txt
+++ b/drivers/gpu/drm/ci/xfails/i915-glk-fails.txt
@@ -4,41 +4,31 @@ i915_module_load@load,Fail
i915_module_load@reload,Fail
i915_module_load@reload-no-display,Fail
i915_module_load@resize-bar,Fail
+kms_dirtyfb@default-dirtyfb-ioctl,Fail
kms_dirtyfb@drrs-dirtyfb-ioctl,Fail
+kms_dirtyfb@fbc-dirtyfb-ioctl,Fail
kms_flip@blocking-wf_vblank,Fail
-kms_flip@wf_vblank-ts-check,Fail
-kms_flip@wf_vblank-ts-check-interruptible,Fail
-kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-downscaling,Fail
kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-upscaling,Fail
kms_flip_scaled_crc@flip-32bpp-xtile-to-64bpp-xtile-upscaling,Fail
-kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-downscaling,Fail
-kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-upscaling,Fail
kms_flip_scaled_crc@flip-32bpp-ytileccs-to-64bpp-ytile-downscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-linear-to-16bpp-linear-downscaling,Fail
+kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-upscaling,Fail
kms_flip_scaled_crc@flip-64bpp-linear-to-16bpp-linear-upscaling,Fail
kms_flip_scaled_crc@flip-64bpp-linear-to-32bpp-linear-downscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-linear-to-32bpp-linear-upscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-xtile-to-16bpp-xtile-downscaling,Fail
kms_flip_scaled_crc@flip-64bpp-xtile-to-16bpp-xtile-upscaling,Fail
kms_flip_scaled_crc@flip-64bpp-xtile-to-32bpp-xtile-downscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-xtile-to-32bpp-xtile-upscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-ytile-to-16bpp-ytile-downscaling,Fail
kms_flip_scaled_crc@flip-64bpp-ytile-to-16bpp-ytile-upscaling,Fail
kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-downscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-upscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilegen12rcccs-upscaling,Fail
kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilercccs-downscaling,Fail
-kms_frontbuffer_tracking@fbc-rgb101010-draw-mmap-cpu,Timeout
+kms_flip@wf_vblank-ts-check,Fail
+kms_flip@wf_vblank-ts-check-interruptible,Fail
+kms_frontbuffer_tracking@fbcdrrs-tiling-linear,Fail
kms_frontbuffer_tracking@fbc-tiling-linear,Fail
kms_lease@lease-uevent,Fail
kms_plane_alpha_blend@alpha-opaque-fb,Fail
kms_plane_scaling@planes-upscale-factor-0-25,Timeout
-kms_pm_backlight@brightness-with-dpms,Crash
-kms_pm_backlight@fade,Crash
kms_prop_blob@invalid-set-prop-any,Fail
kms_properties@connector-properties-legacy,Timeout
kms_rotation_crc@multiplane-rotation,Fail
-kms_rotation_crc@multiplane-rotation-cropping-top,Fail
kms_universal_plane@disable-primary-vs-flip,Timeout
perf@non-zero-reason,Timeout
sysfs_heartbeat_interval@long,Timeout
diff --git a/drivers/gpu/drm/ci/xfails/i915-jsl-fails.txt b/drivers/gpu/drm/ci/xfails/i915-jsl-fails.txt
index 57453e340040..9ad246917598 100644
--- a/drivers/gpu/drm/ci/xfails/i915-jsl-fails.txt
+++ b/drivers/gpu/drm/ci/xfails/i915-jsl-fails.txt
@@ -1,45 +1,24 @@
+core_setmaster@master-drop-set-root,Fail
drm_fdinfo@busy-check-all,Fail
i915_module_load@load,Fail
i915_module_load@reload,Fail
i915_module_load@reload-no-display,Fail
i915_module_load@resize-bar,Fail
i915_pm_rpm@gem-execbuf-stress,Timeout
+i915_pm_rpm@module-reload,Fail
kms_flip@dpms-off-confusion,Fail
-kms_flip@nonexisting-fb,Fail
-kms_flip@single-buffer-flip-vs-dpms-off-vs-modeset,Fail
-kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-downscaling,Fail
kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-upscaling,Fail
kms_flip_scaled_crc@flip-32bpp-xtile-to-64bpp-xtile-downscaling,UnexpectedImprovement(Skip)
-kms_flip_scaled_crc@flip-32bpp-xtile-to-64bpp-xtile-upscaling,Fail
-kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-downscaling,Fail
-kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-upscaling,Fail
kms_flip_scaled_crc@flip-32bpp-ytileccs-to-64bpp-ytile-downscaling,Fail
-kms_flip_scaled_crc@flip-32bpp-ytileccs-to-64bpp-ytile-upscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-linear-to-16bpp-linear-downscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-linear-to-16bpp-linear-upscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-linear-to-32bpp-linear-downscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-linear-to-32bpp-linear-upscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-xtile-to-16bpp-xtile-downscaling,Fail
+kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-upscaling,Fail
kms_flip_scaled_crc@flip-64bpp-xtile-to-16bpp-xtile-upscaling,Fail
kms_flip_scaled_crc@flip-64bpp-xtile-to-32bpp-xtile-downscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-xtile-to-32bpp-xtile-upscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-ytile-to-16bpp-ytile-downscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-ytile-to-16bpp-ytile-upscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-downscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-upscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilegen12rcccs-upscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilercccs-downscaling,Fail
kms_lease@lease-uevent,Fail
kms_pm_rpm@modeset-stress-extra-wait,Timeout
-kms_rotation_crc@bad-pixel-format,Fail
kms_rotation_crc@multiplane-rotation,Fail
-kms_rotation_crc@multiplane-rotation-cropping-bottom,Fail
-kms_rotation_crc@multiplane-rotation-cropping-top,Fail
perf@i915-ref-count,Fail
perf_pmu@module-unload,Fail
-perf_pmu@most-busy-idle-check-all,Fail
perf_pmu@rc6,Crash
-prime_busy@before-wait,Fail
sysfs_heartbeat_interval@long,Timeout
sysfs_heartbeat_interval@off,Timeout
sysfs_preempt_timeout@off,Timeout
diff --git a/drivers/gpu/drm/ci/xfails/i915-kbl-fails.txt b/drivers/gpu/drm/ci/xfails/i915-kbl-fails.txt
index 117098bc95d9..f37302331516 100644
--- a/drivers/gpu/drm/ci/xfails/i915-kbl-fails.txt
+++ b/drivers/gpu/drm/ci/xfails/i915-kbl-fails.txt
@@ -1,11 +1,12 @@
+core_setmaster@master-drop-set-user,Fail
i915_module_load@load,Fail
i915_module_load@reload,Fail
i915_module_load@reload-no-display,Fail
i915_module_load@resize-bar,Fail
i915_pm_rpm@gem-execbuf-stress,Timeout
kms_flip_scaled_crc@flip-32bpp-xtile-to-64bpp-xtile-downscaling,Fail
-kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-upscaling,Fail
kms_flip_scaled_crc@flip-32bpp-ytileccs-to-64bpp-ytile-upscaling,Fail
+kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-upscaling,Fail
kms_flip_scaled_crc@flip-64bpp-linear-to-16bpp-linear-downscaling,Fail
kms_flip_scaled_crc@flip-64bpp-linear-to-32bpp-linear-upscaling,Fail
kms_flip_scaled_crc@flip-64bpp-xtile-to-16bpp-xtile-upscaling,Fail
@@ -17,6 +18,8 @@ perf@i915-ref-count,Fail
perf_pmu@busy-accuracy-50,Fail
perf_pmu@module-unload,Fail
perf_pmu@rc6,Crash
+prime_busy@after-wait,Fail
+prime_busy@before,Fail
sysfs_heartbeat_interval@long,Timeout
sysfs_heartbeat_interval@off,Timeout
sysfs_preempt_timeout@off,Timeout
diff --git a/drivers/gpu/drm/ci/xfails/i915-tgl-fails.txt b/drivers/gpu/drm/ci/xfails/i915-tgl-fails.txt
index 462c050a8b2d..102c4b3eef4d 100644
--- a/drivers/gpu/drm/ci/xfails/i915-tgl-fails.txt
+++ b/drivers/gpu/drm/ci/xfails/i915-tgl-fails.txt
@@ -1,14 +1,14 @@
api_intel_allocator@reopen,Timeout
api_intel_bb@destroy-bb,Timeout
core_hotunplug@hotrebind-lateclose,Timeout
+core_setmaster@master-drop-set-user,Fail
+drm_read@short-buffer-block,Timeout
dumb_buffer@map-valid,Timeout
i915_module_load@load,Fail
i915_module_load@reload,Fail
i915_module_load@reload-no-display,Fail
i915_module_load@resize-bar,Fail
-i915_pm_rpm@gem-execbuf-stress,Timeout
i915_pm_rps@engine-order,Timeout
-i915_pm_rps@waitboost,Fail
kms_lease@lease-uevent,Fail
kms_rotation_crc@multiplane-rotation,Fail
perf@i915-ref-count,Fail
@@ -17,7 +17,6 @@ perf_pmu@enable-race,Timeout
perf_pmu@module-unload,Fail
perf_pmu@rc6,Crash
perf_pmu@semaphore-wait-idle,Timeout
-prime_busy@before,Fail
prime_mmap@test_refcounting,Timeout
sriov_basic@enable-vfs-bind-unbind-each-numvfs-all,Timeout
syncobj_basic@illegal-fd-to-handle,Timeout
diff --git a/drivers/gpu/drm/ci/xfails/i915-tgl-flakes.txt b/drivers/gpu/drm/ci/xfails/i915-tgl-flakes.txt
new file mode 100644
index 000000000000..9738006e3759
--- /dev/null
+++ b/drivers/gpu/drm/ci/xfails/i915-tgl-flakes.txt
@@ -0,0 +1,6 @@
+# Board Name: acer-cp514-2h-1130g7-volteer
+# Bug Report: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14624
+# Failure Rate: 100
+# IGT Version: 2.1-g26ddb59c1
+# Linux Version: 6.16.0-rc2
+perf@gen12-unprivileged-single-ctx-counters
diff --git a/drivers/gpu/drm/ci/xfails/i915-whl-fails.txt b/drivers/gpu/drm/ci/xfails/i915-whl-fails.txt
index 0f167cfd503c..3bb5496036d8 100644
--- a/drivers/gpu/drm/ci/xfails/i915-whl-fails.txt
+++ b/drivers/gpu/drm/ci/xfails/i915-whl-fails.txt
@@ -6,17 +6,17 @@ i915_module_load@resize-bar,Fail
i915_pm_rpm@gem-execbuf-stress,Timeout
i915_pm_rpm@module-reload,Fail
i915_pm_rpm@system-suspend-execbuf,Timeout
-kms_ccs@ccs-on-another-bo-y-tiled-gen12-rc-ccs-cc,Timeout
-kms_cursor_crc@cursor-suspend,Timeout
+kms_dirtyfb@default-dirtyfb-ioctl,Fail
+kms_dirtyfb@fbc-dirtyfb-ioctl,Fail
kms_fb_coherency@memset-crc,Crash
kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-downscaling,Fail
kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-upscaling,Fail
kms_flip_scaled_crc@flip-32bpp-xtile-to-64bpp-xtile-downscaling,Fail
kms_flip_scaled_crc@flip-32bpp-xtile-to-64bpp-xtile-upscaling,Fail
-kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-downscaling,Fail
-kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-upscaling,Fail
kms_flip_scaled_crc@flip-32bpp-ytileccs-to-64bpp-ytile-downscaling,Fail
kms_flip_scaled_crc@flip-32bpp-ytileccs-to-64bpp-ytile-upscaling,Fail
+kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-downscaling,Fail
+kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-upscaling,Fail
kms_flip_scaled_crc@flip-64bpp-linear-to-16bpp-linear-downscaling,Fail
kms_flip_scaled_crc@flip-64bpp-linear-to-32bpp-linear-upscaling,Fail
kms_flip_scaled_crc@flip-64bpp-xtile-to-16bpp-xtile-downscaling,Fail
@@ -26,10 +26,9 @@ kms_flip_scaled_crc@flip-64bpp-xtile-to-32bpp-xtile-upscaling,Fail
kms_flip_scaled_crc@flip-64bpp-ytile-to-16bpp-ytile-downscaling,Fail
kms_flip_scaled_crc@flip-64bpp-ytile-to-16bpp-ytile-upscaling,Fail
kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-downscaling,Fail
-kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-upscaling,Fail
kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilegen12rcccs-upscaling,Fail
kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilercccs-downscaling,Fail
-kms_frontbuffer_tracking@fbc-rgb101010-draw-mmap-cpu,Timeout
+kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-upscaling,Fail
kms_frontbuffer_tracking@fbc-tiling-linear,Fail
kms_lease@lease-uevent,Fail
kms_plane_alpha_blend@alpha-basic,Fail
@@ -37,8 +36,6 @@ kms_plane_alpha_blend@alpha-opaque-fb,Fail
kms_plane_alpha_blend@alpha-transparent-fb,Fail
kms_plane_alpha_blend@constant-alpha-max,Fail
kms_plane_scaling@planes-upscale-factor-0-25,Timeout
-kms_pm_backlight@brightness-with-dpms,Crash
-kms_pm_backlight@fade,Crash
kms_prop_blob@invalid-set-prop-any,Fail
kms_properties@connector-properties-legacy,Timeout
kms_universal_plane@disable-primary-vs-flip,Timeout
diff --git a/drivers/gpu/drm/ci/xfails/mediatek-mt8173-fails.txt b/drivers/gpu/drm/ci/xfails/mediatek-mt8173-fails.txt
index 592d7d69e6fc..31b8a0b27e13 100644
--- a/drivers/gpu/drm/ci/xfails/mediatek-mt8173-fails.txt
+++ b/drivers/gpu/drm/ci/xfails/mediatek-mt8173-fails.txt
@@ -1,7 +1,8 @@
+core_setmaster@master-drop-set-root,Fail
+core_setmaster@master-drop-set-shared-fd,Fail
+core_setmaster@master-drop-set-user,Fail
kms_3d,Fail
-kms_bw@connected-linear-tiling-1-displays-1920x1080p,Fail
kms_bw@connected-linear-tiling-1-displays-2560x1440p,Fail
-kms_bw@connected-linear-tiling-1-displays-3840x2160p,Fail
kms_bw@connected-linear-tiling-2-displays-1920x1080p,Fail
kms_bw@connected-linear-tiling-2-displays-2160x1440p,Fail
kms_bw@connected-linear-tiling-2-displays-2560x1440p,Fail
@@ -14,9 +15,7 @@ kms_bw@linear-tiling-2-displays-1920x1080p,Fail
kms_bw@linear-tiling-2-displays-2160x1440p,Fail
kms_bw@linear-tiling-2-displays-2560x1440p,Fail
kms_bw@linear-tiling-2-displays-3840x2160p,Fail
-kms_color@invalid-gamma-lut-sizes,Fail
kms_cursor_legacy@cursor-vs-flip-atomic,Fail
-kms_cursor_legacy@cursor-vs-flip-legacy,Fail
kms_cursor_legacy@flip-vs-cursor-atomic,Fail
kms_cursor_legacy@flip-vs-cursor-legacy,Fail
kms_cursor_legacy@flip-vs-cursor-toggle,Fail
@@ -24,9 +23,9 @@ kms_cursor_legacy@flip-vs-cursor-varying-size,Fail
kms_flip@basic-plain-flip,Fail
kms_flip@dpms-off-confusion,Fail
kms_flip@dpms-off-confusion-interruptible,Fail
-kms_flip@flip-vs-absolute-wf_vblank,Fail
-kms_flip@flip-vs-absolute-wf_vblank-interruptible,Fail
kms_flip@flip-vs-blocking-wf-vblank,Fail
+kms_flip@flip-vs-dpms-on-nop,Fail
+kms_flip@flip-vs-dpms-on-nop-interruptible,Fail
kms_flip@flip-vs-expired-vblank,Fail
kms_flip@flip-vs-expired-vblank-interruptible,Fail
kms_flip@flip-vs-modeset-vs-hang,Fail
@@ -40,5 +39,4 @@ kms_flip@plain-flip-fb-recreate-interruptible,Fail
kms_flip@plain-flip-interruptible,Fail
kms_flip@plain-flip-ts-check,Fail
kms_flip@plain-flip-ts-check-interruptible,Fail
-kms_invalid_mode@overflow-vrefresh,Fail
kms_lease@lease-uevent,Fail
diff --git a/drivers/gpu/drm/ci/xfails/mediatek-mt8173-flakes.txt b/drivers/gpu/drm/ci/xfails/mediatek-mt8173-flakes.txt
index 443596d9e662..6f4d41e16e19 100644
--- a/drivers/gpu/drm/ci/xfails/mediatek-mt8173-flakes.txt
+++ b/drivers/gpu/drm/ci/xfails/mediatek-mt8173-flakes.txt
@@ -53,3 +53,38 @@ kms_bw@connected-linear-tiling-1-displays-2160x1440p
# IGT Version: 1.30-g04bedb923
# Linux Version: 6.14.0-rc4
kms_flip@flip-vs-wf_vblank-interruptible
+
+# Board Name: mt8173-elm-hana
+# Bug Report: https://lore.kernel.org/dri-devel/7559dd68-c9dd-410f-880f-201679e2dd54@collabora.com/T/#u
+# Failure Rate: 20
+# IGT Version: 2.1-g26ddb59c1
+# Linux Version: 6.16.0-rc2
+kms_flip@blocking-wf_vblank
+
+# Board Name: mt8173-elm-hana
+# Bug Report: https://lore.kernel.org/dri-devel/953ab66e-9dda-4003-9b98-9e0d81e18a1f@collabora.com/T/#u
+# Failure Rate: 40
+# IGT Version: 2.1-g26ddb59c1
+# Linux Version: 6.16.0-rc2
+kms_flip@busy-flip
+
+# Board Name: mt8173-elm-hana
+# Bug Report: https://lore.kernel.org/dri-devel/6ab7f59c-042e-4c7a-baaa-86c7d47ab308@collabora.com/
+# Failure Rate: 40
+# IGT Version: 2.1-g26ddb59c1
+# Linux Version: 6.16.0-rc2
+kms_flip@flip-vs-rmfb
+
+# Board Name: mt8173-elm-hana
+# Bug Report: https://lore.kernel.org/dri-devel/30b3f8b0-3409-4329-bb60-b6287e1a439d@collabora.com/
+# Failure Rate: 60
+# IGT Version: 2.1-g26ddb59c1
+# Linux Version: 6.16.0-rc2
+kms_atomic_transition@plane-all-modeset-transition-internal-panels
+
+# Board Name: mt8173-elm-hana
+# Bug Report: https://lore.kernel.org/dri-devel/4c9e1501-52cd-4659-a894-8a2ac58c3996@collabora.com/
+# Failure Rate: 40
+# IGT Version: 2.1-g26ddb59c1
+# Linux Version: 6.16.0-rc2
+kms_flip@absolute-wf_vblank
diff --git a/drivers/gpu/drm/ci/xfails/msm-apq8016-fails.txt b/drivers/gpu/drm/ci/xfails/msm-apq8016-fails.txt
index 72c469021b66..4546363447ff 100644
--- a/drivers/gpu/drm/ci/xfails/msm-apq8016-fails.txt
+++ b/drivers/gpu/drm/ci/xfails/msm-apq8016-fails.txt
@@ -1,5 +1,9 @@
+core_setmaster@master-drop-set-user,Fail
kms_3d,Fail
+kms_cursor_legacy@forked-move,Fail
+kms_cursor_legacy@single-bo,Fail
kms_force_connector_basic@force-edid,Fail
kms_hdmi_inject@inject-4k,Fail
kms_lease@lease-uevent,Fail
+msm/msm_mapping@memptrs,Fail
msm/msm_mapping@ring,Fail
diff --git a/drivers/gpu/drm/ci/xfails/msm-apq8096-fails.txt b/drivers/gpu/drm/ci/xfails/msm-apq8096-fails.txt
index 2893f98a6b97..0d5cb2a87e67 100644
--- a/drivers/gpu/drm/ci/xfails/msm-apq8096-fails.txt
+++ b/drivers/gpu/drm/ci/xfails/msm-apq8096-fails.txt
@@ -1,2 +1,4 @@
+core_setmaster@master-drop-set-user,Fail
kms_3d,Fail
kms_lease@lease-uevent,Fail
+msm/msm_mapping@memptrs,Fail
diff --git a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-fails.txt b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-fails.txt
index ae36a39619c6..2daf4ab879a9 100644
--- a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-fails.txt
+++ b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-fails.txt
@@ -1,3 +1,4 @@
+core_setmaster@master-drop-set-user,Fail
kms_color@ctm-0-25,Fail
kms_color@ctm-0-50,Fail
kms_color@ctm-0-75,Fail
@@ -14,8 +15,8 @@ kms_flip@flip-vs-modeset-vs-hang,Fail
kms_flip@flip-vs-panning-vs-hang,Fail
kms_lease@lease-uevent,Fail
kms_pipe_crc_basic@compare-crc-sanitycheck-nv12,Fail
-kms_plane@pixel-format,Fail
-kms_plane@pixel-format-source-clamping,Fail
kms_plane_alpha_blend@alpha-7efc,Fail
kms_plane_alpha_blend@coverage-7efc,Fail
kms_plane_alpha_blend@coverage-vs-premult-vs-constant,Fail
+kms_plane@pixel-format,Fail
+kms_plane@pixel-format-source-clamping,Fail
diff --git a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-fails.txt b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-fails.txt
index ae36a39619c6..2daf4ab879a9 100644
--- a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-fails.txt
+++ b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-fails.txt
@@ -1,3 +1,4 @@
+core_setmaster@master-drop-set-user,Fail
kms_color@ctm-0-25,Fail
kms_color@ctm-0-50,Fail
kms_color@ctm-0-75,Fail
@@ -14,8 +15,8 @@ kms_flip@flip-vs-modeset-vs-hang,Fail
kms_flip@flip-vs-panning-vs-hang,Fail
kms_lease@lease-uevent,Fail
kms_pipe_crc_basic@compare-crc-sanitycheck-nv12,Fail
-kms_plane@pixel-format,Fail
-kms_plane@pixel-format-source-clamping,Fail
kms_plane_alpha_blend@alpha-7efc,Fail
kms_plane_alpha_blend@coverage-7efc,Fail
kms_plane_alpha_blend@coverage-vs-premult-vs-constant,Fail
+kms_plane@pixel-format,Fail
+kms_plane@pixel-format-source-clamping,Fail
diff --git a/drivers/gpu/drm/ci/xfails/msm-sm8350-hdk-fails.txt b/drivers/gpu/drm/ci/xfails/msm-sm8350-hdk-fails.txt
index 8d26b23133aa..f387c73193c6 100644
--- a/drivers/gpu/drm/ci/xfails/msm-sm8350-hdk-fails.txt
+++ b/drivers/gpu/drm/ci/xfails/msm-sm8350-hdk-fails.txt
@@ -1,3 +1,4 @@
+core_setmaster@master-drop-set-user,Fail
kms_3d,Fail
kms_cursor_legacy@forked-bo,Fail
kms_cursor_legacy@forked-move,Fail
diff --git a/drivers/gpu/drm/ci/xfails/panfrost-mt8183-fails.txt b/drivers/gpu/drm/ci/xfails/panfrost-mt8183-fails.txt
index abd1ccb71561..cc5f7fe98dd7 100644
--- a/drivers/gpu/drm/ci/xfails/panfrost-mt8183-fails.txt
+++ b/drivers/gpu/drm/ci/xfails/panfrost-mt8183-fails.txt
@@ -1,2 +1,3 @@
+core_setmaster@master-drop-set-user,Fail
panfrost/panfrost_prime@gem-prime-import,Fail
panfrost/panfrost_submit@pan-submit-error-bad-requirements,Fail
diff --git a/drivers/gpu/drm/ci/xfails/panfrost-rk3288-fails.txt b/drivers/gpu/drm/ci/xfails/panfrost-rk3288-fails.txt
index 8330b934602a..8d0b7682e640 100644
--- a/drivers/gpu/drm/ci/xfails/panfrost-rk3288-fails.txt
+++ b/drivers/gpu/drm/ci/xfails/panfrost-rk3288-fails.txt
@@ -1,2 +1,3 @@
+core_setmaster@master-drop-set-user,Crash
panfrost/panfrost_prime@gem-prime-import,Crash
panfrost/panfrost_submit@pan-submit-error-bad-requirements,Crash
diff --git a/drivers/gpu/drm/ci/xfails/panfrost-rk3399-fails.txt b/drivers/gpu/drm/ci/xfails/panfrost-rk3399-fails.txt
index abd1ccb71561..cc5f7fe98dd7 100644
--- a/drivers/gpu/drm/ci/xfails/panfrost-rk3399-fails.txt
+++ b/drivers/gpu/drm/ci/xfails/panfrost-rk3399-fails.txt
@@ -1,2 +1,3 @@
+core_setmaster@master-drop-set-user,Fail
panfrost/panfrost_prime@gem-prime-import,Fail
panfrost/panfrost_submit@pan-submit-error-bad-requirements,Fail
diff --git a/drivers/gpu/drm/ci/xfails/panthor-rk3588-fails.txt b/drivers/gpu/drm/ci/xfails/panthor-rk3588-fails.txt
new file mode 100644
index 000000000000..7407bd0128d4
--- /dev/null
+++ b/drivers/gpu/drm/ci/xfails/panthor-rk3588-fails.txt
@@ -0,0 +1,5 @@
+core_hotunplug@hotreplug,Fail
+core_hotunplug@hotreplug-lateclose,Fail
+core_hotunplug@hotunplug-rescan,Fail
+core_hotunplug@unplug-rescan,Fail
+core_setmaster@master-drop-set-user,Fail
diff --git a/drivers/gpu/drm/ci/xfails/panthor-rk3588-skips.txt b/drivers/gpu/drm/ci/xfails/panthor-rk3588-skips.txt
new file mode 100644
index 000000000000..b724cf04e3b3
--- /dev/null
+++ b/drivers/gpu/drm/ci/xfails/panthor-rk3588-skips.txt
@@ -0,0 +1,20 @@
+# Skip driver specific tests
+^amdgpu.*
+^msm.*
+nouveau_.*
+^v3d.*
+^vc4.*
+^vmwgfx*
+
+# Skip intel specific tests
+gem_.*
+i915_.*
+tools_test.*
+kms_dp_link_training.*
+
+# Panfrost is not a KMS driver, so skip the KMS tests
+kms_.*
+
+# Skip display functionality tests for GPU-only drivers
+dumb_buffer.*
+fbdev.*
diff --git a/drivers/gpu/drm/ci/xfails/rockchip-rk3288-fails.txt b/drivers/gpu/drm/ci/xfails/rockchip-rk3288-fails.txt
index 61122ea7f008..526f582038d3 100644
--- a/drivers/gpu/drm/ci/xfails/rockchip-rk3288-fails.txt
+++ b/drivers/gpu/drm/ci/xfails/rockchip-rk3288-fails.txt
@@ -2,8 +2,17 @@ core_setmaster@master-drop-set-root,Crash
core_setmaster@master-drop-set-shared-fd,Crash
core_setmaster@master-drop-set-user,Crash
core_setmaster_vs_auth,Crash
-dumb_buffer@create-clear,Crash
fbdev@pan,Crash
-kms_cursor_legacy@basic-flip-before-cursor-legacy,Fail
-kms_prop_blob@invalid-set-prop,Crash
+kms_cursor_crc@cursor-dpms,Crash
+kms_cursor_crc@cursor-sliding-32x32,Crash
+kms_cursor_legacy@basic-flip-before-cursor-atomic,Crash
+kms_cursor_legacy@cursor-vs-flip-atomic,Crash
+kms_flip@basic-flip-vs-wf_vblank,Crash
+kms_flip@flip-vs-panning-vs-hang,Crash
+kms_flip@plain-flip-fb-recreate-interruptible,Crash
+kms_pipe_crc_basic@read-crc-frame-sequence,Crash
+kms_plane_cursor@overlay,Crash
+kms_plane_cursor@viewport,Crash
kms_prop_blob@invalid-set-prop-any,Crash
+kms_prop_blob@invalid-set-prop,Crash
+kms_properties@get_properties-sanity-non-atomic,Fail
diff --git a/drivers/gpu/drm/ci/xfails/rockchip-rk3288-flakes.txt b/drivers/gpu/drm/ci/xfails/rockchip-rk3288-flakes.txt
index cd0b27d8b636..34f43e95a51b 100644
--- a/drivers/gpu/drm/ci/xfails/rockchip-rk3288-flakes.txt
+++ b/drivers/gpu/drm/ci/xfails/rockchip-rk3288-flakes.txt
@@ -32,3 +32,24 @@ kms_flip@plain-flip-ts-check
# IGT Version: 1.28-ga73311079
# Linux Version: 6.11.0-rc2
kms_cursor_crc@cursor-alpha-opaque
+
+# Board Name: rk3288-veyron-jaq
+# Bug Report: https://lore.kernel.org/dri-devel/acfd5838-d861-4dd9-97c3-99fffc9bfa04@collabora.com/T/#u
+# Failure Rate: 40
+# IGT Version: 2.1-g26ddb59c1
+# Linux Version: 6.16.0-rc2
+kms_flip@flip-vs-absolute-wf_vblank
+
+# Board Name: rk3288-veyron-jaq
+# Bug Report: https://lore.kernel.org/dri-devel/81e13fcc-d916-4eb8-91cd-f74f64f53f72@collabora.com/T/#u
+# Failure Rate: 40
+# IGT Version: 2.1-g26ddb59c1
+# Linux Version: 6.16.0-rc2
+kms_flip@flip-vs-dpms-on-nop-interruptible
+
+# Board Name: rk3288-veyron-jaq
+# Bug Report: https://lore.kernel.org/dri-devel/10c5abab-c8fe-4eff-8eed-009038436b49@collabora.com/T/#u
+# Failure Rate: 20
+# IGT Version: 2.1-g26ddb59c1
+# Linux Version: 6.16.0-rc2
+kms_flip@plain-flip-fb-recreate
diff --git a/drivers/gpu/drm/ci/xfails/rockchip-rk3399-fails.txt b/drivers/gpu/drm/ci/xfails/rockchip-rk3399-fails.txt
index 45dd8d493f6e..5110ce2dc56e 100644
--- a/drivers/gpu/drm/ci/xfails/rockchip-rk3399-fails.txt
+++ b/drivers/gpu/drm/ci/xfails/rockchip-rk3399-fails.txt
@@ -1,9 +1,9 @@
-dumb_buffer@create-clear,Crash
+core_setmaster@master-drop-set-user,Fail
kms_atomic_transition@modeset-transition,Fail
kms_atomic_transition@modeset-transition-fencing,Fail
kms_atomic_transition@plane-toggle-modeset-transition,Fail
-kms_color@gamma,Fail
-kms_color@legacy-gamma,Fail
+kms_cursor_crc@async-cursor-crc-framebuffer-change,Fail
+kms_cursor_crc@async-cursor-crc-position-change,Fail
kms_cursor_crc@cursor-alpha-opaque,Fail
kms_cursor_crc@cursor-alpha-transparent,Fail
kms_cursor_crc@cursor-dpms,Fail
@@ -41,8 +41,11 @@ kms_cursor_legacy@flip-vs-cursor-crc-atomic,Fail
kms_cursor_legacy@flip-vs-cursor-crc-legacy,Fail
kms_cursor_legacy@flip-vs-cursor-legacy,Fail
kms_cursor_legacy@long-nonblocking-modeset-vs-cursor-atomic,Fail
+kms_flip@basic-flip-vs-dpms,Fail
kms_flip@basic-flip-vs-wf_vblank,Fail
kms_flip@blocking-wf_vblank,Fail
+kms_flip@flip-vs-dpms-on-nop,Fail
+kms_flip@flip-vs-dpms-on-nop-interruptible,Fail
kms_flip@flip-vs-modeset-vs-hang,Fail
kms_flip@flip-vs-panning,Fail
kms_flip@flip-vs-panning-interruptible,Fail
@@ -51,7 +54,6 @@ kms_flip@modeset-vs-vblank-race,Fail
kms_flip@plain-flip-fb-recreate,Fail
kms_flip@plain-flip-fb-recreate-interruptible,Fail
kms_flip@plain-flip-ts-check,Fail
-kms_flip@plain-flip-ts-check-interruptible,Fail
kms_flip@wf_vblank-ts-check-interruptible,Fail
kms_invalid_mode@int-max-clock,Fail
kms_invalid_mode@overflow-vrefresh,Fail
@@ -64,11 +66,11 @@ kms_pipe_crc_basic@nonblocking-crc,Fail
kms_pipe_crc_basic@nonblocking-crc-frame-sequence,Fail
kms_pipe_crc_basic@read-crc,Fail
kms_pipe_crc_basic@read-crc-frame-sequence,Fail
+kms_plane_cursor@primary,Fail
kms_plane@pixel-format,Fail
kms_plane@pixel-format-source-clamping,Fail
kms_plane@plane-panning-bottom-right,Fail
kms_plane@plane-panning-top-left,Fail
kms_plane@plane-position-covered,Fail
kms_plane@plane-position-hole,Fail
-kms_plane_cursor@primary,Fail
kms_universal_plane@universal-plane-functional,Fail
diff --git a/drivers/gpu/drm/ci/xfails/rockchip-rk3399-flakes.txt b/drivers/gpu/drm/ci/xfails/rockchip-rk3399-flakes.txt
index b467991d4094..918dd33c2092 100644
--- a/drivers/gpu/drm/ci/xfails/rockchip-rk3399-flakes.txt
+++ b/drivers/gpu/drm/ci/xfails/rockchip-rk3399-flakes.txt
@@ -144,3 +144,38 @@ kms_bw@connected-linear-tiling-1-displays-2160x1440p
# IGT Version: 1.30-g04bedb923
# Linux Version: 6.14.0-rc4
kms_bw@linear-tiling-1-displays-3840x2160p
+
+# Board Name: rk3399-gru-kevin
+# Bug Report: https://lore.kernel.org/dri-devel/7b6e2e3b-2ea2-4cd7-92a5-68d23a63e426@collabora.com/T/#u
+# Failure Rate: 60
+# IGT Version: 2.1-g26ddb59c1
+# Linux Version: 6.16.0-rc2
+kms_color@gamma
+
+# Board Name: rk3399-gru-kevin
+# Bug Report: https://lore.kernel.org/dri-devel/e29c2892-08f2-423f-af72-e4d8b207fd1c@collabora.com/T/#u
+# Failure Rate: 60
+# IGT Version: 2.1-g26ddb59c1
+# Linux Version: 6.16.0-rc2
+kms_bw@connected-linear-tiling-1-displays-3840x2160p
+
+# Board Name: rk3399-gru-kevin
+# Bug Report: https://lore.kernel.org/dri-devel/ad9ce463-c803-4502-ae89-381a6b6eb19f@collabora.com/T/#u
+# Failure Rate: 40
+# IGT Version: 2.1-g26ddb59c1
+# Linux Version: 6.16.0-rc2
+kms_color@legacy-gamma
+
+# Board Name: rk3399-gru-kevin
+# Bug Report: https://lore.kernel.org/dri-devel/59724e10-12ca-4481-b0e4-72d7b6e4dae0@collabora.com/T/#u
+# Failure Rate: 40
+# IGT Version: 2.1-g26ddb59c1
+# Linux Version: 6.16.0-rc2
+kms_flip@plain-flip-ts-check-interruptible
+
+# Board Name: rk3399-gru-kevin
+# Bug Report: https://lore.kernel.org/dri-devel/d790db5f-a1ba-47f9-9af0-d3287ef3274c@collabora.com/T/#u
+# Failure Rate: 20
+# IGT Version: 2.1-g26ddb59c1
+# Linux Version: 6.16.0-rc2
+kms_bw@linear-tiling-2-displays-3840x2160p
diff --git a/drivers/gpu/drm/ci/xfails/rockchip-rk3588-fails.txt b/drivers/gpu/drm/ci/xfails/rockchip-rk3588-fails.txt
new file mode 100644
index 000000000000..799c3b04c3f2
--- /dev/null
+++ b/drivers/gpu/drm/ci/xfails/rockchip-rk3588-fails.txt
@@ -0,0 +1,9 @@
+core_setmaster@master-drop-set-user,Fail
+kms_3d,Fail
+kms_cursor_legacy@forked-bo,Fail
+kms_cursor_legacy@forked-move,Fail
+kms_cursor_legacy@single-bo,Fail
+kms_cursor_legacy@single-move,Fail
+kms_cursor_legacy@torture-bo,Fail
+kms_cursor_legacy@torture-move,Fail
+kms_lease@lease-uevent,Fail
diff --git a/drivers/gpu/drm/ci/xfails/rockchip-rk3588-skips.txt b/drivers/gpu/drm/ci/xfails/rockchip-rk3588-skips.txt
new file mode 100644
index 000000000000..a165fccd8a93
--- /dev/null
+++ b/drivers/gpu/drm/ci/xfails/rockchip-rk3588-skips.txt
@@ -0,0 +1,14 @@
+# Skip driver specific tests
+^amdgpu.*
+^msm.*
+nouveau_.*
+^panfrost.*
+^v3d.*
+^vc4.*
+^vmwgfx*
+
+# Skip intel specific tests
+gem_.*
+i915_.*
+tools_test.*
+kms_dp_link_training.*
diff --git a/drivers/gpu/drm/ci/xfails/virtio_gpu-none-fails.txt b/drivers/gpu/drm/ci/xfails/virtio_gpu-none-fails.txt
index 9749ddb75121..62cb7b94f3fd 100644
--- a/drivers/gpu/drm/ci/xfails/virtio_gpu-none-fails.txt
+++ b/drivers/gpu/drm/ci/xfails/virtio_gpu-none-fails.txt
@@ -2,11 +2,6 @@ kms_addfb_basic@bad-pitch-65536,Fail
kms_addfb_basic@bo-too-small,Fail
kms_addfb_basic@size-max,Fail
kms_addfb_basic@too-high,Fail
-kms_atomic_transition@plane-primary-toggle-with-vblank-wait,Fail
-kms_bw@connected-linear-tiling-1-displays-1920x1080p,Fail
-kms_bw@connected-linear-tiling-1-displays-2160x1440p,Fail
-kms_bw@connected-linear-tiling-1-displays-2560x1440p,Fail
-kms_bw@connected-linear-tiling-1-displays-3840x2160p,Fail
kms_bw@connected-linear-tiling-10-displays-1920x1080p,Fail
kms_bw@connected-linear-tiling-10-displays-2160x1440p,Fail
kms_bw@connected-linear-tiling-10-displays-2560x1440p,Fail
@@ -35,6 +30,10 @@ kms_bw@connected-linear-tiling-16-displays-1920x1080p,Fail
kms_bw@connected-linear-tiling-16-displays-2160x1440p,Fail
kms_bw@connected-linear-tiling-16-displays-2560x1440p,Fail
kms_bw@connected-linear-tiling-16-displays-3840x2160p,Fail
+kms_bw@connected-linear-tiling-1-displays-1920x1080p,Fail
+kms_bw@connected-linear-tiling-1-displays-2160x1440p,Fail
+kms_bw@connected-linear-tiling-1-displays-2560x1440p,Fail
+kms_bw@connected-linear-tiling-1-displays-3840x2160p,Fail
kms_bw@connected-linear-tiling-2-displays-1920x1080p,Fail
kms_bw@connected-linear-tiling-2-displays-2160x1440p,Fail
kms_bw@connected-linear-tiling-2-displays-2560x1440p,Fail
@@ -67,10 +66,6 @@ kms_bw@connected-linear-tiling-9-displays-1920x1080p,Fail
kms_bw@connected-linear-tiling-9-displays-2160x1440p,Fail
kms_bw@connected-linear-tiling-9-displays-2560x1440p,Fail
kms_bw@connected-linear-tiling-9-displays-3840x2160p,Fail
-kms_bw@linear-tiling-1-displays-1920x1080p,Fail
-kms_bw@linear-tiling-1-displays-2160x1440p,Fail
-kms_bw@linear-tiling-1-displays-2560x1440p,Fail
-kms_bw@linear-tiling-1-displays-3840x2160p,Fail
kms_bw@linear-tiling-10-displays-1920x1080p,Fail
kms_bw@linear-tiling-10-displays-2160x1440p,Fail
kms_bw@linear-tiling-10-displays-2560x1440p,Fail
@@ -99,6 +94,10 @@ kms_bw@linear-tiling-16-displays-1920x1080p,Fail
kms_bw@linear-tiling-16-displays-2160x1440p,Fail
kms_bw@linear-tiling-16-displays-2560x1440p,Fail
kms_bw@linear-tiling-16-displays-3840x2160p,Fail
+kms_bw@linear-tiling-1-displays-1920x1080p,Fail
+kms_bw@linear-tiling-1-displays-2160x1440p,Fail
+kms_bw@linear-tiling-1-displays-2560x1440p,Fail
+kms_bw@linear-tiling-1-displays-3840x2160p,Fail
kms_bw@linear-tiling-2-displays-1920x1080p,Fail
kms_bw@linear-tiling-2-displays-2160x1440p,Fail
kms_bw@linear-tiling-2-displays-2560x1440p,Fail
@@ -131,60 +130,11 @@ kms_bw@linear-tiling-9-displays-1920x1080p,Fail
kms_bw@linear-tiling-9-displays-2160x1440p,Fail
kms_bw@linear-tiling-9-displays-2560x1440p,Fail
kms_bw@linear-tiling-9-displays-3840x2160p,Fail
-kms_flip@absolute-wf_vblank,Fail
-kms_flip@absolute-wf_vblank-interruptible,Fail
-kms_flip@basic-flip-vs-wf_vblank,Fail
-kms_flip@blocking-absolute-wf_vblank,Fail
-kms_flip@blocking-absolute-wf_vblank-interruptible,Fail
-kms_flip@blocking-wf_vblank,Fail
-kms_flip@busy-flip,Fail
-kms_flip@dpms-vs-vblank-race,Fail
-kms_flip@dpms-vs-vblank-race-interruptible,Fail
-kms_flip@flip-vs-absolute-wf_vblank,Fail
-kms_flip@flip-vs-absolute-wf_vblank-interruptible,Fail
-kms_flip@flip-vs-blocking-wf-vblank,Fail
-kms_flip@flip-vs-expired-vblank,Fail
-kms_flip@flip-vs-expired-vblank-interruptible,Fail
kms_flip@flip-vs-modeset-vs-hang,Fail
kms_flip@flip-vs-panning-vs-hang,Fail
-kms_flip@flip-vs-wf_vblank-interruptible,Fail
-kms_flip@modeset-vs-vblank-race,Fail
-kms_flip@modeset-vs-vblank-race-interruptible,Fail
-kms_flip@plain-flip-fb-recreate,Fail
-kms_flip@plain-flip-fb-recreate-interruptible,Fail
-kms_flip@plain-flip-ts-check,Fail
-kms_flip@plain-flip-ts-check-interruptible,Fail
-kms_flip@wf_vblank-ts-check,Fail
-kms_flip@wf_vblank-ts-check-interruptible,Fail
kms_invalid_mode@int-max-clock,Fail
kms_invalid_mode@overflow-vrefresh,Fail
-kms_lease@cursor-implicit-plane,Fail
kms_lease@lease-uevent,Fail
-kms_lease@page-flip-implicit-plane,Fail
-kms_lease@setcrtc-implicit-plane,Fail
-kms_lease@simple-lease,Fail
-kms_sequence@get-busy,Fail
-kms_sequence@get-forked,Fail
-kms_sequence@get-forked-busy,Fail
-kms_sequence@get-idle,Fail
-kms_sequence@queue-busy,Fail
-kms_sequence@queue-idle,Fail
-kms_setmode@basic,Fail
-kms_vblank@accuracy-idle,Fail
-kms_vblank@crtc-id,Fail
-kms_vblank@invalid,Fail
-kms_vblank@query-busy,Fail
-kms_vblank@query-forked,Fail
-kms_vblank@query-forked-busy,Fail
-kms_vblank@query-idle,Fail
-kms_vblank@ts-continuation-dpms-rpm,Fail
kms_vblank@ts-continuation-dpms-suspend,Fail
-kms_vblank@ts-continuation-idle,Fail
-kms_vblank@ts-continuation-modeset,Fail
-kms_vblank@ts-continuation-modeset-rpm,Fail
kms_vblank@ts-continuation-suspend,Fail
-kms_vblank@wait-busy,Fail
-kms_vblank@wait-forked,Fail
-kms_vblank@wait-forked-busy,Fail
-kms_vblank@wait-idle,Fail
perf@i915-ref-count,Fail
diff --git a/drivers/gpu/drm/ci/xfails/vkms-none-fails.txt b/drivers/gpu/drm/ci/xfails/vkms-none-fails.txt
index 6ebcc7d89fbd..029bd4956e85 100644
--- a/drivers/gpu/drm/ci/xfails/vkms-none-fails.txt
+++ b/drivers/gpu/drm/ci/xfails/vkms-none-fails.txt
@@ -16,6 +16,8 @@ kms_flip@flip-vs-panning-vs-hang,Fail
kms_flip@flip-vs-suspend,Fail
kms_flip@flip-vs-suspend-interruptible,Fail
kms_lease@lease-uevent,Fail
+kms_plane@pixel-format-source-clamping,Timeout
+kms_plane@pixel-format,Timeout
kms_writeback@writeback-check-output,Fail
kms_writeback@writeback-check-output-XRGB2101010,Fail
kms_writeback@writeback-fb-id,Fail
diff --git a/drivers/gpu/drm/display/drm_bridge_connector.c b/drivers/gpu/drm/display/drm_bridge_connector.c
index f686aa5c0ed9..39cc18f78eda 100644
--- a/drivers/gpu/drm/display/drm_bridge_connector.c
+++ b/drivers/gpu/drm/display/drm_bridge_connector.c
@@ -789,7 +789,7 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm,
struct drm_connector *connector;
struct i2c_adapter *ddc = NULL;
struct drm_bridge *panel_bridge __free(drm_bridge_put) = NULL;
- unsigned int supported_formats = BIT(HDMI_COLORSPACE_RGB);
+ unsigned int supported_formats = BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444);
unsigned int max_bpc = 8;
bool support_hdcp = false;
int connector_type;
@@ -960,7 +960,7 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm,
if (bridge_connector->bridge_hdmi) {
if (!connector->ycbcr_420_allowed)
- supported_formats &= ~BIT(HDMI_COLORSPACE_YUV420);
+ supported_formats &= ~BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420);
bridge_connector->hdmi_funcs = drm_bridge_connector_hdmi_funcs;
diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index d8a732f21d3c..8757972e8e24 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -5765,7 +5765,6 @@ int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr,
mgr->conn_base_id = conn_base_id;
drm_atomic_private_obj_init(dev, &mgr->base,
- NULL,
&drm_dp_mst_topology_state_funcs);
return 0;
diff --git a/drivers/gpu/drm/display/drm_dp_tunnel.c b/drivers/gpu/drm/display/drm_dp_tunnel.c
index f442430d8de7..6519b4244728 100644
--- a/drivers/gpu/drm/display/drm_dp_tunnel.c
+++ b/drivers/gpu/drm/display/drm_dp_tunnel.c
@@ -1600,7 +1600,7 @@ static bool init_group(struct drm_dp_tunnel_mgr *mgr, struct drm_dp_tunnel_group
group->available_bw = -1;
INIT_LIST_HEAD(&group->tunnels);
- drm_atomic_private_obj_init(mgr->dev, &group->base, NULL,
+ drm_atomic_private_obj_init(mgr->dev, &group->base,
&tunnel_group_funcs);
return true;
diff --git a/drivers/gpu/drm/display/drm_hdmi_helper.c b/drivers/gpu/drm/display/drm_hdmi_helper.c
index a237dc55805d..5cb0b033b171 100644
--- a/drivers/gpu/drm/display/drm_hdmi_helper.c
+++ b/drivers/gpu/drm/display/drm_hdmi_helper.c
@@ -210,7 +210,8 @@ EXPORT_SYMBOL(drm_hdmi_avi_infoframe_content_type);
*/
unsigned long long
drm_hdmi_compute_mode_clock(const struct drm_display_mode *mode,
- unsigned int bpc, enum hdmi_colorspace fmt)
+ unsigned int bpc,
+ enum drm_output_color_format fmt)
{
unsigned long long clock = mode->clock * 1000ULL;
unsigned int vic = drm_match_cea_mode(mode);
@@ -222,7 +223,7 @@ drm_hdmi_compute_mode_clock(const struct drm_display_mode *mode,
if (vic == 1 && bpc != 8)
return 0;
- if (fmt == HDMI_COLORSPACE_YUV422) {
+ if (fmt == DRM_OUTPUT_COLOR_FORMAT_YCBCR422) {
/*
* HDMI 1.0 Spec, section 6.5 - Pixel Encoding states that
* YUV422 sends 24 bits over three channels, with Cb and Cr
@@ -248,7 +249,7 @@ drm_hdmi_compute_mode_clock(const struct drm_display_mode *mode,
* specifies that YUV420 encoding is carried at a TMDS Character Rate
* equal to half the pixel clock rate.
*/
- if (fmt == HDMI_COLORSPACE_YUV420)
+ if (fmt == DRM_OUTPUT_COLOR_FORMAT_YCBCR420)
clock = clock / 2;
if (mode->flags & DRM_MODE_FLAG_DBLCLK)
diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
index a1d16762ac7a..9f3b696aceeb 100644
--- a/drivers/gpu/drm/display/drm_hdmi_state_helper.c
+++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
@@ -326,6 +326,25 @@ void __drm_atomic_helper_connector_hdmi_reset(struct drm_connector *connector,
}
EXPORT_SYMBOL(__drm_atomic_helper_connector_hdmi_reset);
+static enum hdmi_colorspace
+output_color_format_to_hdmi_colorspace(const struct drm_connector *connector,
+ enum drm_output_color_format fmt)
+{
+ switch (fmt) {
+ case DRM_OUTPUT_COLOR_FORMAT_YCBCR420:
+ return HDMI_COLORSPACE_YUV420;
+ case DRM_OUTPUT_COLOR_FORMAT_YCBCR422:
+ return HDMI_COLORSPACE_YUV422;
+ case DRM_OUTPUT_COLOR_FORMAT_YCBCR444:
+ return HDMI_COLORSPACE_YUV444;
+ default:
+ drm_warn(connector->dev, "Unsupported output color format. Defaulting to RGB.");
+ fallthrough;
+ case DRM_OUTPUT_COLOR_FORMAT_RGB444:
+ return HDMI_COLORSPACE_RGB;
+ }
+}
+
static const struct drm_display_mode *
connector_state_get_mode(const struct drm_connector_state *conn_state)
{
@@ -360,7 +379,7 @@ static bool hdmi_is_limited_range(const struct drm_connector *connector,
* i915 just assumes limited range for YCbCr output, so let's
* just do the same.
*/
- if (conn_state->hdmi.output_format != HDMI_COLORSPACE_RGB)
+ if (conn_state->hdmi.output_format != DRM_OUTPUT_COLOR_FORMAT_RGB444)
return true;
if (conn_state->hdmi.broadcast_rgb == DRM_HDMI_BROADCAST_RGB_FULL)
@@ -379,7 +398,8 @@ static bool
sink_supports_format_bpc(const struct drm_connector *connector,
const struct drm_display_info *info,
const struct drm_display_mode *mode,
- unsigned int format, unsigned int bpc)
+ enum drm_output_color_format format,
+ unsigned int bpc)
{
struct drm_device *dev = connector->dev;
u8 vic = drm_match_cea_mode(mode);
@@ -400,7 +420,7 @@ sink_supports_format_bpc(const struct drm_connector *connector,
}
if (!info->is_hdmi &&
- (format != HDMI_COLORSPACE_RGB || bpc != 8)) {
+ (format != DRM_OUTPUT_COLOR_FORMAT_RGB444 || bpc != 8)) {
drm_dbg_kms(dev, "DVI Monitors require an RGB output at 8 bpc\n");
return false;
}
@@ -411,13 +431,13 @@ sink_supports_format_bpc(const struct drm_connector *connector,
return false;
}
- if (drm_mode_is_420_only(info, mode) && format != HDMI_COLORSPACE_YUV420) {
+ if (drm_mode_is_420_only(info, mode) && format != DRM_OUTPUT_COLOR_FORMAT_YCBCR420) {
drm_dbg_kms(dev, "Mode can be only supported in YUV420 format.\n");
return false;
}
switch (format) {
- case HDMI_COLORSPACE_RGB:
+ case DRM_OUTPUT_COLOR_FORMAT_RGB444:
drm_dbg_kms(dev, "RGB Format, checking the constraints.\n");
/*
@@ -428,7 +448,7 @@ sink_supports_format_bpc(const struct drm_connector *connector,
* supported so we can keep things going and light up
* the display.
*/
- if (!(info->color_formats & DRM_COLOR_FORMAT_RGB444))
+ if (!(info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444)))
drm_warn(dev, "HDMI Sink doesn't support RGB, something's wrong.\n");
if (bpc == 10 && !(info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_30)) {
@@ -445,10 +465,10 @@ sink_supports_format_bpc(const struct drm_connector *connector,
return true;
- case HDMI_COLORSPACE_YUV420:
+ case DRM_OUTPUT_COLOR_FORMAT_YCBCR420:
drm_dbg_kms(dev, "YUV420 format, checking the constraints.\n");
- if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR420)) {
+ if (!(info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420))) {
drm_dbg_kms(dev, "Sink doesn't support YUV420.\n");
return false;
}
@@ -477,10 +497,10 @@ sink_supports_format_bpc(const struct drm_connector *connector,
return true;
- case HDMI_COLORSPACE_YUV422:
+ case DRM_OUTPUT_COLOR_FORMAT_YCBCR422:
drm_dbg_kms(dev, "YUV422 format, checking the constraints.\n");
- if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR422)) {
+ if (!(info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422))) {
drm_dbg_kms(dev, "Sink doesn't support YUV422.\n");
return false;
}
@@ -500,10 +520,10 @@ sink_supports_format_bpc(const struct drm_connector *connector,
return true;
- case HDMI_COLORSPACE_YUV444:
+ case DRM_OUTPUT_COLOR_FORMAT_YCBCR444:
drm_dbg_kms(dev, "YUV444 format, checking the constraints.\n");
- if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR444)) {
+ if (!(info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444))) {
drm_dbg_kms(dev, "Sink doesn't support YUV444.\n");
return false;
}
@@ -553,7 +573,7 @@ static int
hdmi_compute_clock(const struct drm_connector *connector,
struct drm_connector_state *conn_state,
const struct drm_display_mode *mode,
- unsigned int bpc, enum hdmi_colorspace fmt)
+ unsigned int bpc, enum drm_output_color_format fmt)
{
enum drm_mode_status status;
unsigned long long clock;
@@ -575,7 +595,7 @@ static bool
hdmi_try_format_bpc(const struct drm_connector *connector,
struct drm_connector_state *conn_state,
const struct drm_display_mode *mode,
- unsigned int bpc, enum hdmi_colorspace fmt)
+ unsigned int bpc, enum drm_output_color_format fmt)
{
const struct drm_display_info *info = &connector->display_info;
struct drm_device *dev = connector->dev;
@@ -611,7 +631,7 @@ static int
hdmi_compute_format_bpc(const struct drm_connector *connector,
struct drm_connector_state *conn_state,
const struct drm_display_mode *mode,
- unsigned int max_bpc, enum hdmi_colorspace fmt)
+ unsigned int max_bpc, enum drm_output_color_format fmt)
{
struct drm_device *dev = connector->dev;
unsigned int bpc;
@@ -652,12 +672,12 @@ hdmi_compute_config(const struct drm_connector *connector,
int ret;
ret = hdmi_compute_format_bpc(connector, conn_state, mode, max_bpc,
- HDMI_COLORSPACE_RGB);
+ DRM_OUTPUT_COLOR_FORMAT_RGB444);
if (ret) {
if (connector->ycbcr_420_allowed) {
ret = hdmi_compute_format_bpc(connector, conn_state,
mode, max_bpc,
- HDMI_COLORSPACE_YUV420);
+ DRM_OUTPUT_COLOR_FORMAT_YCBCR420);
if (ret)
drm_dbg_kms(connector->dev,
"YUV420 output format doesn't work.\n");
@@ -691,7 +711,9 @@ static int hdmi_generate_avi_infoframe(const struct drm_connector *connector,
if (ret)
return ret;
- frame->colorspace = conn_state->hdmi.output_format;
+ frame->colorspace =
+ output_color_format_to_hdmi_colorspace(connector,
+ conn_state->hdmi.output_format);
/*
* FIXME: drm_hdmi_avi_infoframe_quant_range() doesn't handle
@@ -889,7 +911,7 @@ drm_hdmi_connector_mode_valid(struct drm_connector *connector,
{
unsigned long long clock;
- clock = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_RGB);
+ clock = drm_hdmi_compute_mode_clock(mode, 8, DRM_OUTPUT_COLOR_FORMAT_RGB444);
if (!clock)
return MODE_ERROR;
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 04925166df98..41c57063f3b4 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -475,6 +475,7 @@ static void drm_atomic_crtc_print_state(struct drm_printer *p,
drm_printf(p, "\tconnector_mask=%x\n", state->connector_mask);
drm_printf(p, "\tencoder_mask=%x\n", state->encoder_mask);
drm_printf(p, "\tmode: " DRM_MODE_FMT "\n", DRM_MODE_ARG(&state->mode));
+ drm_printf(p, "\tbackground_color=%llx\n", state->background_color);
if (crtc->funcs->atomic_print_state)
crtc->funcs->atomic_print_state(p, state);
@@ -920,7 +921,6 @@ static void drm_atomic_plane_print_state(struct drm_printer *p,
* drm_atomic_private_obj_init - initialize private object
* @dev: DRM device this object will be attached to
* @obj: private object
- * @state: initial private object state
* @funcs: pointer to the struct of function pointers that identify the object
* type
*
@@ -932,9 +932,9 @@ static void drm_atomic_plane_print_state(struct drm_printer *p,
*/
int drm_atomic_private_obj_init(struct drm_device *dev,
struct drm_private_obj *obj,
- struct drm_private_state *state,
const struct drm_private_state_funcs *funcs)
{
+ struct drm_private_state *state;
memset(obj, 0, sizeof(*obj));
drm_modeset_lock_init(&obj->lock);
@@ -943,22 +943,11 @@ int drm_atomic_private_obj_init(struct drm_device *dev,
obj->funcs = funcs;
list_add_tail(&obj->head, &dev->mode_config.privobj_list);
- /*
- * Not all users of drm_atomic_private_obj_init have been
- * converted to using &drm_private_obj_funcs.atomic_create_state yet.
- * For the time being, let's only call reset if the passed state is
- * NULL. Otherwise, we will fallback to the previous behaviour.
- */
- if (!state) {
- state = obj->funcs->atomic_create_state(obj);
- if (IS_ERR(state))
- return PTR_ERR(state);
+ state = obj->funcs->atomic_create_state(obj);
+ if (IS_ERR(state))
+ return PTR_ERR(state);
- obj->state = state;
- } else {
- obj->state = state;
- state->obj = obj;
- }
+ obj->state = state;
return 0;
}
@@ -1587,6 +1576,7 @@ drm_atomic_add_affected_planes(struct drm_atomic_state *state,
const struct drm_crtc_state *old_crtc_state =
drm_atomic_get_old_crtc_state(state, crtc);
struct drm_plane *plane;
+ int ret;
WARN_ON(!drm_atomic_get_new_crtc_state(state, crtc));
@@ -1600,6 +1590,12 @@ drm_atomic_add_affected_planes(struct drm_atomic_state *state,
if (IS_ERR(plane_state))
return PTR_ERR(plane_state);
+
+ if (plane_state->color_pipeline) {
+ ret = drm_atomic_add_affected_colorops(state, plane);
+ if (ret)
+ return ret;
+ }
}
return 0;
}
diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c
index bd6faa09f83b..76746ad4a1bb 100644
--- a/drivers/gpu/drm/drm_atomic_state_helper.c
+++ b/drivers/gpu/drm/drm_atomic_state_helper.c
@@ -75,6 +75,7 @@ __drm_atomic_helper_crtc_state_reset(struct drm_crtc_state *crtc_state,
struct drm_crtc *crtc)
{
crtc_state->crtc = crtc;
+ crtc_state->background_color = DRM_ARGB64_PREP(0xffff, 0, 0, 0);
}
EXPORT_SYMBOL(__drm_atomic_helper_crtc_state_reset);
diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
index 87de41fb4459..5bd5bf6661df 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -454,6 +454,8 @@ static int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
&replaced);
state->color_mgmt_changed |= replaced;
return ret;
+ } else if (property == config->background_color_property) {
+ state->background_color = val;
} else if (property == config->prop_out_fence_ptr) {
s32 __user *fence_ptr = u64_to_user_ptr(val);
@@ -501,6 +503,8 @@ drm_atomic_crtc_get_property(struct drm_crtc *crtc,
*val = (state->ctm) ? state->ctm->base.id : 0;
else if (property == config->gamma_lut_property)
*val = (state->gamma_lut) ? state->gamma_lut->base.id : 0;
+ else if (property == config->background_color_property)
+ *val = state->background_color;
else if (property == config->prop_out_fence_ptr)
*val = 0;
else if (property == crtc->scaling_filter_property)
diff --git a/drivers/gpu/drm/drm_blend.c b/drivers/gpu/drm/drm_blend.c
index 3b1f5f72885e..1f3af27d2418 100644
--- a/drivers/gpu/drm/drm_blend.c
+++ b/drivers/gpu/drm/drm_blend.c
@@ -191,10 +191,6 @@
* plane does not expose the "alpha" property, then this is
* assumed to be 1.0
*
- * Note that all the property extensions described here apply either to the
- * plane or the CRTC (e.g. for the background color, which currently is not
- * exposed and assumed to be black).
- *
* SCALING_FILTER:
* Indicates scaling filter to be used for plane scaler
*
@@ -207,6 +203,25 @@
*
* Drivers can set up this property for a plane by calling
* drm_plane_create_scaling_filter_property
+ *
+ * The property extensions described above all apply to the plane. Drivers
+ * may also expose the following crtc property extension:
+ *
+ * BACKGROUND_COLOR:
+ * Background color is set up with drm_crtc_attach_background_color_property(),
+ * and expects a 64-bit ARGB value following DRM_FORMAT_ARGB16161616, as
+ * generated by the DRM_ARGB64_PREP*() helpers. It controls the color of a
+ * full-screen layer that exists below all planes. This color will be used
+ * for pixels not covered by any plane and may also be blended with plane
+ * contents as allowed by a plane's alpha values.
+ * The background color defaults to black, and is assumed to be black for
+ * drivers that do not expose this property. Although background color
+ * isn't a plane, it is assumed that the color provided here undergoes the
+ * CRTC degamma/CSC/gamma transformations applied after the planes blending.
+ * Note that the color value includes an alpha channel, hence non-opaque
+ * background color values are allowed, but since physically transparent
+ * monitors do not (yet) exists, the final alpha value may not reach the
+ * video sink or it may simply ignore it.
*/
/**
@@ -621,3 +636,19 @@ int drm_plane_create_blend_mode_property(struct drm_plane *plane,
return 0;
}
EXPORT_SYMBOL(drm_plane_create_blend_mode_property);
+
+/**
+ * drm_crtc_attach_background_color_property - attach background color property
+ * @crtc: drm crtc
+ *
+ * Attaches the background color property to @crtc. The property defaults to
+ * solid black and will accept 64-bit ARGB values in the format generated by
+ * DRM_ARGB64_PREP*() helpers.
+ */
+void drm_crtc_attach_background_color_property(struct drm_crtc *crtc)
+{
+ drm_object_attach_property(&crtc->base,
+ crtc->dev->mode_config.background_color_property,
+ DRM_ARGB64_PREP(0xffff, 0, 0, 0));
+}
+EXPORT_SYMBOL(drm_crtc_attach_background_color_property);
diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index f8b0333a0a3b..d6f512b73389 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -304,6 +304,9 @@ EXPORT_SYMBOL(drm_bridge_get);
*
* This function decrements the bridge's reference count and frees the
* object if the reference count drops to zero.
+ *
+ * See also drm_bridge_clear_and_put() if you also need to set the pointer
+ * to NULL
*/
void drm_bridge_put(struct drm_bridge *bridge)
{
@@ -313,6 +316,37 @@ void drm_bridge_put(struct drm_bridge *bridge)
EXPORT_SYMBOL(drm_bridge_put);
/**
+ * drm_bridge_clear_and_put - Given a bridge pointer, clear the pointer
+ * then put the bridge
+ * @bridge_pp: pointer to pointer to a struct drm_bridge; ``bridge_pp``
+ * must be non-NULL; if ``*bridge_pp`` is NULL this function
+ * does nothing
+ *
+ * Helper to put a DRM bridge, but only after setting its pointer to
+ * NULL. Useful when a struct drm_bridge reference must be dropped without
+ * leaving a use-after-free window where the pointed bridge might have been
+ * freed while still holding a pointer to it.
+ *
+ * For struct ``drm_bridge *some_bridge``, this code::
+ *
+ * drm_bridge_clear_and_put(&some_bridge);
+ *
+ * is equivalent to the more complex::
+ *
+ * struct drm_bridge *temp = some_bridge;
+ * some_bridge = NULL;
+ * drm_bridge_put(temp);
+ */
+void drm_bridge_clear_and_put(struct drm_bridge **bridge_pp)
+{
+ struct drm_bridge *bridge = *bridge_pp;
+
+ *bridge_pp = NULL;
+ drm_bridge_put(bridge);
+}
+EXPORT_SYMBOL(drm_bridge_clear_and_put);
+
+/**
* drm_bridge_put_void - wrapper to drm_bridge_put() taking a void pointer
*
* @data: pointer to @struct drm_bridge, cast to a void pointer
@@ -387,7 +421,7 @@ void drm_bridge_add(struct drm_bridge *bridge)
if (bridge->ops & DRM_BRIDGE_OP_HDMI)
bridge->ycbcr_420_allowed = !!(bridge->supported_formats &
- BIT(HDMI_COLORSPACE_YUV420));
+ BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420));
mutex_lock(&bridge_lock);
list_add_tail(&bridge->list, &bridge_list);
@@ -553,7 +587,6 @@ int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
if (drm_bridge_is_atomic(bridge))
drm_atomic_private_obj_init(bridge->dev, &bridge->base,
- NULL,
&drm_bridge_priv_state_funcs);
return 0;
@@ -1570,11 +1603,17 @@ EXPORT_SYMBOL(devm_drm_put_bridge);
static void drm_bridge_debugfs_show_bridge(struct drm_printer *p,
struct drm_bridge *bridge,
unsigned int idx,
- bool lingering)
+ bool lingering,
+ bool scoped)
{
+ unsigned int refcount = kref_read(&bridge->refcount);
+
+ if (scoped)
+ refcount--;
+
drm_printf(p, "bridge[%u]: %ps\n", idx, bridge->funcs);
- drm_printf(p, "\trefcount: %u%s\n", kref_read(&bridge->refcount),
+ drm_printf(p, "\trefcount: %u%s\n", refcount,
lingering ? " [lingering]" : "");
drm_printf(p, "\ttype: [%d] %s\n",
@@ -1608,10 +1647,10 @@ static int allbridges_show(struct seq_file *m, void *data)
mutex_lock(&bridge_lock);
list_for_each_entry(bridge, &bridge_list, list)
- drm_bridge_debugfs_show_bridge(&p, bridge, idx++, false);
+ drm_bridge_debugfs_show_bridge(&p, bridge, idx++, false, false);
list_for_each_entry(bridge, &bridge_lingering_list, list)
- drm_bridge_debugfs_show_bridge(&p, bridge, idx++, true);
+ drm_bridge_debugfs_show_bridge(&p, bridge, idx++, true, false);
mutex_unlock(&bridge_lock);
@@ -1626,7 +1665,7 @@ static int encoder_bridges_show(struct seq_file *m, void *data)
unsigned int idx = 0;
drm_for_each_bridge_in_chain_scoped(encoder, bridge)
- drm_bridge_debugfs_show_bridge(&p, bridge, idx++, false);
+ drm_bridge_debugfs_show_bridge(&p, bridge, idx++, false, true);
return 0;
}
diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c
index f421c623b3f0..566816e3c6f0 100644
--- a/drivers/gpu/drm/drm_colorop.c
+++ b/drivers/gpu/drm/drm_colorop.c
@@ -171,12 +171,8 @@ void drm_colorop_cleanup(struct drm_colorop *colorop)
list_del(&colorop->head);
config->num_colorop--;
- if (colorop->state && colorop->state->data) {
- drm_property_blob_put(colorop->state->data);
- colorop->state->data = NULL;
- }
-
- kfree(colorop->state);
+ if (colorop->state)
+ drm_colorop_atomic_destroy_state(colorop, colorop->state);
}
EXPORT_SYMBOL(drm_colorop_cleanup);
@@ -466,8 +462,6 @@ static void __drm_atomic_helper_colorop_duplicate_state(struct drm_colorop *colo
if (state->data)
drm_property_blob_get(state->data);
-
- state->bypass = true;
}
struct drm_colorop_state *
@@ -485,9 +479,23 @@ drm_atomic_helper_colorop_duplicate_state(struct drm_colorop *colorop)
return state;
}
+/**
+ * __drm_atomic_helper_colorop_destroy_state - release colorop state
+ * @state: colorop state object to release
+ *
+ * Releases all resources stored in the colorop state without actually freeing
+ * the memory of the colorop state. This is useful for drivers that subclass the
+ * colorop state.
+ */
+static void __drm_atomic_helper_colorop_destroy_state(struct drm_colorop_state *state)
+{
+ drm_property_blob_put(state->data);
+}
+
void drm_colorop_atomic_destroy_state(struct drm_colorop *colorop,
struct drm_colorop_state *state)
{
+ __drm_atomic_helper_colorop_destroy_state(state);
kfree(state);
}
@@ -538,7 +546,9 @@ static void __drm_colorop_reset(struct drm_colorop *colorop,
void drm_colorop_reset(struct drm_colorop *colorop)
{
- kfree(colorop->state);
+ if (colorop->state)
+ drm_colorop_atomic_destroy_state(colorop, colorop->state);
+
colorop->state = kzalloc_obj(*colorop->state);
if (colorop->state)
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index e70699c59c43..47dc53c4a738 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -552,7 +552,7 @@ EXPORT_SYMBOL(drmm_connector_init);
* @hdmi_funcs: HDMI-related callbacks for this connector
* @connector_type: user visible type of the connector
* @ddc: optional pointer to the associated ddc adapter
- * @supported_formats: Bitmask of @hdmi_colorspace listing supported output formats
+ * @supported_formats: Bitmask of @drm_output_color_format listing supported output formats
* @max_bpc: Maximum bits per char the HDMI connector supports
*
* Initialises a preallocated HDMI connector. Connectors can be
@@ -591,10 +591,10 @@ int drmm_connector_hdmi_init(struct drm_device *dev,
connector_type == DRM_MODE_CONNECTOR_HDMIB))
return -EINVAL;
- if (!supported_formats || !(supported_formats & BIT(HDMI_COLORSPACE_RGB)))
+ if (!supported_formats || !(supported_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444)))
return -EINVAL;
- if (connector->ycbcr_420_allowed != !!(supported_formats & BIT(HDMI_COLORSPACE_YUV420)))
+ if (connector->ycbcr_420_allowed != !!(supported_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420)))
return -EINVAL;
if (!(max_bpc == 8 || max_bpc == 10 || max_bpc == 12))
@@ -1431,10 +1431,10 @@ drm_hdmi_connector_get_broadcast_rgb_name(enum drm_hdmi_broadcast_rgb broadcast_
EXPORT_SYMBOL(drm_hdmi_connector_get_broadcast_rgb_name);
static const char * const output_format_str[] = {
- [HDMI_COLORSPACE_RGB] = "RGB",
- [HDMI_COLORSPACE_YUV420] = "YUV 4:2:0",
- [HDMI_COLORSPACE_YUV422] = "YUV 4:2:2",
- [HDMI_COLORSPACE_YUV444] = "YUV 4:4:4",
+ [DRM_OUTPUT_COLOR_FORMAT_RGB444] = "RGB",
+ [DRM_OUTPUT_COLOR_FORMAT_YCBCR420] = "YUV 4:2:0",
+ [DRM_OUTPUT_COLOR_FORMAT_YCBCR422] = "YUV 4:2:2",
+ [DRM_OUTPUT_COLOR_FORMAT_YCBCR444] = "YUV 4:4:4",
};
/*
@@ -1445,7 +1445,7 @@ static const char * const output_format_str[] = {
* valid.
*/
const char *
-drm_hdmi_connector_get_output_format_name(enum hdmi_colorspace fmt)
+drm_hdmi_connector_get_output_format_name(enum drm_output_color_format fmt)
{
if (fmt >= ARRAY_SIZE(output_format_str))
return NULL;
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 8d6f721c2c9a..63ead8ba6756 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -340,8 +340,7 @@ static int __drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *
* Inits a new object created as base part of a driver crtc object. Drivers
* should use this function instead of drm_crtc_init(), which is only provided
* for backwards compatibility with drivers which do not yet support universal
- * planes). For really simple hardware which has only 1 plane look at
- * drm_simple_display_pipe_init() instead.
+ * planes).
* The &drm_crtc_funcs.destroy hook should call drm_crtc_cleanup() and kfree()
* the crtc structure. The crtc structure should not be allocated with
* devm_kzalloc().
@@ -424,8 +423,7 @@ static int __drmm_crtc_init_with_planes(struct drm_device *dev,
* Inits a new object created as base part of a driver crtc object. Drivers
* should use this function instead of drm_crtc_init(), which is only provided
* for backwards compatibility with drivers which do not yet support universal
- * planes). For really simple hardware which has only 1 plane look at
- * drm_simple_display_pipe_init() instead.
+ * planes).
*
* Cleanup is automatically handled through registering
* drmm_crtc_cleanup() with drmm_add_action(). The crtc structure should
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 6b965c3d3307..985c283cf59f 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -587,7 +587,7 @@ int drm_dev_wedged_event(struct drm_device *dev, unsigned long method,
snprintf(event_string, sizeof(event_string), "%s", "WEDGED=unknown");
drm_info(dev, "device wedged, %s\n", method == DRM_WEDGE_RECOVERY_NONE ?
- "but recovered through reset" : "needs recovery");
+ "but no recovery needed" : "needs recovery");
if (info && (info->comm[0] != '\0') && (info->pid >= 0)) {
snprintf(pid_string, sizeof(pid_string), "PID=%u", info->pid);
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index ff432ac6b569..5f9fcd7d9ce4 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -5316,7 +5316,7 @@ static void parse_cta_y420cmdb(struct drm_connector *connector,
out:
if (map)
- info->color_formats |= DRM_COLOR_FORMAT_YCBCR420;
+ info->color_formats |= BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420);
*y420cmdb_map = map;
}
@@ -6092,7 +6092,7 @@ static void parse_cta_y420vdb(struct drm_connector *connector,
continue;
bitmap_set(hdmi->y420_vdb_modes, vic, 1);
- info->color_formats |= DRM_COLOR_FORMAT_YCBCR420;
+ info->color_formats |= BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420);
}
}
@@ -6426,11 +6426,11 @@ static void drm_parse_cea_ext(struct drm_connector *connector,
info->cea_rev, edid_ext[1]);
/* The existence of a CTA extension should imply RGB support */
- info->color_formats = DRM_COLOR_FORMAT_RGB444;
+ info->color_formats = BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444);
if (edid_ext[3] & EDID_CEA_YCRCB444)
- info->color_formats |= DRM_COLOR_FORMAT_YCBCR444;
+ info->color_formats |= BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444);
if (edid_ext[3] & EDID_CEA_YCRCB422)
- info->color_formats |= DRM_COLOR_FORMAT_YCBCR422;
+ info->color_formats |= BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422);
if (edid_ext[3] & EDID_BASIC_AUDIO)
info->has_audio = true;
@@ -6698,7 +6698,7 @@ static void update_display_info(struct drm_connector *connector,
if (!drm_edid_is_digital(drm_edid))
goto out;
- info->color_formats |= DRM_COLOR_FORMAT_RGB444;
+ info->color_formats |= BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444);
drm_parse_cea_ext(connector, drm_edid);
update_displayid_info(connector, drm_edid);
@@ -6752,9 +6752,9 @@ static void update_display_info(struct drm_connector *connector,
connector->base.id, connector->name, info->bpc);
if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB444)
- info->color_formats |= DRM_COLOR_FORMAT_YCBCR444;
+ info->color_formats |= BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444);
if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB422)
- info->color_formats |= DRM_COLOR_FORMAT_YCBCR422;
+ info->color_formats |= BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422);
drm_update_mso(connector, drm_edid);
@@ -7229,7 +7229,7 @@ static bool is_hdmi2_sink(const struct drm_connector *connector)
return true;
return connector->display_info.hdmi.scdc.supported ||
- connector->display_info.color_formats & DRM_COLOR_FORMAT_YCBCR420;
+ connector->display_info.color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420);
}
static u8 drm_mode_hdmi_vic(const struct drm_connector *connector,
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index fdf08cae1c5b..0377a5fd402d 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -821,13 +821,14 @@ err:
* Takes an array of userspace handles and returns a newly allocated array of
* GEM objects.
*
- * For a single handle lookup, use drm_gem_object_lookup().
+ * After a successful lookup GEM objects need to be released using
+ * drm_gem_object_put() and the array returned in @objs_out must be freed using
+ * kvfree().
*
- * Returns:
- * @objs filled in with GEM object pointers. Returned GEM objects need to be
- * released with drm_gem_object_put(). -ENOENT is returned on a lookup
- * failure. 0 is returned on success.
+ * For a single handle lookup, use drm_gem_object_lookup().
*
+ * Return:
+ * Zero on success or a negative error code.
*/
int drm_gem_objects_lookup(struct drm_file *filp, void __user *bo_handles,
int count, struct drm_gem_object ***objs_out)
diff --git a/drivers/gpu/drm/drm_gem_atomic_helper.c b/drivers/gpu/drm/drm_gem_atomic_helper.c
index 421c460ac972..abef865c5f2c 100644
--- a/drivers/gpu/drm/drm_gem_atomic_helper.c
+++ b/drivers/gpu/drm/drm_gem_atomic_helper.c
@@ -87,28 +87,6 @@
* A mapping address for each of the framebuffer's buffer object is stored in
* struct &drm_shadow_plane_state.map. The mappings are valid while the state
* is being used.
- *
- * Drivers that use struct drm_simple_display_pipe can use
- * %DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS to initialize the rsp
- * callbacks. Access to shadow-buffer mappings is similar to regular
- * atomic_update.
- *
- * .. code-block:: c
- *
- * struct drm_simple_display_pipe_funcs driver_pipe_funcs = {
- * ...,
- * DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS,
- * };
- *
- * void driver_pipe_enable(struct drm_simple_display_pipe *pipe,
- * struct drm_crtc_state *crtc_state,
- * struct drm_plane_state *plane_state)
- * {
- * struct drm_shadow_plane_state *shadow_plane_state =
- * to_drm_shadow_plane_state(plane_state);
- *
- * // access shadow buffer via shadow_plane_state->map
- * }
*/
/*
diff --git a/drivers/gpu/drm/drm_gem_dma_helper.c b/drivers/gpu/drm/drm_gem_dma_helper.c
index ecb9746f4da8..1c00a71ab3c9 100644
--- a/drivers/gpu/drm/drm_gem_dma_helper.c
+++ b/drivers/gpu/drm/drm_gem_dma_helper.c
@@ -146,12 +146,13 @@ struct drm_gem_dma_object *drm_gem_dma_create(struct drm_device *drm,
return dma_obj;
if (dma_obj->map_noncoherent) {
- dma_obj->vaddr = dma_alloc_noncoherent(drm->dev, size,
+ dma_obj->vaddr = dma_alloc_noncoherent(drm_dev_dma_dev(drm),
+ size,
&dma_obj->dma_addr,
DMA_TO_DEVICE,
GFP_KERNEL | __GFP_NOWARN);
} else {
- dma_obj->vaddr = dma_alloc_wc(drm->dev, size,
+ dma_obj->vaddr = dma_alloc_wc(drm_dev_dma_dev(drm), size,
&dma_obj->dma_addr,
GFP_KERNEL | __GFP_NOWARN);
}
@@ -236,12 +237,14 @@ void drm_gem_dma_free(struct drm_gem_dma_object *dma_obj)
drm_prime_gem_destroy(gem_obj, dma_obj->sgt);
} else if (dma_obj->vaddr) {
if (dma_obj->map_noncoherent)
- dma_free_noncoherent(gem_obj->dev->dev, dma_obj->base.size,
+ dma_free_noncoherent(drm_dev_dma_dev(gem_obj->dev),
+ dma_obj->base.size,
dma_obj->vaddr, dma_obj->dma_addr,
DMA_TO_DEVICE);
else
- dma_free_wc(gem_obj->dev->dev, dma_obj->base.size,
- dma_obj->vaddr, dma_obj->dma_addr);
+ dma_free_wc(drm_dev_dma_dev(gem_obj->dev),
+ dma_obj->base.size, dma_obj->vaddr,
+ dma_obj->dma_addr);
}
drm_gem_object_release(gem_obj);
@@ -432,7 +435,7 @@ struct sg_table *drm_gem_dma_get_sg_table(struct drm_gem_dma_object *dma_obj)
if (!sgt)
return ERR_PTR(-ENOMEM);
- ret = dma_get_sgtable(obj->dev->dev, sgt, dma_obj->vaddr,
+ ret = dma_get_sgtable(drm_dev_dma_dev(obj->dev), sgt, dma_obj->vaddr,
dma_obj->dma_addr, obj->size);
if (ret < 0)
goto out;
@@ -534,17 +537,17 @@ int drm_gem_dma_mmap(struct drm_gem_dma_object *dma_obj, struct vm_area_struct *
* the whole buffer.
*/
vma->vm_pgoff -= drm_vma_node_start(&obj->vma_node);
- vm_flags_mod(vma, VM_DONTEXPAND, VM_PFNMAP);
+ vm_flags_mod(vma, VM_DONTDUMP | VM_DONTEXPAND, VM_PFNMAP);
if (dma_obj->map_noncoherent) {
vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
- ret = dma_mmap_pages(dma_obj->base.dev->dev,
+ ret = dma_mmap_pages(drm_dev_dma_dev(dma_obj->base.dev),
vma, vma->vm_end - vma->vm_start,
virt_to_page(dma_obj->vaddr));
} else {
- ret = dma_mmap_wc(dma_obj->base.dev->dev, vma, dma_obj->vaddr,
- dma_obj->dma_addr,
+ ret = dma_mmap_wc(drm_dev_dma_dev(dma_obj->base.dev), vma,
+ dma_obj->vaddr, dma_obj->dma_addr,
vma->vm_end - vma->vm_start);
}
if (ret)
diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c b/drivers/gpu/drm/drm_gem_shmem_helper.c
index 4500deef4127..2062ca607833 100644
--- a/drivers/gpu/drm/drm_gem_shmem_helper.c
+++ b/drivers/gpu/drm/drm_gem_shmem_helper.c
@@ -554,23 +554,27 @@ int drm_gem_shmem_dumb_create(struct drm_file *file, struct drm_device *dev,
}
EXPORT_SYMBOL_GPL(drm_gem_shmem_dumb_create);
-static vm_fault_t drm_gem_shmem_try_insert_pfn_pmd(struct vm_fault *vmf, unsigned long pfn)
+static vm_fault_t try_insert_pfn(struct vm_fault *vmf, unsigned int order,
+ unsigned long pfn)
{
+ if (!order) {
+ return vmf_insert_pfn(vmf->vma, vmf->address, pfn);
#ifdef CONFIG_ARCH_SUPPORTS_PMD_PFNMAP
- unsigned long paddr = pfn << PAGE_SHIFT;
- bool aligned = (vmf->address & ~PMD_MASK) == (paddr & ~PMD_MASK);
-
- if (aligned && pmd_none(*vmf->pmd)) {
- /* Read-only mapping; split upon write fault */
- pfn &= PMD_MASK >> PAGE_SHIFT;
- return vmf_insert_pfn_pmd(vmf, pfn, false);
- }
+ } else if (order == PMD_ORDER) {
+ unsigned long paddr = pfn << PAGE_SHIFT;
+ bool aligned = (vmf->address & ~PMD_MASK) == (paddr & ~PMD_MASK);
+
+ if (aligned &&
+ folio_test_pmd_mappable(page_folio(pfn_to_page(pfn)))) {
+ pfn &= PMD_MASK >> PAGE_SHIFT;
+ return vmf_insert_pfn_pmd(vmf, pfn, false);
+ }
#endif
-
- return 0;
+ }
+ return VM_FAULT_FALLBACK;
}
-static vm_fault_t drm_gem_shmem_fault(struct vm_fault *vmf)
+static vm_fault_t drm_gem_shmem_any_fault(struct vm_fault *vmf, unsigned int order)
{
struct vm_area_struct *vma = vmf->vma;
struct drm_gem_object *obj = vma->vm_private_data;
@@ -584,6 +588,9 @@ static vm_fault_t drm_gem_shmem_fault(struct vm_fault *vmf)
struct folio *folio;
unsigned long pfn;
+ if (order && order != PMD_ORDER)
+ return VM_FAULT_FALLBACK;
+
dma_resv_lock(obj->resv, NULL);
if (page_offset >= num_pages || drm_WARN_ON_ONCE(dev, !shmem->pages) ||
@@ -597,11 +604,7 @@ static vm_fault_t drm_gem_shmem_fault(struct vm_fault *vmf)
pfn = page_to_pfn(page);
- if (folio_test_pmd_mappable(folio))
- ret = drm_gem_shmem_try_insert_pfn_pmd(vmf, pfn);
- if (ret != VM_FAULT_NOPAGE)
- ret = vmf_insert_pfn(vma, vmf->address, pfn);
-
+ ret = try_insert_pfn(vmf, order, pfn);
if (ret == VM_FAULT_NOPAGE)
folio_mark_accessed(folio);
@@ -611,6 +614,11 @@ out:
return ret;
}
+static vm_fault_t drm_gem_shmem_fault(struct vm_fault *vmf)
+{
+ return drm_gem_shmem_any_fault(vmf, 0);
+}
+
static void drm_gem_shmem_vm_open(struct vm_area_struct *vma)
{
struct drm_gem_object *obj = vma->vm_private_data;
@@ -665,6 +673,9 @@ static vm_fault_t drm_gem_shmem_pfn_mkwrite(struct vm_fault *vmf)
const struct vm_operations_struct drm_gem_shmem_vm_ops = {
.fault = drm_gem_shmem_fault,
+#ifdef CONFIG_ARCH_SUPPORTS_PMD_PFNMAP
+ .huge_fault = drm_gem_shmem_any_fault,
+#endif
.open = drm_gem_shmem_vm_open,
.close = drm_gem_shmem_vm_close,
.pfn_mkwrite = drm_gem_shmem_pfn_mkwrite,
diff --git a/drivers/gpu/drm/drm_ioc32.c b/drivers/gpu/drm/drm_ioc32.c
index e6b5b06de148..f3e40d1e6098 100644
--- a/drivers/gpu/drm/drm_ioc32.c
+++ b/drivers/gpu/drm/drm_ioc32.c
@@ -28,6 +28,7 @@
* IN THE SOFTWARE.
*/
#include <linux/compat.h>
+#include <linux/nospec.h>
#include <linux/ratelimit.h>
#include <linux/export.h>
@@ -374,6 +375,7 @@ long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
if (nr >= ARRAY_SIZE(drm_compat_ioctls))
return drm_ioctl(filp, cmd, arg);
+ nr = array_index_nospec(nr, ARRAY_SIZE(drm_compat_ioctls));
fn = drm_compat_ioctls[nr].fn;
if (!fn)
return drm_ioctl(filp, cmd, arg);
diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c
index 00482227a9cd..9ab6113d74a2 100644
--- a/drivers/gpu/drm/drm_mipi_dbi.c
+++ b/drivers/gpu/drm/drm_mipi_dbi.c
@@ -14,7 +14,7 @@
#include <linux/regulator/consumer.h>
#include <linux/spi/spi.h>
-#include <drm/drm_connector.h>
+#include <drm/drm_atomic.h>
#include <drm/drm_damage_helper.h>
#include <drm/drm_drv.h>
#include <drm/drm_file.h>
@@ -22,12 +22,9 @@
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem.h>
-#include <drm/drm_gem_atomic_helper.h>
-#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_mipi_dbi.h>
#include <drm/drm_modes.h>
#include <drm/drm_print.h>
-#include <drm/drm_probe_helper.h>
#include <drm/drm_rect.h>
#include <video/mipi_display.h>
@@ -317,94 +314,87 @@ err_msg:
}
/**
- * mipi_dbi_pipe_mode_valid - MIPI DBI mode-valid helper
- * @pipe: Simple display pipe
+ * drm_mipi_dbi_crtc_helper_mode_valid - MIPI DBI mode-valid helper
+ * @crtc: The CRTC
* @mode: The mode to test
*
* This function validates a given display mode against the MIPI DBI's hardware
- * display. Drivers can use this as their &drm_simple_display_pipe_funcs->mode_valid
+ * display. Drivers can use this as their struct &drm_crtc_helper_funcs.mode_valid
* callback.
*/
-enum drm_mode_status mipi_dbi_pipe_mode_valid(struct drm_simple_display_pipe *pipe,
- const struct drm_display_mode *mode)
+enum drm_mode_status drm_mipi_dbi_crtc_helper_mode_valid(struct drm_crtc *crtc,
+ const struct drm_display_mode *mode)
{
- struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev);
+ struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(crtc->dev);
- return drm_crtc_helper_mode_valid_fixed(&pipe->crtc, mode, &dbidev->mode);
+ return drm_crtc_helper_mode_valid_fixed(crtc, mode, &dbidev->mode);
}
-EXPORT_SYMBOL(mipi_dbi_pipe_mode_valid);
+EXPORT_SYMBOL(drm_mipi_dbi_crtc_helper_mode_valid);
/**
- * mipi_dbi_pipe_update - Display pipe update helper
- * @pipe: Simple display pipe
- * @old_state: Old plane state
+ * drm_mipi_dbi_plane_helper_atomic_check - MIPI DBI plane check helper
+ * @plane: Plane to check
+ * @state: Atomic state
*
- * This function handles framebuffer flushing and vblank events. Drivers can use
- * this as their &drm_simple_display_pipe_funcs->update callback.
+ * This function performs the default checks on the primary plane
+ * of a MIPI DBI device. Drivers can use this as their
+ * struct &drm_crtc_helper_funcs.atomic_check callback.
+ *
+ * Returns:
+ * 0 on success, or a negative errno code otherwise.
*/
-void mipi_dbi_pipe_update(struct drm_simple_display_pipe *pipe,
- struct drm_plane_state *old_state)
+int drm_mipi_dbi_plane_helper_atomic_check(struct drm_plane *plane,
+ struct drm_atomic_state *state)
{
- struct drm_plane_state *state = pipe->plane.state;
- struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(state);
- struct drm_framebuffer *fb = state->fb;
- struct drm_rect rect;
- int idx;
-
- if (!pipe->crtc.state->active)
- return;
-
- if (WARN_ON(!fb))
- return;
+ struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
+ struct drm_crtc_state *new_crtc_state = NULL;
+ int ret;
- if (!drm_dev_enter(fb->dev, &idx))
- return;
+ if (new_plane_state->crtc)
+ new_crtc_state = drm_atomic_get_new_crtc_state(state, new_plane_state->crtc);
- if (drm_atomic_helper_damage_merged(old_state, state, &rect))
- mipi_dbi_fb_dirty(&shadow_plane_state->data[0], fb, &rect,
- &shadow_plane_state->fmtcnv_state);
+ ret = drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state,
+ DRM_PLANE_NO_SCALING,
+ DRM_PLANE_NO_SCALING,
+ false, false);
+ if (ret)
+ return ret;
+ else if (!new_plane_state->visible)
+ return 0;
- drm_dev_exit(idx);
+ return 0;
}
-EXPORT_SYMBOL(mipi_dbi_pipe_update);
+EXPORT_SYMBOL(drm_mipi_dbi_plane_helper_atomic_check);
/**
- * mipi_dbi_enable_flush - MIPI DBI enable helper
- * @dbidev: MIPI DBI device structure
- * @crtc_state: CRTC state
- * @plane_state: Plane state
- *
- * Flushes the whole framebuffer and enables the backlight. Drivers can use this
- * in their &drm_simple_display_pipe_funcs->enable callback.
+ * drm_mipi_dbi_plane_helper_atomic_update - Display update helper
+ * @plane: Plane
+ * @state: Atomic state
*
- * Note: Drivers which don't use mipi_dbi_pipe_update() because they have custom
- * framebuffer flushing, can't use this function since they both use the same
- * flushing code.
+ * This function handles framebuffer flushing and vblank events. Drivers can use
+ * this as their struct &drm_plane_helper_funcs.atomic_update callback.
*/
-void mipi_dbi_enable_flush(struct mipi_dbi_dev *dbidev,
- struct drm_crtc_state *crtc_state,
- struct drm_plane_state *plane_state)
+void drm_mipi_dbi_plane_helper_atomic_update(struct drm_plane *plane,
+ struct drm_atomic_state *state)
{
+ struct drm_plane_state *plane_state = plane->state;
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
struct drm_framebuffer *fb = plane_state->fb;
- struct drm_rect rect = {
- .x1 = 0,
- .x2 = fb->width,
- .y1 = 0,
- .y2 = fb->height,
- };
+ struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
+ struct drm_rect rect;
int idx;
- if (!drm_dev_enter(&dbidev->drm, &idx))
+ if (!fb)
return;
- mipi_dbi_fb_dirty(&shadow_plane_state->data[0], fb, &rect,
- &shadow_plane_state->fmtcnv_state);
- backlight_enable(dbidev->backlight);
-
- drm_dev_exit(idx);
+ if (drm_dev_enter(plane->dev, &idx)) {
+ if (drm_atomic_helper_damage_merged(old_plane_state, plane_state, &rect))
+ mipi_dbi_fb_dirty(&shadow_plane_state->data[0], fb, &rect,
+ &shadow_plane_state->fmtcnv_state);
+ drm_dev_exit(idx);
+ }
}
-EXPORT_SYMBOL(mipi_dbi_enable_flush);
+EXPORT_SYMBOL(drm_mipi_dbi_plane_helper_atomic_update);
static void mipi_dbi_blank(struct mipi_dbi_dev *dbidev)
{
@@ -432,18 +422,48 @@ static void mipi_dbi_blank(struct mipi_dbi_dev *dbidev)
}
/**
- * mipi_dbi_pipe_disable - MIPI DBI pipe disable helper
- * @pipe: Display pipe
+ * drm_mipi_dbi_crtc_helper_atomic_check - MIPI DBI CRTC check helper
+ * @crtc: CRTC to check
+ * @state: Atomic state
+ *
+ * This function performs the default checks on the CRTC of a MIPI DBI
+ * device and ensures that the primary plane as been set up correctly.
+ * Drivers can use this as their struct &drm_crtc_helper_funcs.atomic_check
+ * callback.
+ *
+ * Returns:
+ * 0 on success, or a negative errno code otherwise.
+ */
+int drm_mipi_dbi_crtc_helper_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state)
+{
+ struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+ int ret;
+
+ if (!crtc_state->enable)
+ goto out;
+
+ ret = drm_atomic_helper_check_crtc_primary_plane(crtc_state);
+ if (ret)
+ return ret;
+
+out:
+ return drm_atomic_add_affected_planes(state, crtc);
+}
+EXPORT_SYMBOL(drm_mipi_dbi_crtc_helper_atomic_check);
+
+/**
+ * drm_mipi_dbi_crtc_helper_atomic_disable - MIPI DBI CRTC disable helper
+ * @crtc: CRTC to disable
+ * @state: Atomic state
*
* This function disables backlight if present, if not the display memory is
* blanked. The regulator is disabled if in use. Drivers can use this as their
- * &drm_simple_display_pipe_funcs->disable callback.
+ * struct &drm_crtc_helper_funcs.atomic_disable callback.
*/
-void mipi_dbi_pipe_disable(struct drm_simple_display_pipe *pipe)
+void drm_mipi_dbi_crtc_helper_atomic_disable(struct drm_crtc *crtc,
+ struct drm_atomic_state *state)
{
- struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev);
-
- DRM_DEBUG_KMS("\n");
+ struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(crtc->dev);
if (dbidev->backlight)
backlight_disable(dbidev->backlight);
@@ -455,110 +475,26 @@ void mipi_dbi_pipe_disable(struct drm_simple_display_pipe *pipe)
if (dbidev->io_regulator)
regulator_disable(dbidev->io_regulator);
}
-EXPORT_SYMBOL(mipi_dbi_pipe_disable);
+EXPORT_SYMBOL(drm_mipi_dbi_crtc_helper_atomic_disable);
/**
- * mipi_dbi_pipe_begin_fb_access - MIPI DBI pipe begin-access helper
- * @pipe: Display pipe
- * @plane_state: Plane state
- *
- * This function implements struct &drm_simple_display_funcs.begin_fb_access.
+ * drm_mipi_dbi_connector_helper_get_modes - Duplicates the MIPI DBI mode for the connector
+ * @connector: The connector
*
- * See drm_gem_begin_shadow_fb_access() for details and mipi_dbi_pipe_cleanup_fb()
- * for cleanup.
+ * Sets the connecto rmodes from the MIPI DBI mode. Drivers can use this as their
+ * &drm_connector_helper_funcs->get_mods callback. See drm_gem_destroy_shadow_plane_state()
+ * for additional details.
*
* Returns:
- * 0 on success, or a negative errno code otherwise.
- */
-int mipi_dbi_pipe_begin_fb_access(struct drm_simple_display_pipe *pipe,
- struct drm_plane_state *plane_state)
-{
- return drm_gem_begin_shadow_fb_access(&pipe->plane, plane_state);
-}
-EXPORT_SYMBOL(mipi_dbi_pipe_begin_fb_access);
-
-/**
- * mipi_dbi_pipe_end_fb_access - MIPI DBI pipe end-access helper
- * @pipe: Display pipe
- * @plane_state: Plane state
- *
- * This function implements struct &drm_simple_display_funcs.end_fb_access.
- *
- * See mipi_dbi_pipe_begin_fb_access().
- */
-void mipi_dbi_pipe_end_fb_access(struct drm_simple_display_pipe *pipe,
- struct drm_plane_state *plane_state)
-{
- drm_gem_end_shadow_fb_access(&pipe->plane, plane_state);
-}
-EXPORT_SYMBOL(mipi_dbi_pipe_end_fb_access);
-
-/**
- * mipi_dbi_pipe_reset_plane - MIPI DBI plane-reset helper
- * @pipe: Display pipe
- *
- * This function implements struct &drm_simple_display_funcs.reset_plane
- * for MIPI DBI planes.
+ * The number of created modes.
*/
-void mipi_dbi_pipe_reset_plane(struct drm_simple_display_pipe *pipe)
-{
- drm_gem_reset_shadow_plane(&pipe->plane);
-}
-EXPORT_SYMBOL(mipi_dbi_pipe_reset_plane);
-
-/**
- * mipi_dbi_pipe_duplicate_plane_state - duplicates MIPI DBI plane state
- * @pipe: Display pipe
- *
- * This function implements struct &drm_simple_display_funcs.duplicate_plane_state
- * for MIPI DBI planes.
- *
- * See drm_gem_duplicate_shadow_plane_state() for additional details.
- *
- * Returns:
- * A pointer to a new plane state on success, or NULL otherwise.
- */
-struct drm_plane_state *mipi_dbi_pipe_duplicate_plane_state(struct drm_simple_display_pipe *pipe)
-{
- return drm_gem_duplicate_shadow_plane_state(&pipe->plane);
-}
-EXPORT_SYMBOL(mipi_dbi_pipe_duplicate_plane_state);
-
-/**
- * mipi_dbi_pipe_destroy_plane_state - cleans up MIPI DBI plane state
- * @pipe: Display pipe
- * @plane_state: Plane state
- *
- * This function implements struct drm_simple_display_funcs.destroy_plane_state
- * for MIPI DBI planes.
- *
- * See drm_gem_destroy_shadow_plane_state() for additional details.
- */
-void mipi_dbi_pipe_destroy_plane_state(struct drm_simple_display_pipe *pipe,
- struct drm_plane_state *plane_state)
-{
- drm_gem_destroy_shadow_plane_state(&pipe->plane, plane_state);
-}
-EXPORT_SYMBOL(mipi_dbi_pipe_destroy_plane_state);
-
-static int mipi_dbi_connector_get_modes(struct drm_connector *connector)
+int drm_mipi_dbi_connector_helper_get_modes(struct drm_connector *connector)
{
struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(connector->dev);
return drm_connector_helper_get_modes_fixed(connector, &dbidev->mode);
}
-
-static const struct drm_connector_helper_funcs mipi_dbi_connector_hfuncs = {
- .get_modes = mipi_dbi_connector_get_modes,
-};
-
-static const struct drm_connector_funcs mipi_dbi_connector_funcs = {
- .reset = drm_atomic_helper_connector_reset,
- .fill_modes = drm_helper_probe_single_connector_modes,
- .destroy = drm_connector_cleanup,
- .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
- .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
-};
+EXPORT_SYMBOL(drm_mipi_dbi_connector_helper_get_modes);
static int mipi_dbi_rotate_mode(struct drm_display_mode *mode,
unsigned int rotation)
@@ -577,59 +513,36 @@ static int mipi_dbi_rotate_mode(struct drm_display_mode *mode,
}
}
-static const struct drm_mode_config_funcs mipi_dbi_mode_config_funcs = {
- .fb_create = drm_gem_fb_create_with_dirty,
- .atomic_check = drm_atomic_helper_check,
- .atomic_commit = drm_atomic_helper_commit,
-};
-
-static const uint32_t mipi_dbi_formats[] = {
- DRM_FORMAT_RGB565,
- DRM_FORMAT_XRGB8888,
-};
-
/**
- * mipi_dbi_dev_init_with_formats - MIPI DBI device initialization with custom formats
+ * drm_mipi_dbi_dev_init - MIPI DBI device initialization
* @dbidev: MIPI DBI device structure to initialize
- * @funcs: Display pipe functions
- * @formats: Array of supported formats (DRM_FORMAT\_\*).
- * @format_count: Number of elements in @formats
- * @mode: Display mode
+ * @mode: Hardware display mode
+ * @format: Hardware color format (DRM_FORMAT\_\*).
* @rotation: Initial rotation in degrees Counter Clock Wise
- * @tx_buf_size: Allocate a transmit buffer of this size.
- *
- * This function sets up a &drm_simple_display_pipe with a &drm_connector that
- * has one fixed &drm_display_mode which is rotated according to @rotation.
- * This mode is used to set the mode config min/max width/height properties.
- *
- * Use mipi_dbi_dev_init() if you want native RGB565 and emulated XRGB8888 format.
+ * @tx_buf_size: Allocate a transmit buffer of at least this size.
*
- * Note:
- * Some of the helper functions expects RGB565 to be the default format and the
- * transmit buffer sized to fit that.
+ * Initializes a MIPI-DBI device. The minimum size of the transmit buffer
+ * in @tx_buf_size is optional. Pass 0 to allocate enough memory to transmit
+ * a single scanline of the display.
*
* Returns:
* Zero on success, negative error code on failure.
*/
-int mipi_dbi_dev_init_with_formats(struct mipi_dbi_dev *dbidev,
- const struct drm_simple_display_pipe_funcs *funcs,
- const uint32_t *formats, unsigned int format_count,
- const struct drm_display_mode *mode,
- unsigned int rotation, size_t tx_buf_size)
+int drm_mipi_dbi_dev_init(struct mipi_dbi_dev *dbidev, const struct drm_display_mode *mode,
+ u32 format, unsigned int rotation, size_t tx_buf_size)
{
- static const uint64_t modifiers[] = {
- DRM_FORMAT_MOD_LINEAR,
- DRM_FORMAT_MOD_INVALID
- };
struct drm_device *drm = &dbidev->drm;
int ret;
if (!dbidev->dbi.command)
return -EINVAL;
- ret = drmm_mode_config_init(drm);
- if (ret)
- return ret;
+ if (!tx_buf_size) {
+ const struct drm_format_info *info = drm_format_info(format);
+
+ tx_buf_size = drm_format_info_min_pitch(info, 0, mode->hdisplay) *
+ mode->vdisplay;
+ }
dbidev->tx_buf = devm_kmalloc(drm->dev, tx_buf_size, GFP_KERNEL);
if (!dbidev->tx_buf)
@@ -638,69 +551,20 @@ int mipi_dbi_dev_init_with_formats(struct mipi_dbi_dev *dbidev,
drm_mode_copy(&dbidev->mode, mode);
ret = mipi_dbi_rotate_mode(&dbidev->mode, rotation);
if (ret) {
- DRM_ERROR("Illegal rotation value %u\n", rotation);
+ drm_err(drm, "Illegal rotation value %u\n", rotation);
return -EINVAL;
}
- drm_connector_helper_add(&dbidev->connector, &mipi_dbi_connector_hfuncs);
- ret = drm_connector_init(drm, &dbidev->connector, &mipi_dbi_connector_funcs,
- DRM_MODE_CONNECTOR_SPI);
- if (ret)
- return ret;
-
- ret = drm_simple_display_pipe_init(drm, &dbidev->pipe, funcs, formats, format_count,
- modifiers, &dbidev->connector);
- if (ret)
- return ret;
-
- drm_plane_enable_fb_damage_clips(&dbidev->pipe.plane);
-
- drm->mode_config.funcs = &mipi_dbi_mode_config_funcs;
- drm->mode_config.min_width = dbidev->mode.hdisplay;
- drm->mode_config.max_width = dbidev->mode.hdisplay;
- drm->mode_config.min_height = dbidev->mode.vdisplay;
- drm->mode_config.max_height = dbidev->mode.vdisplay;
dbidev->rotation = rotation;
- dbidev->pixel_format = formats[0];
- if (formats[0] == DRM_FORMAT_RGB888)
- dbidev->dbi.write_memory_bpw = 8;
+ drm_dbg(drm, "rotation = %u\n", rotation);
- DRM_DEBUG_KMS("rotation = %u\n", rotation);
+ dbidev->pixel_format = format;
+ if (dbidev->pixel_format == DRM_FORMAT_RGB888)
+ dbidev->dbi.write_memory_bpw = 8;
return 0;
}
-EXPORT_SYMBOL(mipi_dbi_dev_init_with_formats);
-
-/**
- * mipi_dbi_dev_init - MIPI DBI device initialization
- * @dbidev: MIPI DBI device structure to initialize
- * @funcs: Display pipe functions
- * @mode: Display mode
- * @rotation: Initial rotation in degrees Counter Clock Wise
- *
- * This function sets up a &drm_simple_display_pipe with a &drm_connector that
- * has one fixed &drm_display_mode which is rotated according to @rotation.
- * This mode is used to set the mode config min/max width/height properties.
- * Additionally &mipi_dbi.tx_buf is allocated.
- *
- * Supported formats: Native RGB565 and emulated XRGB8888.
- *
- * Returns:
- * Zero on success, negative error code on failure.
- */
-int mipi_dbi_dev_init(struct mipi_dbi_dev *dbidev,
- const struct drm_simple_display_pipe_funcs *funcs,
- const struct drm_display_mode *mode, unsigned int rotation)
-{
- size_t bufsize = (u32)mode->vdisplay * mode->hdisplay * sizeof(u16);
-
- dbidev->drm.mode_config.preferred_depth = 16;
-
- return mipi_dbi_dev_init_with_formats(dbidev, funcs, mipi_dbi_formats,
- ARRAY_SIZE(mipi_dbi_formats), mode,
- rotation, bufsize);
-}
-EXPORT_SYMBOL(mipi_dbi_dev_init);
+EXPORT_SYMBOL(drm_mipi_dbi_dev_init);
/**
* mipi_dbi_hw_reset - Hardware reset of controller
diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c
index 84ae8a23a367..66f7dc37b597 100644
--- a/drivers/gpu/drm/drm_mode_config.c
+++ b/drivers/gpu/drm/drm_mode_config.c
@@ -380,6 +380,12 @@ static int drm_mode_create_standard_properties(struct drm_device *dev)
return -ENOMEM;
dev->mode_config.gamma_lut_size_property = prop;
+ prop = drm_property_create_range(dev, 0,
+ "BACKGROUND_COLOR", 0, U64_MAX);
+ if (!prop)
+ return -ENOMEM;
+ dev->mode_config.background_color_property = prop;
+
prop = drm_property_create(dev,
DRM_MODE_PROP_IMMUTABLE | DRM_MODE_PROP_BLOB,
"IN_FORMATS", 0);
diff --git a/drivers/gpu/drm/drm_modeset_helper.c b/drivers/gpu/drm/drm_modeset_helper.c
index a57f6a10ada4..d7721df744e7 100644
--- a/drivers/gpu/drm/drm_modeset_helper.c
+++ b/drivers/gpu/drm/drm_modeset_helper.c
@@ -135,9 +135,6 @@ static const struct drm_plane_funcs primary_plane_funcs = {
*
* This is purely a backwards compatibility helper for old drivers. Drivers
* should instead implement their own primary plane. Atomic drivers must do so.
- * Drivers with the above hardware restriction can look into using &struct
- * drm_simple_display_pipe, which encapsulates the above limitations into a nice
- * interface.
*
* Returns:
* Zero on success, error code on failure.
diff --git a/drivers/gpu/drm/drm_pagemap_util.c b/drivers/gpu/drm/drm_pagemap_util.c
index 14ddb948a32e..6111d90a38e2 100644
--- a/drivers/gpu/drm/drm_pagemap_util.c
+++ b/drivers/gpu/drm/drm_pagemap_util.c
@@ -65,18 +65,14 @@ static void drm_pagemap_cache_fini(void *arg)
drm_dbg(cache->shrinker->drm, "Destroying dpagemap cache.\n");
spin_lock(&cache->lock);
dpagemap = cache->dpagemap;
- if (!dpagemap) {
- spin_unlock(&cache->lock);
- goto out;
- }
+ cache->dpagemap = NULL;
+ if (dpagemap && !drm_pagemap_shrinker_cancel(dpagemap))
+ dpagemap = NULL;
+ spin_unlock(&cache->lock);
- if (drm_pagemap_shrinker_cancel(dpagemap)) {
- cache->dpagemap = NULL;
- spin_unlock(&cache->lock);
+ if (dpagemap)
drm_pagemap_destroy(dpagemap, false);
- }
-out:
mutex_destroy(&cache->lookup_mutex);
kfree(cache);
}
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
index 51fdb06d3e9f..9b44c78cd77f 100644
--- a/drivers/gpu/drm/drm_prime.c
+++ b/drivers/gpu/drm/drm_prime.c
@@ -859,7 +859,7 @@ struct sg_table *drm_prime_pages_to_sg(struct drm_device *dev,
return ERR_PTR(-ENOMEM);
if (dev)
- max_segment = dma_max_mapping_size(dev->dev);
+ max_segment = dma_max_mapping_size(drm_dev_dma_dev(dev));
if (max_segment == 0)
max_segment = UINT_MAX;
err = sg_alloc_table_from_pages_segment(sg, pages, nr_pages, 0,
diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c
index fcbcaaa36b5f..4d91513a1e34 100644
--- a/drivers/gpu/drm/drm_simple_kms_helper.c
+++ b/drivers/gpu/drm/drm_simple_kms_helper.c
@@ -16,55 +16,10 @@
#include <drm/drm_probe_helper.h>
#include <drm/drm_simple_kms_helper.h>
-/**
- * DOC: overview
- *
- * This helper library provides helpers for drivers for simple display
- * hardware.
- *
- * drm_simple_display_pipe_init() initializes a simple display pipeline
- * which has only one full-screen scanout buffer feeding one output. The
- * pipeline is represented by &struct drm_simple_display_pipe and binds
- * together &drm_plane, &drm_crtc and &drm_encoder structures into one fixed
- * entity. Some flexibility for code reuse is provided through a separately
- * allocated &drm_connector object and supporting optional &drm_bridge
- * encoder drivers.
- *
- * Many drivers require only a very simple encoder that fulfills the minimum
- * requirements of the display pipeline and does not add additional
- * functionality. The function drm_simple_encoder_init() provides an
- * implementation of such an encoder.
- */
-
static const struct drm_encoder_funcs drm_simple_encoder_funcs_cleanup = {
.destroy = drm_encoder_cleanup,
};
-/**
- * drm_simple_encoder_init - Initialize a preallocated encoder with
- * basic functionality.
- * @dev: drm device
- * @encoder: the encoder to initialize
- * @encoder_type: user visible type of the encoder
- *
- * Initialises a preallocated encoder that has no further functionality.
- * Settings for possible CRTC and clones are left to their initial values.
- * The encoder will be cleaned up automatically as part of the mode-setting
- * cleanup.
- *
- * The caller of drm_simple_encoder_init() is responsible for freeing
- * the encoder's memory after the encoder has been cleaned up. At the
- * moment this only works reliably if the encoder data structure is
- * stored in the device structure. Free the encoder's memory as part of
- * the device release function.
- *
- * Note: consider using drmm_simple_encoder_alloc() instead of
- * drm_simple_encoder_init() to let the DRM managed resource infrastructure
- * take care of cleanup and deallocation.
- *
- * Returns:
- * Zero on success, error code on failure.
- */
int drm_simple_encoder_init(struct drm_device *dev,
struct drm_encoder *encoder,
int encoder_type)
@@ -370,20 +325,6 @@ static const struct drm_plane_funcs drm_simple_kms_plane_funcs = {
.format_mod_supported = drm_simple_kms_format_mod_supported,
};
-/**
- * drm_simple_display_pipe_attach_bridge - Attach a bridge to the display pipe
- * @pipe: simple display pipe object
- * @bridge: bridge to attach
- *
- * Makes it possible to still use the drm_simple_display_pipe helpers when
- * a DRM bridge has to be used.
- *
- * Note that you probably want to initialize the pipe by passing a NULL
- * connector to drm_simple_display_pipe_init().
- *
- * Returns:
- * Zero on success, negative error code on failure.
- */
int drm_simple_display_pipe_attach_bridge(struct drm_simple_display_pipe *pipe,
struct drm_bridge *bridge)
{
@@ -391,30 +332,6 @@ int drm_simple_display_pipe_attach_bridge(struct drm_simple_display_pipe *pipe,
}
EXPORT_SYMBOL(drm_simple_display_pipe_attach_bridge);
-/**
- * drm_simple_display_pipe_init - Initialize a simple display pipeline
- * @dev: DRM device
- * @pipe: simple display pipe object to initialize
- * @funcs: callbacks for the display pipe (optional)
- * @formats: array of supported formats (DRM_FORMAT\_\*)
- * @format_count: number of elements in @formats
- * @format_modifiers: array of formats modifiers
- * @connector: connector to attach and register (optional)
- *
- * Sets up a display pipeline which consist of a really simple
- * plane-crtc-encoder pipe.
- *
- * If a connector is supplied, the pipe will be coupled with the provided
- * connector. You may supply a NULL connector when using drm bridges, that
- * handle connectors themselves (see drm_simple_display_pipe_attach_bridge()).
- *
- * Teardown of a simple display pipe is all handled automatically by the drm
- * core through calling drm_mode_config_cleanup(). Drivers afterwards need to
- * release the memory for the structure themselves.
- *
- * Returns:
- * Zero on success, negative error code on failure.
- */
int drm_simple_display_pipe_init(struct drm_device *dev,
struct drm_simple_display_pipe *pipe,
const struct drm_simple_display_pipe_funcs *funcs,
diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c
index 250734dee928..8d9fd1917c6e 100644
--- a/drivers/gpu/drm/drm_syncobj.c
+++ b/drivers/gpu/drm/drm_syncobj.c
@@ -602,7 +602,7 @@ int drm_syncobj_get_handle(struct drm_file *file_private,
drm_syncobj_get(syncobj);
ret = xa_alloc(&file_private->syncobj_xa, handle, syncobj, xa_limit_32b,
- GFP_NOWAIT);
+ GFP_KERNEL);
if (ret)
drm_syncobj_put(syncobj);
@@ -716,7 +716,7 @@ static int drm_syncobj_fd_to_handle(struct drm_file *file_private,
drm_syncobj_get(syncobj);
ret = xa_alloc(&file_private->syncobj_xa, handle, syncobj, xa_limit_32b,
- GFP_NOWAIT);
+ GFP_KERNEL);
if (ret)
drm_syncobj_put(syncobj);
diff --git a/drivers/gpu/drm/gud/gud_drv.c b/drivers/gpu/drm/gud/gud_drv.c
index d0122d477610..17c2dead2c13 100644
--- a/drivers/gpu/drm/gud/gud_drv.c
+++ b/drivers/gpu/drm/gud/gud_drv.c
@@ -339,7 +339,9 @@ static int gud_stats_debugfs(struct seq_file *m, void *data)
}
static const struct drm_crtc_helper_funcs gud_crtc_helper_funcs = {
- .atomic_check = drm_crtc_helper_atomic_check
+ .atomic_check = drm_crtc_helper_atomic_check,
+ .atomic_enable = gud_crtc_atomic_enable,
+ .atomic_disable = gud_crtc_atomic_disable,
};
static const struct drm_crtc_funcs gud_crtc_funcs = {
@@ -364,6 +366,10 @@ static const struct drm_plane_funcs gud_plane_funcs = {
DRM_GEM_SHADOW_PLANE_FUNCS,
};
+static const struct drm_mode_config_helper_funcs gud_mode_config_helpers = {
+ .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm,
+};
+
static const struct drm_mode_config_funcs gud_mode_config_funcs = {
.fb_create = drm_gem_fb_create_with_dirty,
.atomic_check = drm_atomic_helper_check,
@@ -499,6 +505,7 @@ static int gud_probe(struct usb_interface *intf, const struct usb_device_id *id)
drm->mode_config.min_height = le32_to_cpu(desc.min_height);
drm->mode_config.max_height = le32_to_cpu(desc.max_height);
drm->mode_config.funcs = &gud_mode_config_funcs;
+ drm->mode_config.helper_private = &gud_mode_config_helpers;
/* Format init */
formats_dev = devm_kmalloc(dev, GUD_FORMATS_MAX_NUM, GFP_KERNEL);
diff --git a/drivers/gpu/drm/gud/gud_internal.h b/drivers/gpu/drm/gud/gud_internal.h
index d27c31648341..8eec8335f5f9 100644
--- a/drivers/gpu/drm/gud/gud_internal.h
+++ b/drivers/gpu/drm/gud/gud_internal.h
@@ -62,6 +62,10 @@ int gud_usb_set_u8(struct gud_device *gdrm, u8 request, u8 val);
void gud_clear_damage(struct gud_device *gdrm);
void gud_flush_work(struct work_struct *work);
+void gud_crtc_atomic_enable(struct drm_crtc *crtc,
+ struct drm_atomic_state *state);
+void gud_crtc_atomic_disable(struct drm_crtc *crtc,
+ struct drm_atomic_state *state);
int gud_plane_atomic_check(struct drm_plane *plane,
struct drm_atomic_state *state);
void gud_plane_atomic_update(struct drm_plane *plane,
diff --git a/drivers/gpu/drm/gud/gud_pipe.c b/drivers/gpu/drm/gud/gud_pipe.c
index 11e7441de63b..495804e1d200 100644
--- a/drivers/gpu/drm/gud/gud_pipe.c
+++ b/drivers/gpu/drm/gud/gud_pipe.c
@@ -580,6 +580,39 @@ out:
return ret;
}
+void gud_crtc_atomic_enable(struct drm_crtc *crtc,
+ struct drm_atomic_state *state)
+{
+ struct drm_device *drm = crtc->dev;
+ struct gud_device *gdrm = to_gud_device(drm);
+ int idx;
+
+ if (!drm_dev_enter(drm, &idx))
+ return;
+
+ gud_usb_set_u8(gdrm, GUD_REQ_SET_CONTROLLER_ENABLE, 1);
+ gud_usb_set(gdrm, GUD_REQ_SET_STATE_COMMIT, 0, NULL, 0);
+ gud_usb_set_u8(gdrm, GUD_REQ_SET_DISPLAY_ENABLE, 1);
+
+ drm_dev_exit(idx);
+}
+
+void gud_crtc_atomic_disable(struct drm_crtc *crtc,
+ struct drm_atomic_state *state)
+{
+ struct drm_device *drm = crtc->dev;
+ struct gud_device *gdrm = to_gud_device(drm);
+ int idx;
+
+ if (!drm_dev_enter(drm, &idx))
+ return;
+
+ gud_usb_set_u8(gdrm, GUD_REQ_SET_DISPLAY_ENABLE, 0);
+ gud_usb_set_u8(gdrm, GUD_REQ_SET_CONTROLLER_ENABLE, 0);
+
+ drm_dev_exit(idx);
+}
+
void gud_plane_atomic_update(struct drm_plane *plane,
struct drm_atomic_state *atomic_state)
{
@@ -607,24 +640,12 @@ void gud_plane_atomic_update(struct drm_plane *plane,
mutex_unlock(&gdrm->damage_lock);
}
- if (!drm_dev_enter(drm, &idx))
+ if (!crtc || !drm_dev_enter(drm, &idx))
return;
- if (!old_state->fb)
- gud_usb_set_u8(gdrm, GUD_REQ_SET_CONTROLLER_ENABLE, 1);
-
- if (fb && (crtc->state->mode_changed || crtc->state->connectors_changed))
- gud_usb_set(gdrm, GUD_REQ_SET_STATE_COMMIT, 0, NULL, 0);
-
- if (crtc->state->active_changed)
- gud_usb_set_u8(gdrm, GUD_REQ_SET_DISPLAY_ENABLE, crtc->state->active);
-
- if (!fb)
- goto ctrl_disable;
-
ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE);
if (ret)
- goto ctrl_disable;
+ goto out;
drm_atomic_helper_damage_iter_init(&iter, old_state, new_state);
drm_atomic_for_each_plane_damage(&iter, &damage)
@@ -632,9 +653,6 @@ void gud_plane_atomic_update(struct drm_plane *plane,
drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
-ctrl_disable:
- if (!crtc->state->enable)
- gud_usb_set_u8(gdrm, GUD_REQ_SET_CONTROLLER_ENABLE, 0);
-
+out:
drm_dev_exit(idx);
}
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index be976a90c5a6..b677720a1c2d 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -254,6 +254,7 @@ i915-y += \
display/intel_crtc_state_dump.o \
display/intel_cursor.o \
display/intel_dbuf_bw.o \
+ display/intel_de.o \
display/intel_display.o \
display/intel_display_conversion.o \
display/intel_display_driver.o \
diff --git a/drivers/gpu/drm/i915/display/g4x_dp.c b/drivers/gpu/drm/i915/display/g4x_dp.c
index d7de329abf19..5e74d8a3ba5c 100644
--- a/drivers/gpu/drm/i915/display/g4x_dp.c
+++ b/drivers/gpu/drm/i915/display/g4x_dp.c
@@ -136,7 +136,7 @@ static void intel_dp_prepare(struct intel_encoder *encoder,
intel_dp->DP |= DP_SYNC_VS_HIGH;
intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;
- if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
+ if (pipe_config->enhanced_framing)
intel_dp->DP |= DP_ENHANCED_FRAMING;
intel_dp->DP |= DP_PIPE_SEL_IVB(crtc->pipe);
diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c
index c04327979678..afbaa0465842 100644
--- a/drivers/gpu/drm/i915/display/icl_dsi.c
+++ b/drivers/gpu/drm/i915/display/icl_dsi.c
@@ -711,7 +711,7 @@ gen11_dsi_configure_transcoder(struct intel_encoder *encoder,
dsi_trans = dsi_port_to_transcoder(port);
tmp = intel_de_read(display, DSI_TRANS_FUNC_CONF(dsi_trans));
- if (intel_dsi->eotp_pkt)
+ if (intel_dsi->eot_pkt)
tmp &= ~EOTP_DISABLED;
else
tmp |= EOTP_DISABLED;
@@ -729,6 +729,12 @@ gen11_dsi_configure_transcoder(struct intel_encoder *encoder,
else
tmp |= CLK_HS_CONTINUOUS;
+ if (DISPLAY_VER(display) >= 12 &&
+ intel_dsi->lp_clock_during_lpm)
+ tmp |= LP_CLK_DURING_LPM;
+ else
+ tmp &= ~LP_CLK_DURING_LPM;
+
/* configure buffer threshold limit to minimum */
tmp &= ~PIX_BUF_THRESHOLD_MASK;
tmp |= PIX_BUF_THRESHOLD_1_4;
@@ -765,10 +771,11 @@ gen11_dsi_configure_transcoder(struct intel_encoder *encoder,
}
}
- if (DISPLAY_VER(display) >= 12) {
- if (is_vid_mode(intel_dsi))
- tmp |= BLANKING_PACKET_ENABLE;
- }
+ if (DISPLAY_VER(display) >= 12 &&
+ is_vid_mode(intel_dsi) && intel_dsi->blanking_pkt)
+ tmp |= BLANKING_PACKET_ENABLE;
+ else
+ tmp &= ~BLANKING_PACKET_ENABLE;
/* program DSI operation mode */
if (is_vid_mode(intel_dsi)) {
@@ -888,7 +895,7 @@ gen11_dsi_set_transcoder_timings(struct intel_encoder *encoder,
* non-compressed link speeds, and simplifies down to the ratio between
* compressed and non-compressed bpp.
*/
- if (crtc_state->dsc.compression_enable) {
+ if (is_vid_mode(intel_dsi) && crtc_state->dsc.compression_enable) {
mul = fxp_q4_to_int(crtc_state->dsc.compressed_bpp_x16);
div = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format);
}
@@ -1502,7 +1509,7 @@ static void gen11_dsi_get_timings(struct intel_encoder *encoder,
struct drm_display_mode *adjusted_mode =
&pipe_config->hw.adjusted_mode;
- if (pipe_config->dsc.compressed_bpp_x16) {
+ if (is_vid_mode(intel_dsi) && pipe_config->dsc.compressed_bpp_x16) {
int div = fxp_q4_to_int(pipe_config->dsc.compressed_bpp_x16);
int mul = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format);
diff --git a/drivers/gpu/drm/i915/display/icl_dsi_regs.h b/drivers/gpu/drm/i915/display/icl_dsi_regs.h
index b601b7632339..55ab57adcb0f 100644
--- a/drivers/gpu/drm/i915/display/icl_dsi_regs.h
+++ b/drivers/gpu/drm/i915/display/icl_dsi_regs.h
@@ -227,12 +227,13 @@
#define CLK_ENTER_LP_AFTER_DATA (0x0 << 8)
#define CLK_HS_OR_LP (0x2 << 8)
#define CLK_HS_CONTINUOUS (0x3 << 8)
+#define LP_CLK_DURING_LPM (1 << 7) /* tgl+ */
#define LINK_CALIBRATION_MASK (0x3 << 4)
#define LINK_CALIBRATION_SHIFT 4
#define CALIBRATION_DISABLED (0x0 << 4)
#define CALIBRATION_ENABLED_INITIAL_ONLY (0x2 << 4)
#define CALIBRATION_ENABLED_INITIAL_PERIODIC (0x3 << 4)
-#define BLANKING_PACKET_ENABLE (1 << 2)
+#define BLANKING_PACKET_ENABLE (1 << 2) /* tgl+ */
#define S3D_ORIENTATION_LANDSCAPE (1 << 1)
#define EOTP_DISABLED (1 << 0)
diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c
index 121a12c5b8ac..a47736613f6e 100644
--- a/drivers/gpu/drm/i915/display/intel_cdclk.c
+++ b/drivers/gpu/drm/i915/display/intel_cdclk.c
@@ -2972,6 +2972,53 @@ static int intel_cdclk_update_crtc_min_cdclk(struct intel_atomic_state *state,
return 0;
}
+static int intel_cdclk_update_crtc_min_voltage_level(struct intel_atomic_state *state,
+ struct intel_crtc *crtc,
+ u8 old_min_voltage_level,
+ u8 new_min_voltage_level,
+ bool *need_cdclk_calc)
+{
+ struct intel_display *display = to_intel_display(state);
+ struct intel_cdclk_state *cdclk_state;
+ bool allow_voltage_level_decrease = intel_any_crtc_needs_modeset(state);
+ int ret;
+
+ if (new_min_voltage_level == old_min_voltage_level)
+ return 0;
+
+ if (!allow_voltage_level_decrease &&
+ new_min_voltage_level < old_min_voltage_level)
+ return 0;
+
+ cdclk_state = intel_atomic_get_cdclk_state(state);
+ if (IS_ERR(cdclk_state))
+ return PTR_ERR(cdclk_state);
+
+ old_min_voltage_level = cdclk_state->min_voltage_level[crtc->pipe];
+
+ if (new_min_voltage_level == old_min_voltage_level)
+ return 0;
+
+ if (!allow_voltage_level_decrease &&
+ new_min_voltage_level < old_min_voltage_level)
+ return 0;
+
+ cdclk_state->min_voltage_level[crtc->pipe] = new_min_voltage_level;
+
+ ret = intel_atomic_lock_global_state(&cdclk_state->base);
+ if (ret)
+ return ret;
+
+ *need_cdclk_calc = true;
+
+ drm_dbg_kms(display->drm,
+ "[CRTC:%d:%s] min voltage level: %d -> %d\n",
+ crtc->base.base.id, crtc->base.name,
+ old_min_voltage_level, new_min_voltage_level);
+
+ return 0;
+}
+
int intel_cdclk_update_dbuf_bw_min_cdclk(struct intel_atomic_state *state,
int old_min_cdclk, int new_min_cdclk,
bool *need_cdclk_calc)
@@ -3387,6 +3434,13 @@ static int intel_crtcs_calc_min_cdclk(struct intel_atomic_state *state,
need_cdclk_calc);
if (ret)
return ret;
+
+ ret = intel_cdclk_update_crtc_min_voltage_level(state, crtc,
+ old_crtc_state->min_voltage_level,
+ new_crtc_state->min_voltage_level,
+ need_cdclk_calc);
+ if (ret)
+ return ret;
}
return 0;
diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index 6a471c021c0e..7e59409bbf01 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -2180,7 +2180,7 @@ static int intel_c10pll_calc_state(const struct intel_crtc_state *crtc_state,
return 0;
}
-static int readout_enabled_lane_count(struct intel_encoder *encoder)
+int intel_readout_lane_count(struct intel_encoder *encoder, int lane0, int lane1)
{
struct intel_display *display = to_intel_display(encoder);
u8 enabled_tx_lane_count = 0;
@@ -2212,7 +2212,7 @@ static int readout_enabled_lane_count(struct intel_encoder *encoder)
max_tx_lane_count = round_up(max_tx_lane_count, 2);
for (tx_lane = 0; tx_lane < max_tx_lane_count; tx_lane++) {
- u8 phy_lane_mask = tx_lane < 2 ? INTEL_CX0_LANE0 : INTEL_CX0_LANE1;
+ u8 phy_lane_mask = tx_lane < 2 ? lane0 : lane1;
int tx = tx_lane % 2 + 1;
u8 val;
@@ -2252,7 +2252,8 @@ static void intel_c10pll_readout_hw_state(struct intel_encoder *encoder,
*/
intel_c10_msgbus_access_begin(encoder, lane);
- cx0pll_state->lane_count = readout_enabled_lane_count(encoder);
+ cx0pll_state->lane_count = intel_readout_lane_count(encoder, INTEL_CX0_LANE0,
+ INTEL_CX0_LANE1);
for (i = 0; i < ARRAY_SIZE(pll_state->pll); i++)
pll_state->pll[i] = intel_cx0_read(encoder, lane, PHY_C10_VDR_PLL(i));
@@ -2707,7 +2708,8 @@ static void intel_c20pll_readout_hw_state(struct intel_encoder *encoder,
wakeref = intel_cx0_phy_transaction_begin(encoder);
- cx0pll_state->lane_count = readout_enabled_lane_count(encoder);
+ cx0pll_state->lane_count = intel_readout_lane_count(encoder, INTEL_CX0_LANE0,
+ INTEL_CX0_LANE1);
/* 1. Read VDR params and current context selection */
intel_c20_readout_vdr_params(encoder, &pll_state->vdr, &cntx);
diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.h b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
index 1d4480b8bf39..1428e7a5a318 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.h
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
@@ -28,6 +28,7 @@ struct intel_hdmi;
void intel_cx0_clear_response_ready_flag(struct intel_encoder *encoder,
int lane);
bool intel_encoder_is_c10phy(struct intel_encoder *encoder);
+int intel_readout_lane_count(struct intel_encoder *encoder, int lane0, int lane1);
void intel_mtl_pll_enable(struct intel_encoder *encoder,
struct intel_dpll *pll,
const struct intel_dpll_hw_state *dpll_hw_state);
diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
index 7f1576bfe4b0..ebefa889bc8c 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -4243,21 +4243,6 @@ void intel_ddi_get_clock(struct intel_encoder *encoder,
&crtc_state->dpll_hw_state);
}
-static void xe3plpd_ddi_get_config(struct intel_encoder *encoder,
- struct intel_crtc_state *crtc_state)
-{
- struct intel_display *display = to_intel_display(encoder);
-
- intel_lt_phy_pll_readout_hw_state(encoder, crtc_state, &crtc_state->dpll_hw_state.ltpll);
-
- if (crtc_state->dpll_hw_state.ltpll.tbt_mode)
- crtc_state->port_clock = intel_mtl_tbt_calc_port_clock(encoder);
- else
- crtc_state->port_clock =
- intel_lt_phy_calc_port_clock(display, &crtc_state->dpll_hw_state.ltpll);
- intel_ddi_get_config(encoder, crtc_state);
-}
-
static bool icl_ddi_tc_pll_is_tbt(const struct intel_dpll *pll)
{
return pll->info->id == DPLL_ID_ICL_TBTPLL;
@@ -5298,10 +5283,13 @@ void intel_ddi_init(struct intel_display *display,
encoder->pipe_mask = ~0;
if (HAS_LT_PHY(display)) {
- encoder->enable_clock = intel_xe3plpd_pll_enable;
- encoder->disable_clock = intel_xe3plpd_pll_disable;
- encoder->port_pll_type = intel_mtl_port_pll_type;
- encoder->get_config = xe3plpd_ddi_get_config;
+ encoder->enable_clock = intel_mtl_pll_enable_clock;
+ encoder->disable_clock = intel_mtl_pll_disable_clock;
+ encoder->port_pll_type = icl_ddi_tc_port_pll_type;
+ if (intel_encoder_is_tc(encoder))
+ encoder->get_config = mtl_ddi_tc_phy_get_config;
+ else
+ encoder->get_config = mtl_ddi_non_tc_phy_get_config;
} else if (DISPLAY_VER(display) >= 14) {
encoder->enable_clock = intel_mtl_pll_enable_clock;
encoder->disable_clock = intel_mtl_pll_disable_clock;
diff --git a/drivers/gpu/drm/i915/display/intel_de.c b/drivers/gpu/drm/i915/display/intel_de.c
new file mode 100644
index 000000000000..d2a418da2d54
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_de.c
@@ -0,0 +1,178 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2026 Intel Corporation
+ */
+
+#include <linux/delay.h>
+
+#include <drm/drm_print.h>
+
+#include "intel_de.h"
+
+static int __intel_de_wait_for_register(struct intel_display *display,
+ i915_reg_t reg, u32 mask, u32 value,
+ unsigned int timeout_us,
+ u32 (*read)(struct intel_display *display, i915_reg_t reg),
+ u32 *out_val, bool is_atomic)
+{
+ const ktime_t end = ktime_add_us(ktime_get_raw(), timeout_us);
+ int wait_max = 1000;
+ int wait = 10;
+ u32 reg_value;
+ int ret;
+
+ might_sleep_if(!is_atomic);
+
+ if (timeout_us <= 10) {
+ is_atomic = true;
+ wait = 1;
+ }
+
+ for (;;) {
+ bool expired = ktime_after(ktime_get_raw(), end);
+
+ /* guarantee the condition is evaluated after timeout expired */
+ barrier();
+
+ reg_value = read(display, reg);
+ if ((reg_value & mask) == value) {
+ ret = 0;
+ break;
+ }
+
+ if (expired) {
+ ret = -ETIMEDOUT;
+ break;
+ }
+
+ if (is_atomic)
+ udelay(wait);
+ else
+ usleep_range(wait, wait << 1);
+
+ if (wait < wait_max)
+ wait <<= 1;
+ }
+
+ if (out_val)
+ *out_val = reg_value;
+
+ return ret;
+}
+
+static int intel_de_wait_for_register(struct intel_display *display,
+ i915_reg_t reg, u32 mask, u32 value,
+ unsigned int fast_timeout_us,
+ unsigned int slow_timeout_us,
+ u32 (*read)(struct intel_display *display, i915_reg_t reg),
+ u32 *out_value, bool is_atomic)
+{
+ int ret = -EINVAL;
+
+ if (fast_timeout_us)
+ ret = __intel_de_wait_for_register(display, reg, mask, value,
+ fast_timeout_us, read,
+ out_value, is_atomic);
+
+ if (ret && slow_timeout_us)
+ ret = __intel_de_wait_for_register(display, reg, mask, value,
+ slow_timeout_us, read,
+ out_value, is_atomic);
+
+ return ret;
+}
+
+int intel_de_wait_us(struct intel_display *display, i915_reg_t reg,
+ u32 mask, u32 value, unsigned int timeout_us,
+ u32 *out_value)
+{
+ int ret;
+
+ intel_dmc_wl_get(display, reg);
+
+ ret = intel_de_wait_for_register(display, reg, mask, value,
+ timeout_us, 0,
+ intel_de_read,
+ out_value, false);
+
+ intel_dmc_wl_put(display, reg);
+
+ return ret;
+}
+
+int intel_de_wait_ms(struct intel_display *display, i915_reg_t reg,
+ u32 mask, u32 value, unsigned int timeout_ms,
+ u32 *out_value)
+{
+ int ret;
+
+ intel_dmc_wl_get(display, reg);
+
+ ret = intel_de_wait_for_register(display, reg, mask, value,
+ 2, timeout_ms * 1000,
+ intel_de_read,
+ out_value, false);
+
+ intel_dmc_wl_put(display, reg);
+
+ return ret;
+}
+
+int intel_de_wait_fw_ms(struct intel_display *display, i915_reg_t reg,
+ u32 mask, u32 value, unsigned int timeout_ms,
+ u32 *out_value)
+{
+ return intel_de_wait_for_register(display, reg, mask, value,
+ 2, timeout_ms * 1000,
+ intel_de_read_fw,
+ out_value, false);
+}
+
+int intel_de_wait_fw_us_atomic(struct intel_display *display, i915_reg_t reg,
+ u32 mask, u32 value, unsigned int timeout_us,
+ u32 *out_value)
+{
+ return intel_de_wait_for_register(display, reg, mask, value,
+ timeout_us, 0,
+ intel_de_read_fw,
+ out_value, true);
+}
+
+int intel_de_wait_for_set_us(struct intel_display *display, i915_reg_t reg,
+ u32 mask, unsigned int timeout_us)
+{
+ return intel_de_wait_us(display, reg, mask, mask, timeout_us, NULL);
+}
+
+int intel_de_wait_for_clear_us(struct intel_display *display, i915_reg_t reg,
+ u32 mask, unsigned int timeout_us)
+{
+ return intel_de_wait_us(display, reg, mask, 0, timeout_us, NULL);
+}
+
+int intel_de_wait_for_set_ms(struct intel_display *display, i915_reg_t reg,
+ u32 mask, unsigned int timeout_ms)
+{
+ return intel_de_wait_ms(display, reg, mask, mask, timeout_ms, NULL);
+}
+
+int intel_de_wait_for_clear_ms(struct intel_display *display, i915_reg_t reg,
+ u32 mask, unsigned int timeout_ms)
+{
+ return intel_de_wait_ms(display, reg, mask, 0, timeout_ms, NULL);
+}
+
+u8 intel_de_read8(struct intel_display *display, i915_reg_t reg)
+{
+ /* this is only used on VGA registers (possible on pre-g4x) */
+ drm_WARN_ON(display->drm, DISPLAY_VER(display) >= 5 || display->platform.g4x);
+
+ return intel_uncore_read8(__to_uncore(display), reg);
+}
+
+void intel_de_write8(struct intel_display *display, i915_reg_t reg, u8 val)
+{
+ drm_WARN_ON(display->drm, DISPLAY_VER(display) >= 5 || display->platform.g4x);
+
+ intel_uncore_write8(__to_uncore(display), reg, val);
+}
diff --git a/drivers/gpu/drm/i915/display/intel_de.h b/drivers/gpu/drm/i915/display/intel_de.h
index f30f3f8ebee1..f87b84ab9d6d 100644
--- a/drivers/gpu/drm/i915/display/intel_de.h
+++ b/drivers/gpu/drm/i915/display/intel_de.h
@@ -6,8 +6,6 @@
#ifndef __INTEL_DE_H__
#define __INTEL_DE_H__
-#include <drm/drm_print.h>
-
#include "intel_display_core.h"
#include "intel_dmc_wl.h"
#include "intel_dsb.h"
@@ -19,6 +17,9 @@ static inline struct intel_uncore *__to_uncore(struct intel_display *display)
return to_intel_uncore(display->drm);
}
+u8 intel_de_read8(struct intel_display *display, i915_reg_t reg);
+void intel_de_write8(struct intel_display *display, i915_reg_t reg, u8 val);
+
static inline u32
intel_de_read(struct intel_display *display, i915_reg_t reg)
{
@@ -33,23 +34,6 @@ intel_de_read(struct intel_display *display, i915_reg_t reg)
return val;
}
-static inline u8
-intel_de_read8(struct intel_display *display, i915_reg_t reg)
-{
- /* this is only used on VGA registers (possible on pre-g4x) */
- drm_WARN_ON(display->drm, DISPLAY_VER(display) >= 5 || display->platform.g4x);
-
- return intel_uncore_read8(__to_uncore(display), reg);
-}
-
-static inline void
-intel_de_write8(struct intel_display *display, i915_reg_t reg, u8 val)
-{
- drm_WARN_ON(display->drm, DISPLAY_VER(display) >= 5 || display->platform.g4x);
-
- intel_uncore_write8(__to_uncore(display), reg, val);
-}
-
static inline u64
intel_de_read64_2x32(struct intel_display *display,
i915_reg_t lower_reg, i915_reg_t upper_reg)
@@ -102,85 +86,26 @@ intel_de_rmw(struct intel_display *display, i915_reg_t reg, u32 clear, u32 set)
return val;
}
-static inline int
-intel_de_wait_us(struct intel_display *display, i915_reg_t reg,
- u32 mask, u32 value, unsigned int timeout_us,
- u32 *out_value)
-{
- int ret;
-
- intel_dmc_wl_get(display, reg);
-
- ret = __intel_wait_for_register(__to_uncore(display), reg, mask,
- value, timeout_us, 0, out_value);
-
- intel_dmc_wl_put(display, reg);
-
- return ret;
-}
-
-static inline int
-intel_de_wait_ms(struct intel_display *display, i915_reg_t reg,
- u32 mask, u32 value, unsigned int timeout_ms,
- u32 *out_value)
-{
- int ret;
-
- intel_dmc_wl_get(display, reg);
-
- ret = __intel_wait_for_register(__to_uncore(display), reg, mask,
- value, 2, timeout_ms, out_value);
-
- intel_dmc_wl_put(display, reg);
-
- return ret;
-}
-
-static inline int
-intel_de_wait_fw_ms(struct intel_display *display, i915_reg_t reg,
- u32 mask, u32 value, unsigned int timeout_ms,
- u32 *out_value)
-{
- return __intel_wait_for_register_fw(__to_uncore(display), reg, mask,
- value, 2, timeout_ms, out_value);
-}
-
-static inline int
-intel_de_wait_fw_us_atomic(struct intel_display *display, i915_reg_t reg,
- u32 mask, u32 value, unsigned int timeout_us,
- u32 *out_value)
-{
- return __intel_wait_for_register_fw(__to_uncore(display), reg, mask,
- value, timeout_us, 0, out_value);
-}
-
-static inline int
-intel_de_wait_for_set_us(struct intel_display *display, i915_reg_t reg,
- u32 mask, unsigned int timeout_us)
-{
- return intel_de_wait_us(display, reg, mask, mask, timeout_us, NULL);
-}
-
-static inline int
-intel_de_wait_for_clear_us(struct intel_display *display, i915_reg_t reg,
- u32 mask, unsigned int timeout_us)
-{
- return intel_de_wait_us(display, reg, mask, 0, timeout_us, NULL);
-}
-
-static inline int
-intel_de_wait_for_set_ms(struct intel_display *display, i915_reg_t reg,
- u32 mask, unsigned int timeout_ms)
-{
- return intel_de_wait_ms(display, reg, mask, mask, timeout_ms, NULL);
-}
-
-static inline int
-intel_de_wait_for_clear_ms(struct intel_display *display, i915_reg_t reg,
- u32 mask, unsigned int timeout_ms)
-{
- return intel_de_wait_ms(display, reg, mask, 0, timeout_ms, NULL);
-}
+int intel_de_wait_us(struct intel_display *display, i915_reg_t reg,
+ u32 mask, u32 value, unsigned int timeout_us,
+ u32 *out_value);
+int intel_de_wait_ms(struct intel_display *display, i915_reg_t reg,
+ u32 mask, u32 value, unsigned int timeout_ms,
+ u32 *out_value);
+int intel_de_wait_fw_ms(struct intel_display *display, i915_reg_t reg,
+ u32 mask, u32 value, unsigned int timeout_ms,
+ u32 *out_value);
+int intel_de_wait_fw_us_atomic(struct intel_display *display, i915_reg_t reg,
+ u32 mask, u32 value, unsigned int timeout_us,
+ u32 *out_value);
+int intel_de_wait_for_set_us(struct intel_display *display, i915_reg_t reg,
+ u32 mask, unsigned int timeout_us);
+int intel_de_wait_for_clear_us(struct intel_display *display, i915_reg_t reg,
+ u32 mask, unsigned int timeout_us);
+int intel_de_wait_for_set_ms(struct intel_display *display, i915_reg_t reg,
+ u32 mask, unsigned int timeout_ms);
+int intel_de_wait_for_clear_ms(struct intel_display *display, i915_reg_t reg,
+ u32 mask, unsigned int timeout_ms);
/*
* Unlocked mmio-accessors, think carefully before using these.
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index b18ce0c36a64..10b6c6fcb03f 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -4640,6 +4640,7 @@ intel_crtc_prepare_cleared_state(struct intel_atomic_state *state,
struct intel_crtc_state *crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
struct intel_crtc_state *saved_state;
+ int err;
saved_state = intel_crtc_state_alloc(crtc);
if (!saved_state)
@@ -4648,7 +4649,12 @@ intel_crtc_prepare_cleared_state(struct intel_atomic_state *state,
/* free the old crtc_state->hw members */
intel_crtc_free_hw_state(crtc_state);
- intel_dp_tunnel_atomic_clear_stream_bw(state, crtc_state);
+ err = intel_dp_tunnel_atomic_clear_stream_bw(state, crtc_state);
+ if (err) {
+ kfree(saved_state);
+
+ return err;
+ }
/* FIXME: before the switch to atomic started, a new pipe_config was
* kzalloc'd. Code that depends on any field being zero should be
@@ -5057,24 +5063,6 @@ static bool allow_vblank_delay_fastset(const struct intel_crtc_state *old_crtc_s
!intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_DSI);
}
-static void
-pipe_config_lt_phy_pll_mismatch(struct drm_printer *p, bool fastset,
- const struct intel_crtc *crtc,
- const char *name,
- const struct intel_lt_phy_pll_state *a,
- const struct intel_lt_phy_pll_state *b)
-{
- struct intel_display *display = to_intel_display(crtc);
- char *chipname = "LTPHY";
-
- pipe_config_mismatch(p, fastset, crtc, name, chipname);
-
- drm_printf(p, "expected:\n");
- intel_lt_phy_dump_hw_state(display, a);
- drm_printf(p, "found:\n");
- intel_lt_phy_dump_hw_state(display, b);
-}
-
bool
intel_pipe_config_compare(const struct intel_crtc_state *current_config,
const struct intel_crtc_state *pipe_config,
@@ -5189,16 +5177,6 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
} \
} while (0)
-#define PIPE_CONF_CHECK_PLL_LT(name) do { \
- if (!intel_lt_phy_pll_compare_hw_state(&current_config->name, \
- &pipe_config->name)) { \
- pipe_config_lt_phy_pll_mismatch(&p, fastset, crtc, __stringify(name), \
- &current_config->name, \
- &pipe_config->name); \
- ret = false; \
- } \
-} while (0)
-
#define PIPE_CONF_CHECK_TIMINGS(name) do { \
PIPE_CONF_CHECK_I(name.crtc_hdisplay); \
PIPE_CONF_CHECK_I(name.crtc_htotal); \
@@ -5425,10 +5403,6 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
if (display->dpll.mgr || HAS_GMCH(display))
PIPE_CONF_CHECK_PLL(dpll_hw_state);
- /* FIXME convert MTL+ platforms over to dpll_mgr */
- if (HAS_LT_PHY(display))
- PIPE_CONF_CHECK_PLL_LT(dpll_hw_state.ltpll);
-
PIPE_CONF_CHECK_X(dsi_pll.ctrl);
PIPE_CONF_CHECK_X(dsi_pll.div);
@@ -7890,7 +7864,8 @@ static bool intel_ddi_crt_present(struct intel_display *display)
bool assert_port_valid(struct intel_display *display, enum port port)
{
- return !drm_WARN(display->drm, !(DISPLAY_RUNTIME_INFO(display)->port_mask & BIT(port)),
+ return !drm_WARN(display->drm,
+ !(port >= 0 && DISPLAY_RUNTIME_INFO(display)->port_mask & BIT(port)),
"Platform does not support port %c\n", port_name(port));
}
diff --git a/drivers/gpu/drm/i915/display/intel_display_device.c b/drivers/gpu/drm/i915/display/intel_display_device.c
index a8ef1e6193b8..be55ef8ea617 100644
--- a/drivers/gpu/drm/i915/display/intel_display_device.c
+++ b/drivers/gpu/drm/i915/display/intel_display_device.c
@@ -1654,6 +1654,28 @@ static void display_platforms_or(struct intel_display_platforms *dst,
bitmap_or(dst->bitmap, dst->bitmap, src->bitmap, display_platforms_num_bits());
}
+#define __STEP_NAME(name) [STEP_##name] = #name,
+
+static void initialize_step(struct intel_display *display, enum intel_step step)
+{
+ static const char step_names[][3] = {
+ STEP_NAME_LIST(__STEP_NAME)
+ };
+
+ DISPLAY_RUNTIME_INFO(display)->step = step;
+
+ /* Step name will remain an empty string if not applicable */
+ if (step >= 0 && step < ARRAY_SIZE(step_names))
+ strscpy(DISPLAY_RUNTIME_INFO(display)->step_name, step_names[step]);
+}
+
+#undef __STEP_NAME
+
+static const char *step_name(const struct intel_display_runtime_info *runtime)
+{
+ return strlen(runtime->step_name) ? runtime->step_name : "N/A";
+}
+
struct intel_display *intel_display_device_probe(struct pci_dev *pdev,
const struct intel_display_parent_interface *parent)
{
@@ -1731,14 +1753,14 @@ struct intel_display *intel_display_device_probe(struct pci_dev *pdev,
subdesc ? &subdesc->step_info : NULL);
}
- DISPLAY_RUNTIME_INFO(display)->step = step;
+ initialize_step(display, step);
drm_info(display->drm, "Found %s%s%s (device ID %04x) %s display version %u.%02u stepping %s\n",
desc->name, subdesc ? "/" : "", subdesc ? subdesc->name : "",
pdev->device, display->platform.dgfx ? "discrete" : "integrated",
DISPLAY_RUNTIME_INFO(display)->ip.ver,
DISPLAY_RUNTIME_INFO(display)->ip.rel,
- step != STEP_NONE ? intel_step_name(step) : "N/A");
+ step_name(DISPLAY_RUNTIME_INFO(display)));
return display;
@@ -1954,7 +1976,7 @@ void intel_display_device_info_print(const struct intel_display_device_info *inf
drm_printf(p, "display version: %u\n",
runtime->ip.ver);
- drm_printf(p, "display stepping: %s\n", intel_step_name(runtime->step));
+ drm_printf(p, "display stepping: %s\n", step_name(runtime));
#define PRINT_FLAG(name) drm_printf(p, "%s: %s\n", #name, str_yes_no(info->name))
DEV_INFO_DISPLAY_FOR_EACH_FLAG(PRINT_FLAG);
diff --git a/drivers/gpu/drm/i915/display/intel_display_device.h b/drivers/gpu/drm/i915/display/intel_display_device.h
index e84c190dcc4f..1170ac346615 100644
--- a/drivers/gpu/drm/i915/display/intel_display_device.h
+++ b/drivers/gpu/drm/i915/display/intel_display_device.h
@@ -287,6 +287,7 @@ struct intel_display_runtime_info {
u16 step; /* hardware */
} ip;
int step; /* symbolic */
+ char step_name[3]; /* empty string if not applicable */
u32 rawclk_freq;
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index e189f8c39ccb..e2496db1642a 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -835,6 +835,7 @@ struct intel_pipe_wm {
struct skl_wm_level {
u16 min_ddb_alloc;
+ u16 min_ddb_alloc_uv; /* for pre-icl */
u16 blocks;
u8 lines;
bool enable;
@@ -845,13 +846,11 @@ struct skl_wm_level {
struct skl_plane_wm {
struct skl_wm_level wm[8];
- struct skl_wm_level uv_wm[8];
struct skl_wm_level trans_wm;
struct {
struct skl_wm_level wm0;
struct skl_wm_level trans_wm;
} sagv;
- bool is_planar;
};
struct skl_pipe_wm {
@@ -1188,6 +1187,7 @@ struct intel_crtc_state {
u32 dc3co_exitline;
u16 su_y_granularity;
u8 active_non_psr_pipes;
+ u8 entry_setup_frames;
const char *no_psr_reason;
/*
diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c
index 90ba932d940a..1667a829e708 100644
--- a/drivers/gpu/drm/i915/display/intel_dmc.c
+++ b/drivers/gpu/drm/i915/display/intel_dmc.c
@@ -39,7 +39,6 @@
#include "intel_dmc.h"
#include "intel_dmc_regs.h"
#include "intel_flipq.h"
-#include "intel_step.h"
/**
* DOC: DMC Firmware Support
@@ -418,15 +417,12 @@ bool intel_dmc_has_payload(struct intel_display *display)
return has_dmc_id_fw(display, DMC_FW_MAIN);
}
-static const struct stepping_info *
-intel_get_stepping_info(struct intel_display *display,
- struct stepping_info *si)
+static void initialize_stepping_info(struct intel_display *display, struct stepping_info *si)
{
- const char *step_name = intel_step_name(INTEL_DISPLAY_STEP(display));
+ const char *step_name = DISPLAY_RUNTIME_INFO(display)->step_name;
- si->stepping = step_name[0];
- si->substepping = step_name[1];
- return si;
+ si->stepping = step_name[0] ?: '*';
+ si->substepping = step_name[1] ?: '*';
}
static void gen9_set_dc_state_debugmask(struct intel_display *display)
@@ -1274,8 +1270,7 @@ static int parse_dmc_fw(struct intel_dmc *dmc, const struct firmware *fw)
struct intel_css_header *css_header;
struct intel_package_header *package_header;
struct intel_dmc_header_base *dmc_header;
- struct stepping_info display_info = { '*', '*'};
- const struct stepping_info *si = intel_get_stepping_info(display, &display_info);
+ struct stepping_info si = {};
enum intel_dmc_id dmc_id;
u32 readcount = 0;
u32 r, offset;
@@ -1283,6 +1278,8 @@ static int parse_dmc_fw(struct intel_dmc *dmc, const struct firmware *fw)
if (!fw)
return -EINVAL;
+ initialize_stepping_info(display, &si);
+
/* Extract CSS Header information */
css_header = (struct intel_css_header *)fw->data;
r = parse_dmc_fw_css(dmc, css_header, fw->size);
@@ -1293,7 +1290,7 @@ static int parse_dmc_fw(struct intel_dmc *dmc, const struct firmware *fw)
/* Extract Package Header information */
package_header = (struct intel_package_header *)&fw->data[readcount];
- r = parse_dmc_fw_package(dmc, package_header, si, fw->size - readcount);
+ r = parse_dmc_fw_package(dmc, package_header, &si, fw->size - readcount);
if (!r)
return -EINVAL;
diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
index a7b186d0e3c4..d0c76632a946 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
@@ -610,6 +610,34 @@ static int intel_dp_aux_vesa_setup_backlight(struct intel_connector *connector,
}
static bool
+check_if_vesa_backlight_possible(struct intel_dp *intel_dp)
+{
+ int ret;
+ u8 bit_min, bit_max;
+
+ if (!(intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_AUX_SET_CAP))
+ return true;
+
+ ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_EDP_PWMGEN_BIT_COUNT_CAP_MIN, &bit_min);
+ if (ret < 0)
+ return false;
+
+ bit_min &= DP_EDP_PWMGEN_BIT_COUNT_MASK;
+ if (bit_min < 1)
+ return false;
+
+ ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_EDP_PWMGEN_BIT_COUNT_CAP_MAX, &bit_max);
+ if (ret < 0)
+ return false;
+
+ bit_max &= DP_EDP_PWMGEN_BIT_COUNT_MASK;
+ if (bit_max < bit_min)
+ return false;
+
+ return true;
+}
+
+static bool
intel_dp_aux_supports_vesa_backlight(struct intel_connector *connector)
{
struct intel_display *display = to_intel_display(connector);
@@ -625,12 +653,14 @@ intel_dp_aux_supports_vesa_backlight(struct intel_connector *connector)
return true;
}
- if (drm_edp_backlight_supported(intel_dp->edp_dpcd)) {
+ if (drm_edp_backlight_supported(intel_dp->edp_dpcd) &&
+ check_if_vesa_backlight_possible(intel_dp)) {
drm_dbg_kms(display->drm,
"[CONNECTOR:%d:%s] AUX Backlight Control Supported!\n",
connector->base.base.id, connector->base.name);
return true;
}
+
return false;
}
diff --git a/drivers/gpu/drm/i915/display/intel_dp_tunnel.c b/drivers/gpu/drm/i915/display/intel_dp_tunnel.c
index 1fd1ac8d556d..7363c9817297 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_tunnel.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_tunnel.c
@@ -659,19 +659,27 @@ int intel_dp_tunnel_atomic_compute_stream_bw(struct intel_atomic_state *state,
*
* Clear any DP tunnel stream BW requirement set by
* intel_dp_tunnel_atomic_compute_stream_bw().
+ *
+ * Returns 0 in case of success, a negative error code otherwise.
*/
-void intel_dp_tunnel_atomic_clear_stream_bw(struct intel_atomic_state *state,
- struct intel_crtc_state *crtc_state)
+int intel_dp_tunnel_atomic_clear_stream_bw(struct intel_atomic_state *state,
+ struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ int err;
if (!crtc_state->dp_tunnel_ref.tunnel)
- return;
+ return 0;
+
+ err = drm_dp_tunnel_atomic_set_stream_bw(&state->base,
+ crtc_state->dp_tunnel_ref.tunnel,
+ crtc->pipe, 0);
+ if (err)
+ return err;
- drm_dp_tunnel_atomic_set_stream_bw(&state->base,
- crtc_state->dp_tunnel_ref.tunnel,
- crtc->pipe, 0);
drm_dp_tunnel_ref_put(&crtc_state->dp_tunnel_ref);
+
+ return 0;
}
/**
diff --git a/drivers/gpu/drm/i915/display/intel_dp_tunnel.h b/drivers/gpu/drm/i915/display/intel_dp_tunnel.h
index 7f0f720e8dca..10ab9eebcef6 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_tunnel.h
+++ b/drivers/gpu/drm/i915/display/intel_dp_tunnel.h
@@ -40,8 +40,8 @@ int intel_dp_tunnel_atomic_compute_stream_bw(struct intel_atomic_state *state,
struct intel_dp *intel_dp,
const struct intel_connector *connector,
struct intel_crtc_state *crtc_state);
-void intel_dp_tunnel_atomic_clear_stream_bw(struct intel_atomic_state *state,
- struct intel_crtc_state *crtc_state);
+int intel_dp_tunnel_atomic_clear_stream_bw(struct intel_atomic_state *state,
+ struct intel_crtc_state *crtc_state);
int intel_dp_tunnel_atomic_add_state_for_crtc(struct intel_atomic_state *state,
struct intel_crtc *crtc);
@@ -88,9 +88,12 @@ intel_dp_tunnel_atomic_compute_stream_bw(struct intel_atomic_state *state,
return 0;
}
-static inline void
+static inline int
intel_dp_tunnel_atomic_clear_stream_bw(struct intel_atomic_state *state,
- struct intel_crtc_state *crtc_state) {}
+ struct intel_crtc_state *crtc_state)
+{
+ return 0;
+}
static inline int
intel_dp_tunnel_atomic_add_state_for_crtc(struct intel_atomic_state *state,
diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c
index 8433e3ff0319..c7d37e74fbe9 100644
--- a/drivers/gpu/drm/i915/display/intel_dpll.c
+++ b/drivers/gpu/drm/i915/display/intel_dpll.c
@@ -1212,29 +1212,6 @@ static int dg2_crtc_compute_clock(struct intel_atomic_state *state,
return 0;
}
-static int xe3plpd_crtc_compute_clock(struct intel_atomic_state *state,
- struct intel_crtc *crtc)
-{
- struct intel_crtc_state *crtc_state =
- intel_atomic_get_new_crtc_state(state, crtc);
- struct intel_encoder *encoder =
- intel_get_crtc_new_encoder(state, crtc_state);
- struct intel_display *display = to_intel_display(encoder);
- int ret;
-
- ret = intel_lt_phy_pll_calc_state(crtc_state, encoder);
- if (ret)
- return ret;
-
- /* TODO: Do the readback via intel_compute_shared_dplls() */
- crtc_state->port_clock =
- intel_lt_phy_calc_port_clock(display, &crtc_state->dpll_hw_state.ltpll);
-
- crtc_state->hw.adjusted_mode.crtc_clock = intel_crtc_dotclock(crtc_state);
-
- return 0;
-}
-
static int ilk_fb_cb_factor(const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(crtc_state);
@@ -1695,7 +1672,8 @@ static int i8xx_crtc_compute_clock(struct intel_atomic_state *state,
}
static const struct intel_dpll_global_funcs xe3plpd_dpll_funcs = {
- .crtc_compute_clock = xe3plpd_crtc_compute_clock,
+ .crtc_compute_clock = hsw_crtc_compute_clock,
+ .crtc_get_dpll = hsw_crtc_get_dpll,
};
static const struct intel_dpll_global_funcs mtl_dpll_funcs = {
diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c
index f35a9252f4e1..f5d4f7146fbc 100644
--- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c
+++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c
@@ -4571,6 +4571,170 @@ static const struct intel_dpll_mgr mtl_pll_mgr = {
.compare_hw_state = mtl_compare_hw_state,
};
+static bool xe3plpd_pll_get_hw_state(struct intel_display *display,
+ struct intel_dpll *pll,
+ struct intel_dpll_hw_state *dpll_hw_state)
+{
+ struct intel_encoder *encoder = get_intel_encoder(display, pll);
+
+ if (!encoder)
+ return false;
+
+ return intel_lt_phy_pll_readout_hw_state(encoder, &dpll_hw_state->ltpll);
+}
+
+static int xe3plpd_pll_get_freq(struct intel_display *display,
+ const struct intel_dpll *pll,
+ const struct intel_dpll_hw_state *dpll_hw_state)
+{
+ struct intel_encoder *encoder = get_intel_encoder(display, pll);
+
+ if (drm_WARN_ON(display->drm, !encoder))
+ return -EINVAL;
+
+ return intel_lt_phy_calc_port_clock(display, &dpll_hw_state->ltpll);
+}
+
+static void xe3plpd_pll_enable(struct intel_display *display,
+ struct intel_dpll *pll,
+ const struct intel_dpll_hw_state *dpll_hw_state)
+{
+ struct intel_encoder *encoder = get_intel_encoder(display, pll);
+
+ if (drm_WARN_ON(display->drm, !encoder))
+ return;
+
+ intel_xe3plpd_pll_enable(encoder, pll, dpll_hw_state);
+}
+
+static void xe3plpd_pll_disable(struct intel_display *display,
+ struct intel_dpll *pll)
+{
+ struct intel_encoder *encoder = get_intel_encoder(display, pll);
+
+ if (drm_WARN_ON(display->drm, !encoder))
+ return;
+
+ intel_xe3plpd_pll_disable(encoder);
+}
+
+static const struct intel_dpll_funcs xe3plpd_tbt_pll_funcs = {
+ .enable = mtl_tbt_pll_enable,
+ .disable = mtl_tbt_pll_disable,
+ .get_hw_state = intel_lt_phy_tbt_pll_readout_hw_state,
+ .get_freq = mtl_tbt_pll_get_freq,
+};
+
+static const struct intel_dpll_funcs xe3plpd_pll_funcs = {
+ .enable = xe3plpd_pll_enable,
+ .disable = xe3plpd_pll_disable,
+ .get_hw_state = xe3plpd_pll_get_hw_state,
+ .get_freq = xe3plpd_pll_get_freq,
+};
+
+static const struct dpll_info xe3plpd_plls[] = {
+ { .name = "DPLL 0", .funcs = &xe3plpd_pll_funcs, .id = DPLL_ID_ICL_DPLL0, },
+ { .name = "DPLL 1", .funcs = &xe3plpd_pll_funcs, .id = DPLL_ID_ICL_DPLL1, },
+ { .name = "TBT PLL", .funcs = &xe3plpd_tbt_pll_funcs, .id = DPLL_ID_ICL_TBTPLL,
+ .is_alt_port_dpll = true, .always_on = true },
+ { .name = "TC PLL 1", .funcs = &xe3plpd_pll_funcs, .id = DPLL_ID_ICL_MGPLL1, },
+ { .name = "TC PLL 2", .funcs = &xe3plpd_pll_funcs, .id = DPLL_ID_ICL_MGPLL2, },
+ { .name = "TC PLL 3", .funcs = &xe3plpd_pll_funcs, .id = DPLL_ID_ICL_MGPLL3, },
+ { .name = "TC PLL 4", .funcs = &xe3plpd_pll_funcs, .id = DPLL_ID_ICL_MGPLL4, },
+ {}
+};
+
+static int xe3plpd_compute_non_tc_phy_dpll(struct intel_atomic_state *state,
+ struct intel_crtc *crtc,
+ struct intel_encoder *encoder)
+{
+ struct intel_display *display = to_intel_display(encoder);
+ struct intel_crtc_state *crtc_state =
+ intel_atomic_get_new_crtc_state(state, crtc);
+ struct icl_port_dpll *port_dpll =
+ &crtc_state->icl_port_dplls[ICL_PORT_DPLL_DEFAULT];
+ int ret;
+
+ ret = intel_lt_phy_pll_calc_state(crtc_state, encoder, &port_dpll->hw_state);
+ if (ret)
+ return ret;
+
+ /* this is mainly for the fastset check */
+ icl_set_active_port_dpll(crtc_state, ICL_PORT_DPLL_DEFAULT);
+
+ crtc_state->port_clock = intel_lt_phy_calc_port_clock(display, &port_dpll->hw_state.ltpll);
+
+ return 0;
+}
+
+static int xe3plpd_compute_tc_phy_dplls(struct intel_atomic_state *state,
+ struct intel_crtc *crtc,
+ struct intel_encoder *encoder)
+{
+ struct intel_display *display = to_intel_display(encoder);
+ struct intel_crtc_state *crtc_state =
+ intel_atomic_get_new_crtc_state(state, crtc);
+ const struct intel_crtc_state *old_crtc_state =
+ intel_atomic_get_old_crtc_state(state, crtc);
+ struct icl_port_dpll *port_dpll;
+ int ret;
+
+ port_dpll = &crtc_state->icl_port_dplls[ICL_PORT_DPLL_DEFAULT];
+ intel_lt_phy_tbt_pll_calc_state(&port_dpll->hw_state);
+
+ port_dpll = &crtc_state->icl_port_dplls[ICL_PORT_DPLL_MG_PHY];
+ ret = intel_lt_phy_pll_calc_state(crtc_state, encoder, &port_dpll->hw_state);
+ if (ret)
+ return ret;
+
+ /* this is mainly for the fastset check */
+ if (old_crtc_state->intel_dpll &&
+ old_crtc_state->intel_dpll->info->id == DPLL_ID_ICL_TBTPLL)
+ icl_set_active_port_dpll(crtc_state, ICL_PORT_DPLL_DEFAULT);
+ else
+ icl_set_active_port_dpll(crtc_state, ICL_PORT_DPLL_MG_PHY);
+
+ crtc_state->port_clock = intel_lt_phy_calc_port_clock(display, &port_dpll->hw_state.ltpll);
+
+ return 0;
+}
+
+static int xe3plpd_compute_dplls(struct intel_atomic_state *state,
+ struct intel_crtc *crtc,
+ struct intel_encoder *encoder)
+{
+ if (intel_encoder_is_tc(encoder))
+ return xe3plpd_compute_tc_phy_dplls(state, crtc, encoder);
+ else
+ return xe3plpd_compute_non_tc_phy_dpll(state, crtc, encoder);
+}
+
+static void xe3plpd_dump_hw_state(struct drm_printer *p,
+ const struct intel_dpll_hw_state *dpll_hw_state)
+{
+ intel_lt_phy_dump_hw_state(p, &dpll_hw_state->ltpll);
+}
+
+static bool xe3plpd_compare_hw_state(const struct intel_dpll_hw_state *_a,
+ const struct intel_dpll_hw_state *_b)
+{
+ const struct intel_lt_phy_pll_state *a = &_a->ltpll;
+ const struct intel_lt_phy_pll_state *b = &_b->ltpll;
+
+ return intel_lt_phy_pll_compare_hw_state(a, b);
+}
+
+static const struct intel_dpll_mgr xe3plpd_pll_mgr = {
+ .dpll_info = xe3plpd_plls,
+ .compute_dplls = xe3plpd_compute_dplls,
+ .get_dplls = mtl_get_dplls,
+ .put_dplls = icl_put_dplls,
+ .update_active_dpll = icl_update_active_dpll,
+ .update_ref_clks = icl_update_dpll_ref_clks,
+ .dump_hw_state = xe3plpd_dump_hw_state,
+ .compare_hw_state = xe3plpd_compare_hw_state,
+};
+
/**
* intel_dpll_init - Initialize DPLLs
* @display: intel_display device
@@ -4585,9 +4749,11 @@ void intel_dpll_init(struct intel_display *display)
mutex_init(&display->dpll.lock);
- if (DISPLAY_VER(display) >= 35 || display->platform.dg2)
- /* No shared DPLLs on NVL or DG2; port PLLs are part of the PHY */
+ if (display->platform.dg2)
+ /* No shared DPLLs on DG2; port PLLs are part of the PHY */
dpll_mgr = NULL;
+ else if (DISPLAY_VER(display) >= 35)
+ dpll_mgr = &xe3plpd_pll_mgr;
else if (DISPLAY_VER(display) >= 14)
dpll_mgr = &mtl_pll_mgr;
else if (display->platform.alderlake_p)
@@ -4910,6 +5076,7 @@ verify_single_dpll_state(struct intel_display *display,
const struct intel_crtc_state *new_crtc_state)
{
struct intel_dpll_hw_state dpll_hw_state = {};
+ bool pll_mismatch = false;
u8 pipe_mask;
bool active;
@@ -4951,9 +5118,18 @@ verify_single_dpll_state(struct intel_display *display,
"%s: pll enabled crtcs mismatch (expected 0x%x in 0x%x)\n",
pll->info->name, pipe_mask, pll->state.pipe_mask);
- if (INTEL_DISPLAY_STATE_WARN(display,
- pll->on && memcmp(&pll->state.hw_state, &dpll_hw_state,
- sizeof(dpll_hw_state)),
+ if (pll->on) {
+ const struct intel_dpll_mgr *dpll_mgr = display->dpll.mgr;
+
+ if (HAS_LT_PHY(display))
+ pll_mismatch = !dpll_mgr->compare_hw_state(&pll->state.hw_state,
+ &dpll_hw_state);
+ else
+ pll_mismatch = memcmp(&pll->state.hw_state, &dpll_hw_state,
+ sizeof(dpll_hw_state));
+ }
+
+ if (INTEL_DISPLAY_STATE_WARN(display, pll_mismatch,
"%s: pll hw state mismatch\n",
pll->info->name)) {
struct drm_printer p = drm_dbg_printer(display->drm, DRM_UT_KMS, NULL);
diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h
index 4cc14ce5eebe..d408ccf6f902 100644
--- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h
+++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h
@@ -278,6 +278,7 @@ struct intel_lt_phy_pll_state {
u8 config[3];
bool ssc_enabled;
bool tbt_mode;
+ int lane_count;
};
struct intel_dpll_hw_state {
diff --git a/drivers/gpu/drm/i915/display/intel_dsi.h b/drivers/gpu/drm/i915/display/intel_dsi.h
index 489d26ffd235..9fcdabbf3740 100644
--- a/drivers/gpu/drm/i915/display/intel_dsi.h
+++ b/drivers/gpu/drm/i915/display/intel_dsi.h
@@ -80,9 +80,10 @@ struct intel_dsi {
/* NON_BURST_SYNC_PULSE, NON_BURST_SYNC_EVENTS, or BURST_MODE */
int video_mode;
- /* eot for MIPI_EOT_DISABLE register */
- u8 eotp_pkt;
- u8 clock_stop;
+ bool lp_clock_during_lpm;
+ bool blanking_pkt;
+ bool eot_pkt;
+ bool clock_stop;
u8 escape_clk_div;
u8 dual_link;
diff --git a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c
index 18755a8e613d..fe12041e913c 100644
--- a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c
+++ b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c
@@ -718,8 +718,10 @@ void intel_dsi_log_params(struct intel_dsi *intel_dsi)
"burst" : "<unknown>");
drm_printf(&p, "Burst mode ratio %d\n", intel_dsi->burst_mode_ratio);
drm_printf(&p, "Reset timer %d\n", intel_dsi->rst_timer_val);
- drm_printf(&p, "Eot %s\n", str_enabled_disabled(intel_dsi->eotp_pkt));
- drm_printf(&p, "Clockstop %s\n", str_enabled_disabled(!intel_dsi->clock_stop));
+ drm_printf(&p, "LP clock during LPM %s\n", str_enabled_disabled(intel_dsi->lp_clock_during_lpm));
+ drm_printf(&p, "Blanking packets during BLLP %s\n", str_enabled_disabled(intel_dsi->blanking_pkt));
+ drm_printf(&p, "EoT packet %s\n", str_enabled_disabled(intel_dsi->eot_pkt));
+ drm_printf(&p, "Clock stop during BLLP %s\n", str_enabled_disabled(intel_dsi->clock_stop));
drm_printf(&p, "Mode %s\n", intel_dsi->operation_mode ? "command" : "video");
if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK)
drm_printf(&p, "Dual link: DSI_DUAL_LINK_FRONT_BACK\n");
@@ -770,8 +772,10 @@ bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id)
drm_dbg_kms(display->drm, "\n");
- intel_dsi->eotp_pkt = mipi_config->eot_pkt_disabled ? 0 : 1;
- intel_dsi->clock_stop = mipi_config->enable_clk_stop ? 1 : 0;
+ intel_dsi->lp_clock_during_lpm = mipi_config->lp_clock_during_lpm;
+ intel_dsi->blanking_pkt = mipi_config->blanking_packets_during_bllp;
+ intel_dsi->eot_pkt = !mipi_config->eot_pkt_disabled;
+ intel_dsi->clock_stop = mipi_config->enable_clk_stop;
intel_dsi->lane_count = mipi_config->lane_cnt + 1;
intel_dsi->pixel_format =
vbt_to_dsi_pixel_format(mipi_config->videomode_color_format);
diff --git a/drivers/gpu/drm/i915/display/intel_gmbus.c b/drivers/gpu/drm/i915/display/intel_gmbus.c
index df48f27f1cc1..ea5cf8f51b31 100644
--- a/drivers/gpu/drm/i915/display/intel_gmbus.c
+++ b/drivers/gpu/drm/i915/display/intel_gmbus.c
@@ -495,8 +495,10 @@ gmbus_xfer_read_chunk(struct intel_display *display,
val = intel_de_read_fw(display, GMBUS3(display));
do {
- if (extra_byte_added && len == 1)
+ if (extra_byte_added && len == 1) {
+ len--;
break;
+ }
*buf++ = val & 0xff;
val >>= 8;
@@ -692,7 +694,7 @@ retry:
goto clear_err;
}
- /* Generate a STOP condition on the bus. Note that gmbus can't generata
+ /* Generate a STOP condition on the bus. Note that gmbus can't generate
* a STOP on the very first cycle. To simplify the code we
* unconditionally generate the STOP condition with an additional gmbus
* cycle. */
diff --git a/drivers/gpu/drm/i915/display/intel_lt_phy.c b/drivers/gpu/drm/i915/display/intel_lt_phy.c
index eced8493e566..657ad5cb0eff 100644
--- a/drivers/gpu/drm/i915/display/intel_lt_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_lt_phy.c
@@ -11,6 +11,7 @@
#include "intel_ddi_buf_trans.h"
#include "intel_de.h"
#include "intel_display.h"
+#include "intel_display_regs.h"
#include "intel_display_types.h"
#include "intel_display_utils.h"
#include "intel_dpll.h"
@@ -32,6 +33,7 @@
INTEL_LT_PHY_LANE0)
#define MODE_DP 3
#define MODE_HDMI_20 4
+#define MODE_HDMI_FRL 5
#define Q32_TO_INT(x) ((x) >> 32)
#define Q32_TO_FRAC(x) ((x) & 0xFFFFFFFF)
#define DCO_MIN_FREQ_MHZ 11850
@@ -1176,9 +1178,30 @@ intel_lt_phy_lane_reset(struct intel_encoder *encoder,
intel_de_rmw(display, XELPDP_PORT_BUF_CTL2(display, port), lane_phy_pulse_status, 0);
}
+static bool intel_lt_phy_is_hdmi(const struct intel_lt_phy_pll_state *ltpll)
+{
+ u8 mode = REG_FIELD_GET8(LT_PHY_VDR_MODE_ENCODING_MASK, ltpll->config[0]);
+
+ if (mode == MODE_HDMI_20 || mode == MODE_HDMI_FRL)
+ return true;
+
+ return false;
+}
+
+static bool intel_lt_phy_is_dp(const struct intel_lt_phy_pll_state *ltpll)
+{
+ u8 mode = REG_FIELD_GET8(LT_PHY_VDR_MODE_ENCODING_MASK, ltpll->config[0]);
+
+ if (mode == MODE_DP)
+ return true;
+
+ return false;
+}
+
static void
intel_lt_phy_program_port_clock_ctl(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state,
+ const struct intel_lt_phy_pll_state *ltpll,
+ int port_clock,
bool lane_reversal)
{
struct intel_display *display = to_intel_display(encoder);
@@ -1195,17 +1218,16 @@ intel_lt_phy_program_port_clock_ctl(struct intel_encoder *encoder,
* but since the register bits still remain the same we use
* the same definition
*/
- if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI) &&
- intel_hdmi_is_frl(crtc_state->port_clock))
+ if (intel_lt_phy_is_hdmi(ltpll) && intel_hdmi_is_frl(port_clock))
val |= XELPDP_DDI_CLOCK_SELECT_PREP(display, XELPDP_DDI_CLOCK_SELECT_DIV18CLK);
else
val |= XELPDP_DDI_CLOCK_SELECT_PREP(display, XELPDP_DDI_CLOCK_SELECT_MAXPCLK);
/* DP2.0 10G and 20G rates enable MPLLA*/
- if (crtc_state->port_clock == 1000000 || crtc_state->port_clock == 2000000)
+ if (port_clock == 1000000 || port_clock == 2000000)
val |= XELPDP_SSC_ENABLE_PLLA;
else
- val |= crtc_state->dpll_hw_state.ltpll.ssc_enabled ? XELPDP_SSC_ENABLE_PLLB : 0;
+ val |= ltpll->ssc_enabled ? XELPDP_SSC_ENABLE_PLLB : 0;
intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port),
XELPDP_LANE1_PHY_CLOCK_SELECT | XELPDP_FORWARD_CLOCK_UNGATE |
@@ -1248,7 +1270,8 @@ static u32 intel_lt_phy_get_dp_clock(u8 rate)
static bool
intel_lt_phy_config_changed(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state)
+ const struct intel_lt_phy_pll_state *ltpll,
+ u32 port_clock)
{
u8 val, rate;
u32 clock;
@@ -1262,9 +1285,9 @@ intel_lt_phy_config_changed(struct intel_encoder *encoder,
* using 1.62 Gbps clock since PHY PLL defaults to that
* otherwise we always need to reconfigure it.
*/
- if (intel_crtc_has_dp_encoder(crtc_state)) {
+ if (intel_lt_phy_is_dp(ltpll)) {
clock = intel_lt_phy_get_dp_clock(rate);
- if (crtc_state->port_clock == 1620000 && crtc_state->port_clock == clock)
+ if (port_clock == 1620000 && port_clock == clock)
return false;
}
@@ -1723,12 +1746,15 @@ intel_lt_phy_calc_port_clock(struct intel_display *display,
int
intel_lt_phy_pll_calc_state(struct intel_crtc_state *crtc_state,
- struct intel_encoder *encoder)
+ struct intel_encoder *encoder,
+ struct intel_dpll_hw_state *hw_state)
{
struct intel_display *display = to_intel_display(crtc_state);
const struct intel_lt_phy_pll_params *tables;
int i;
+ memset(hw_state, 0, sizeof(*hw_state));
+
tables = intel_lt_phy_pll_tables_get(crtc_state, encoder);
if (!tables)
return -EINVAL;
@@ -1738,62 +1764,71 @@ intel_lt_phy_pll_calc_state(struct intel_crtc_state *crtc_state,
drm_WARN_ON(display->drm, !intel_dpll_clock_matches(clock, tables[i].clock_rate));
if (intel_dpll_clock_matches(crtc_state->port_clock, clock)) {
- crtc_state->dpll_hw_state.ltpll = *tables[i].state;
+ hw_state->ltpll = *tables[i].state;
if (intel_crtc_has_dp_encoder(crtc_state)) {
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP))
- crtc_state->dpll_hw_state.ltpll.config[2] = 1;
+ hw_state->ltpll.config[2] = 1;
}
- crtc_state->dpll_hw_state.ltpll.ssc_enabled =
+ hw_state->ltpll.ssc_enabled =
intel_lt_phy_pll_is_ssc_enabled(crtc_state, encoder);
+ hw_state->ltpll.lane_count = crtc_state->lane_count;
return 0;
}
}
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
- return intel_lt_phy_calculate_hdmi_state(&crtc_state->dpll_hw_state.ltpll,
+ hw_state->ltpll.lane_count = crtc_state->lane_count;
+ return intel_lt_phy_calculate_hdmi_state(&hw_state->ltpll,
crtc_state->port_clock);
}
return -EINVAL;
}
+void intel_lt_phy_tbt_pll_calc_state(struct intel_dpll_hw_state *hw_state)
+{
+ memset(hw_state, 0, sizeof(*hw_state));
+
+ hw_state->ltpll.tbt_mode = true;
+}
+
static void
intel_lt_phy_program_pll(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state)
+ const struct intel_lt_phy_pll_state *ltpll)
{
u8 owned_lane_mask = intel_lt_phy_get_owned_lane_mask(encoder);
int i, j, k;
intel_lt_phy_write(encoder, owned_lane_mask, LT_PHY_VDR_0_CONFIG,
- crtc_state->dpll_hw_state.ltpll.config[0], MB_WRITE_COMMITTED);
+ ltpll->config[0], MB_WRITE_COMMITTED);
intel_lt_phy_write(encoder, INTEL_LT_PHY_LANE0, LT_PHY_VDR_1_CONFIG,
- crtc_state->dpll_hw_state.ltpll.config[1], MB_WRITE_COMMITTED);
+ ltpll->config[1], MB_WRITE_COMMITTED);
intel_lt_phy_write(encoder, owned_lane_mask, LT_PHY_VDR_2_CONFIG,
- crtc_state->dpll_hw_state.ltpll.config[2], MB_WRITE_COMMITTED);
+ ltpll->config[2], MB_WRITE_COMMITTED);
for (i = 0; i <= 12; i++) {
intel_lt_phy_write(encoder, INTEL_LT_PHY_LANE0, LT_PHY_VDR_X_ADDR_MSB(i),
- crtc_state->dpll_hw_state.ltpll.addr_msb[i],
+ ltpll->addr_msb[i],
MB_WRITE_COMMITTED);
intel_lt_phy_write(encoder, INTEL_LT_PHY_LANE0, LT_PHY_VDR_X_ADDR_LSB(i),
- crtc_state->dpll_hw_state.ltpll.addr_lsb[i],
+ ltpll->addr_lsb[i],
MB_WRITE_COMMITTED);
for (j = 3, k = 0; j >= 0; j--, k++)
intel_lt_phy_write(encoder, INTEL_LT_PHY_LANE0,
LT_PHY_VDR_X_DATAY(i, j),
- crtc_state->dpll_hw_state.ltpll.data[i][k],
+ ltpll->data[i][k],
MB_WRITE_COMMITTED);
}
}
static void
intel_lt_phy_enable_disable_tx(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state)
+ const struct intel_lt_phy_pll_state *ltpll)
{
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
bool lane_reversal = dig_port->lane_reversal;
- u8 lane_count = crtc_state->lane_count;
+ u8 lane_count = ltpll->lane_count;
bool is_dp_alt =
intel_tc_port_in_dp_alt_mode(dig_port);
enum intel_tc_pin_assignment tc_pin =
@@ -1874,9 +1909,11 @@ intel_lt_phy_enable_disable_tx(struct intel_encoder *encoder,
}
void intel_lt_phy_pll_enable(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state)
+ struct intel_dpll *pll,
+ const struct intel_dpll_hw_state *dpll_hw_state)
{
struct intel_display *display = to_intel_display(encoder);
+ int port_clock = intel_lt_phy_calc_port_clock(display, &dpll_hw_state->ltpll);
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
bool lane_reversal = dig_port->lane_reversal;
u8 owned_lane_mask = intel_lt_phy_get_owned_lane_mask(encoder);
@@ -1892,10 +1929,11 @@ void intel_lt_phy_pll_enable(struct intel_encoder *encoder,
wakeref = intel_lt_phy_transaction_begin(encoder);
/* 1. Enable MacCLK at default 162 MHz frequency. */
- intel_lt_phy_lane_reset(encoder, crtc_state->lane_count);
+ intel_lt_phy_lane_reset(encoder, dpll_hw_state->ltpll.lane_count);
/* 2. Program PORT_CLOCK_CTL register to configure clock muxes, gating, and SSC. */
- intel_lt_phy_program_port_clock_ctl(encoder, crtc_state, lane_reversal);
+ intel_lt_phy_program_port_clock_ctl(encoder, &dpll_hw_state->ltpll,
+ port_clock, lane_reversal);
/* 3. Change owned PHY lanes power to Ready state. */
intel_lt_phy_powerdown_change_sequence(encoder, owned_lane_mask,
@@ -1905,12 +1943,12 @@ void intel_lt_phy_pll_enable(struct intel_encoder *encoder,
* 4. Read the PHY message bus VDR register PHY_VDR_0_Config check enabled PLL type,
* encoded rate and encoded mode.
*/
- if (intel_lt_phy_config_changed(encoder, crtc_state)) {
+ if (intel_lt_phy_config_changed(encoder, &dpll_hw_state->ltpll, port_clock)) {
/*
* 5. Program the PHY internal PLL registers over PHY message bus for the desired
* frequency and protocol type
*/
- intel_lt_phy_program_pll(encoder, crtc_state);
+ intel_lt_phy_program_pll(encoder, &dpll_hw_state->ltpll);
/* 6. Use the P2P transaction flow */
/*
@@ -1942,8 +1980,7 @@ void intel_lt_phy_pll_enable(struct intel_encoder *encoder,
* Change. We handle this step in bxt_set_cdclk().
*/
/* 10. Program DDI_CLK_VALFREQ to match intended DDI clock frequency. */
- intel_de_write(display, DDI_CLK_VALFREQ(encoder->port),
- crtc_state->port_clock);
+ intel_de_write(display, DDI_CLK_VALFREQ(encoder->port), port_clock);
/* 11. Program PORT_CLOCK_CTL[PCLK PLL Request LN0] = 1. */
intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, port),
@@ -1990,7 +2027,7 @@ void intel_lt_phy_pll_enable(struct intel_encoder *encoder,
lane_phy_pulse_status,
lane_phy_pulse_status);
} else {
- intel_de_write(display, DDI_CLK_VALFREQ(encoder->port), crtc_state->port_clock);
+ intel_de_write(display, DDI_CLK_VALFREQ(encoder->port), port_clock);
}
/*
@@ -2001,7 +2038,7 @@ void intel_lt_phy_pll_enable(struct intel_encoder *encoder,
intel_lt_phy_powerdown_change_sequence(encoder, owned_lane_mask,
XELPDP_P0_STATE_ACTIVE);
- intel_lt_phy_enable_disable_tx(encoder, crtc_state);
+ intel_lt_phy_enable_disable_tx(encoder, &dpll_hw_state->ltpll);
intel_lt_phy_transaction_end(encoder, wakeref);
}
@@ -2136,21 +2173,23 @@ void intel_lt_phy_set_signal_levels(struct intel_encoder *encoder,
intel_lt_phy_transaction_end(encoder, wakeref);
}
-void intel_lt_phy_dump_hw_state(struct intel_display *display,
+void intel_lt_phy_dump_hw_state(struct drm_printer *p,
const struct intel_lt_phy_pll_state *hw_state)
{
int i, j;
- drm_dbg_kms(display->drm, "lt_phy_pll_hw_state:\n");
+ drm_printf(p, "lt_phy_pll_hw_state: lane count: %d, ssc enabled: %d, tbt mode: %d\n",
+ hw_state->lane_count, hw_state->ssc_enabled, hw_state->tbt_mode);
+
for (i = 0; i < 3; i++) {
- drm_dbg_kms(display->drm, "config[%d] = 0x%.4x,\n",
- i, hw_state->config[i]);
+ drm_printf(p, "config[%d] = 0x%.4x,\n",
+ i, hw_state->config[i]);
}
for (i = 0; i <= 12; i++)
for (j = 3; j >= 0; j--)
- drm_dbg_kms(display->drm, "vdr_data[%d][%d] = 0x%.4x,\n",
- i, j, hw_state->data[i][j]);
+ drm_printf(p, "vdr_data[%d][%d] = 0x%.4x,\n",
+ i, j, hw_state->data[i][j]);
}
bool
@@ -2174,8 +2213,26 @@ intel_lt_phy_pll_compare_hw_state(const struct intel_lt_phy_pll_state *a,
return false;
}
-void intel_lt_phy_pll_readout_hw_state(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state,
+static bool intel_lt_phy_pll_is_enabled(struct intel_encoder *encoder)
+{
+ struct intel_display *display = to_intel_display(encoder);
+
+ return intel_de_read(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port)) &
+ XELPDP_LANE_PCLK_PLL_ACK(0);
+}
+
+bool intel_lt_phy_tbt_pll_readout_hw_state(struct intel_display *display,
+ struct intel_dpll *pll,
+ struct intel_dpll_hw_state *hw_state)
+{
+ memset(hw_state, 0, sizeof(*hw_state));
+
+ hw_state->ltpll.tbt_mode = true;
+
+ return true;
+}
+
+bool intel_lt_phy_pll_readout_hw_state(struct intel_encoder *encoder,
struct intel_lt_phy_pll_state *pll_state)
{
u8 owned_lane_mask;
@@ -2183,14 +2240,19 @@ void intel_lt_phy_pll_readout_hw_state(struct intel_encoder *encoder,
struct ref_tracker *wakeref;
int i, j, k;
+ if (!intel_lt_phy_pll_is_enabled(encoder))
+ return false;
+
pll_state->tbt_mode = intel_tc_port_in_tbt_alt_mode(enc_to_dig_port(encoder));
if (pll_state->tbt_mode)
- return;
+ return false;
owned_lane_mask = intel_lt_phy_get_owned_lane_mask(encoder);
lane = owned_lane_mask & INTEL_LT_PHY_LANE0 ? : INTEL_LT_PHY_LANE1;
wakeref = intel_lt_phy_transaction_begin(encoder);
+ pll_state->lane_count = intel_readout_lane_count(encoder, INTEL_LT_PHY_LANE0,
+ INTEL_LT_PHY_LANE1);
pll_state->config[0] = intel_lt_phy_read(encoder, lane, LT_PHY_VDR_0_CONFIG);
pll_state->config[1] = intel_lt_phy_read(encoder, INTEL_LT_PHY_LANE0, LT_PHY_VDR_1_CONFIG);
pll_state->config[2] = intel_lt_phy_read(encoder, lane, LT_PHY_VDR_2_CONFIG);
@@ -2203,56 +2265,15 @@ void intel_lt_phy_pll_readout_hw_state(struct intel_encoder *encoder,
}
intel_lt_phy_transaction_end(encoder, wakeref);
-}
-
-void intel_lt_phy_pll_state_verify(struct intel_atomic_state *state,
- struct intel_crtc *crtc)
-{
- struct intel_display *display = to_intel_display(state);
- struct intel_digital_port *dig_port;
- const struct intel_crtc_state *new_crtc_state =
- intel_atomic_get_new_crtc_state(state, crtc);
- struct intel_encoder *encoder;
- struct intel_lt_phy_pll_state pll_hw_state = {};
- const struct intel_lt_phy_pll_state *pll_sw_state = &new_crtc_state->dpll_hw_state.ltpll;
-
- if (DISPLAY_VER(display) < 35)
- return;
- if (!new_crtc_state->hw.active)
- return;
-
- /* intel_get_crtc_new_encoder() only works for modeset/fastset commits */
- if (!intel_crtc_needs_modeset(new_crtc_state) &&
- !intel_crtc_needs_fastset(new_crtc_state))
- return;
-
- encoder = intel_get_crtc_new_encoder(state, new_crtc_state);
- intel_lt_phy_pll_readout_hw_state(encoder, new_crtc_state, &pll_hw_state);
-
- dig_port = enc_to_dig_port(encoder);
- if (intel_tc_port_in_tbt_alt_mode(dig_port))
- return;
-
- INTEL_DISPLAY_STATE_WARN(display, pll_hw_state.config[0] != pll_sw_state->config[0],
- "[CRTC:%d:%s] mismatch in LT PHY PLL CONFIG 0: (expected 0x%04x, found 0x%04x)",
- crtc->base.base.id, crtc->base.name,
- pll_sw_state->config[0], pll_hw_state.config[0]);
- INTEL_DISPLAY_STATE_WARN(display, pll_hw_state.config[2] != pll_sw_state->config[2],
- "[CRTC:%d:%s] mismatch in LT PHY PLL CONFIG 2: (expected 0x%04x, found 0x%04x)",
- crtc->base.base.id, crtc->base.name,
- pll_sw_state->config[2], pll_hw_state.config[2]);
+ return true;
}
void intel_xe3plpd_pll_enable(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state)
+ struct intel_dpll *pll,
+ const struct intel_dpll_hw_state *dpll_hw_state)
{
- struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
-
- if (intel_tc_port_in_tbt_alt_mode(dig_port))
- intel_mtl_tbt_pll_enable_clock(encoder, crtc_state->port_clock);
- else
- intel_lt_phy_pll_enable(encoder, crtc_state);
+ intel_lt_phy_pll_enable(encoder, pll, dpll_hw_state);
}
void intel_xe3plpd_pll_disable(struct intel_encoder *encoder)
@@ -2294,7 +2315,7 @@ static void intel_lt_phy_pll_verify_clock(struct intel_display *display,
drm_printf(&p, "PLL state %s (%s):\n",
pll_state_name,
is_precomputed_state ? "precomputed" : "computed");
- intel_lt_phy_dump_hw_state(display, pll_state);
+ intel_lt_phy_dump_hw_state(&p, pll_state);
}
static void intel_lt_phy_pll_verify_params(struct intel_display *display,
diff --git a/drivers/gpu/drm/i915/display/intel_lt_phy.h b/drivers/gpu/drm/i915/display/intel_lt_phy.h
index db905668f86d..16de39484779 100644
--- a/drivers/gpu/drm/i915/display/intel_lt_phy.h
+++ b/drivers/gpu/drm/i915/display/intel_lt_phy.h
@@ -8,38 +8,45 @@
#include <linux/types.h>
+struct drm_printer;
struct intel_atomic_state;
struct intel_display;
+struct intel_dpll;
+struct intel_dpll_hw_state;
struct intel_encoder;
struct intel_crtc_state;
struct intel_crtc;
struct intel_lt_phy_pll_state;
void intel_lt_phy_pll_enable(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state);
+ struct intel_dpll *pll,
+ const struct intel_dpll_hw_state *dpll_hw_state);
void intel_lt_phy_pll_disable(struct intel_encoder *encoder);
int
intel_lt_phy_pll_calc_state(struct intel_crtc_state *crtc_state,
- struct intel_encoder *encoder);
+ struct intel_encoder *encoder,
+ struct intel_dpll_hw_state *hw_state);
+void intel_lt_phy_tbt_pll_calc_state(struct intel_dpll_hw_state *hw_state);
int intel_lt_phy_calc_port_clock(struct intel_display *display,
const struct intel_lt_phy_pll_state *lt_state);
void intel_lt_phy_set_signal_levels(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
-void intel_lt_phy_dump_hw_state(struct intel_display *display,
+void intel_lt_phy_dump_hw_state(struct drm_printer *p,
const struct intel_lt_phy_pll_state *hw_state);
bool
intel_lt_phy_pll_compare_hw_state(const struct intel_lt_phy_pll_state *a,
const struct intel_lt_phy_pll_state *b);
-void intel_lt_phy_pll_readout_hw_state(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state,
+bool intel_lt_phy_tbt_pll_readout_hw_state(struct intel_display *display,
+ struct intel_dpll *pll,
+ struct intel_dpll_hw_state *hw_state);
+bool intel_lt_phy_pll_readout_hw_state(struct intel_encoder *encoder,
struct intel_lt_phy_pll_state *pll_state);
-void intel_lt_phy_pll_state_verify(struct intel_atomic_state *state,
- struct intel_crtc *crtc);
int
intel_lt_phy_calculate_hdmi_state(struct intel_lt_phy_pll_state *lt_state,
u32 frequency_khz);
void intel_xe3plpd_pll_enable(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state);
+ struct intel_dpll *pll,
+ const struct intel_dpll_hw_state *dpll_hw_state);
void intel_xe3plpd_pll_disable(struct intel_encoder *encoder);
void intel_lt_phy_verify_plls(struct intel_display *display);
diff --git a/drivers/gpu/drm/i915/display/intel_modeset_verify.c b/drivers/gpu/drm/i915/display/intel_modeset_verify.c
index 12a00121c274..2ec17c2bfe0f 100644
--- a/drivers/gpu/drm/i915/display/intel_modeset_verify.c
+++ b/drivers/gpu/drm/i915/display/intel_modeset_verify.c
@@ -246,7 +246,6 @@ void intel_modeset_verify_crtc(struct intel_atomic_state *state,
verify_crtc_state(state, crtc);
intel_dpll_state_verify(state, crtc);
intel_mpllb_state_verify(state, crtc);
- intel_lt_phy_pll_state_verify(state, crtc);
}
void intel_modeset_verify_disabled(struct intel_atomic_state *state)
diff --git a/drivers/gpu/drm/i915/display/intel_pch.c b/drivers/gpu/drm/i915/display/intel_pch.c
index 65359a36df48..d2c1b1751838 100644
--- a/drivers/gpu/drm/i915/display/intel_pch.c
+++ b/drivers/gpu/drm/i915/display/intel_pch.c
@@ -5,6 +5,9 @@
#include <drm/drm_print.h>
+#include "intel_de.h"
+#include "intel_display.h"
+#include "intel_display_regs.h"
#include "intel_display_core.h"
#include "intel_display_utils.h"
#include "intel_pch.h"
@@ -214,6 +217,96 @@ intel_pch_type(const struct intel_display *display, unsigned short id)
}
}
+static void intel_pch_ibx_init_clock_gating(struct intel_display *display)
+{
+ /*
+ * On Ibex Peak and Cougar Point, we need to disable clock
+ * gating for the panel power sequencer or it will fail to
+ * start up when no ports are active.
+ */
+ intel_de_write(display, SOUTH_DSPCLK_GATE_D,
+ PCH_DPLSUNIT_CLOCK_GATE_DISABLE);
+}
+
+static void intel_pch_cpt_init_clock_gating(struct intel_display *display)
+{
+ enum pipe pipe;
+ u32 val;
+
+ /*
+ * On Ibex Peak and Cougar Point, we need to disable clock
+ * gating for the panel power sequencer or it will fail to
+ * start up when no ports are active.
+ */
+ intel_de_write(display, SOUTH_DSPCLK_GATE_D,
+ PCH_DPLSUNIT_CLOCK_GATE_DISABLE |
+ PCH_DPLUNIT_CLOCK_GATE_DISABLE |
+ PCH_CPUNIT_CLOCK_GATE_DISABLE);
+ intel_de_rmw(display, SOUTH_CHICKEN2, 0, DPLS_EDP_PPS_FIX_DIS);
+
+ /* The below fixes the weird display corruption, a few pixels shifted
+ * downward, on (only) LVDS of some HP laptops with IVY.
+ */
+ for_each_pipe(display, pipe) {
+ val = intel_de_read(display, TRANS_CHICKEN2(pipe));
+ val |= TRANS_CHICKEN2_TIMING_OVERRIDE;
+ val &= ~TRANS_CHICKEN2_FDI_POLARITY_REVERSED;
+ if (display->vbt.fdi_rx_polarity_inverted)
+ val |= TRANS_CHICKEN2_FDI_POLARITY_REVERSED;
+ val &= ~TRANS_CHICKEN2_DISABLE_DEEP_COLOR_COUNTER;
+ val &= ~TRANS_CHICKEN2_DISABLE_DEEP_COLOR_MODESWITCH;
+ intel_de_write(display, TRANS_CHICKEN2(pipe), val);
+ }
+
+ /* WADP0ClockGatingDisable */
+ for_each_pipe(display, pipe)
+ intel_de_write(display, TRANS_CHICKEN1(pipe),
+ TRANS_CHICKEN1_DP0UNIT_GC_DISABLE);
+}
+
+static void intel_pch_lpt_init_clock_gating(struct intel_display *display)
+{
+ /*
+ * TODO: this bit should only be enabled when really needed, then
+ * disabled when not needed anymore in order to save power.
+ */
+ if (HAS_PCH_LPT_LP(display))
+ intel_de_rmw(display, SOUTH_DSPCLK_GATE_D, 0,
+ PCH_LP_PARTITION_LEVEL_DISABLE);
+
+ /* WADPOClockGatingDisable:hsw */
+ intel_de_rmw(display, TRANS_CHICKEN1(PIPE_A), 0,
+ TRANS_CHICKEN1_DP0UNIT_GC_DISABLE);
+}
+
+static void intel_pch_cnp_init_clock_gating(struct intel_display *display)
+{
+ /* Display WA #1181 WaSouthDisplayDisablePWMCGEGating: cnp */
+ intel_de_rmw(display, SOUTH_DSPCLK_GATE_D, 0,
+ CNP_PWM_CGE_GATING_DISABLE);
+}
+
+void intel_pch_init_clock_gating(struct intel_display *display)
+{
+ switch (INTEL_PCH_TYPE(display)) {
+ case PCH_IBX:
+ intel_pch_ibx_init_clock_gating(display);
+ break;
+ case PCH_CPT:
+ intel_pch_cpt_init_clock_gating(display);
+ break;
+ case PCH_LPT_H:
+ case PCH_LPT_LP:
+ intel_pch_lpt_init_clock_gating(display);
+ break;
+ case PCH_CNP:
+ intel_pch_cnp_init_clock_gating(display);
+ break;
+ default:
+ break;
+ }
+}
+
static bool intel_is_virt_pch(unsigned short id,
unsigned short svendor, unsigned short sdevice)
{
diff --git a/drivers/gpu/drm/i915/display/intel_pch.h b/drivers/gpu/drm/i915/display/intel_pch.h
index 19cac7412d0a..aa971fa141e7 100644
--- a/drivers/gpu/drm/i915/display/intel_pch.h
+++ b/drivers/gpu/drm/i915/display/intel_pch.h
@@ -52,5 +52,6 @@ enum intel_pch {
#define HAS_PCH_SPLIT(display) (INTEL_PCH_TYPE(display) != PCH_NONE)
void intel_pch_detect(struct intel_display *display);
+void intel_pch_init_clock_gating(struct intel_display *display);
#endif /* __INTEL_PCH__ */
diff --git a/drivers/gpu/drm/i915/display/intel_plane.c b/drivers/gpu/drm/i915/display/intel_plane.c
index e06a0618b4c6..5390ceb21ca4 100644
--- a/drivers/gpu/drm/i915/display/intel_plane.c
+++ b/drivers/gpu/drm/i915/display/intel_plane.c
@@ -436,11 +436,38 @@ void intel_plane_copy_hw_state(struct intel_plane_state *plane_state,
drm_framebuffer_get(plane_state->hw.fb);
}
+static void unlink_nv12_plane(struct intel_crtc_state *crtc_state,
+ struct intel_plane_state *plane_state)
+{
+ struct intel_display *display = to_intel_display(plane_state);
+ struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
+
+ if (!plane_state->planar_linked_plane)
+ return;
+
+ plane_state->planar_linked_plane = NULL;
+
+ if (!plane_state->is_y_plane)
+ return;
+
+ drm_WARN_ON(display->drm, plane_state->uapi.visible);
+
+ plane_state->is_y_plane = false;
+
+ crtc_state->enabled_planes &= ~BIT(plane->id);
+ crtc_state->active_planes &= ~BIT(plane->id);
+ crtc_state->update_planes |= BIT(plane->id);
+ crtc_state->data_rate[plane->id] = 0;
+ crtc_state->rel_data_rate[plane->id] = 0;
+}
+
void intel_plane_set_invisible(struct intel_crtc_state *crtc_state,
struct intel_plane_state *plane_state)
{
struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
+ unlink_nv12_plane(crtc_state, plane_state);
+
crtc_state->active_planes &= ~BIT(plane->id);
crtc_state->scaled_planes &= ~BIT(plane->id);
crtc_state->nv12_planes &= ~BIT(plane->id);
@@ -1507,28 +1534,6 @@ static void link_nv12_planes(struct intel_crtc_state *crtc_state,
icl_link_nv12_planes(uv_plane_state, y_plane_state);
}
-static void unlink_nv12_plane(struct intel_crtc_state *crtc_state,
- struct intel_plane_state *plane_state)
-{
- struct intel_display *display = to_intel_display(plane_state);
- struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
-
- plane_state->planar_linked_plane = NULL;
-
- if (!plane_state->is_y_plane)
- return;
-
- drm_WARN_ON(display->drm, plane_state->uapi.visible);
-
- plane_state->is_y_plane = false;
-
- crtc_state->enabled_planes &= ~BIT(plane->id);
- crtc_state->active_planes &= ~BIT(plane->id);
- crtc_state->update_planes |= BIT(plane->id);
- crtc_state->data_rate[plane->id] = 0;
- crtc_state->rel_data_rate[plane->id] = 0;
-}
-
static int icl_check_nv12_planes(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
@@ -1542,18 +1547,6 @@ static int icl_check_nv12_planes(struct intel_atomic_state *state,
if (DISPLAY_VER(display) < 11)
return 0;
- /*
- * Destroy all old plane links and make the Y plane invisible
- * in the crtc_state->active_planes mask.
- */
- for_each_new_intel_plane_in_state(state, plane, plane_state, i) {
- if (plane->pipe != crtc->pipe)
- continue;
-
- if (plane_state->planar_linked_plane)
- unlink_nv12_plane(crtc_state, plane_state);
- }
-
if (!crtc_state->nv12_planes)
return 0;
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
index 5041a5a138d1..2f1b48cd8efd 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -49,6 +49,7 @@
#include "intel_hdmi.h"
#include "intel_psr.h"
#include "intel_psr_regs.h"
+#include "intel_quirks.h"
#include "intel_snps_phy.h"
#include "intel_step.h"
#include "intel_vblank.h"
@@ -609,6 +610,13 @@ static void _panel_replay_init_dpcd(struct intel_dp *intel_dp, struct intel_conn
if (intel_dp->mst_detect == DRM_DP_MST)
return;
+ if (intel_dp_is_edp(intel_dp) &&
+ intel_has_dpcd_quirk(intel_dp, QUIRK_DISABLE_EDP_PANEL_REPLAY)) {
+ drm_dbg_kms(display->drm,
+ "Panel Replay support not currently available for this setup\n");
+ return;
+ }
+
ret = drm_dp_dpcd_read_data(&intel_dp->aux, DP_PANEL_REPLAY_CAP_SUPPORT,
&connector->dp.panel_replay_caps.dpcd,
sizeof(connector->dp.panel_replay_caps.dpcd));
@@ -1716,7 +1724,7 @@ static bool _psr_compute_config(struct intel_dp *intel_dp,
entry_setup_frames = intel_psr_entry_setup_frames(intel_dp, conn_state, adjusted_mode);
if (entry_setup_frames >= 0) {
- intel_dp->psr.entry_setup_frames = entry_setup_frames;
+ crtc_state->entry_setup_frames = entry_setup_frames;
} else {
crtc_state->no_psr_reason = "PSR setup timing not met";
drm_dbg_kms(display->drm,
@@ -1814,7 +1822,7 @@ static bool intel_psr_needs_wa_18037818876(struct intel_dp *intel_dp,
{
struct intel_display *display = to_intel_display(intel_dp);
- return (DISPLAY_VER(display) == 20 && intel_dp->psr.entry_setup_frames > 0 &&
+ return (DISPLAY_VER(display) == 20 && crtc_state->entry_setup_frames > 0 &&
!crtc_state->has_sel_update);
}
@@ -2190,6 +2198,7 @@ static void intel_psr_enable_locked(struct intel_dp *intel_dp,
intel_dp->psr.pkg_c_latency_used = crtc_state->pkg_c_latency_used;
intel_dp->psr.io_wake_lines = crtc_state->alpm_state.io_wake_lines;
intel_dp->psr.fast_wake_lines = crtc_state->alpm_state.fast_wake_lines;
+ intel_dp->psr.entry_setup_frames = crtc_state->entry_setup_frames;
if (!psr_interrupt_error_check(intel_dp))
return;
@@ -3112,6 +3121,8 @@ void intel_psr_pre_plane_update(struct intel_atomic_state *state,
* - Display WA #1136: skl, bxt
*/
if (intel_crtc_needs_modeset(new_crtc_state) ||
+ new_crtc_state->update_m_n ||
+ new_crtc_state->update_lrr ||
!new_crtc_state->has_psr ||
!new_crtc_state->active_planes ||
new_crtc_state->has_sel_update != psr->sel_update_enabled ||
diff --git a/drivers/gpu/drm/i915/display/intel_quirks.c b/drivers/gpu/drm/i915/display/intel_quirks.c
index 1abbdd426e58..883f297d4b83 100644
--- a/drivers/gpu/drm/i915/display/intel_quirks.c
+++ b/drivers/gpu/drm/i915/display/intel_quirks.c
@@ -86,6 +86,14 @@ static void quirk_edp_limit_rate_hbr2(struct intel_display *display)
drm_info(display->drm, "Applying eDP Limit rate to HBR2 quirk\n");
}
+static void quirk_disable_edp_panel_replay(struct intel_dp *intel_dp)
+{
+ struct intel_display *display = to_intel_display(intel_dp);
+
+ intel_set_dpcd_quirk(intel_dp, QUIRK_DISABLE_EDP_PANEL_REPLAY);
+ drm_info(display->drm, "Applying disable Panel Replay quirk\n");
+}
+
struct intel_quirk {
int device;
int subsystem_vendor;
@@ -108,6 +116,8 @@ struct intel_dpcd_quirk {
#define SINK_DEVICE_ID_ANY SINK_DEVICE_ID(0, 0, 0, 0, 0, 0)
+#define DEVICE_ID_ANY 0
+
/* For systems that don't have a meaningful PCI subdevice/subvendor ID */
struct intel_dmi_quirk {
void (*hook)(struct intel_display *display);
@@ -251,7 +261,14 @@ static const struct intel_dpcd_quirk intel_dpcd_quirks[] = {
.sink_oui = SINK_OUI(0x38, 0xec, 0x11),
.hook = quirk_fw_sync_len,
},
-
+ /* Dell XPS 14 DA14260 */
+ {
+ .device = DEVICE_ID_ANY,
+ .subsystem_vendor = 0x1028,
+ .subsystem_device = 0x0db9,
+ .sink_oui = SINK_OUI(0x00, 0x22, 0xb9),
+ .hook = quirk_disable_edp_panel_replay,
+ },
};
void intel_init_quirks(struct intel_display *display)
@@ -262,7 +279,8 @@ void intel_init_quirks(struct intel_display *display)
for (i = 0; i < ARRAY_SIZE(intel_quirks); i++) {
struct intel_quirk *q = &intel_quirks[i];
- if (d->device == q->device &&
+ if ((d->device == q->device ||
+ q->device == DEVICE_ID_ANY) &&
(d->subsystem_vendor == q->subsystem_vendor ||
q->subsystem_vendor == PCI_ANY_ID) &&
(d->subsystem_device == q->subsystem_device ||
@@ -285,7 +303,8 @@ void intel_init_dpcd_quirks(struct intel_dp *intel_dp,
for (i = 0; i < ARRAY_SIZE(intel_dpcd_quirks); i++) {
const struct intel_dpcd_quirk *q = &intel_dpcd_quirks[i];
- if (d->device == q->device &&
+ if ((d->device == q->device ||
+ q->device == DEVICE_ID_ANY) &&
(d->subsystem_vendor == q->subsystem_vendor ||
q->subsystem_vendor == PCI_ANY_ID) &&
(d->subsystem_device == q->subsystem_device ||
diff --git a/drivers/gpu/drm/i915/display/intel_quirks.h b/drivers/gpu/drm/i915/display/intel_quirks.h
index 06da0e286c67..83214eb94b0c 100644
--- a/drivers/gpu/drm/i915/display/intel_quirks.h
+++ b/drivers/gpu/drm/i915/display/intel_quirks.h
@@ -21,6 +21,7 @@ enum intel_quirk_id {
QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK,
QUIRK_FW_SYNC_LEN,
QUIRK_EDP_LIMIT_RATE_HBR2,
+ QUIRK_DISABLE_EDP_PANEL_REPLAY,
};
void intel_init_quirks(struct intel_display *display);
diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c
index b1f9546b8cda..d45b3bcc6ef0 100644
--- a/drivers/gpu/drm/i915/display/skl_watermark.c
+++ b/drivers/gpu/drm/i915/display/skl_watermark.c
@@ -63,7 +63,6 @@ static void skl_sagv_disable(struct intel_display *display);
struct skl_wm_params {
bool x_tiled, y_tiled;
bool rc_surface;
- bool is_planar;
u32 width;
u8 cpp;
u32 plane_pixel_rate;
@@ -1357,14 +1356,13 @@ skl_check_wm_level(struct skl_wm_level *wm, const struct skl_ddb_entry *ddb)
}
static void
-skl_check_nv12_wm_level(struct skl_wm_level *wm, struct skl_wm_level *uv_wm,
- const struct skl_ddb_entry *ddb_y, const struct skl_ddb_entry *ddb)
+skl_check_wm_level_nv12(struct skl_wm_level *wm,
+ const struct skl_ddb_entry *ddb_y,
+ const struct skl_ddb_entry *ddb)
{
if (wm->min_ddb_alloc > skl_ddb_entry_size(ddb_y) ||
- uv_wm->min_ddb_alloc > skl_ddb_entry_size(ddb)) {
+ wm->min_ddb_alloc_uv > skl_ddb_entry_size(ddb))
memset(wm, 0, sizeof(*wm));
- memset(uv_wm, 0, sizeof(*uv_wm));
- }
}
static bool skl_need_wm_copy_wa(struct intel_display *display, int level,
@@ -1391,10 +1389,9 @@ struct skl_plane_ddb_iter {
};
static void
-skl_allocate_plane_ddb(struct skl_plane_ddb_iter *iter,
- struct skl_ddb_entry *ddb,
- const struct skl_wm_level *wm,
- u64 data_rate)
+_skl_allocate_plane_ddb(struct skl_plane_ddb_iter *iter,
+ u16 min_ddb_alloc,
+ struct skl_ddb_entry *ddb, u64 data_rate)
{
u16 size, extra = 0;
@@ -1411,12 +1408,30 @@ skl_allocate_plane_ddb(struct skl_plane_ddb_iter *iter,
* to avoid skl_ddb_add_affected_planes() adding them to
* the state when other planes change their allocations.
*/
- size = wm->min_ddb_alloc + extra;
+ size = min_ddb_alloc + extra;
if (size)
iter->start = skl_ddb_entry_init(ddb, iter->start,
iter->start + size);
}
+static void
+skl_allocate_plane_ddb(struct skl_plane_ddb_iter *iter,
+ const struct skl_wm_level *wm,
+ struct skl_ddb_entry *ddb, u64 data_rate)
+{
+ _skl_allocate_plane_ddb(iter, wm->min_ddb_alloc, ddb, data_rate);
+}
+
+static void
+skl_allocate_plane_ddb_nv12(struct skl_plane_ddb_iter *iter,
+ const struct skl_wm_level *wm,
+ struct skl_ddb_entry *ddb_y, u64 data_rate_y,
+ struct skl_ddb_entry *ddb, u64 data_rate)
+{
+ _skl_allocate_plane_ddb(iter, wm->min_ddb_alloc, ddb_y, data_rate_y);
+ _skl_allocate_plane_ddb(iter, wm->min_ddb_alloc_uv, ddb, data_rate);
+}
+
static int
skl_crtc_allocate_plane_ddb(struct intel_atomic_state *state,
struct intel_crtc *crtc)
@@ -1482,7 +1497,7 @@ skl_crtc_allocate_plane_ddb(struct intel_atomic_state *state,
}
blocks += wm->wm[level].min_ddb_alloc;
- blocks += wm->uv_wm[level].min_ddb_alloc;
+ blocks += wm->wm[level].min_ddb_alloc_uv;
}
if (blocks <= iter.size) {
@@ -1523,15 +1538,13 @@ skl_crtc_allocate_plane_ddb(struct intel_atomic_state *state,
continue;
if (DISPLAY_VER(display) < 11 &&
- crtc_state->nv12_planes & BIT(plane_id)) {
- skl_allocate_plane_ddb(&iter, ddb_y, &wm->wm[level],
- crtc_state->rel_data_rate_y[plane_id]);
- skl_allocate_plane_ddb(&iter, ddb, &wm->uv_wm[level],
- crtc_state->rel_data_rate[plane_id]);
- } else {
- skl_allocate_plane_ddb(&iter, ddb, &wm->wm[level],
- crtc_state->rel_data_rate[plane_id]);
- }
+ crtc_state->nv12_planes & BIT(plane_id))
+ skl_allocate_plane_ddb_nv12(&iter, &wm->wm[level],
+ ddb_y, crtc_state->rel_data_rate_y[plane_id],
+ ddb, crtc_state->rel_data_rate[plane_id]);
+ else
+ skl_allocate_plane_ddb(&iter, &wm->wm[level],
+ ddb, crtc_state->rel_data_rate[plane_id]);
if (DISPLAY_VER(display) >= 30) {
*min_ddb = wm->wm[0].min_ddb_alloc;
@@ -1557,9 +1570,7 @@ skl_crtc_allocate_plane_ddb(struct intel_atomic_state *state,
if (DISPLAY_VER(display) < 11 &&
crtc_state->nv12_planes & BIT(plane_id))
- skl_check_nv12_wm_level(&wm->wm[level],
- &wm->uv_wm[level],
- ddb_y, ddb);
+ skl_check_wm_level_nv12(&wm->wm[level], ddb_y, ddb);
else
skl_check_wm_level(&wm->wm[level], ddb);
@@ -1675,10 +1686,9 @@ skl_compute_wm_params(const struct intel_crtc_state *crtc_state,
wp->y_tiled = modifier != I915_FORMAT_MOD_X_TILED &&
intel_fb_is_tiled_modifier(modifier);
wp->rc_surface = intel_fb_is_ccs_modifier(modifier);
- wp->is_planar = intel_format_info_is_yuv_semiplanar(format, modifier);
wp->width = width;
- if (color_plane == 1 && wp->is_planar)
+ if (color_plane == 1 && intel_format_info_is_yuv_semiplanar(format, modifier))
wp->width /= 2;
wp->cpp = format->cpp[color_plane];
@@ -2069,11 +2079,11 @@ static int skl_build_plane_wm_uv(struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state,
struct intel_plane *plane)
{
+ struct intel_display *display = to_intel_display(crtc_state);
struct skl_plane_wm *wm = &crtc_state->wm.skl.raw.planes[plane->id];
+ struct skl_wm_level uv_wm[ARRAY_SIZE(wm->wm)] = {};
struct skl_wm_params wm_params;
- int ret;
-
- wm->is_planar = true;
+ int ret, level;
/* uv plane watermarks must also be validated for NV12/Planar */
ret = skl_compute_plane_wm_params(crtc_state, plane_state,
@@ -2081,7 +2091,14 @@ static int skl_build_plane_wm_uv(struct intel_crtc_state *crtc_state,
if (ret)
return ret;
- skl_compute_wm_levels(crtc_state, plane, &wm_params, wm->uv_wm);
+ skl_compute_wm_levels(crtc_state, plane, &wm_params, uv_wm);
+
+ /*
+ * Only keep the min_ddb_alloc for UV as
+ * the hardware needs nothing else.
+ */
+ for (level = 0; level < display->wm.num_levels; level++)
+ wm->wm[level].min_ddb_alloc_uv = uv_wm[level].min_ddb_alloc;
return 0;
}
@@ -2304,7 +2321,6 @@ static int skl_wm_check_vblank(struct intel_crtc_state *crtc_state)
* thing as bad via min_ddb_alloc=U16_MAX?
*/
wm->wm[level].enable = false;
- wm->uv_wm[level].enable = false;
}
}
@@ -2375,11 +2391,6 @@ static bool skl_plane_wm_equals(struct intel_display *display,
int level;
for (level = 0; level < display->wm.num_levels; level++) {
- /*
- * We don't check uv_wm as the hardware doesn't actually
- * use it. It only gets used for calculating the required
- * ddb allocation.
- */
if (!skl_wm_level_equals(&wm1->wm[level], &wm2->wm[level]))
return false;
}
@@ -2590,14 +2601,30 @@ static char enast(bool enable)
return enable ? '*' : ' ';
}
+static void
+skl_print_plane_ddb_changes(struct intel_plane *plane,
+ const struct skl_ddb_entry *old,
+ const struct skl_ddb_entry *new,
+ const char *ddb_name)
+{
+ struct intel_display *display = to_intel_display(plane);
+
+ drm_dbg_kms(display->drm,
+ "[PLANE:%d:%s] %5s (%4d - %4d) -> (%4d - %4d), size %4d -> %4d\n",
+ plane->base.base.id, plane->base.name, ddb_name,
+ old->start, old->end, new->start, new->end,
+ skl_ddb_entry_size(old), skl_ddb_entry_size(new));
+}
+
static noinline_for_stack void
-skl_print_plane_changes(struct intel_display *display,
- struct intel_plane *plane,
- const struct skl_plane_wm *old_wm,
- const struct skl_plane_wm *new_wm)
+skl_print_plane_wm_changes(struct intel_plane *plane,
+ const struct skl_plane_wm *old_wm,
+ const struct skl_plane_wm *new_wm)
{
+ struct intel_display *display = to_intel_display(plane);
+
drm_dbg_kms(display->drm,
- "[PLANE:%d:%s] level %cwm0,%cwm1,%cwm2,%cwm3,%cwm4,%cwm5,%cwm6,%cwm7,%ctwm,%cswm,%cstwm"
+ "[PLANE:%d:%s] level %cwm0,%cwm1,%cwm2,%cwm3,%cwm4,%cwm5,%cwm6,%cwm7,%ctwm,%cswm,%cstwm"
" -> %cwm0,%cwm1,%cwm2,%cwm3,%cwm4,%cwm5,%cwm6,%cwm7,%ctwm,%cswm,%cstwm\n",
plane->base.base.id, plane->base.name,
enast(old_wm->wm[0].enable), enast(old_wm->wm[1].enable),
@@ -2616,7 +2643,7 @@ skl_print_plane_changes(struct intel_display *display,
enast(new_wm->sagv.trans_wm.enable));
drm_dbg_kms(display->drm,
- "[PLANE:%d:%s] lines %c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%4d"
+ "[PLANE:%d:%s] lines %c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%4d"
" -> %c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%4d\n",
plane->base.base.id, plane->base.name,
enast(old_wm->wm[0].ignore_lines), old_wm->wm[0].lines,
@@ -2643,7 +2670,7 @@ skl_print_plane_changes(struct intel_display *display,
enast(new_wm->sagv.trans_wm.ignore_lines), new_wm->sagv.trans_wm.lines);
drm_dbg_kms(display->drm,
- "[PLANE:%d:%s] blocks %4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%5d"
+ "[PLANE:%d:%s] blocks %4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%5d"
" -> %4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%5d\n",
plane->base.base.id, plane->base.name,
old_wm->wm[0].blocks, old_wm->wm[1].blocks,
@@ -2662,7 +2689,7 @@ skl_print_plane_changes(struct intel_display *display,
new_wm->sagv.trans_wm.blocks);
drm_dbg_kms(display->drm,
- "[PLANE:%d:%s] min_ddb %4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%5d"
+ "[PLANE:%d:%s] min_ddb %4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%5d"
" -> %4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%5d\n",
plane->base.base.id, plane->base.name,
old_wm->wm[0].min_ddb_alloc, old_wm->wm[1].min_ddb_alloc,
@@ -2679,6 +2706,28 @@ skl_print_plane_changes(struct intel_display *display,
new_wm->trans_wm.min_ddb_alloc,
new_wm->sagv.wm0.min_ddb_alloc,
new_wm->sagv.trans_wm.min_ddb_alloc);
+
+ if (DISPLAY_VER(display) >= 11)
+ return;
+
+ drm_dbg_kms(display->drm,
+ "[PLANE:%d:%s] min_ddb_uv %4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%5d"
+ " -> %4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%5d\n",
+ plane->base.base.id, plane->base.name,
+ old_wm->wm[0].min_ddb_alloc_uv, old_wm->wm[1].min_ddb_alloc_uv,
+ old_wm->wm[2].min_ddb_alloc_uv, old_wm->wm[3].min_ddb_alloc_uv,
+ old_wm->wm[4].min_ddb_alloc_uv, old_wm->wm[5].min_ddb_alloc_uv,
+ old_wm->wm[6].min_ddb_alloc_uv, old_wm->wm[7].min_ddb_alloc_uv,
+ old_wm->trans_wm.min_ddb_alloc_uv,
+ old_wm->sagv.wm0.min_ddb_alloc_uv,
+ old_wm->sagv.trans_wm.min_ddb_alloc_uv,
+ new_wm->wm[0].min_ddb_alloc_uv, new_wm->wm[1].min_ddb_alloc_uv,
+ new_wm->wm[2].min_ddb_alloc_uv, new_wm->wm[3].min_ddb_alloc_uv,
+ new_wm->wm[4].min_ddb_alloc_uv, new_wm->wm[5].min_ddb_alloc_uv,
+ new_wm->wm[6].min_ddb_alloc_uv, new_wm->wm[7].min_ddb_alloc_uv,
+ new_wm->trans_wm.min_ddb_alloc_uv,
+ new_wm->sagv.wm0.min_ddb_alloc_uv,
+ new_wm->sagv.trans_wm.min_ddb_alloc_uv);
}
static void
@@ -2708,13 +2757,17 @@ skl_print_wm_changes(struct intel_atomic_state *state)
old = &old_crtc_state->wm.skl.plane_ddb[plane_id];
new = &new_crtc_state->wm.skl.plane_ddb[plane_id];
- if (skl_ddb_entry_equal(old, new))
+ if (!skl_ddb_entry_equal(old, new))
+ skl_print_plane_ddb_changes(plane, old, new, "ddb");
+
+ if (DISPLAY_VER(display) >= 11)
continue;
- drm_dbg_kms(display->drm,
- "[PLANE:%d:%s] ddb (%4d - %4d) -> (%4d - %4d), size %4d -> %4d\n",
- plane->base.base.id, plane->base.name,
- old->start, old->end, new->start, new->end,
- skl_ddb_entry_size(old), skl_ddb_entry_size(new));
+
+ old = &old_crtc_state->wm.skl.plane_ddb_y[plane_id];
+ new = &new_crtc_state->wm.skl.plane_ddb_y[plane_id];
+
+ if (!skl_ddb_entry_equal(old, new))
+ skl_print_plane_ddb_changes(plane, old, new, "ddb_y");
}
for_each_intel_plane_on_crtc(display->drm, crtc, plane) {
@@ -2727,7 +2780,7 @@ skl_print_wm_changes(struct intel_atomic_state *state)
if (skl_plane_wm_equals(display, old_wm, new_wm))
continue;
- skl_print_plane_changes(display, plane, old_wm, new_wm);
+ skl_print_plane_wm_changes(plane, old_wm, new_wm);
}
}
}
@@ -2740,11 +2793,6 @@ static bool skl_plane_selected_wm_equals(struct intel_plane *plane,
int level;
for (level = 0; level < display->wm.num_levels; level++) {
- /*
- * We don't check uv_wm as the hardware doesn't actually
- * use it. It only gets used for calculating the required
- * ddb allocation.
- */
if (!skl_wm_level_equals(skl_plane_wm_level(old_pipe_wm, plane->id, level),
skl_plane_wm_level(new_pipe_wm, plane->id, level)))
return false;
diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c
index 36591d724638..d4db73c184e5 100644
--- a/drivers/gpu/drm/i915/display/vlv_dsi.c
+++ b/drivers/gpu/drm/i915/display/vlv_dsi.c
@@ -1367,7 +1367,7 @@ static void intel_dsi_prepare(struct intel_encoder *encoder,
}
tmp = 0;
- if (intel_dsi->eotp_pkt == 0)
+ if (!intel_dsi->eot_pkt)
tmp |= EOT_DISABLE;
if (intel_dsi->clock_stop)
tmp |= CLOCKSTOP;
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
index e7918f896a26..942f4eed817f 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
@@ -898,6 +898,8 @@ static struct i915_vma *eb_lookup_vma(struct i915_execbuffer *eb, u32 handle)
vma = radix_tree_lookup(&eb->gem_context->handles_vma, handle);
if (likely(vma && vma->vm == vm))
vma = i915_vma_tryget(vma);
+ else
+ vma = NULL;
rcu_read_unlock();
if (likely(vma))
return vma;
diff --git a/drivers/gpu/drm/i915/gvt/edid.c b/drivers/gpu/drm/i915/gvt/edid.c
index 021afff1cd5d..ca5b54466a65 100644
--- a/drivers/gpu/drm/i915/gvt/edid.c
+++ b/drivers/gpu/drm/i915/gvt/edid.c
@@ -535,16 +535,7 @@ void intel_gvt_i2c_handle_aux_ch_write(struct intel_vgpu *vgpu,
i2c_edid->edid_available = true;
}
}
- } else if ((op & 0x1) == DP_AUX_I2C_WRITE) {
- /* TODO
- * We only support EDID reading from I2C_over_AUX. And
- * we do not expect the index mode to be used. Right now
- * the WRITE operation is ignored. It is good enough to
- * support the gfx driver to do EDID access.
- */
- } else {
- if (drm_WARN_ON(&i915->drm, (op & 0x1) != DP_AUX_I2C_READ))
- return;
+ } else if ((op & 0x1) == DP_AUX_I2C_READ) {
if (drm_WARN_ON(&i915->drm, msg_length != 4))
return;
if (i2c_edid->edid_available && i2c_edid->target_selected) {
@@ -553,6 +544,13 @@ void intel_gvt_i2c_handle_aux_ch_write(struct intel_vgpu *vgpu,
aux_data_for_write = (val << 16);
} else
aux_data_for_write = (0xff << 16);
+ } else {
+ /* TODO
+ * We only support EDID reading from I2C_over_AUX. And
+ * we do not expect the index mode to be used. Right now
+ * the WRITE operation is ignored. It is good enough to
+ * support the gfx driver to do EDID access.
+ */
}
/* write the return value in AUX_CH_DATA reg which includes:
* ACK of I2C_WRITE
diff --git a/drivers/gpu/drm/i915/i915_initial_plane.c b/drivers/gpu/drm/i915/i915_initial_plane.c
index 5594548f51d8..390a9248d631 100644
--- a/drivers/gpu/drm/i915/i915_initial_plane.c
+++ b/drivers/gpu/drm/i915/i915_initial_plane.c
@@ -115,7 +115,8 @@ initial_plane_vma(struct drm_i915_private *i915,
* important and we should probably use that space with FBC or other
* features.
*/
- if (IS_ENABLED(CONFIG_FRAMEBUFFER_CONSOLE) &&
+ if (IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION) &&
+ IS_ENABLED(CONFIG_FRAMEBUFFER_CONSOLE) &&
mem == i915->mm.stolen_region &&
!intel_fbdev_fb_prefer_stolen(&i915->drm, size)) {
drm_dbg_kms(&i915->drm, "Initial FB size exceeds half of stolen, discarding\n");
diff --git a/drivers/gpu/drm/i915/i915_wait_util.h b/drivers/gpu/drm/i915/i915_wait_util.h
index 7376898e3bf8..e1ed7921ec70 100644
--- a/drivers/gpu/drm/i915/i915_wait_util.h
+++ b/drivers/gpu/drm/i915/i915_wait_util.h
@@ -25,9 +25,9 @@
might_sleep(); \
for (;;) { \
const bool expired__ = ktime_after(ktime_get_raw(), end__); \
- OP; \
/* Guarantee COND check prior to timeout */ \
barrier(); \
+ OP; \
if (COND) { \
ret__ = 0; \
break; \
diff --git a/drivers/gpu/drm/i915/intel_clock_gating.c b/drivers/gpu/drm/i915/intel_clock_gating.c
index 68a6f94f2a37..ee2489a2fbe7 100644
--- a/drivers/gpu/drm/i915/intel_clock_gating.c
+++ b/drivers/gpu/drm/i915/intel_clock_gating.c
@@ -33,6 +33,7 @@
#include "display/intel_display.h"
#include "display/intel_display_core.h"
#include "display/intel_display_regs.h"
+#include "display/intel_pch.h"
#include "gt/intel_engine_regs.h"
#include "gt/intel_gt.h"
#include "gt/intel_gt_mcr.h"
@@ -124,16 +125,6 @@ static void glk_init_clock_gating(struct drm_i915_private *i915)
PWM1_GATING_DIS | PWM2_GATING_DIS);
}
-static void ibx_init_clock_gating(struct drm_i915_private *i915)
-{
- /*
- * On Ibex Peak and Cougar Point, we need to disable clock
- * gating for the panel power sequencer or it will fail to
- * start up when no ports are active.
- */
- intel_uncore_write(&i915->uncore, SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE);
-}
-
static void g4x_disable_trickle_feed(struct drm_i915_private *dev_priv)
{
struct intel_display *display = dev_priv->display;
@@ -202,42 +193,7 @@ static void ilk_init_clock_gating(struct drm_i915_private *i915)
g4x_disable_trickle_feed(i915);
- ibx_init_clock_gating(i915);
-}
-
-static void cpt_init_clock_gating(struct drm_i915_private *i915)
-{
- struct intel_display *display = i915->display;
- enum pipe pipe;
- u32 val;
-
- /*
- * On Ibex Peak and Cougar Point, we need to disable clock
- * gating for the panel power sequencer or it will fail to
- * start up when no ports are active.
- */
- intel_uncore_write(&i915->uncore, SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE |
- PCH_DPLUNIT_CLOCK_GATE_DISABLE |
- PCH_CPUNIT_CLOCK_GATE_DISABLE);
- intel_uncore_rmw(&i915->uncore, SOUTH_CHICKEN2, 0, DPLS_EDP_PPS_FIX_DIS);
- /* The below fixes the weird display corruption, a few pixels shifted
- * downward, on (only) LVDS of some HP laptops with IVY.
- */
- for_each_pipe(display, pipe) {
- val = intel_uncore_read(&i915->uncore, TRANS_CHICKEN2(pipe));
- val |= TRANS_CHICKEN2_TIMING_OVERRIDE;
- val &= ~TRANS_CHICKEN2_FDI_POLARITY_REVERSED;
- if (display->vbt.fdi_rx_polarity_inverted)
- val |= TRANS_CHICKEN2_FDI_POLARITY_REVERSED;
- val &= ~TRANS_CHICKEN2_DISABLE_DEEP_COLOR_COUNTER;
- val &= ~TRANS_CHICKEN2_DISABLE_DEEP_COLOR_MODESWITCH;
- intel_uncore_write(&i915->uncore, TRANS_CHICKEN2(pipe), val);
- }
- /* WADP0ClockGatingDisable */
- for_each_pipe(display, pipe) {
- intel_uncore_write(&i915->uncore, TRANS_CHICKEN1(pipe),
- TRANS_CHICKEN1_DP0UNIT_GC_DISABLE);
- }
+ intel_pch_init_clock_gating(i915->display);
}
static void gen6_check_mch_setup(struct drm_i915_private *i915)
@@ -305,28 +261,11 @@ static void gen6_init_clock_gating(struct drm_i915_private *i915)
g4x_disable_trickle_feed(i915);
- cpt_init_clock_gating(i915);
+ intel_pch_init_clock_gating(i915->display);
gen6_check_mch_setup(i915);
}
-static void lpt_init_clock_gating(struct drm_i915_private *i915)
-{
- struct intel_display *display = i915->display;
-
- /*
- * TODO: this bit should only be enabled when really needed, then
- * disabled when not needed anymore in order to save power.
- */
- if (HAS_PCH_LPT_LP(display))
- intel_uncore_rmw(&i915->uncore, SOUTH_DSPCLK_GATE_D,
- 0, PCH_LP_PARTITION_LEVEL_DISABLE);
-
- /* WADPOClockGatingDisable:hsw */
- intel_uncore_rmw(&i915->uncore, TRANS_CHICKEN1(PIPE_A),
- 0, TRANS_CHICKEN1_DP0UNIT_GC_DISABLE);
-}
-
static void gen8_set_l3sqc_credits(struct drm_i915_private *i915,
int general_prio_credits,
int high_prio_credits)
@@ -360,20 +299,9 @@ static void dg2_init_clock_gating(struct drm_i915_private *i915)
SGSI_SIDECLK_DIS);
}
-static void cnp_init_clock_gating(struct drm_i915_private *i915)
-{
- struct intel_display *display = i915->display;
-
- if (!HAS_PCH_CNP(display))
- return;
-
- /* Display WA #1181 WaSouthDisplayDisablePWMCGEGating: cnp */
- intel_uncore_rmw(&i915->uncore, SOUTH_DSPCLK_GATE_D, 0, CNP_PWM_CGE_GATING_DISABLE);
-}
-
static void cfl_init_clock_gating(struct drm_i915_private *i915)
{
- cnp_init_clock_gating(i915);
+ intel_pch_init_clock_gating(i915->display);
gen9_init_clock_gating(i915);
/* WAC6entrylatency:cfl */
@@ -466,7 +394,7 @@ static void bdw_init_clock_gating(struct drm_i915_private *i915)
intel_uncore_rmw(&i915->uncore, CHICKEN_PAR2_1,
0, KVM_CONFIG_CHANGE_NOTIFICATION_SELECT);
- lpt_init_clock_gating(i915);
+ intel_pch_init_clock_gating(i915->display);
/* WaDisableDopClockGating:bdw
*
@@ -500,7 +428,7 @@ static void hsw_init_clock_gating(struct drm_i915_private *i915)
/* WaSwitchSolVfFArbitrationPriority:hsw */
intel_uncore_rmw(&i915->uncore, GAM_ECOCHK, 0, HSW_ECOCHK_ARB_PRIO_SOL);
- lpt_init_clock_gating(i915);
+ intel_pch_init_clock_gating(i915->display);
}
static void ivb_init_clock_gating(struct drm_i915_private *i915)
@@ -545,7 +473,7 @@ static void ivb_init_clock_gating(struct drm_i915_private *i915)
GEN6_MBC_SNPCR_MED);
if (!HAS_PCH_NOP(display))
- cpt_init_clock_gating(i915);
+ intel_pch_init_clock_gating(display);
gen6_check_mch_setup(i915);
}
diff --git a/drivers/gpu/drm/i915/intel_step.h b/drivers/gpu/drm/i915/intel_step.h
index 22f1d6905160..2ca36eae4b5a 100644
--- a/drivers/gpu/drm/i915/intel_step.h
+++ b/drivers/gpu/drm/i915/intel_step.h
@@ -8,6 +8,8 @@
#include <linux/types.h>
+#include <drm/intel/step.h>
+
struct drm_i915_private;
struct intel_step_info {
@@ -19,61 +21,6 @@ struct intel_step_info {
u8 media_step;
};
-#define STEP_ENUM_VAL(name) STEP_##name,
-
-#define STEP_NAME_LIST(func) \
- func(A0) \
- func(A1) \
- func(A2) \
- func(A3) \
- func(B0) \
- func(B1) \
- func(B2) \
- func(B3) \
- func(C0) \
- func(C1) \
- func(C2) \
- func(C3) \
- func(D0) \
- func(D1) \
- func(D2) \
- func(D3) \
- func(E0) \
- func(E1) \
- func(E2) \
- func(E3) \
- func(F0) \
- func(F1) \
- func(F2) \
- func(F3) \
- func(G0) \
- func(G1) \
- func(G2) \
- func(G3) \
- func(H0) \
- func(H1) \
- func(H2) \
- func(H3) \
- func(I0) \
- func(I1) \
- func(I2) \
- func(I3) \
- func(J0) \
- func(J1) \
- func(J2) \
- func(J3)
-
-/*
- * Symbolic steppings that do not match the hardware. These are valid both as gt
- * and display steppings as symbolic names.
- */
-enum intel_step {
- STEP_NONE = 0,
- STEP_NAME_LIST(STEP_ENUM_VAL)
- STEP_FUTURE,
- STEP_FOREVER,
-};
-
void intel_step_init(struct drm_i915_private *i915);
const char *intel_step_name(enum intel_step step);
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index 5b698d4d7a7f..170e83a8c9fc 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -399,6 +399,35 @@ static void fw_domains_get_with_thread_status(struct intel_uncore *uncore,
__gen6_gt_wait_for_thread_c0(uncore);
}
+static void
+gen6_check_for_fifo_debug(struct intel_uncore *uncore)
+{
+ u32 fifodbg;
+
+ fifodbg = __raw_uncore_read32(uncore, GTFIFODBG);
+
+ if (unlikely(fifodbg)) {
+ drm_dbg(&uncore->i915->drm, "GTFIFODBG = 0x08%x\n", fifodbg);
+ __raw_uncore_write32(uncore, GTFIFODBG, fifodbg);
+ }
+}
+
+static void
+fw_domains_get_normal_fifo(struct intel_uncore *uncore,
+ enum forcewake_domains fw_domains)
+{
+ gen6_check_for_fifo_debug(uncore);
+ fw_domains_get_normal(uncore, fw_domains);
+}
+
+static void
+fw_domains_get_with_thread_status_fifo(struct intel_uncore *uncore,
+ enum forcewake_domains fw_domains)
+{
+ gen6_check_for_fifo_debug(uncore);
+ fw_domains_get_with_thread_status(uncore, fw_domains);
+}
+
static inline u32 fifo_free_entries(struct intel_uncore *uncore)
{
u32 count = __raw_uncore_read32(uncore, GTFIFOCTL);
@@ -562,21 +591,6 @@ vlv_check_for_unclaimed_mmio(struct intel_uncore *uncore)
}
static bool
-gen6_check_for_fifo_debug(struct intel_uncore *uncore)
-{
- u32 fifodbg;
-
- fifodbg = __raw_uncore_read32(uncore, GTFIFODBG);
-
- if (unlikely(fifodbg)) {
- drm_dbg(&uncore->i915->drm, "GTFIFODBG = 0x08%x\n", fifodbg);
- __raw_uncore_write32(uncore, GTFIFODBG, fifodbg);
- }
-
- return fifodbg;
-}
-
-static bool
check_for_unclaimed_mmio(struct intel_uncore *uncore)
{
bool ret = false;
@@ -592,9 +606,6 @@ check_for_unclaimed_mmio(struct intel_uncore *uncore)
if (intel_uncore_has_dbg_unclaimed(uncore))
ret |= vlv_check_for_unclaimed_mmio(uncore);
- if (intel_uncore_has_fifo(uncore))
- ret |= gen6_check_for_fifo_debug(uncore);
-
return ret;
}
@@ -611,6 +622,9 @@ static void forcewake_early_sanitize(struct intel_uncore *uncore,
GT_FIFO_CTL_RC6_POLICY_STALL);
}
+ if (intel_uncore_has_fifo(uncore))
+ gen6_check_for_fifo_debug(uncore);
+
iosf_mbi_punit_acquire();
intel_uncore_forcewake_reset(uncore);
if (restore_forcewake) {
@@ -2155,6 +2169,14 @@ static const struct intel_uncore_fw_get uncore_get_thread_status = {
.force_wake_get = fw_domains_get_with_thread_status
};
+static const struct intel_uncore_fw_get uncore_get_normal_fifo = {
+ .force_wake_get = fw_domains_get_normal_fifo,
+};
+
+static const struct intel_uncore_fw_get uncore_get_thread_status_fifo = {
+ .force_wake_get = fw_domains_get_with_thread_status_fifo
+};
+
static int intel_uncore_fw_domains_init(struct intel_uncore *uncore)
{
struct drm_i915_private *i915 = uncore->i915;
@@ -2218,13 +2240,19 @@ static int intel_uncore_fw_domains_init(struct intel_uncore *uncore)
fw_domain_init(uncore, FW_DOMAIN_ID_MEDIA,
FORCEWAKE_MEDIA_GEN9, FORCEWAKE_ACK_MEDIA_GEN9);
} else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) {
- uncore->fw_get_funcs = &uncore_get_normal;
+ if (intel_uncore_has_fifo(uncore))
+ uncore->fw_get_funcs = &uncore_get_normal_fifo;
+ else
+ uncore->fw_get_funcs = &uncore_get_normal;
fw_domain_init(uncore, FW_DOMAIN_ID_RENDER,
FORCEWAKE_VLV, FORCEWAKE_ACK_VLV);
fw_domain_init(uncore, FW_DOMAIN_ID_MEDIA,
FORCEWAKE_MEDIA_VLV, FORCEWAKE_ACK_MEDIA_VLV);
} else if (IS_HASWELL(i915) || IS_BROADWELL(i915)) {
- uncore->fw_get_funcs = &uncore_get_thread_status;
+ if (intel_uncore_has_fifo(uncore))
+ uncore->fw_get_funcs = &uncore_get_thread_status_fifo;
+ else
+ uncore->fw_get_funcs = &uncore_get_thread_status;
fw_domain_init(uncore, FW_DOMAIN_ID_RENDER,
FORCEWAKE_MT, FORCEWAKE_ACK_HSW);
} else if (IS_IVYBRIDGE(i915)) {
@@ -2239,7 +2267,7 @@ static int intel_uncore_fw_domains_init(struct intel_uncore *uncore)
* (correctly) interpreted by the test below as MT
* forcewake being disabled.
*/
- uncore->fw_get_funcs = &uncore_get_thread_status;
+ uncore->fw_get_funcs = &uncore_get_thread_status_fifo;
/* We need to init first for ECOBUS access and then
* determine later if we want to reinit, in case of MT access is
@@ -2270,7 +2298,7 @@ static int intel_uncore_fw_domains_init(struct intel_uncore *uncore)
FORCEWAKE, FORCEWAKE_ACK);
}
} else if (GRAPHICS_VER(i915) == 6) {
- uncore->fw_get_funcs = &uncore_get_thread_status;
+ uncore->fw_get_funcs = &uncore_get_thread_status_fifo;
fw_domain_init(uncore, FW_DOMAIN_ID_RENDER,
FORCEWAKE, FORCEWAKE_ACK);
}
diff --git a/drivers/gpu/drm/i915/selftests/intel_uncore.c b/drivers/gpu/drm/i915/selftests/intel_uncore.c
index 507bf42a1aaf..514d2200751b 100644
--- a/drivers/gpu/drm/i915/selftests/intel_uncore.c
+++ b/drivers/gpu/drm/i915/selftests/intel_uncore.c
@@ -272,67 +272,6 @@ out_rpm:
return err;
}
-static int live_forcewake_domains(void *arg)
-{
-#define FW_RANGE 0x40000
- struct intel_gt *gt = arg;
- struct intel_uncore *uncore = gt->uncore;
- struct drm_i915_private *i915 = gt->i915;
- struct intel_display *display = i915->display;
- unsigned long *valid;
- u32 offset;
- int err;
-
- if (!HAS_FPGA_DBG_UNCLAIMED(display) &&
- !IS_VALLEYVIEW(i915) &&
- !IS_CHERRYVIEW(i915))
- return 0;
-
- /*
- * This test may lockup the machine or cause GPU hangs afterwards.
- */
- if (!IS_ENABLED(CONFIG_DRM_I915_SELFTEST_BROKEN))
- return 0;
-
- valid = bitmap_zalloc(FW_RANGE, GFP_KERNEL);
- if (!valid)
- return -ENOMEM;
-
- intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL);
-
- check_for_unclaimed_mmio(uncore);
- for (offset = 0; offset < FW_RANGE; offset += 4) {
- i915_reg_t reg = { offset };
-
- intel_uncore_posting_read_fw(uncore, reg);
- if (!check_for_unclaimed_mmio(uncore))
- set_bit(offset, valid);
- }
-
- intel_uncore_forcewake_put(uncore, FORCEWAKE_ALL);
-
- err = 0;
- for_each_set_bit(offset, valid, FW_RANGE) {
- i915_reg_t reg = { offset };
-
- iosf_mbi_punit_acquire();
- intel_uncore_forcewake_reset(uncore);
- iosf_mbi_punit_release();
-
- check_for_unclaimed_mmio(uncore);
-
- intel_uncore_posting_read_fw(uncore, reg);
- if (check_for_unclaimed_mmio(uncore)) {
- pr_err("Unclaimed mmio read to register 0x%04x\n",
- offset);
- err = -EINVAL;
- }
- }
-
- bitmap_free(valid);
- return err;
-}
-
static int live_fw_table(void *arg)
{
struct intel_gt *gt = arg;
@@ -348,7 +287,6 @@ int intel_uncore_live_selftests(struct drm_i915_private *i915)
static const struct i915_subtest tests[] = {
SUBTEST(live_fw_table),
SUBTEST(live_forcewake_ops),
- SUBTEST(live_forcewake_domains),
};
return intel_gt_live_subtests(tests, to_gt(i915));
diff --git a/drivers/gpu/drm/imagination/Makefile b/drivers/gpu/drm/imagination/Makefile
index f5072f06b4c4..1222a14262e4 100644
--- a/drivers/gpu/drm/imagination/Makefile
+++ b/drivers/gpu/drm/imagination/Makefile
@@ -8,6 +8,7 @@ powervr-y := \
pvr_device.o \
pvr_device_info.o \
pvr_drv.o \
+ pvr_dump.o \
pvr_free_list.o \
pvr_fw.o \
pvr_fw_meta.o \
diff --git a/drivers/gpu/drm/imagination/pvr_ccb.c b/drivers/gpu/drm/imagination/pvr_ccb.c
index f89db5e3baa2..4accf18e2341 100644
--- a/drivers/gpu/drm/imagination/pvr_ccb.c
+++ b/drivers/gpu/drm/imagination/pvr_ccb.c
@@ -4,6 +4,7 @@
#include "pvr_ccb.h"
#include "pvr_device.h"
#include "pvr_drv.h"
+#include "pvr_dump.h"
#include "pvr_free_list.h"
#include "pvr_fw.h"
#include "pvr_gem.h"
@@ -165,6 +166,10 @@ process_fwccb_command(struct pvr_device *pvr_dev, struct rogue_fwif_fwccb_cmd *c
* suppress the "unknown" warning when receiving this command.
*/
break;
+ case ROGUE_FWIF_FWCCB_CMD_CONTEXT_RESET_NOTIFICATION:
+ pvr_dump_context_reset_notification(pvr_dev,
+ &cmd->cmd_data.cmd_context_reset_notification);
+ break;
default:
drm_info(drm_dev, "Received unknown FWCCB command (type=%d)\n",
diff --git a/drivers/gpu/drm/imagination/pvr_device.c b/drivers/gpu/drm/imagination/pvr_device.c
index f58bb66a6327..dbb6f5a8ded1 100644
--- a/drivers/gpu/drm/imagination/pvr_device.c
+++ b/drivers/gpu/drm/imagination/pvr_device.c
@@ -225,29 +225,12 @@ static irqreturn_t pvr_device_irq_thread_handler(int irq, void *data)
}
if (pvr_dev->has_safety_events) {
- int err;
-
- /*
- * Ensure the GPU is powered on since some safety events (such
- * as ECC faults) can happen outside of job submissions, which
- * are otherwise the only time a power reference is held.
- */
- err = pvr_power_get(pvr_dev);
- if (err) {
- drm_err_ratelimited(drm_dev,
- "%s: could not take power reference (%d)\n",
- __func__, err);
- return ret;
- }
-
while (pvr_device_safety_irq_pending(pvr_dev)) {
pvr_device_safety_irq_clear(pvr_dev);
pvr_device_handle_safety_events(pvr_dev);
ret = IRQ_HANDLED;
}
-
- pvr_power_put(pvr_dev);
}
return ret;
diff --git a/drivers/gpu/drm/imagination/pvr_dump.c b/drivers/gpu/drm/imagination/pvr_dump.c
new file mode 100644
index 000000000000..52e95fce2817
--- /dev/null
+++ b/drivers/gpu/drm/imagination/pvr_dump.c
@@ -0,0 +1,113 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+/* Copyright (c) 2026 Imagination Technologies Ltd. */
+
+#include "pvr_device.h"
+#include "pvr_dump.h"
+#include "pvr_rogue_fwif.h"
+
+#include <drm/drm_print.h>
+#include <linux/types.h>
+
+static const char *
+get_reset_reason_desc(enum rogue_context_reset_reason reason)
+{
+ switch (reason) {
+ case ROGUE_CONTEXT_RESET_REASON_NONE:
+ return "None";
+ case ROGUE_CONTEXT_RESET_REASON_GUILTY_LOCKUP:
+ return "Guilty lockup";
+ case ROGUE_CONTEXT_RESET_REASON_INNOCENT_LOCKUP:
+ return "Innocent lockup";
+ case ROGUE_CONTEXT_RESET_REASON_GUILTY_OVERRUNING:
+ return "Guilty overrunning";
+ case ROGUE_CONTEXT_RESET_REASON_INNOCENT_OVERRUNING:
+ return "Innocent overrunning";
+ case ROGUE_CONTEXT_RESET_REASON_HARD_CONTEXT_SWITCH:
+ return "Hard context switch";
+ case ROGUE_CONTEXT_RESET_REASON_WGP_CHECKSUM:
+ return "CDM Mission/safety checksum mismatch";
+ case ROGUE_CONTEXT_RESET_REASON_TRP_CHECKSUM:
+ return "TRP checksum mismatch";
+ case ROGUE_CONTEXT_RESET_REASON_GPU_ECC_OK:
+ return "GPU ECC error (corrected, OK)";
+ case ROGUE_CONTEXT_RESET_REASON_GPU_ECC_HWR:
+ return "GPU ECC error (uncorrected, HWR)";
+ case ROGUE_CONTEXT_RESET_REASON_FW_ECC_OK:
+ return "Firmware ECC error (corrected, OK)";
+ case ROGUE_CONTEXT_RESET_REASON_FW_ECC_ERR:
+ return "Firmware ECC error (uncorrected, ERR)";
+ case ROGUE_CONTEXT_RESET_REASON_FW_WATCHDOG:
+ return "Firmware watchdog";
+ case ROGUE_CONTEXT_RESET_REASON_FW_PAGEFAULT:
+ return "Firmware pagefault";
+ case ROGUE_CONTEXT_RESET_REASON_FW_EXEC_ERR:
+ return "Firmware execution error";
+ case ROGUE_CONTEXT_RESET_REASON_HOST_WDG_FW_ERR:
+ return "Host watchdog";
+ case ROGUE_CONTEXT_GEOM_OOM_DISABLED:
+ return "Geometry OOM disabled";
+
+ default:
+ return "Unknown";
+ }
+}
+
+static const char *
+get_dm_name(u32 dm)
+{
+ switch (dm) {
+ case PVR_FWIF_DM_GP:
+ return "General purpose";
+ /* PVR_FWIF_DM_TDM has the same index, but is discriminated by a device feature */
+ case PVR_FWIF_DM_2D:
+ return "2D or TDM";
+ case PVR_FWIF_DM_GEOM:
+ return "Geometry";
+ case PVR_FWIF_DM_FRAG:
+ return "Fragment";
+ case PVR_FWIF_DM_CDM:
+ return "Compute";
+ case PVR_FWIF_DM_RAY:
+ return "Raytracing";
+ case PVR_FWIF_DM_GEOM2:
+ return "Geometry 2";
+ case PVR_FWIF_DM_GEOM3:
+ return "Geometry 3";
+ case PVR_FWIF_DM_GEOM4:
+ return "Geometry 4";
+
+ default:
+ return "Unknown";
+ }
+}
+
+/**
+ * pvr_dump_context_reset_notification() - Handle context reset notification from FW
+ * @pvr_dev: Device pointer.
+ * @data: Data provided by FW.
+ *
+ * This will decode the data structure provided by FW and print the results via drm_info().
+ */
+void
+pvr_dump_context_reset_notification(struct pvr_device *pvr_dev,
+ struct rogue_fwif_fwccb_cmd_context_reset_data *data)
+{
+ struct drm_device *drm_dev = from_pvr_device(pvr_dev);
+
+ if (data->flags & ROGUE_FWIF_FWCCB_CMD_CONTEXT_RESET_FLAG_ALL_CTXS) {
+ drm_info(drm_dev, "Received context reset notification for all contexts\n");
+ } else {
+ drm_info(drm_dev, "Received context reset notification on context %u\n",
+ data->server_common_context_id);
+ }
+
+ drm_info(drm_dev, " Reset reason=%u (%s)\n", data->reset_reason,
+ get_reset_reason_desc((enum rogue_context_reset_reason)data->reset_reason));
+ drm_info(drm_dev, " Data Master=%u (%s)\n", data->dm, get_dm_name(data->dm));
+ drm_info(drm_dev, " Job ref=%u\n", data->reset_job_ref);
+
+ if (data->flags & ROGUE_FWIF_FWCCB_CMD_CONTEXT_RESET_FLAG_PF) {
+ drm_info(drm_dev, " Page fault occurred, fault address=%llx\n",
+ data->fault_address);
+ }
+}
diff --git a/drivers/gpu/drm/imagination/pvr_dump.h b/drivers/gpu/drm/imagination/pvr_dump.h
new file mode 100644
index 000000000000..3c0728c05596
--- /dev/null
+++ b/drivers/gpu/drm/imagination/pvr_dump.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 OR MIT */
+/* Copyright (c) 2026 Imagination Technologies Ltd. */
+
+#ifndef PVR_DUMP_H
+#define PVR_DUMP_H
+
+/* Forward declaration from pvr_device.h. */
+struct pvr_device;
+
+/* Forward declaration from pvr_rogue_fwif.h. */
+struct rogue_fwif_fwccb_cmd_context_reset_data;
+
+void
+pvr_dump_context_reset_notification(struct pvr_device *pvr_dev,
+ struct rogue_fwif_fwccb_cmd_context_reset_data *data);
+
+#endif /* PVR_DUMP_H */
diff --git a/drivers/gpu/drm/imagination/pvr_fw_startstop.c b/drivers/gpu/drm/imagination/pvr_fw_startstop.c
index dcbb9903e791..e24ed6fc4362 100644
--- a/drivers/gpu/drm/imagination/pvr_fw_startstop.c
+++ b/drivers/gpu/drm/imagination/pvr_fw_startstop.c
@@ -209,18 +209,32 @@ pvr_fw_stop(struct pvr_device *pvr_dev)
ROGUE_CR_SIDEKICK_IDLE_SOCIF_EN |
ROGUE_CR_SIDEKICK_IDLE_HOSTIF_EN);
bool skip_garten_idle = false;
+ u64 layout_mars_value = 0;
+ bool layout_mars = false;
+ bool meta_fw = pvr_dev->fw_dev.processor_type == PVR_FW_PROCESSOR_TYPE_META;
u32 reg_value;
int err;
+ if (PVR_FEATURE_VALUE(pvr_dev, layout_mars, &layout_mars_value) == 0)
+ layout_mars = layout_mars_value > 0;
+
/*
- * Wait for Sidekick/Jones to signal IDLE except for the Garten Wrapper.
- * For cores with the LAYOUT_MARS feature, SIDEKICK would have been
+ * For cores with the LAYOUT_MARS feature, SIDEKICK and SLC would have been
* powered down by the FW.
*/
- err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_SIDEKICK_IDLE, sidekick_idle_mask,
- sidekick_idle_mask, POLL_TIMEOUT_USEC);
- if (err)
- return err;
+ if (!layout_mars) {
+ /* Wait for Sidekick/Jones to signal IDLE except for the Garten Wrapper. */
+ err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_SIDEKICK_IDLE, sidekick_idle_mask,
+ sidekick_idle_mask, POLL_TIMEOUT_USEC);
+ if (err)
+ return err;
+
+ /* Wait for SLC to signal IDLE. */
+ err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_SLC_IDLE, ROGUE_CR_SLC_IDLE_MASKFULL,
+ ROGUE_CR_SLC_IDLE_MASKFULL, POLL_TIMEOUT_USEC);
+ if (err)
+ return err;
+ }
/* Unset MTS DM association with threads. */
pvr_cr_write32(pvr_dev, ROGUE_CR_MTS_INTCTX_THREAD0_DM_ASSOC,
@@ -229,12 +243,15 @@ pvr_fw_stop(struct pvr_device *pvr_dev)
pvr_cr_write32(pvr_dev, ROGUE_CR_MTS_BGCTX_THREAD0_DM_ASSOC,
ROGUE_CR_MTS_BGCTX_THREAD0_DM_ASSOC_MASKFULL &
ROGUE_CR_MTS_BGCTX_THREAD0_DM_ASSOC_DM_ASSOC_CLRMSK);
- pvr_cr_write32(pvr_dev, ROGUE_CR_MTS_INTCTX_THREAD1_DM_ASSOC,
- ROGUE_CR_MTS_INTCTX_THREAD1_DM_ASSOC_MASKFULL &
- ROGUE_CR_MTS_INTCTX_THREAD1_DM_ASSOC_DM_ASSOC_CLRMSK);
- pvr_cr_write32(pvr_dev, ROGUE_CR_MTS_BGCTX_THREAD1_DM_ASSOC,
- ROGUE_CR_MTS_BGCTX_THREAD1_DM_ASSOC_MASKFULL &
- ROGUE_CR_MTS_BGCTX_THREAD1_DM_ASSOC_DM_ASSOC_CLRMSK);
+
+ if (meta_fw) {
+ pvr_cr_write32(pvr_dev, ROGUE_CR_MTS_INTCTX_THREAD1_DM_ASSOC,
+ ROGUE_CR_MTS_INTCTX_THREAD1_DM_ASSOC_MASKFULL &
+ ROGUE_CR_MTS_INTCTX_THREAD1_DM_ASSOC_DM_ASSOC_CLRMSK);
+ pvr_cr_write32(pvr_dev, ROGUE_CR_MTS_BGCTX_THREAD1_DM_ASSOC,
+ ROGUE_CR_MTS_BGCTX_THREAD1_DM_ASSOC_MASKFULL &
+ ROGUE_CR_MTS_BGCTX_THREAD1_DM_ASSOC_DM_ASSOC_CLRMSK);
+ }
/* Extra Idle checks. */
err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_BIF_STATUS_MMU, 0,
@@ -270,27 +287,25 @@ pvr_fw_stop(struct pvr_device *pvr_dev)
return err;
/*
- * Wait for SLC to signal IDLE.
- * For cores with the LAYOUT_MARS feature, SLC would have been powered
- * down by the FW.
+ * For cores with the LAYOUT_MARS feature, SIDEKICK and SLC would have been
+ * powered down by the FW.
*/
- err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_SLC_IDLE,
- ROGUE_CR_SLC_IDLE_MASKFULL,
- ROGUE_CR_SLC_IDLE_MASKFULL, POLL_TIMEOUT_USEC);
- if (err)
- return err;
+ if (!layout_mars) {
+ /* Wait for SLC to signal IDLE. */
+ err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_SLC_IDLE,
+ ROGUE_CR_SLC_IDLE_MASKFULL,
+ ROGUE_CR_SLC_IDLE_MASKFULL, POLL_TIMEOUT_USEC);
+ if (err)
+ return err;
- /*
- * Wait for Sidekick/Jones to signal IDLE except for the Garten Wrapper.
- * For cores with the LAYOUT_MARS feature, SIDEKICK would have been powered
- * down by the FW.
- */
- err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_SIDEKICK_IDLE, sidekick_idle_mask,
- sidekick_idle_mask, POLL_TIMEOUT_USEC);
- if (err)
- return err;
+ /* Wait for Sidekick/Jones to signal IDLE except for the Garten Wrapper. */
+ err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_SIDEKICK_IDLE, sidekick_idle_mask,
+ sidekick_idle_mask, POLL_TIMEOUT_USEC);
+ if (err)
+ return err;
+ }
- if (pvr_dev->fw_dev.processor_type == PVR_FW_PROCESSOR_TYPE_META) {
+ if (meta_fw) {
err = pvr_meta_cr_read32(pvr_dev, META_CR_TxVECINT_BHALT, &reg_value);
if (err)
return err;
@@ -304,11 +319,28 @@ pvr_fw_stop(struct pvr_device *pvr_dev)
skip_garten_idle = true;
}
- if (!skip_garten_idle) {
- err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_SIDEKICK_IDLE,
- ROGUE_CR_SIDEKICK_IDLE_GARTEN_EN,
- ROGUE_CR_SIDEKICK_IDLE_GARTEN_EN,
+ if (meta_fw || !layout_mars) {
+ if (!skip_garten_idle) {
+ err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_SIDEKICK_IDLE,
+ ROGUE_CR_SIDEKICK_IDLE_GARTEN_EN,
+ ROGUE_CR_SIDEKICK_IDLE_GARTEN_EN,
+ POLL_TIMEOUT_USEC);
+ if (err)
+ return err;
+ }
+ } else {
+ /*
+ * As FW core has been moved from SIDEKICK to the new MARS domain, checking
+ * idle bits for CPU & System Arbiter excluding SOCIF which will never be
+ * idle if Host polling on this register
+ */
+ err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_MARS_IDLE,
+ ROGUE_CR_MARS_IDLE_CPU_EN |
+ ROGUE_CR_MARS_IDLE_MH_SYSARB0_EN,
+ ROGUE_CR_MARS_IDLE_CPU_EN |
+ ROGUE_CR_MARS_IDLE_MH_SYSARB0_EN,
POLL_TIMEOUT_USEC);
+
if (err)
return err;
}
diff --git a/drivers/gpu/drm/imagination/pvr_power.c b/drivers/gpu/drm/imagination/pvr_power.c
index 7a8765c0c1ed..88fcce433d12 100644
--- a/drivers/gpu/drm/imagination/pvr_power.c
+++ b/drivers/gpu/drm/imagination/pvr_power.c
@@ -90,11 +90,11 @@ pvr_power_request_pwr_off(struct pvr_device *pvr_dev)
}
static int
-pvr_power_fw_disable(struct pvr_device *pvr_dev, bool hard_reset)
+pvr_power_fw_disable(struct pvr_device *pvr_dev, bool hard_reset, bool rpm_suspend)
{
- if (!hard_reset) {
- int err;
+ int err;
+ if (!hard_reset) {
cancel_delayed_work_sync(&pvr_dev->watchdog.work);
err = pvr_power_request_idle(pvr_dev);
@@ -106,29 +106,47 @@ pvr_power_fw_disable(struct pvr_device *pvr_dev, bool hard_reset)
return err;
}
- return pvr_fw_stop(pvr_dev);
+ if (rpm_suspend) {
+ /* This also waits for late processing of GPU or firmware IRQs in other cores */
+ disable_irq(pvr_dev->irq);
+ }
+
+ err = pvr_fw_stop(pvr_dev);
+ if (err && rpm_suspend)
+ enable_irq(pvr_dev->irq);
+
+ return err;
}
static int
-pvr_power_fw_enable(struct pvr_device *pvr_dev)
+pvr_power_fw_enable(struct pvr_device *pvr_dev, bool rpm_resume)
{
int err;
+ if (rpm_resume)
+ enable_irq(pvr_dev->irq);
+
err = pvr_fw_start(pvr_dev);
if (err)
- return err;
+ goto out;
err = pvr_wait_for_fw_boot(pvr_dev);
if (err) {
drm_err(from_pvr_device(pvr_dev), "Firmware failed to boot\n");
pvr_fw_stop(pvr_dev);
- return err;
+ goto out;
}
queue_delayed_work(pvr_dev->sched_wq, &pvr_dev->watchdog.work,
msecs_to_jiffies(WATCHDOG_TIME_MS));
return 0;
+
+out:
+ if (rpm_resume)
+ disable_irq(pvr_dev->irq);
+
+ return err;
}
bool
@@ -361,7 +379,7 @@ pvr_power_device_suspend(struct device *dev)
return -EIO;
if (pvr_dev->fw_dev.booted) {
- err = pvr_power_fw_disable(pvr_dev, false);
+ err = pvr_power_fw_disable(pvr_dev, false, true);
if (err)
goto err_drm_dev_exit;
}
@@ -391,7 +409,7 @@ pvr_power_device_resume(struct device *dev)
goto err_drm_dev_exit;
if (pvr_dev->fw_dev.booted) {
- err = pvr_power_fw_enable(pvr_dev);
+ err = pvr_power_fw_enable(pvr_dev, true);
if (err)
goto err_power_off;
}
@@ -510,7 +528,16 @@ pvr_power_reset(struct pvr_device *pvr_dev, bool hard_reset)
}
/* Disable IRQs for the duration of the reset. */
- disable_irq(pvr_dev->irq);
+ if (hard_reset) {
+ disable_irq(pvr_dev->irq);
+ } else {
+ /*
+ * Soft reset is triggered as a response to a FW command to the Host and is
+ * processed from the threaded IRQ handler. This code cannot (nor needs to)
+ * wait for any IRQ processing to complete.
+ */
+ disable_irq_nosync(pvr_dev->irq);
+ }
do {
if (hard_reset) {
@@ -518,7 +545,7 @@ pvr_power_reset(struct pvr_device *pvr_dev, bool hard_reset)
queues_disabled = true;
}
- err = pvr_power_fw_disable(pvr_dev, hard_reset);
+ err = pvr_power_fw_disable(pvr_dev, hard_reset, false);
if (!err) {
if (hard_reset) {
pvr_dev->fw_dev.booted = false;
@@ -541,7 +568,7 @@ pvr_power_reset(struct pvr_device *pvr_dev, bool hard_reset)
pvr_fw_irq_clear(pvr_dev);
- err = pvr_power_fw_enable(pvr_dev);
+ err = pvr_power_fw_enable(pvr_dev, false);
}
if (err && hard_reset)
diff --git a/drivers/gpu/drm/imagination/pvr_rogue_fwif.h b/drivers/gpu/drm/imagination/pvr_rogue_fwif.h
index 172886be4c82..5d590c4c2566 100644
--- a/drivers/gpu/drm/imagination/pvr_rogue_fwif.h
+++ b/drivers/gpu/drm/imagination/pvr_rogue_fwif.h
@@ -1347,8 +1347,12 @@ struct rogue_fwif_fwccb_cmd_freelists_reconstruction_data {
struct rogue_fwif_fwccb_cmd_context_reset_data {
/* Context affected by the reset */
u32 server_common_context_id;
- /* Reason for reset */
- enum rogue_context_reset_reason reset_reason;
+ /*
+ * Reason for reset
+ * The valid values for reset_reason are the ones from
+ * enum rogue_context_reset_reason
+ */
+ u32 reset_reason;
/* Data Master affected by the reset */
u32 dm;
/* Job ref running at the time of reset */
diff --git a/drivers/gpu/drm/imagination/pvr_rogue_fwif_shared.h b/drivers/gpu/drm/imagination/pvr_rogue_fwif_shared.h
index 6c09c15bf9bd..869d904e3649 100644
--- a/drivers/gpu/drm/imagination/pvr_rogue_fwif_shared.h
+++ b/drivers/gpu/drm/imagination/pvr_rogue_fwif_shared.h
@@ -236,6 +236,18 @@ enum rogue_context_reset_reason {
ROGUE_CONTEXT_RESET_REASON_INNOCENT_OVERRUNING = 4,
/* Forced reset to ensure scheduling requirements */
ROGUE_CONTEXT_RESET_REASON_HARD_CONTEXT_SWITCH = 5,
+ /* CDM Mission/safety checksum mismatch */
+ ROGUE_CONTEXT_RESET_REASON_WGP_CHECKSUM = 6,
+ /* TRP checksum mismatch */
+ ROGUE_CONTEXT_RESET_REASON_TRP_CHECKSUM = 7,
+ /* GPU ECC error (corrected, OK) */
+ ROGUE_CONTEXT_RESET_REASON_GPU_ECC_OK = 8,
+ /* GPU ECC error (uncorrected, HWR) */
+ ROGUE_CONTEXT_RESET_REASON_GPU_ECC_HWR = 9,
+ /* FW ECC error (corrected, OK) */
+ ROGUE_CONTEXT_RESET_REASON_FW_ECC_OK = 10,
+ /* FW ECC error (uncorrected, ERR) */
+ ROGUE_CONTEXT_RESET_REASON_FW_ECC_ERR = 11,
/* FW Safety watchdog triggered */
ROGUE_CONTEXT_RESET_REASON_FW_WATCHDOG = 12,
/* FW page fault (no HWR) */
@@ -249,7 +261,11 @@ enum rogue_context_reset_reason {
};
struct rogue_context_reset_reason_data {
- enum rogue_context_reset_reason reset_reason;
+ /*
+ * The valid values for reset_reason are the ones from
+ * enum rogue_context_reset_reason
+ */
+ u32 reset_reason;
u32 reset_ext_job_ref;
};
diff --git a/drivers/gpu/drm/imx/ipuv3/Kconfig b/drivers/gpu/drm/imx/ipuv3/Kconfig
index acaf25089001..b2240998df4f 100644
--- a/drivers/gpu/drm/imx/ipuv3/Kconfig
+++ b/drivers/gpu/drm/imx/ipuv3/Kconfig
@@ -15,6 +15,7 @@ config DRM_IMX_PARALLEL_DISPLAY
depends on DRM_IMX
select DRM_BRIDGE
select DRM_BRIDGE_CONNECTOR
+ select DRM_DISPLAY_HELPER
select DRM_IMX_LEGACY_BRIDGE
select DRM_PANEL_BRIDGE
select VIDEOMODE_HELPERS
diff --git a/drivers/gpu/drm/imx/ipuv3/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3/ipuv3-plane.c
index 0ea70b8fd743..c1c7be4e26c6 100644
--- a/drivers/gpu/drm/imx/ipuv3/ipuv3-plane.c
+++ b/drivers/gpu/drm/imx/ipuv3/ipuv3-plane.c
@@ -890,7 +890,7 @@ struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
{
struct ipu_plane *ipu_plane;
const uint64_t *modifiers = ipu_format_modifiers;
- unsigned int zpos = (type == DRM_PLANE_TYPE_PRIMARY) ? 0 : 1;
+ unsigned int primary_zpos = 1;
unsigned int format_count;
const uint32_t *formats;
int ret;
@@ -915,7 +915,7 @@ struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
type, NULL);
if (IS_ERR(ipu_plane)) {
DRM_ERROR("failed to allocate and initialize %s plane\n",
- zpos ? "overlay" : "primary");
+ (type == DRM_PLANE_TYPE_PRIMARY) ? "primary" : "overlay");
return ipu_plane;
}
@@ -923,17 +923,16 @@ struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
ipu_plane->dma = dma;
ipu_plane->dp_flow = dp;
- if (type == DRM_PLANE_TYPE_PRIMARY)
+ if (type == DRM_PLANE_TYPE_PRIMARY) {
drm_plane_helper_add(&ipu_plane->base, &ipu_primary_plane_helper_funcs);
- else
- drm_plane_helper_add(&ipu_plane->base, &ipu_plane_helper_funcs);
-
- if (dp == IPU_DP_FLOW_SYNC_BG || dp == IPU_DP_FLOW_SYNC_FG)
- ret = drm_plane_create_zpos_property(&ipu_plane->base, zpos, 0,
- 1);
- else
ret = drm_plane_create_zpos_immutable_property(&ipu_plane->base,
- 0);
+ primary_zpos);
+ } else {
+ drm_plane_helper_add(&ipu_plane->base, &ipu_plane_helper_funcs);
+ ret = drm_plane_create_zpos_property(&ipu_plane->base,
+ primary_zpos + 1, 0,
+ primary_zpos + 1);
+ }
if (ret)
return ERR_PTR(ret);
@@ -949,7 +948,7 @@ struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
ret = ipu_plane_get_resources(dev, ipu_plane);
if (ret) {
DRM_ERROR("failed to get %s plane resources: %pe\n",
- zpos ? "overlay" : "primary", &ret);
+ (type == DRM_PLANE_TYPE_PRIMARY) ? "primary" : "overlay", &ret);
return ERR_PTR(ret);
}
diff --git a/drivers/gpu/drm/imx/ipuv3/parallel-display.c b/drivers/gpu/drm/imx/ipuv3/parallel-display.c
index 4ce772bc3cb3..a356f0b764cb 100644
--- a/drivers/gpu/drm/imx/ipuv3/parallel-display.c
+++ b/drivers/gpu/drm/imx/ipuv3/parallel-display.c
@@ -110,8 +110,7 @@ imx_pd_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
output_fmt = imxpd->bus_format ? : MEDIA_BUS_FMT_RGB888_1X24;
/* Now make sure the requested output format is supported. */
- if ((imxpd->bus_format && imxpd->bus_format != output_fmt) ||
- !imx_pd_format_supported(output_fmt)) {
+ if (!imx_pd_format_supported(output_fmt)) {
*num_input_fmts = 0;
return NULL;
}
@@ -121,7 +120,17 @@ imx_pd_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
if (!input_fmts)
return NULL;
- input_fmts[0] = output_fmt;
+ /*
+ * Prefer bus format set via legacy "interface-pix-fmt" DT property
+ * over panel bus format. This is necessary to retain support for
+ * DTs which configure the IPUv3 parallel output as 24bit, but
+ * connect 18bit DPI panels to it with hardware swizzling.
+ */
+ if (imxpd->bus_format && imxpd->bus_format != output_fmt)
+ input_fmts[0] = imxpd->bus_format;
+ else
+ input_fmts[0] = output_fmt;
+
return input_fmts;
}
diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
index 9522a2e6ecd4..4068114adf8c 100644
--- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
+++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
@@ -1401,7 +1401,7 @@ static int ingenic_drm_bind(struct device *dev, bool has_components)
goto err_devclk_disable;
}
- drm_atomic_private_obj_init(drm, &priv->private_obj, NULL,
+ drm_atomic_private_obj_init(drm, &priv->private_obj,
&ingenic_drm_private_state_funcs);
ret = drmm_add_action_or_reset(drm, ingenic_drm_atomic_private_obj_fini,
diff --git a/drivers/gpu/drm/ingenic/ingenic-ipu.c b/drivers/gpu/drm/ingenic/ingenic-ipu.c
index 4fec37c63e7c..34545b9c8c33 100644
--- a/drivers/gpu/drm/ingenic/ingenic-ipu.c
+++ b/drivers/gpu/drm/ingenic/ingenic-ipu.c
@@ -901,7 +901,7 @@ static int ingenic_ipu_bind(struct device *dev, struct device *master, void *d)
return err;
}
- drm_atomic_private_obj_init(drm, &ipu->private_obj, NULL,
+ drm_atomic_private_obj_init(drm, &ipu->private_obj,
&ingenic_ipu_private_state_funcs);
return 0;
diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile
index e0ac49b07d50..952d294642fb 100644
--- a/drivers/gpu/drm/mediatek/Makefile
+++ b/drivers/gpu/drm/mediatek/Makefile
@@ -14,7 +14,6 @@ mediatek-drm-y := mtk_crtc.o \
mtk_dsi.o \
mtk_dpi.o \
mtk_ethdr.o \
- mtk_gem.o \
mtk_mdp_rdma.o \
mtk_padding.o \
mtk_plane.o
diff --git a/drivers/gpu/drm/mediatek/mtk_crtc.c b/drivers/gpu/drm/mediatek/mtk_crtc.c
index 351d58c50b84..fcb16f3f7b23 100644
--- a/drivers/gpu/drm/mediatek/mtk_crtc.c
+++ b/drivers/gpu/drm/mediatek/mtk_crtc.c
@@ -23,7 +23,6 @@
#include "mtk_crtc.h"
#include "mtk_ddp_comp.h"
#include "mtk_drm_drv.h"
-#include "mtk_gem.h"
#include "mtk_plane.h"
/*
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
index e0236353d499..97a899e4bd99 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
@@ -671,6 +671,16 @@ static const struct mtk_disp_ovl_data mt2701_ovl_driver_data = {
.num_formats = ARRAY_SIZE(mt8173_formats),
};
+static const struct mtk_disp_ovl_data mt8167_ovl_driver_data = {
+ .addr = DISP_REG_OVL_ADDR_MT8173,
+ .gmc_bits = 8,
+ .layer_nr = 4,
+ .fmt_rgb565_is_0 = true,
+ .smi_id_en = true,
+ .formats = mt8173_formats,
+ .num_formats = ARRAY_SIZE(mt8173_formats),
+};
+
static const struct mtk_disp_ovl_data mt8173_ovl_driver_data = {
.addr = DISP_REG_OVL_ADDR_MT8173,
.gmc_bits = 8,
@@ -742,6 +752,8 @@ static const struct mtk_disp_ovl_data mt8195_ovl_driver_data = {
static const struct of_device_id mtk_disp_ovl_driver_dt_match[] = {
{ .compatible = "mediatek,mt2701-disp-ovl",
.data = &mt2701_ovl_driver_data},
+ { .compatible = "mediatek,mt8167-disp-ovl",
+ .data = &mt8167_ovl_driver_data},
{ .compatible = "mediatek,mt8173-disp-ovl",
.data = &mt8173_ovl_driver_data},
{ .compatible = "mediatek,mt8183-disp-ovl",
diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c
index 08c4d64b87b9..c52cc7c2e200 100644
--- a/drivers/gpu/drm/mediatek/mtk_dp.c
+++ b/drivers/gpu/drm/mediatek/mtk_dp.c
@@ -2454,7 +2454,7 @@ mtk_dp_bridge_mode_valid(struct drm_bridge *bridge,
const struct drm_display_mode *mode)
{
struct mtk_dp *mtk_dp = mtk_dp_from_bridge(bridge);
- u32 bpp = info->color_formats & DRM_COLOR_FORMAT_YCBCR422 ? 16 : 24;
+ u32 bpp = info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422) ? 16 : 24;
u32 lane_count_min = mtk_dp->train_info.lane_count;
u32 rate = drm_dp_bw_code_to_link_rate(mtk_dp->train_info.link_rate) *
lane_count_min;
@@ -2521,7 +2521,7 @@ static u32 *mtk_dp_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
*/
if (((rate * 97 / 100) < (mode->clock * 24 / 8)) &&
((rate * 97 / 100) > (mode->clock * 16 / 8)) &&
- (display_info->color_formats & DRM_COLOR_FORMAT_YCBCR422)) {
+ (display_info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422))) {
input_fmts = kcalloc(1, sizeof(*input_fmts), GFP_KERNEL);
if (!input_fmts)
return NULL;
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index a94c51a83261..c86a3f54f35b 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -4,6 +4,7 @@
* Author: YT SHEN <yt.shen@mediatek.com>
*/
+#include <linux/aperture.h>
#include <linux/component.h>
#include <linux/module.h>
#include <linux/of.h>
@@ -19,6 +20,7 @@
#include <drm/drm_fbdev_dma.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>
@@ -29,7 +31,6 @@
#include "mtk_ddp_comp.h"
#include "mtk_disp_drv.h"
#include "mtk_drm_drv.h"
-#include "mtk_gem.h"
#define DRIVER_NAME "mediatek"
#define DRIVER_DESC "Mediatek SoC DRM"
@@ -565,8 +566,7 @@ static int mtk_drm_kms_init(struct drm_device *drm)
goto err_component_unbind;
}
- for (i = 0; i < private->data->mmsys_dev_num; i++)
- private->all_drm_private[i]->dma_dev = dma_dev;
+ drm_dev_set_dma_dev(drm, dma_dev);
/*
* Configure the DMA segment size to make sure we get contiguous IOVA
@@ -600,26 +600,12 @@ static void mtk_drm_kms_deinit(struct drm_device *drm)
DEFINE_DRM_GEM_FOPS(mtk_drm_fops);
-/*
- * We need to override this because the device used to import the memory is
- * not dev->dev, as drm_gem_prime_import() expects.
- */
-static struct drm_gem_object *mtk_gem_prime_import(struct drm_device *dev,
- struct dma_buf *dma_buf)
-{
- struct mtk_drm_private *private = dev->dev_private;
-
- return drm_gem_prime_import_dev(dev, dma_buf, private->dma_dev);
-}
-
static const struct drm_driver mtk_drm_driver = {
.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
- .dumb_create = mtk_gem_dumb_create,
+ DRM_GEM_DMA_DRIVER_OPS,
DRM_FBDEV_DMA_DRIVER_OPS,
- .gem_prime_import = mtk_gem_prime_import,
- .gem_prime_import_sg_table = mtk_gem_prime_import_sg_table,
.fops = &mtk_drm_fops,
.name = DRIVER_NAME,
@@ -670,6 +656,10 @@ static int mtk_drm_bind(struct device *dev)
if (ret < 0)
goto err_free;
+ ret = aperture_remove_all_conflicting_devices(DRIVER_NAME);
+ if (ret < 0)
+ dev_err(dev, "Error %d while removing conflicting aperture devices", ret);
+
ret = drm_dev_register(drm, 0);
if (ret < 0)
goto err_deinit;
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
index 675cdc90a440..1fc3df4b5485 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
@@ -54,7 +54,6 @@ struct mtk_mmsys_driver_data {
struct mtk_drm_private {
struct drm_device *drm;
- struct device *dma_dev;
bool mtk_drm_bound;
bool drm_master;
struct device *dev;
diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
index 17c67f02016b..5aa71fcdcfab 100644
--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
@@ -673,6 +673,21 @@ static s32 mtk_dsi_switch_to_cmd_mode(struct mtk_dsi *dsi, u8 irq_flag, u32 t)
}
}
+static void mtk_dsi_lane_ready(struct mtk_dsi *dsi)
+{
+ if (!dsi->lanes_ready) {
+ dsi->lanes_ready = true;
+ mtk_dsi_rxtx_control(dsi);
+ usleep_range(30, 100);
+ mtk_dsi_reset_dphy(dsi);
+ mtk_dsi_clk_ulp_mode_leave(dsi);
+ mtk_dsi_lane0_ulp_mode_leave(dsi);
+ mtk_dsi_clk_hs_mode(dsi, 0);
+ usleep_range(1000, 3000);
+ /* The reaction time after pulling up the mipi signal for dsi_rx */
+ }
+}
+
static int mtk_dsi_poweron(struct mtk_dsi *dsi)
{
struct device *dev = dsi->host.dev;
@@ -725,6 +740,8 @@ static int mtk_dsi_poweron(struct mtk_dsi *dsi)
mtk_dsi_set_vm_cmd(dsi);
mtk_dsi_config_vdo_timing(dsi);
mtk_dsi_set_interrupt_enable(dsi);
+ mtk_dsi_lane_ready(dsi);
+ mtk_dsi_clk_hs_mode(dsi, 1);
return 0;
err_disable_engine_clk:
@@ -770,30 +787,12 @@ static void mtk_dsi_poweroff(struct mtk_dsi *dsi)
dsi->lanes_ready = false;
}
-static void mtk_dsi_lane_ready(struct mtk_dsi *dsi)
-{
- if (!dsi->lanes_ready) {
- dsi->lanes_ready = true;
- mtk_dsi_rxtx_control(dsi);
- usleep_range(30, 100);
- mtk_dsi_reset_dphy(dsi);
- mtk_dsi_clk_ulp_mode_leave(dsi);
- mtk_dsi_lane0_ulp_mode_leave(dsi);
- mtk_dsi_clk_hs_mode(dsi, 0);
- usleep_range(1000, 3000);
- /* The reaction time after pulling up the mipi signal for dsi_rx */
- }
-}
-
static void mtk_output_dsi_enable(struct mtk_dsi *dsi)
{
if (dsi->enabled)
return;
- mtk_dsi_lane_ready(dsi);
mtk_dsi_set_mode(dsi);
- mtk_dsi_clk_hs_mode(dsi, 1);
-
mtk_dsi_start(dsi);
dsi->enabled = true;
@@ -1236,6 +1235,11 @@ static int mtk_dsi_probe(struct platform_device *pdev)
dsi->host.ops = &mtk_dsi_ops;
dsi->host.dev = dev;
+
+ init_waitqueue_head(&dsi->irq_wait_queue);
+
+ platform_set_drvdata(pdev, dsi);
+
ret = mipi_dsi_host_register(&dsi->host);
if (ret < 0)
return dev_err_probe(dev, ret, "Failed to register DSI host\n");
@@ -1247,10 +1251,6 @@ static int mtk_dsi_probe(struct platform_device *pdev)
return dev_err_probe(&pdev->dev, ret, "Failed to request DSI irq\n");
}
- init_waitqueue_head(&dsi->irq_wait_queue);
-
- platform_set_drvdata(pdev, dsi);
-
dsi->bridge.of_node = dev->of_node;
dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
diff --git a/drivers/gpu/drm/mediatek/mtk_gem.c b/drivers/gpu/drm/mediatek/mtk_gem.c
deleted file mode 100644
index f059a1452220..000000000000
--- a/drivers/gpu/drm/mediatek/mtk_gem.c
+++ /dev/null
@@ -1,231 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (c) 2015 MediaTek Inc.
- * Copyright (c) 2025 Collabora Ltd.
- * AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
- */
-
-#include <linux/dma-buf.h>
-#include <linux/vmalloc.h>
-
-#include <drm/drm.h>
-#include <drm/drm_device.h>
-#include <drm/drm_gem.h>
-#include <drm/drm_gem_dma_helper.h>
-#include <drm/drm_prime.h>
-#include <drm/drm_print.h>
-
-#include "mtk_drm_drv.h"
-#include "mtk_gem.h"
-
-static int mtk_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma);
-
-static void mtk_gem_free_object(struct drm_gem_object *obj)
-{
- struct drm_gem_dma_object *dma_obj = to_drm_gem_dma_obj(obj);
- struct mtk_drm_private *priv = obj->dev->dev_private;
-
- if (dma_obj->sgt)
- drm_prime_gem_destroy(obj, dma_obj->sgt);
- else
- dma_free_wc(priv->dma_dev, dma_obj->base.size,
- dma_obj->vaddr, dma_obj->dma_addr);
-
- /* release file pointer to gem object. */
- drm_gem_object_release(obj);
-
- kfree(dma_obj);
-}
-
-/*
- * Allocate a sg_table for this GEM object.
- * Note: Both the table's contents, and the sg_table itself must be freed by
- * the caller.
- * Returns a pointer to the newly allocated sg_table, or an ERR_PTR() error.
- */
-static struct sg_table *mtk_gem_prime_get_sg_table(struct drm_gem_object *obj)
-{
- struct drm_gem_dma_object *dma_obj = to_drm_gem_dma_obj(obj);
- struct mtk_drm_private *priv = obj->dev->dev_private;
- struct sg_table *sgt;
- int ret;
-
- sgt = kzalloc_obj(*sgt);
- if (!sgt)
- return ERR_PTR(-ENOMEM);
-
- ret = dma_get_sgtable(priv->dma_dev, sgt, dma_obj->vaddr,
- dma_obj->dma_addr, obj->size);
- if (ret) {
- DRM_ERROR("failed to allocate sgt, %d\n", ret);
- kfree(sgt);
- return ERR_PTR(ret);
- }
-
- return sgt;
-}
-
-static const struct drm_gem_object_funcs mtk_gem_object_funcs = {
- .free = mtk_gem_free_object,
- .print_info = drm_gem_dma_object_print_info,
- .get_sg_table = mtk_gem_prime_get_sg_table,
- .vmap = drm_gem_dma_object_vmap,
- .mmap = mtk_gem_object_mmap,
- .vm_ops = &drm_gem_dma_vm_ops,
-};
-
-static struct drm_gem_dma_object *mtk_gem_init(struct drm_device *dev,
- unsigned long size, bool private)
-{
- struct drm_gem_dma_object *dma_obj;
- int ret;
-
- size = round_up(size, PAGE_SIZE);
-
- if (size == 0)
- return ERR_PTR(-EINVAL);
-
- dma_obj = kzalloc_obj(*dma_obj);
- if (!dma_obj)
- return ERR_PTR(-ENOMEM);
-
- dma_obj->base.funcs = &mtk_gem_object_funcs;
-
- if (private) {
- ret = 0;
- drm_gem_private_object_init(dev, &dma_obj->base, size);
- } else {
- ret = drm_gem_object_init(dev, &dma_obj->base, size);
- }
- if (ret) {
- DRM_ERROR("failed to initialize gem object\n");
- kfree(dma_obj);
- return ERR_PTR(ret);
- }
-
- return dma_obj;
-}
-
-static struct drm_gem_dma_object *mtk_gem_create(struct drm_device *dev, size_t size)
-{
- struct mtk_drm_private *priv = dev->dev_private;
- struct drm_gem_dma_object *dma_obj;
- struct drm_gem_object *obj;
- int ret;
-
- dma_obj = mtk_gem_init(dev, size, false);
- if (IS_ERR(dma_obj))
- return ERR_CAST(dma_obj);
-
- obj = &dma_obj->base;
-
- dma_obj->vaddr = dma_alloc_wc(priv->dma_dev, obj->size,
- &dma_obj->dma_addr,
- GFP_KERNEL | __GFP_NOWARN);
- if (!dma_obj->vaddr) {
- DRM_ERROR("failed to allocate %zx byte dma buffer", obj->size);
- ret = -ENOMEM;
- goto err_gem_free;
- }
-
- DRM_DEBUG_DRIVER("vaddr = %p dma_addr = %pad size = %zu\n",
- dma_obj->vaddr, &dma_obj->dma_addr,
- size);
-
- return dma_obj;
-
-err_gem_free:
- drm_gem_object_release(obj);
- kfree(dma_obj);
- return ERR_PTR(ret);
-}
-
-int mtk_gem_dumb_create(struct drm_file *file_priv, struct drm_device *dev,
- struct drm_mode_create_dumb *args)
-{
- struct drm_gem_dma_object *dma_obj;
- int ret;
-
- args->pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
-
- /*
- * Multiply 2 variables of different types,
- * for example: args->size = args->spacing * args->height;
- * may cause coverity issue with unintentional overflow.
- */
- args->size = args->pitch;
- args->size *= args->height;
-
- dma_obj = mtk_gem_create(dev, args->size);
- if (IS_ERR(dma_obj))
- return PTR_ERR(dma_obj);
-
- /*
- * allocate a id of idr table where the obj is registered
- * and handle has the id what user can see.
- */
- ret = drm_gem_handle_create(file_priv, &dma_obj->base, &args->handle);
- if (ret)
- goto err_handle_create;
-
- /* drop reference from allocate - handle holds it now. */
- drm_gem_object_put(&dma_obj->base);
-
- return 0;
-
-err_handle_create:
- mtk_gem_free_object(&dma_obj->base);
- return ret;
-}
-
-static int mtk_gem_object_mmap(struct drm_gem_object *obj,
- struct vm_area_struct *vma)
-
-{
- struct drm_gem_dma_object *dma_obj = to_drm_gem_dma_obj(obj);
- struct mtk_drm_private *priv = obj->dev->dev_private;
- int ret;
-
- /*
- * Set vm_pgoff (used as a fake buffer offset by DRM) to 0 and map the
- * whole buffer from the start.
- */
- vma->vm_pgoff -= drm_vma_node_start(&obj->vma_node);
-
- /*
- * dma_alloc_attrs() allocated a struct page table for mtk_gem, so clear
- * VM_PFNMAP flag that was set by drm_gem_mmap_obj()/drm_gem_mmap().
- */
- vm_flags_mod(vma, VM_IO | VM_DONTEXPAND | VM_DONTDUMP, VM_PFNMAP);
-
- vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
- vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot);
-
- ret = dma_mmap_wc(priv->dma_dev, vma, dma_obj->vaddr,
- dma_obj->dma_addr, obj->size);
- if (ret)
- drm_gem_vm_close(vma);
-
- return ret;
-}
-
-struct drm_gem_object *mtk_gem_prime_import_sg_table(struct drm_device *dev,
- struct dma_buf_attachment *attach, struct sg_table *sgt)
-{
- struct drm_gem_dma_object *dma_obj;
-
- /* check if the entries in the sg_table are contiguous */
- if (drm_prime_get_contiguous_size(sgt) < attach->dmabuf->size) {
- DRM_ERROR("sg_table is not contiguous");
- return ERR_PTR(-EINVAL);
- }
-
- dma_obj = mtk_gem_init(dev, attach->dmabuf->size, true);
- if (IS_ERR(dma_obj))
- return ERR_CAST(dma_obj);
-
- dma_obj->dma_addr = sg_dma_address(sgt->sgl);
- dma_obj->sgt = sgt;
-
- return &dma_obj->base;
-}
diff --git a/drivers/gpu/drm/mediatek/mtk_gem.h b/drivers/gpu/drm/mediatek/mtk_gem.h
deleted file mode 100644
index afebc3a970a8..000000000000
--- a/drivers/gpu/drm/mediatek/mtk_gem.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (c) 2015 MediaTek Inc.
- */
-
-#ifndef _MTK_GEM_H_
-#define _MTK_GEM_H_
-
-#include <drm/drm_gem.h>
-#include <drm/drm_gem_dma_helper.h>
-
-int mtk_gem_dumb_create(struct drm_file *file_priv, struct drm_device *dev,
- struct drm_mode_create_dumb *args);
-struct drm_gem_object *mtk_gem_prime_import_sg_table(struct drm_device *dev,
- struct dma_buf_attachment *attach, struct sg_table *sg);
-
-#endif
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi_v2.c b/drivers/gpu/drm/mediatek/mtk_hdmi_v2.c
index 279ca896b0a2..b5c738380dc2 100644
--- a/drivers/gpu/drm/mediatek/mtk_hdmi_v2.c
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi_v2.c
@@ -747,12 +747,12 @@ static void mtk_hdmi_v2_change_video_resolution(struct mtk_hdmi *hdmi,
switch (conn_state->hdmi.output_format) {
default:
- case HDMI_COLORSPACE_RGB:
- case HDMI_COLORSPACE_YUV444:
+ case DRM_OUTPUT_COLOR_FORMAT_RGB444:
+ case DRM_OUTPUT_COLOR_FORMAT_YCBCR444:
/* Disable YUV420 downsampling for RGB and YUV444 */
mtk_hdmi_yuv420_downsampling(hdmi, false);
break;
- case HDMI_COLORSPACE_YUV422:
+ case DRM_OUTPUT_COLOR_FORMAT_YCBCR422:
/*
* YUV420 downsampling is special and needs a bit of setup
* so we disable everything there before doing anything else.
@@ -763,7 +763,7 @@ static void mtk_hdmi_v2_change_video_resolution(struct mtk_hdmi *hdmi,
regmap_set_bits(hdmi->regs, VID_DOWNSAMPLE_CONFIG,
C444_C422_CONFIG_ENABLE);
break;
- case HDMI_COLORSPACE_YUV420:
+ case DRM_OUTPUT_COLOR_FORMAT_YCBCR420:
mtk_hdmi_yuv420_downsampling(hdmi, true);
break;
}
diff --git a/drivers/gpu/drm/meson/meson_dw_mipi_dsi.c b/drivers/gpu/drm/meson/meson_dw_mipi_dsi.c
index 66c73c512b0e..4412bd678108 100644
--- a/drivers/gpu/drm/meson/meson_dw_mipi_dsi.c
+++ b/drivers/gpu/drm/meson/meson_dw_mipi_dsi.c
@@ -119,8 +119,7 @@ static int dw_mipi_dsi_phy_init(void *priv_data)
dpi_data_format = DPI_COLOR_18BIT_CFG_2;
venc_data_width = VENC_IN_COLOR_18B;
break;
- case MIPI_DSI_FMT_RGB666_PACKED:
- case MIPI_DSI_FMT_RGB565:
+ default:
return -EINVAL;
}
@@ -232,8 +231,7 @@ static int meson_dw_mipi_dsi_host_attach(void *priv_data,
break;
case MIPI_DSI_FMT_RGB666:
break;
- case MIPI_DSI_FMT_RGB666_PACKED:
- case MIPI_DSI_FMT_RGB565:
+ default:
dev_err(mipi_dsi->dev, "invalid pixel format %d\n", device->format);
return -EINVAL;
}
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 8b94c5f1cb68..ba45e99be05b 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -25,6 +25,7 @@ adreno-y := \
adreno/a6xx_hfi.o \
adreno/a6xx_preempt.o \
adreno/a8xx_gpu.o \
+ adreno/a8xx_preempt.o \
adreno-$(CONFIG_DEBUG_FS) += adreno/a5xx_debugfs.o \
diff --git a/drivers/gpu/drm/msm/adreno/a2xx_gpummu.c b/drivers/gpu/drm/msm/adreno/a2xx_gpummu.c
index d77b4774d414..e2225c5ba647 100644
--- a/drivers/gpu/drm/msm/adreno/a2xx_gpummu.c
+++ b/drivers/gpu/drm/msm/adreno/a2xx_gpummu.c
@@ -78,7 +78,7 @@ static void a2xx_gpummu_destroy(struct msm_mmu *mmu)
{
struct a2xx_gpummu *gpummu = to_a2xx_gpummu(mmu);
- dma_free_attrs(mmu->dev, TABLE_SIZE, gpummu->table, gpummu->pt_base,
+ dma_free_attrs(mmu->dev, TABLE_SIZE + 32, gpummu->table, gpummu->pt_base,
DMA_ATTR_FORCE_CONTIGUOUS);
kfree(gpummu);
diff --git a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c
index 8464d89e37f3..e6ab731f8e9a 100644
--- a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c
@@ -604,11 +604,9 @@ static int a4xx_pm_suspend(struct msm_gpu *gpu) {
return 0;
}
-static int a4xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value)
+static u64 a4xx_get_timestamp(struct msm_gpu *gpu)
{
- *value = gpu_read64(gpu, REG_A4XX_RBBM_PERFCTR_CP_0_LO);
-
- return 0;
+ return gpu_read64(gpu, REG_A4XX_RBBM_PERFCTR_CP_0_LO);
}
static u64 a4xx_gpu_busy(struct msm_gpu *gpu, unsigned long *out_sample_rate)
diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
index ef9fd6171af7..79acae11154a 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
@@ -1435,11 +1435,9 @@ static int a5xx_pm_suspend(struct msm_gpu *gpu)
return 0;
}
-static int a5xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value)
+static u64 a5xx_get_timestamp(struct msm_gpu *gpu)
{
- *value = gpu_read64(gpu, REG_A5XX_RBBM_ALWAYSON_COUNTER_LO);
-
- return 0;
+ return gpu_read64(gpu, REG_A5XX_RBBM_ALWAYSON_COUNTER_LO);
}
struct a5xx_crashdumper {
@@ -1732,6 +1730,7 @@ static struct msm_gpu *a5xx_gpu_init(struct drm_device *dev)
struct adreno_gpu *adreno_gpu;
struct msm_gpu *gpu;
unsigned int nr_rings;
+ u32 speedbin;
int ret;
a5xx_gpu = kzalloc_obj(*a5xx_gpu);
@@ -1758,6 +1757,11 @@ static struct msm_gpu *a5xx_gpu_init(struct drm_device *dev)
return ERR_PTR(ret);
}
+ /* Set the speedbin value that is passed to userspace */
+ if (adreno_read_speedbin(&pdev->dev, &speedbin) || !speedbin)
+ speedbin = 0xffff;
+ adreno_gpu->speedbin = (uint16_t) (0xffff & speedbin);
+
msm_mmu_set_fault_handler(to_msm_vm(gpu->vm)->mmu, gpu,
a5xx_fault_handler);
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_catalog.c b/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
index 550a53a7865e..550ff3a9b82e 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
@@ -1759,7 +1759,45 @@ static const u32 x285_protect_regs[] = {
A6XX_PROTECT_NORDWR(0x27c06, 0x0000),
};
-DECLARE_ADRENO_PROTECT(x285_protect, 64);
+DECLARE_ADRENO_PROTECT(x285_protect, 15);
+
+static const struct adreno_reglist_pipe x285_dyn_pwrup_reglist_regs[] = {
+ { REG_A8XX_GRAS_TSEFE_DBG_ECO_CNTL, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_GRAS_NC_MODE_CNTL, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_GRAS_DBG_ECO_CNTL, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A6XX_PC_AUTO_VERTEX_STRIDE, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_PC_CHICKEN_BITS_1, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_PC_CHICKEN_BITS_2, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_PC_CHICKEN_BITS_3, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_PC_CHICKEN_BITS_4, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_PC_CONTEXT_SWITCH_STABILIZE_CNTL_1, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_PC_VIS_STREAM_CNTL, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A7XX_RB_CCU_CNTL, 0, BIT(PIPE_BR) },
+ { REG_A7XX_RB_CCU_DBG_ECO_CNTL, 0, BIT(PIPE_BR)},
+ { REG_A8XX_RB_CCU_NC_MODE_CNTL, 0, BIT(PIPE_BR) },
+ { REG_A8XX_RB_CMP_NC_MODE_CNTL, 0, BIT(PIPE_BR) },
+ { REG_A6XX_RB_RBP_CNTL, 0, BIT(PIPE_BR) },
+ { REG_A8XX_RB_RESOLVE_PREFETCH_CNTL, 0, BIT(PIPE_BR) },
+ { REG_A8XX_RB_CMP_DBG_ECO_CNTL, 0, BIT(PIPE_BR) },
+ { REG_A7XX_VFD_DBG_ECO_CNTL, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_VFD_CB_BV_THRESHOLD, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_VFD_CB_BR_THRESHOLD, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_VFD_CB_BUSY_REQ_CNT, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_VFD_CB_LP_REQ_CNT, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_VPC_FLATSHADE_MODE_CNTL, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_CP_HW_FAULT_STATUS_MASK_PIPE, 0, BIT(PIPE_BR) |
+ BIT(PIPE_BV) | BIT(PIPE_LPAC) | BIT(PIPE_AQE0) |
+ BIT(PIPE_AQE1) | BIT(PIPE_DDE_BR) | BIT(PIPE_DDE_BV) },
+ { REG_A8XX_CP_INTERRUPT_STATUS_MASK_PIPE, 0, BIT(PIPE_BR) |
+ BIT(PIPE_BV) | BIT(PIPE_LPAC) | BIT(PIPE_AQE0) |
+ BIT(PIPE_AQE1) | BIT(PIPE_DDE_BR) | BIT(PIPE_DDE_BV) },
+ { REG_A8XX_CP_PROTECT_CNTL_PIPE, 0, BIT(PIPE_BR) | BIT(PIPE_BV) | BIT(PIPE_LPAC)},
+ { REG_A8XX_CP_PROTECT_PIPE(15), 0, BIT(PIPE_BR) | BIT(PIPE_BV) | BIT(PIPE_LPAC) },
+ { REG_A8XX_RB_GC_GMEM_PROTECT, 0, BIT(PIPE_BR) },
+ { REG_A8XX_RB_LPAC_GMEM_PROTECT, 0, BIT(PIPE_BR) },
+ { REG_A6XX_RB_CONTEXT_SWITCH_GMEM_SAVE_RESTORE_ENABLE, 0, BIT(PIPE_BR) },
+};
+DECLARE_ADRENO_REGLIST_PIPE_LIST(x285_dyn_pwrup_reglist);
static const struct adreno_reglist_pipe a840_nonctxt_regs[] = {
{ REG_A8XX_CP_SMMU_STREAM_ID_LPAC, 0x00000101, BIT(PIPE_NONE) },
@@ -1891,6 +1929,185 @@ static const struct adreno_reglist a840_gbif[] = {
{ },
};
+static const uint32_t a840_pwrup_reglist_regs[] = {
+ REG_A7XX_SP_HLSQ_TIMEOUT_THRESHOLD_DP,
+ REG_A7XX_SP_READ_SEL,
+ REG_A6XX_UCHE_MODE_CNTL,
+ REG_A8XX_UCHE_VARB_IDLE_TIMEOUT,
+ REG_A8XX_UCHE_GBIF_GX_CONFIG,
+ REG_A8XX_UCHE_CCHE_MODE_CNTL,
+ REG_A8XX_UCHE_CCHE_CACHE_WAYS,
+ REG_A8XX_UCHE_CACHE_WAYS,
+ REG_A8XX_UCHE_CCHE_GC_GMEM_RANGE_MIN,
+ REG_A8XX_UCHE_CCHE_GC_GMEM_RANGE_MIN + 1,
+ REG_A8XX_UCHE_CCHE_LPAC_GMEM_RANGE_MIN,
+ REG_A8XX_UCHE_CCHE_LPAC_GMEM_RANGE_MIN + 1,
+ REG_A8XX_UCHE_CCHE_TRAP_BASE,
+ REG_A8XX_UCHE_CCHE_TRAP_BASE + 1,
+ REG_A8XX_UCHE_CCHE_WRITE_THRU_BASE,
+ REG_A8XX_UCHE_CCHE_WRITE_THRU_BASE + 1,
+ REG_A8XX_UCHE_HW_DBG_CNTL,
+ REG_A8XX_UCHE_WRITE_THRU_BASE,
+ REG_A8XX_UCHE_WRITE_THRU_BASE + 1,
+ REG_A8XX_UCHE_TRAP_BASE,
+ REG_A8XX_UCHE_TRAP_BASE + 1,
+ REG_A8XX_UCHE_CLIENT_PF,
+ REG_A8XX_RB_CMP_NC_MODE_CNTL,
+ REG_A8XX_SP_HLSQ_GC_GMEM_RANGE_MIN,
+ REG_A8XX_SP_HLSQ_GC_GMEM_RANGE_MIN + 1,
+ REG_A6XX_TPL1_NC_MODE_CNTL,
+ REG_A6XX_TPL1_DBG_ECO_CNTL,
+ REG_A6XX_TPL1_DBG_ECO_CNTL1,
+ REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(0),
+ REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(1),
+ REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(2),
+ REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(3),
+ REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(4),
+ REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(5),
+ REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(6),
+ REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(7),
+ REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(8),
+ REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(9),
+ REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(10),
+ REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(11),
+ REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(12),
+ REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(13),
+ REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(14),
+ REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(15),
+ REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(16),
+ REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(17),
+ REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(18),
+ REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(19),
+};
+DECLARE_ADRENO_REGLIST_LIST(a840_pwrup_reglist);
+
+static const u32 a840_ifpc_reglist_regs[] = {
+ REG_A8XX_RBBM_NC_MODE_CNTL,
+ REG_A8XX_RBBM_SLICE_NC_MODE_CNTL,
+ REG_A6XX_SP_NC_MODE_CNTL,
+ REG_A6XX_SP_CHICKEN_BITS,
+ REG_A8XX_SP_SS_CHICKEN_BITS_0,
+ REG_A7XX_SP_CHICKEN_BITS_1,
+ REG_A7XX_SP_CHICKEN_BITS_2,
+ REG_A7XX_SP_CHICKEN_BITS_3,
+ REG_A8XX_SP_CHICKEN_BITS_4,
+ REG_A6XX_SP_PERFCTR_SHADER_MASK,
+ REG_A8XX_RBBM_SLICE_PERFCTR_CNTL,
+ REG_A8XX_RBBM_SLICE_INTERFACE_HANG_INT_CNTL,
+ REG_A7XX_SP_HLSQ_DBG_ECO_CNTL,
+ REG_A7XX_SP_HLSQ_DBG_ECO_CNTL_1,
+ REG_A7XX_SP_HLSQ_DBG_ECO_CNTL_2,
+ REG_A8XX_SP_HLSQ_DBG_ECO_CNTL_3,
+ REG_A8XX_SP_HLSQ_LPAC_GMEM_RANGE_MIN,
+ REG_A8XX_SP_HLSQ_LPAC_GMEM_RANGE_MIN + 1,
+ REG_A8XX_CP_INTERRUPT_STATUS_MASK_GLOBAL,
+ REG_A8XX_RBBM_PERFCTR_CNTL,
+ REG_A8XX_CP_PROTECT_GLOBAL(0),
+ REG_A8XX_CP_PROTECT_GLOBAL(1),
+ REG_A8XX_CP_PROTECT_GLOBAL(2),
+ REG_A8XX_CP_PROTECT_GLOBAL(3),
+ REG_A8XX_CP_PROTECT_GLOBAL(4),
+ REG_A8XX_CP_PROTECT_GLOBAL(5),
+ REG_A8XX_CP_PROTECT_GLOBAL(6),
+ REG_A8XX_CP_PROTECT_GLOBAL(7),
+ REG_A8XX_CP_PROTECT_GLOBAL(8),
+ REG_A8XX_CP_PROTECT_GLOBAL(9),
+ REG_A8XX_CP_PROTECT_GLOBAL(10),
+ REG_A8XX_CP_PROTECT_GLOBAL(11),
+ REG_A8XX_CP_PROTECT_GLOBAL(12),
+ REG_A8XX_CP_PROTECT_GLOBAL(13),
+ REG_A8XX_CP_PROTECT_GLOBAL(14),
+ REG_A8XX_CP_PROTECT_GLOBAL(15),
+ REG_A8XX_CP_PROTECT_GLOBAL(16),
+ REG_A8XX_CP_PROTECT_GLOBAL(17),
+ REG_A8XX_CP_PROTECT_GLOBAL(18),
+ REG_A8XX_CP_PROTECT_GLOBAL(19),
+ REG_A8XX_CP_PROTECT_GLOBAL(20),
+ REG_A8XX_CP_PROTECT_GLOBAL(21),
+ REG_A8XX_CP_PROTECT_GLOBAL(22),
+ REG_A8XX_CP_PROTECT_GLOBAL(23),
+ REG_A8XX_CP_PROTECT_GLOBAL(24),
+ REG_A8XX_CP_PROTECT_GLOBAL(25),
+ REG_A8XX_CP_PROTECT_GLOBAL(26),
+ REG_A8XX_CP_PROTECT_GLOBAL(27),
+ REG_A8XX_CP_PROTECT_GLOBAL(28),
+ REG_A8XX_CP_PROTECT_GLOBAL(29),
+ REG_A8XX_CP_PROTECT_GLOBAL(30),
+ REG_A8XX_CP_PROTECT_GLOBAL(31),
+ REG_A8XX_CP_PROTECT_GLOBAL(32),
+ REG_A8XX_CP_PROTECT_GLOBAL(33),
+ REG_A8XX_CP_PROTECT_GLOBAL(34),
+ REG_A8XX_CP_PROTECT_GLOBAL(35),
+ REG_A8XX_CP_PROTECT_GLOBAL(36),
+ REG_A8XX_CP_PROTECT_GLOBAL(37),
+ REG_A8XX_CP_PROTECT_GLOBAL(38),
+ REG_A8XX_CP_PROTECT_GLOBAL(39),
+ REG_A8XX_CP_PROTECT_GLOBAL(40),
+ REG_A8XX_CP_PROTECT_GLOBAL(41),
+ REG_A8XX_CP_PROTECT_GLOBAL(42),
+ REG_A8XX_CP_PROTECT_GLOBAL(43),
+ REG_A8XX_CP_PROTECT_GLOBAL(44),
+ REG_A8XX_CP_PROTECT_GLOBAL(45),
+ REG_A8XX_CP_PROTECT_GLOBAL(46),
+ REG_A8XX_CP_PROTECT_GLOBAL(47),
+ REG_A8XX_CP_PROTECT_GLOBAL(48),
+ REG_A8XX_CP_PROTECT_GLOBAL(49),
+ REG_A8XX_CP_PROTECT_GLOBAL(50),
+ REG_A8XX_CP_PROTECT_GLOBAL(51),
+ REG_A8XX_CP_PROTECT_GLOBAL(52),
+ REG_A8XX_CP_PROTECT_GLOBAL(53),
+ REG_A8XX_CP_PROTECT_GLOBAL(54),
+ REG_A8XX_CP_PROTECT_GLOBAL(55),
+ REG_A8XX_CP_PROTECT_GLOBAL(56),
+ REG_A8XX_CP_PROTECT_GLOBAL(57),
+ REG_A8XX_CP_PROTECT_GLOBAL(58),
+ REG_A8XX_CP_PROTECT_GLOBAL(59),
+ REG_A8XX_CP_PROTECT_GLOBAL(60),
+ REG_A8XX_CP_PROTECT_GLOBAL(61),
+ REG_A8XX_CP_PROTECT_GLOBAL(62),
+ REG_A8XX_CP_PROTECT_GLOBAL(63),
+};
+DECLARE_ADRENO_REGLIST_LIST(a840_ifpc_reglist);
+
+static const struct adreno_reglist_pipe a840_dyn_pwrup_reglist_regs[] = {
+ { REG_A8XX_GRAS_TSEFE_DBG_ECO_CNTL, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_GRAS_NC_MODE_CNTL, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_GRAS_DBG_ECO_CNTL, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A6XX_PC_AUTO_VERTEX_STRIDE, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_PC_CHICKEN_BITS_1, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_PC_CHICKEN_BITS_2, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_PC_CHICKEN_BITS_3, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_PC_CHICKEN_BITS_4, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_PC_CONTEXT_SWITCH_STABILIZE_CNTL_1, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_PC_VIS_STREAM_CNTL, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A7XX_RB_CCU_CNTL, 0, BIT(PIPE_BR) },
+ { REG_A7XX_RB_CCU_DBG_ECO_CNTL, 0, BIT(PIPE_BR)},
+ { REG_A8XX_RB_CCU_NC_MODE_CNTL, 0, BIT(PIPE_BR) },
+ { REG_A8XX_RB_CMP_NC_MODE_CNTL, 0, BIT(PIPE_BR) },
+ { REG_A6XX_RB_RBP_CNTL, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_RB_RESOLVE_PREFETCH_CNTL, 0, BIT(PIPE_BR) },
+ { REG_A6XX_RB_DBG_ECO_CNTL, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_RB_CMP_DBG_ECO_CNTL, 0, BIT(PIPE_BR) },
+ { REG_A7XX_VFD_DBG_ECO_CNTL, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_VFD_CB_BV_THRESHOLD, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_VFD_CB_BR_THRESHOLD, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_VFD_CB_BUSY_REQ_CNT, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_VFD_CB_LP_REQ_CNT, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_VPC_FLATSHADE_MODE_CNTL, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_CP_HW_FAULT_STATUS_MASK_PIPE, 0, BIT(PIPE_BR) |
+ BIT(PIPE_BV) | BIT(PIPE_LPAC) | BIT(PIPE_AQE0) |
+ BIT(PIPE_AQE1) | BIT(PIPE_DDE_BR) | BIT(PIPE_DDE_BV) },
+ { REG_A8XX_CP_INTERRUPT_STATUS_MASK_PIPE, 0, BIT(PIPE_BR) |
+ BIT(PIPE_BV) | BIT(PIPE_LPAC) | BIT(PIPE_AQE0) |
+ BIT(PIPE_AQE1) | BIT(PIPE_DDE_BR) | BIT(PIPE_DDE_BV) },
+ { REG_A8XX_CP_PROTECT_CNTL_PIPE, 0, BIT(PIPE_BR) | BIT(PIPE_BV) | BIT(PIPE_LPAC)},
+ { REG_A8XX_CP_PROTECT_PIPE(15), 0, BIT(PIPE_BR) | BIT(PIPE_BV) | BIT(PIPE_LPAC) },
+ { REG_A8XX_RB_GC_GMEM_PROTECT, 0, BIT(PIPE_BR) },
+ { REG_A8XX_RB_LPAC_GMEM_PROTECT, 0, BIT(PIPE_BR) },
+ { REG_A6XX_RB_CONTEXT_SWITCH_GMEM_SAVE_RESTORE_ENABLE, 0, BIT(PIPE_BR) },
+};
+DECLARE_ADRENO_REGLIST_PIPE_LIST(a840_dyn_pwrup_reglist);
+
static const struct adreno_info a8xx_gpus[] = {
{
.chip_ids = ADRENO_CHIP_IDS(0x44070001),
@@ -1902,11 +2119,16 @@ static const struct adreno_info a8xx_gpus[] = {
.gmem = 21 * SZ_1M,
.inactive_period = DRM_MSM_INACTIVE_PERIOD,
.quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT |
- ADRENO_QUIRK_HAS_HW_APRIV,
+ ADRENO_QUIRK_HAS_HW_APRIV |
+ ADRENO_QUIRK_PREEMPTION |
+ ADRENO_QUIRK_SOFTFUSE,
.funcs = &a8xx_gpu_funcs,
.a6xx = &(const struct a6xx_info) {
.protect = &x285_protect,
.nonctxt_reglist = x285_nonctxt_regs,
+ .pwrup_reglist = &a840_pwrup_reglist,
+ .dyn_pwrup_reglist = &x285_dyn_pwrup_reglist,
+ .ifpc_reglist = &a840_ifpc_reglist,
.gbif_cx = a840_gbif,
.max_slices = 4,
.gmu_chipid = 0x8010100,
@@ -1922,6 +2144,12 @@ static const struct adreno_info a8xx_gpus[] = {
{ /* sentinel */ },
},
},
+ .speedbins = ADRENO_SPEEDBINS(
+ { 0, 0 },
+ { 388, 1 },
+ { 357, 2 },
+ { 284, 3 },
+ ),
}, {
.chip_ids = ADRENO_CHIP_IDS(0x44050a01),
.family = ADRENO_8XX_GEN2,
@@ -1933,11 +2161,16 @@ static const struct adreno_info a8xx_gpus[] = {
.gmem = 18 * SZ_1M,
.inactive_period = DRM_MSM_INACTIVE_PERIOD,
.quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT |
- ADRENO_QUIRK_HAS_HW_APRIV,
+ ADRENO_QUIRK_HAS_HW_APRIV |
+ ADRENO_QUIRK_PREEMPTION |
+ ADRENO_QUIRK_IFPC,
.funcs = &a8xx_gpu_funcs,
.a6xx = &(const struct a6xx_info) {
.protect = &a840_protect,
.nonctxt_reglist = a840_nonctxt_regs,
+ .pwrup_reglist = &a840_pwrup_reglist,
+ .dyn_pwrup_reglist = &a840_dyn_pwrup_reglist,
+ .ifpc_reglist = &a840_ifpc_reglist,
.gbif_cx = a840_gbif,
.max_slices = 3,
.gmu_chipid = 0x8020100,
@@ -1954,6 +2187,12 @@ static const struct adreno_info a8xx_gpus[] = {
},
},
.preempt_record_size = 19708 * SZ_1K,
+ .speedbins = ADRENO_SPEEDBINS(
+ { 0, 0 },
+ { 273, 1 },
+ { 252, 2 },
+ { 221, 3 },
+ ),
}
};
@@ -1966,5 +2205,4 @@ static inline __always_unused void __build_asserts(void)
BUILD_BUG_ON(a660_protect.count > a660_protect.count_max);
BUILD_BUG_ON(a690_protect.count > a690_protect.count_max);
BUILD_BUG_ON(a730_protect.count > a730_protect.count_max);
- BUILD_BUG_ON(a840_protect.count > a840_protect.count_max);
}
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index 9662201cd2e9..1b44b9e21ad8 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -3,6 +3,7 @@
#include <linux/bitfield.h>
#include <linux/clk.h>
+#include <linux/firmware/qcom/qcom_scm.h>
#include <linux/interconnect.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
@@ -91,10 +92,10 @@ bool a6xx_gmu_sptprac_is_on(struct a6xx_gmu *gmu)
}
/* Check to see if the GX rail is still powered */
-bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu)
+bool a6xx_gmu_gx_is_on(struct adreno_gpu *adreno_gpu)
{
- struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu);
- struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
+ struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
+ struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
u32 val;
/* This can be called from gpu state code so make sure GMU is valid */
@@ -117,6 +118,40 @@ bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu)
A6XX_GMU_SPTPRAC_PWR_CLK_STATUS_GX_HM_CLK_OFF));
}
+bool a7xx_gmu_gx_is_on(struct adreno_gpu *adreno_gpu)
+{
+ struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
+ struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
+ u32 val;
+
+ /* This can be called from gpu state code so make sure GMU is valid */
+ if (!gmu->initialized)
+ return false;
+
+ val = gmu_read(gmu, REG_A6XX_GMU_SPTPRAC_PWR_CLK_STATUS);
+
+ return !(val &
+ (A7XX_GMU_SPTPRAC_PWR_CLK_STATUS_GX_HM_GDSC_POWER_OFF |
+ A7XX_GMU_SPTPRAC_PWR_CLK_STATUS_GX_HM_CLK_OFF));
+}
+
+bool a8xx_gmu_gx_is_on(struct adreno_gpu *adreno_gpu)
+{
+ struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
+ struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
+ u32 val;
+
+ /* This can be called from gpu state code so make sure GMU is valid */
+ if (!gmu->initialized)
+ return false;
+
+ val = gmu_read(gmu, REG_A8XX_GMU_PWR_CLK_STATUS);
+
+ return !(val &
+ (A8XX_GMU_PWR_CLK_STATUS_GX_HM_GDSC_POWER_OFF |
+ A8XX_GMU_PWR_CLK_STATUS_GX_HM_CLK_OFF));
+}
+
void a6xx_gmu_set_freq(struct msm_gpu *gpu, struct dev_pm_opp *opp,
bool suspended)
{
@@ -240,7 +275,7 @@ static bool a6xx_gmu_check_idle_level(struct a6xx_gmu *gmu)
if (val == local) {
if (gmu->idle_level != GMU_IDLE_STATE_IFPC ||
- !a6xx_gmu_gx_is_on(gmu))
+ !adreno_gpu->funcs->gx_is_on(adreno_gpu))
return true;
}
@@ -1157,6 +1192,65 @@ static void a6xx_gmu_set_initial_bw(struct msm_gpu *gpu, struct a6xx_gmu *gmu)
dev_pm_opp_put(gpu_opp);
}
+static int a6xx_gmu_secure_init(struct a6xx_gpu *a6xx_gpu)
+{
+ struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
+ struct msm_gpu *gpu = &adreno_gpu->base;
+ struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
+ u32 fuse_val;
+ int ret;
+
+ if (test_bit(GMU_STATUS_SECURE_INIT, &gmu->status))
+ return 0;
+
+ if (adreno_is_a750(adreno_gpu) || adreno_is_a8xx(adreno_gpu)) {
+ /*
+ * Assume that if qcom scm isn't available, that whatever
+ * replacement allows writing the fuse register ourselves.
+ * Users of alternative firmware need to make sure this
+ * register is writeable or indicate that it's not somehow.
+ * Print a warning because if you mess this up you're about to
+ * crash horribly.
+ */
+ if (!qcom_scm_is_available()) {
+ dev_warn_once(gpu->dev->dev,
+ "SCM is not available, poking fuse register\n");
+ a6xx_llc_write(a6xx_gpu, REG_A7XX_CX_MISC_SW_FUSE_VALUE,
+ A7XX_CX_MISC_SW_FUSE_VALUE_RAYTRACING |
+ A7XX_CX_MISC_SW_FUSE_VALUE_FASTBLEND |
+ A7XX_CX_MISC_SW_FUSE_VALUE_LPAC);
+ adreno_gpu->has_ray_tracing = true;
+ goto done;
+ }
+
+ ret = qcom_scm_gpu_init_regs(QCOM_SCM_GPU_ALWAYS_EN_REQ |
+ QCOM_SCM_GPU_TSENSE_EN_REQ);
+ if (ret) {
+ dev_warn_once(gpu->dev->dev,
+ "SCM call failed\n");
+ return ret;
+ }
+
+ /*
+ * On A7XX_GEN3 and newer, raytracing may be disabled by the
+ * firmware, find out whether that's the case. The scm call
+ * above sets the fuse register.
+ */
+ fuse_val = a6xx_llc_read(a6xx_gpu,
+ REG_A7XX_CX_MISC_SW_FUSE_VALUE);
+ adreno_gpu->has_ray_tracing =
+ !!(fuse_val & A7XX_CX_MISC_SW_FUSE_VALUE_RAYTRACING);
+ } else if (adreno_is_a740(adreno_gpu)) {
+ /* Raytracing is always enabled on a740 */
+ adreno_gpu->has_ray_tracing = true;
+ }
+
+done:
+ set_bit(GMU_STATUS_SECURE_INIT, &gmu->status);
+ return 0;
+}
+
+
int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu)
{
struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
@@ -1185,11 +1279,12 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu)
clk_set_rate(gmu->hub_clk, adreno_is_a740_family(adreno_gpu) ?
200000000 : 150000000);
ret = clk_bulk_prepare_enable(gmu->nr_clocks, gmu->clocks);
- if (ret) {
- pm_runtime_put(gmu->gxpd);
- pm_runtime_put(gmu->dev);
- return ret;
- }
+ if (ret)
+ goto rpm_put;
+
+ ret = a6xx_gmu_secure_init(a6xx_gpu);
+ if (ret)
+ goto disable_clk;
/* Read the slice info on A8x GPUs */
a8xx_gpu_get_slice_info(gpu);
@@ -1219,11 +1314,11 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu)
ret = a6xx_gmu_fw_start(gmu, status);
if (ret)
- goto out;
+ goto disable_irq;
ret = a6xx_hfi_start(gmu, status);
if (ret)
- goto out;
+ goto disable_irq;
/*
* Turn on the GMU firmware fault interrupt after we know the boot
@@ -1236,19 +1331,16 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu)
/* Set the GPU to the current freq */
a6xx_gmu_set_initial_freq(gpu, gmu);
- if (refcount_read(&gpu->sysprof_active) > 1) {
- ret = a6xx_gmu_set_oob(gmu, GMU_OOB_PERFCOUNTER_SET);
- if (!ret)
- set_bit(GMU_STATUS_OOB_PERF_SET, &gmu->status);
- }
-out:
- /* On failure, shut down the GMU to leave it in a good state */
- if (ret) {
- disable_irq(gmu->gmu_irq);
- a6xx_rpmh_stop(gmu);
- pm_runtime_put(gmu->gxpd);
- pm_runtime_put(gmu->dev);
- }
+ return 0;
+
+disable_irq:
+ disable_irq(gmu->gmu_irq);
+ a6xx_rpmh_stop(gmu);
+disable_clk:
+ clk_bulk_disable_unprepare(gmu->nr_clocks, gmu->clocks);
+rpm_put:
+ pm_runtime_put(gmu->gxpd);
+ pm_runtime_put(gmu->dev);
return ret;
}
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
index 2af074c8e8cf..3f96b10b5f61 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
@@ -10,6 +10,7 @@
#include <linux/notifier.h>
#include <linux/soc/qcom/qcom_aoss.h>
#include "msm_drv.h"
+#include "adreno_gpu.h"
#include "a6xx_hfi.h"
struct a6xx_gmu_bo {
@@ -110,7 +111,7 @@ struct a6xx_gmu {
unsigned long freq;
- struct a6xx_hfi_queue queues[2];
+ struct a6xx_hfi_queue queues[HFI_MAX_QUEUES];
bool initialized;
bool hung;
@@ -129,6 +130,8 @@ struct a6xx_gmu {
#define GMU_STATUS_PDC_SLEEP 1
/* To track Perfcounter OOB set status */
#define GMU_STATUS_OOB_PERF_SET 2
+/* To track whether secure world init was done */
+#define GMU_STATUS_SECURE_INIT 3
unsigned long status;
};
@@ -231,7 +234,9 @@ void a6xx_hfi_stop(struct a6xx_gmu *gmu);
int a6xx_hfi_send_prep_slumber(struct a6xx_gmu *gmu);
int a6xx_hfi_set_freq(struct a6xx_gmu *gmu, u32 perf_index, u32 bw_index);
-bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu);
+bool a6xx_gmu_gx_is_on(struct adreno_gpu *adreno_gpu);
+bool a7xx_gmu_gx_is_on(struct adreno_gpu *adreno_gpu);
+bool a8xx_gmu_gx_is_on(struct adreno_gpu *adreno_gpu);
bool a6xx_gmu_sptprac_is_on(struct a6xx_gmu *gmu);
void a6xx_sptprac_disable(struct a6xx_gmu *gmu);
int a6xx_sptprac_enable(struct a6xx_gmu *gmu);
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index d6dfe6337bc3..d5aba072f44c 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -10,14 +10,15 @@
#include <linux/bitfield.h>
#include <linux/devfreq.h>
-#include <linux/firmware/qcom/qcom_scm.h>
#include <linux/pm_domain.h>
#include <linux/soc/qcom/llcc-qcom.h>
#define GPU_PAS_ID 13
-static u64 read_gmu_ao_counter(struct a6xx_gpu *a6xx_gpu)
+static u64 a6xx_gmu_get_timestamp(struct msm_gpu *gpu)
{
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
u64 count_hi, count_lo, temp;
do {
@@ -345,7 +346,7 @@ static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
* GPU registers so we need to add 0x1a800 to the register value on A630
* to get the right value from PM4.
*/
- get_stats_counter(ring, REG_A6XX_CP_ALWAYS_ON_COUNTER,
+ get_stats_counter(ring, REG_A6XX_CP_ALWAYS_ON_CONTEXT,
rbmemptr_stats(ring, index, alwayson_start));
/* Invalidate CCU depth and color */
@@ -386,7 +387,7 @@ static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
get_stats_counter(ring, REG_A6XX_RBBM_PERFCTR_CP(0),
rbmemptr_stats(ring, index, cpcycles_end));
- get_stats_counter(ring, REG_A6XX_CP_ALWAYS_ON_COUNTER,
+ get_stats_counter(ring, REG_A6XX_CP_ALWAYS_ON_CONTEXT,
rbmemptr_stats(ring, index, alwayson_end));
/* Write the fence to the scratch register */
@@ -404,12 +405,12 @@ static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
OUT_RING(ring, upper_32_bits(rbmemptr(ring, fence)));
OUT_RING(ring, submit->seqno);
- trace_msm_gpu_submit_flush(submit, read_gmu_ao_counter(a6xx_gpu));
+ trace_msm_gpu_submit_flush(submit, adreno_gpu->funcs->get_timestamp(gpu));
a6xx_flush(gpu, ring);
}
-static void a6xx_emit_set_pseudo_reg(struct msm_ringbuffer *ring,
+void a6xx_emit_set_pseudo_reg(struct msm_ringbuffer *ring,
struct a6xx_gpu *a6xx_gpu, struct msm_gpu_submitqueue *queue)
{
u64 preempt_postamble;
@@ -455,7 +456,7 @@ static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
struct msm_ringbuffer *ring = submit->ring;
- u32 rbbm_perfctr_cp0, cp_always_on_counter;
+ u32 rbbm_perfctr_cp0, cp_always_on_context;
unsigned int i, ibs = 0;
adreno_check_and_reenable_stall(adreno_gpu);
@@ -478,14 +479,14 @@ static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
if (adreno_is_a8xx(adreno_gpu)) {
rbbm_perfctr_cp0 = REG_A8XX_RBBM_PERFCTR_CP(0);
- cp_always_on_counter = REG_A8XX_CP_ALWAYS_ON_COUNTER;
+ cp_always_on_context = REG_A8XX_CP_ALWAYS_ON_CONTEXT;
} else {
rbbm_perfctr_cp0 = REG_A7XX_RBBM_PERFCTR_CP(0);
- cp_always_on_counter = REG_A6XX_CP_ALWAYS_ON_COUNTER;
+ cp_always_on_context = REG_A6XX_CP_ALWAYS_ON_CONTEXT;
}
get_stats_counter(ring, rbbm_perfctr_cp0, rbmemptr_stats(ring, index, cpcycles_start));
- get_stats_counter(ring, cp_always_on_counter, rbmemptr_stats(ring, index, alwayson_start));
+ get_stats_counter(ring, cp_always_on_context, rbmemptr_stats(ring, index, alwayson_start));
OUT_PKT7(ring, CP_THREAD_CONTROL, 1);
OUT_RING(ring, CP_SET_THREAD_BOTH);
@@ -533,7 +534,7 @@ static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
}
get_stats_counter(ring, rbbm_perfctr_cp0, rbmemptr_stats(ring, index, cpcycles_end));
- get_stats_counter(ring, cp_always_on_counter, rbmemptr_stats(ring, index, alwayson_end));
+ get_stats_counter(ring, cp_always_on_context, rbmemptr_stats(ring, index, alwayson_end));
/* Write the fence to the scratch register */
if (adreno_is_a8xx(adreno_gpu)) {
@@ -614,12 +615,15 @@ static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
}
- trace_msm_gpu_submit_flush(submit, read_gmu_ao_counter(a6xx_gpu));
+ trace_msm_gpu_submit_flush(submit, adreno_gpu->funcs->get_timestamp(gpu));
a6xx_flush(gpu, ring);
/* Check to see if we need to start preemption */
- a6xx_preempt_trigger(gpu);
+ if (adreno_is_a8xx(adreno_gpu))
+ a8xx_preempt_trigger(gpu);
+ else
+ a6xx_preempt_trigger(gpu);
}
static void a6xx_set_hwcg(struct msm_gpu *gpu, bool state)
@@ -1603,6 +1607,12 @@ out:
a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_BOOT_SLUMBER);
}
+ if (!ret && (refcount_read(&gpu->sysprof_active) > 1)) {
+ ret = a6xx_gmu_set_oob(gmu, GMU_OOB_PERFCOUNTER_SET);
+ if (!ret)
+ set_bit(GMU_STATUS_OOB_PERF_SET, &gmu->status);
+ }
+
return ret;
}
@@ -1635,7 +1645,7 @@ static void a6xx_recover(struct msm_gpu *gpu)
adreno_dump_info(gpu);
- if (a6xx_gmu_gx_is_on(&a6xx_gpu->gmu)) {
+ if (adreno_gpu->funcs->gx_is_on(adreno_gpu)) {
/* Sometimes crashstate capture is skipped, so SQE should be halted here again */
gpu_write(gpu, REG_A6XX_CP_SQE_CNTL, 3);
@@ -2152,56 +2162,6 @@ static void a6xx_llc_slices_init(struct platform_device *pdev,
a6xx_gpu->llc_mmio = ERR_PTR(-EINVAL);
}
-static int a7xx_cx_mem_init(struct a6xx_gpu *a6xx_gpu)
-{
- struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
- struct msm_gpu *gpu = &adreno_gpu->base;
- u32 fuse_val;
- int ret;
-
- if (adreno_is_a750(adreno_gpu) || adreno_is_a8xx(adreno_gpu)) {
- /*
- * Assume that if qcom scm isn't available, that whatever
- * replacement allows writing the fuse register ourselves.
- * Users of alternative firmware need to make sure this
- * register is writeable or indicate that it's not somehow.
- * Print a warning because if you mess this up you're about to
- * crash horribly.
- */
- if (!qcom_scm_is_available()) {
- dev_warn_once(gpu->dev->dev,
- "SCM is not available, poking fuse register\n");
- a6xx_llc_write(a6xx_gpu, REG_A7XX_CX_MISC_SW_FUSE_VALUE,
- A7XX_CX_MISC_SW_FUSE_VALUE_RAYTRACING |
- A7XX_CX_MISC_SW_FUSE_VALUE_FASTBLEND |
- A7XX_CX_MISC_SW_FUSE_VALUE_LPAC);
- adreno_gpu->has_ray_tracing = true;
- return 0;
- }
-
- ret = qcom_scm_gpu_init_regs(QCOM_SCM_GPU_ALWAYS_EN_REQ |
- QCOM_SCM_GPU_TSENSE_EN_REQ);
- if (ret)
- return ret;
-
- /*
- * On A7XX_GEN3 and newer, raytracing may be disabled by the
- * firmware, find out whether that's the case. The scm call
- * above sets the fuse register.
- */
- fuse_val = a6xx_llc_read(a6xx_gpu,
- REG_A7XX_CX_MISC_SW_FUSE_VALUE);
- adreno_gpu->has_ray_tracing =
- !!(fuse_val & A7XX_CX_MISC_SW_FUSE_VALUE_RAYTRACING);
- } else if (adreno_is_a740(adreno_gpu)) {
- /* Raytracing is always enabled on a740 */
- adreno_gpu->has_ray_tracing = true;
- }
-
- return 0;
-}
-
-
#define GBIF_CLIENT_HALT_MASK BIT(0)
#define GBIF_ARB_HALT_MASK BIT(1)
#define VBIF_XIN_HALT_CTRL0_MASK GENMASK(3, 0)
@@ -2414,20 +2374,9 @@ static int a6xx_pm_suspend(struct msm_gpu *gpu)
return 0;
}
-static int a6xx_gmu_get_timestamp(struct msm_gpu *gpu, uint64_t *value)
-{
- struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
- struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
-
- *value = read_gmu_ao_counter(a6xx_gpu);
-
- return 0;
-}
-
-static int a6xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value)
+static u64 a6xx_get_timestamp(struct msm_gpu *gpu)
{
- *value = gpu_read64(gpu, REG_A6XX_CP_ALWAYS_ON_COUNTER);
- return 0;
+ return gpu_read64(gpu, REG_A6XX_CP_ALWAYS_ON_COUNTER);
}
static struct msm_ringbuffer *a6xx_active_ring(struct msm_gpu *gpu)
@@ -2600,13 +2549,33 @@ static u32 fuse_to_supp_hw(const struct adreno_info *info, u32 fuse)
return UINT_MAX;
}
-static int a6xx_set_supported_hw(struct device *dev, const struct adreno_info *info)
+static int a6xx_read_speedbin(struct device *dev, struct a6xx_gpu *a6xx_gpu,
+ const struct adreno_info *info, u32 *speedbin)
+{
+ int ret;
+
+ /* Use speedbin fuse if present. Otherwise, fallback to softfuse */
+ ret = adreno_read_speedbin(dev, speedbin);
+ if (ret != -ENOENT)
+ return ret;
+
+ if (info->quirks & ADRENO_QUIRK_SOFTFUSE) {
+ *speedbin = a6xx_llc_read(a6xx_gpu, REG_A8XX_CX_MISC_SW_FUSE_FREQ_LIMIT_STATUS);
+ *speedbin = A8XX_CX_MISC_SW_FUSE_FREQ_LIMIT_STATUS_FINALFREQLIMIT(*speedbin);
+ return 0;
+ }
+
+ return -ENOENT;
+}
+
+static int a6xx_set_supported_hw(struct device *dev, struct a6xx_gpu *a6xx_gpu,
+ const struct adreno_info *info)
{
u32 supp_hw;
u32 speedbin;
int ret;
- ret = adreno_read_speedbin(dev, &speedbin);
+ ret = a6xx_read_speedbin(dev, a6xx_gpu, info, &speedbin);
/*
* -ENOENT means that the platform doesn't support speedbin which is
* fine
@@ -2635,16 +2604,29 @@ static int a6xx_set_supported_hw(struct device *dev, const struct adreno_info *i
return 0;
}
+static bool a6xx_aqe_is_enabled(struct adreno_gpu *adreno_gpu)
+{
+ struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
+
+ /*
+ * AQE uses preemption context record as scratch pad, so check if
+ * preemption is enabled
+ */
+ return (adreno_gpu->base.nr_rings > 1) && !!a6xx_gpu->aqe_bo;
+}
+
static struct msm_gpu *a6xx_gpu_init(struct drm_device *dev)
{
struct msm_drm_private *priv = dev->dev_private;
struct platform_device *pdev = priv->gpu_pdev;
struct adreno_platform_config *config = pdev->dev.platform_data;
+ const struct adreno_info *info = config->info;
struct device_node *node;
struct a6xx_gpu *a6xx_gpu;
struct adreno_gpu *adreno_gpu;
struct msm_gpu *gpu;
extern int enable_preemption;
+ u32 speedbin;
bool is_a7xx;
int ret, nr_rings = 1;
@@ -2656,6 +2638,7 @@ static struct msm_gpu *a6xx_gpu_init(struct drm_device *dev)
gpu = &adreno_gpu->base;
mutex_init(&a6xx_gpu->gmu.lock);
+ spin_lock_init(&a6xx_gpu->aperture_lock);
adreno_gpu->registers = NULL;
@@ -2667,14 +2650,14 @@ static struct msm_gpu *a6xx_gpu_init(struct drm_device *dev)
adreno_gpu->gmu_is_wrapper = of_device_is_compatible(node, "qcom,adreno-gmu-wrapper");
adreno_gpu->base.hw_apriv =
- !!(config->info->quirks & ADRENO_QUIRK_HAS_HW_APRIV);
+ !!(info->quirks & ADRENO_QUIRK_HAS_HW_APRIV);
/* gpu->info only gets assigned in adreno_gpu_init(). A8x is included intentionally */
- is_a7xx = config->info->family >= ADRENO_7XX_GEN1;
+ is_a7xx = info->family >= ADRENO_7XX_GEN1;
a6xx_llc_slices_init(pdev, a6xx_gpu, is_a7xx);
- ret = a6xx_set_supported_hw(&pdev->dev, config->info);
+ ret = a6xx_set_supported_hw(&pdev->dev, a6xx_gpu, info);
if (ret) {
a6xx_llc_slices_destroy(a6xx_gpu);
kfree(a6xx_gpu);
@@ -2682,15 +2665,20 @@ static struct msm_gpu *a6xx_gpu_init(struct drm_device *dev)
}
if ((enable_preemption == 1) || (enable_preemption == -1 &&
- (config->info->quirks & ADRENO_QUIRK_PREEMPTION)))
+ (info->quirks & ADRENO_QUIRK_PREEMPTION)))
nr_rings = 4;
- ret = adreno_gpu_init(dev, pdev, adreno_gpu, config->info->funcs, nr_rings);
+ ret = adreno_gpu_init(dev, pdev, adreno_gpu, info->funcs, nr_rings);
if (ret) {
a6xx_destroy(&(a6xx_gpu->base.base));
return ERR_PTR(ret);
}
+ /* Set the speedbin value that is passed to userspace */
+ if (a6xx_read_speedbin(&pdev->dev, a6xx_gpu, info, &speedbin) || !speedbin)
+ speedbin = 0xffff;
+ adreno_gpu->speedbin = (uint16_t) (0xffff & speedbin);
+
/*
* For now only clamp to idle freq for devices where this is known not
* to cause power supply issues:
@@ -2708,14 +2696,6 @@ static struct msm_gpu *a6xx_gpu_init(struct drm_device *dev)
return ERR_PTR(ret);
}
- if (adreno_is_a7xx(adreno_gpu) || adreno_is_a8xx(adreno_gpu)) {
- ret = a7xx_cx_mem_init(a6xx_gpu);
- if (ret) {
- a6xx_destroy(&(a6xx_gpu->base.base));
- return ERR_PTR(ret);
- }
- }
-
adreno_gpu->uche_trap_base = 0x1fffffffff000ull;
msm_mmu_set_fault_handler(to_msm_vm(gpu->vm)->mmu, gpu,
@@ -2765,6 +2745,7 @@ const struct adreno_gpu_funcs a6xx_gpu_funcs = {
.get_timestamp = a6xx_gmu_get_timestamp,
.bus_halt = a6xx_bus_clear_pending_transactions,
.mmu_fault_handler = a6xx_fault_handler,
+ .gx_is_on = a6xx_gmu_gx_is_on,
};
const struct adreno_gpu_funcs a6xx_gmuwrapper_funcs = {
@@ -2797,6 +2778,7 @@ const struct adreno_gpu_funcs a6xx_gmuwrapper_funcs = {
.get_timestamp = a6xx_get_timestamp,
.bus_halt = a6xx_bus_clear_pending_transactions,
.mmu_fault_handler = a6xx_fault_handler,
+ .gx_is_on = a6xx_gmu_gx_is_on,
};
const struct adreno_gpu_funcs a7xx_gpu_funcs = {
@@ -2831,6 +2813,8 @@ const struct adreno_gpu_funcs a7xx_gpu_funcs = {
.get_timestamp = a6xx_gmu_get_timestamp,
.bus_halt = a6xx_bus_clear_pending_transactions,
.mmu_fault_handler = a6xx_fault_handler,
+ .gx_is_on = a7xx_gmu_gx_is_on,
+ .aqe_is_enabled = a6xx_aqe_is_enabled,
};
const struct adreno_gpu_funcs a8xx_gpu_funcs = {
@@ -2858,4 +2842,6 @@ const struct adreno_gpu_funcs a8xx_gpu_funcs = {
.get_timestamp = a8xx_gmu_get_timestamp,
.bus_halt = a8xx_bus_clear_pending_transactions,
.mmu_fault_handler = a8xx_fault_handler,
+ .gx_is_on = a8xx_gmu_gx_is_on,
+ .aqe_is_enabled = a6xx_aqe_is_enabled,
};
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
index 4eaa04711246..eb431e5e00b1 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
@@ -278,6 +278,8 @@ void a6xx_preempt_hw_init(struct msm_gpu *gpu);
void a6xx_preempt_trigger(struct msm_gpu *gpu);
void a6xx_preempt_irq(struct msm_gpu *gpu);
void a6xx_preempt_fini(struct msm_gpu *gpu);
+void a6xx_emit_set_pseudo_reg(struct msm_ringbuffer *ring,
+ struct a6xx_gpu *a6xx_gpu, struct msm_gpu_submitqueue *queue);
int a6xx_preempt_submitqueue_setup(struct msm_gpu *gpu,
struct msm_gpu_submitqueue *queue);
void a6xx_preempt_submitqueue_close(struct msm_gpu *gpu,
@@ -320,13 +322,16 @@ int a6xx_zap_shader_init(struct msm_gpu *gpu);
void a8xx_bus_clear_pending_transactions(struct adreno_gpu *adreno_gpu, bool gx_off);
int a8xx_fault_handler(void *arg, unsigned long iova, int flags, void *data);
void a8xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring);
-int a8xx_gmu_get_timestamp(struct msm_gpu *gpu, uint64_t *value);
+u64 a8xx_gmu_get_timestamp(struct msm_gpu *gpu);
u64 a8xx_gpu_busy(struct msm_gpu *gpu, unsigned long *out_sample_rate);
int a8xx_gpu_feature_probe(struct msm_gpu *gpu);
void a8xx_gpu_get_slice_info(struct msm_gpu *gpu);
int a8xx_hw_init(struct msm_gpu *gpu);
irqreturn_t a8xx_irq(struct msm_gpu *gpu);
void a8xx_llc_activate(struct a6xx_gpu *a6xx_gpu);
+void a8xx_preempt_hw_init(struct msm_gpu *gpu);
+void a8xx_preempt_trigger(struct msm_gpu *gpu);
+void a8xx_preempt_irq(struct msm_gpu *gpu);
bool a8xx_progress(struct msm_gpu *gpu, struct msm_ringbuffer *ring);
void a8xx_recover(struct msm_gpu *gpu);
#endif /* __A6XX_GPU_H__ */
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c
index 2d56fe0a65b7..166365359fa6 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c
@@ -57,7 +57,7 @@ struct a6xx_gpu_state {
struct msm_gpu_state_bo *gmu_hfi;
struct msm_gpu_state_bo *gmu_debug;
- s32 hfi_queue_history[2][HFI_HISTORY_SZ];
+ s32 hfi_queue_history[HFI_MAX_QUEUES][HFI_HISTORY_SZ];
struct list_head objs;
@@ -361,7 +361,7 @@ static void a6xx_get_debugbus_blocks(struct msm_gpu *gpu,
sizeof(*a6xx_state->debugbus));
if (a6xx_state->debugbus) {
- int i;
+ int i, j;
for (i = 0; i < ARRAY_SIZE(a6xx_debugbus_blocks); i++)
a6xx_get_debugbus_block(gpu,
@@ -369,8 +369,6 @@ static void a6xx_get_debugbus_blocks(struct msm_gpu *gpu,
&a6xx_debugbus_blocks[i],
&a6xx_state->debugbus[i]);
- a6xx_state->nr_debugbus = ARRAY_SIZE(a6xx_debugbus_blocks);
-
/*
* GBIF has same debugbus as of other GPU blocks, fall back to
* default path if GPU uses GBIF, also GBIF uses exactly same
@@ -381,17 +379,19 @@ static void a6xx_get_debugbus_blocks(struct msm_gpu *gpu,
&a6xx_gbif_debugbus_block,
&a6xx_state->debugbus[i]);
- a6xx_state->nr_debugbus += 1;
+ i++;
}
if (adreno_is_a650_family(to_adreno_gpu(gpu))) {
- for (i = 0; i < ARRAY_SIZE(a650_debugbus_blocks); i++)
+ for (j = 0; j < ARRAY_SIZE(a650_debugbus_blocks); i++, j++)
a6xx_get_debugbus_block(gpu,
a6xx_state,
- &a650_debugbus_blocks[i],
+ &a650_debugbus_blocks[j],
&a6xx_state->debugbus[i]);
}
+
+ a6xx_state->nr_debugbus = i;
}
}
@@ -1013,7 +1013,7 @@ static void a6xx_get_crashdumper_hlsq_registers(struct msm_gpu *gpu,
u64 out = dumper->iova + A6XX_CD_DATA_OFFSET;
int i, regcount = 0;
- in += CRASHDUMP_WRITE(in, REG_A6XX_HLSQ_DBG_READ_SEL, regs->val1);
+ in += CRASHDUMP_WRITE(in, REG_A6XX_HLSQ_DBG_READ_SEL, (regs->val1 & 0xff) << 8);
for (i = 0; i < regs->count; i += 2) {
u32 count = RANGE(regs->registers, i);
@@ -1251,7 +1251,7 @@ static void a6xx_get_gmu_registers(struct msm_gpu *gpu,
_a6xx_get_gmu_registers(gpu, a6xx_state, &a6xx_gpucc_reg,
&a6xx_state->gmu_registers[2], false);
- if (!a6xx_gmu_gx_is_on(&a6xx_gpu->gmu))
+ if (!adreno_gpu->funcs->gx_is_on(adreno_gpu))
return;
/* Set the fence to ALLOW mode so we can access the registers */
@@ -1607,7 +1607,7 @@ struct msm_gpu_state *a6xx_gpu_state_get(struct msm_gpu *gpu)
}
/* If GX isn't on the rest of the data isn't going to be accessible */
- if (!a6xx_gmu_gx_is_on(&a6xx_gpu->gmu))
+ if (!adreno_gpu->funcs->gx_is_on(adreno_gpu))
return &a6xx_state->base;
/* Halt SQE first */
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
index 53cfdf4e6c34..487c2736f2b3 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
@@ -34,7 +34,7 @@ static int a6xx_hfi_queue_read(struct a6xx_gmu *gmu,
struct a6xx_hfi_queue_header *header = queue->header;
u32 i, hdr, index = header->read_index;
- if (header->read_index == header->write_index) {
+ if (header->read_index == READ_ONCE(header->write_index)) {
header->rx_request = 1;
return 0;
}
@@ -62,7 +62,10 @@ static int a6xx_hfi_queue_read(struct a6xx_gmu *gmu,
if (!gmu->legacy)
index = ALIGN(index, 4) % header->size;
- header->read_index = index;
+ /* Ensure all memory operations are complete before updating the read index */
+ dma_mb();
+
+ WRITE_ONCE(header->read_index, index);
return HFI_HEADER_SIZE(hdr);
}
@@ -74,7 +77,7 @@ static int a6xx_hfi_queue_write(struct a6xx_gmu *gmu,
spin_lock(&queue->lock);
- space = CIRC_SPACE(header->write_index, header->read_index,
+ space = CIRC_SPACE(header->write_index, READ_ONCE(header->read_index),
header->size);
if (space < dwords) {
header->dropped++;
@@ -95,7 +98,10 @@ static int a6xx_hfi_queue_write(struct a6xx_gmu *gmu,
queue->data[index] = 0xfafafafa;
}
- header->write_index = index;
+ /* Ensure all memory operations are complete before updating the write index */
+ dma_mb();
+
+ WRITE_ONCE(header->write_index, index);
spin_unlock(&queue->lock);
gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET, 0x01);
@@ -845,7 +851,6 @@ static int a6xx_hfi_feature_ctrl_msg(struct a6xx_gmu *gmu, u32 feature, u32 enab
return a6xx_hfi_send_msg(gmu, HFI_H2F_FEATURE_CTRL, &msg, sizeof(msg), NULL, 0);
}
-#define HFI_FEATURE_IFPC 9
#define IFPC_LONG_HYST 0x1680
static int a6xx_hfi_enable_ifpc(struct a6xx_gmu *gmu)
@@ -856,8 +861,6 @@ static int a6xx_hfi_enable_ifpc(struct a6xx_gmu *gmu)
return a6xx_hfi_feature_ctrl_msg(gmu, HFI_FEATURE_IFPC, 1, IFPC_LONG_HYST);
}
-#define HFI_FEATURE_ACD 12
-
static int a6xx_hfi_enable_acd(struct a6xx_gmu *gmu)
{
struct a6xx_hfi_acd_table *acd_table = &gmu->acd_table;
@@ -1056,8 +1059,8 @@ void a6xx_hfi_init(struct a6xx_gmu *gmu)
struct a6xx_gmu_bo *hfi = &gmu->hfi;
struct a6xx_hfi_queue_table_header *table = hfi->virt;
struct a6xx_hfi_queue_header *headers = hfi->virt + sizeof(*table);
+ int table_size, idx;
u64 offset;
- int table_size;
/*
* The table size is the size of the table header plus all of the queue
@@ -1076,12 +1079,22 @@ void a6xx_hfi_init(struct a6xx_gmu *gmu)
table->active_queues = ARRAY_SIZE(gmu->queues);
/* Command queue */
+ idx = 0;
offset = SZ_4K;
- a6xx_hfi_queue_init(&gmu->queues[0], &headers[0], hfi->virt + offset,
+ a6xx_hfi_queue_init(&gmu->queues[idx], &headers[idx], hfi->virt + offset,
hfi->iova + offset, 0);
/* GMU response queue */
+ idx++;
offset += SZ_4K;
- a6xx_hfi_queue_init(&gmu->queues[1], &headers[1], hfi->virt + offset,
+ a6xx_hfi_queue_init(&gmu->queues[idx], &headers[idx], hfi->virt + offset,
hfi->iova + offset, gmu->legacy ? 4 : 1);
+
+ /* GMU Debug queue */
+ idx++;
+ offset += SZ_4K;
+ a6xx_hfi_queue_init(&gmu->queues[idx], &headers[idx], hfi->virt + offset,
+ hfi->iova + offset, gmu->legacy ? 5 : 2);
+
+ WARN_ON(idx >= HFI_MAX_QUEUES);
}
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_hfi.h b/drivers/gpu/drm/msm/adreno/a6xx_hfi.h
index 6f9f74a0bc85..e10d32ce93e0 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_hfi.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_hfi.h
@@ -4,6 +4,8 @@
#ifndef _A6XX_HFI_H_
#define _A6XX_HFI_H_
+#define HFI_MAX_QUEUES 3
+
struct a6xx_hfi_queue_table_header {
u32 version;
u32 size; /* Size of the queue table in dwords */
@@ -11,7 +13,7 @@ struct a6xx_hfi_queue_table_header {
u32 qhdr_size; /* Size of the queue headers */
u32 num_queues; /* Number of total queues */
u32 active_queues; /* Number of active queues */
-};
+} __packed;
struct a6xx_hfi_queue_header {
u32 status;
@@ -26,7 +28,7 @@ struct a6xx_hfi_queue_header {
u32 tx_request;
u32 read_index;
u32 write_index;
-};
+} __packed;
struct a6xx_hfi_queue {
struct a6xx_hfi_queue_header *header;
@@ -72,7 +74,7 @@ struct a6xx_hfi_msg_response {
u32 ret_header;
u32 error;
u32 payload[HFI_RESPONSE_PAYLOAD_SIZE];
-};
+} __packed;
#define HFI_F2H_MSG_ERROR 100
@@ -80,7 +82,7 @@ struct a6xx_hfi_msg_error {
u32 header;
u32 code;
u32 payload[2];
-};
+} __packed;
#define HFI_H2F_MSG_INIT 0
@@ -90,27 +92,27 @@ struct a6xx_hfi_msg_gmu_init_cmd {
u32 dbg_buffer_addr;
u32 dbg_buffer_size;
u32 boot_state;
-};
+} __packed;
#define HFI_H2F_MSG_FW_VERSION 1
struct a6xx_hfi_msg_fw_version {
u32 header;
u32 supported_version;
-};
+} __packed;
#define HFI_H2F_MSG_PERF_TABLE 4
struct perf_level {
u32 vote;
u32 freq;
-};
+} __packed;
struct perf_gx_level {
u32 vote;
u32 acd;
u32 freq;
-};
+} __packed;
struct a6xx_hfi_msg_perf_table_v1 {
u32 header;
@@ -119,7 +121,7 @@ struct a6xx_hfi_msg_perf_table_v1 {
struct perf_level gx_votes[16];
struct perf_level cx_votes[4];
-};
+} __packed;
struct a6xx_hfi_msg_perf_table {
u32 header;
@@ -128,7 +130,7 @@ struct a6xx_hfi_msg_perf_table {
struct perf_gx_level gx_votes[16];
struct perf_level cx_votes[4];
-};
+} __packed;
#define HFI_H2F_MSG_BW_TABLE 3
@@ -143,13 +145,13 @@ struct a6xx_hfi_msg_bw_table {
u32 cnoc_cmds_data[2][6];
u32 ddr_cmds_addrs[8];
u32 ddr_cmds_data[16][8];
-};
+} __packed;
#define HFI_H2F_MSG_TEST 5
struct a6xx_hfi_msg_test {
u32 header;
-};
+} __packed;
#define HFI_H2F_MSG_ACD 7
#define MAX_ACD_STRIDE 2
@@ -161,29 +163,100 @@ struct a6xx_hfi_acd_table {
u32 stride;
u32 num_levels;
u32 data[16 * MAX_ACD_STRIDE];
-};
+} __packed;
+
+#define CLX_DATA(irated, num_phases, clx_path, extd_intf) \
+ ((extd_intf << 29) | \
+ (clx_path << 28) | \
+ (num_phases << 22) | \
+ (irated << 16))
+
+struct a6xx_hfi_clx_domain_v2 {
+ /**
+ * @data: BITS[0:15] Migration time
+ * BITS[16:21] Current rating
+ * BITS[22:27] Phases for domain
+ * BITS[28:28] Path notification
+ * BITS[29:31] Extra features
+ */
+ u32 data;
+ /** @clxt: CLX time in microseconds */
+ u32 clxt;
+ /** @clxh: CLH time in microseconds */
+ u32 clxh;
+ /** @urg_mode: Urgent HW throttle mode of operation */
+ u32 urg_mode;
+ /** @lkg_en: Enable leakage current estimate */
+ u32 lkg_en;
+ /** curr_budget: Current Budget */
+ u32 curr_budget;
+} __packed;
+
+#define HFI_H2F_MSG_CLX_TBL 8
+
+#define MAX_CLX_DOMAINS 2
+struct a6xx_hfi_clx_table_v2_cmd {
+ u32 hdr;
+ u32 version;
+ struct a6xx_hfi_clx_domain_v2 domain[MAX_CLX_DOMAINS];
+} __packed;
#define HFI_H2F_MSG_START 10
struct a6xx_hfi_msg_start {
u32 header;
-};
+} __packed;
#define HFI_H2F_FEATURE_CTRL 11
struct a6xx_hfi_msg_feature_ctrl {
u32 header;
u32 feature;
+#define HFI_FEATURE_DCVS 0
+#define HFI_FEATURE_HWSCHED 1
+#define HFI_FEATURE_PREEMPTION 2
+#define HFI_FEATURE_CLOCKS_ON 3
+#define HFI_FEATURE_BUS_ON 4
+#define HFI_FEATURE_RAIL_ON 5
+#define HFI_FEATURE_HWCG 6
+#define HFI_FEATURE_LM 7
+#define HFI_FEATURE_THROTTLE 8
+#define HFI_FEATURE_IFPC 9
+#define HFI_FEATURE_NAP 10
+#define HFI_FEATURE_BCL 11
+#define HFI_FEATURE_ACD 12
+#define HFI_FEATURE_DIDT 13
+#define HFI_FEATURE_DEPRECATED 14
+#define HFI_FEATURE_CB 15
+#define HFI_FEATURE_KPROF 16
+#define HFI_FEATURE_BAIL_OUT_TIMER 17
+#define HFI_FEATURE_GMU_STATS 18
+#define HFI_FEATURE_DBQ 19
+#define HFI_FEATURE_MINBW 20
+#define HFI_FEATURE_CLX 21
+#define HFI_FEATURE_LSR 23
+#define HFI_FEATURE_LPAC 24
+#define HFI_FEATURE_HW_FENCE 25
+#define HFI_FEATURE_PERF_NORETAIN 26
+#define HFI_FEATURE_DMS 27
+#define HFI_FEATURE_THERMAL 28
+#define HFI_FEATURE_AQE 29
+#define HFI_FEATURE_TDCVS 30
+#define HFI_FEATURE_DCE 31
+#define HFI_FEATURE_IFF_PCLX 32
+#define HFI_FEATURE_SOFT_RESET 0x10000001
+#define HFI_FEATURE_DCVS_PROFILE 0x10000002
+#define HFI_FEATURE_FAST_CTX_DESTROY 0x10000003
u32 enable;
u32 data;
-};
+} __packed;
#define HFI_H2F_MSG_CORE_FW_START 14
struct a6xx_hfi_msg_core_fw_start {
u32 header;
u32 handle;
-};
+} __packed;
#define HFI_H2F_MSG_TABLE 15
@@ -191,16 +264,25 @@ struct a6xx_hfi_table_entry {
u32 count;
u32 stride;
u32 data[];
-};
+} __packed;
struct a6xx_hfi_table {
u32 header;
u32 version;
u32 type;
-#define HFI_TABLE_BW_VOTE 0
-#define HFI_TABLE_GPU_PERF 1
+#define HFI_TABLE_BW_VOTE 0
+#define HFI_TABLE_GPU_PERF 1
+#define HFI_TABLE_DIDT 2
+#define HFI_TABLE_ACD 3
+#define HFI_TABLE_CLX_V1 4 /* Unused */
+#define HFI_TABLE_CLX_V2 5
+#define HFI_TABLE_THERM 6
+#define HFI_TABLE_DCVS 7
+#define HFI_TABLE_SYS_TIME 8
+#define HFI_TABLE_GMU_DCVS 9
+#define HFI_TABLE_LIMITS_MIT 10
struct a6xx_hfi_table_entry entry[];
-};
+} __packed;
#define HFI_H2F_MSG_GX_BW_PERF_VOTE 30
@@ -209,7 +291,7 @@ struct a6xx_hfi_gx_bw_perf_vote_cmd {
u32 ack_type;
u32 freq;
u32 bw;
-};
+} __packed;
#define AB_VOTE_MASK GENMASK(31, 16)
#define MAX_AB_VOTE (FIELD_MAX(AB_VOTE_MASK) - 1)
@@ -222,6 +304,35 @@ struct a6xx_hfi_prep_slumber_cmd {
u32 header;
u32 bw;
u32 freq;
-};
+} __packed;
+
+struct a6xx_hfi_limits_cfg {
+ u32 enable;
+ u32 msg_path;
+ u32 lkg_en;
+ /*
+ * BIT[0]: 0 = (static) throttle to fixed sid level
+ * 1 = (dynamic) throttle to sid level calculated by HW
+ * BIT[1]: 0 = Mx
+ * 1 = Bx
+ */
+ u32 mode;
+ u32 sid;
+ /* Mitigation time in microseconds */
+ u32 mit_time;
+ /* Max current in mA during mitigation */
+ u32 curr_limit;
+} __packed;
+
+struct a6xx_hfi_limits_tbl {
+ u8 feature_id;
+#define GMU_MIT_IFF 0
+#define GMU_MIT_PCLX 1
+ u8 domain;
+#define GMU_GX_DOMAIN 0
+#define GMU_MX_DOMAIN 1
+ u16 feature_rev;
+ struct a6xx_hfi_limits_cfg cfg;
+} __packed;
#endif
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_preempt.c b/drivers/gpu/drm/msm/adreno/a6xx_preempt.c
index 747a22afad9f..df4cbf42e9a4 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_preempt.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_preempt.c
@@ -6,85 +6,10 @@
#include "msm_gem.h"
#include "a6xx_gpu.h"
#include "a6xx_gmu.xml.h"
+#include "a6xx_preempt.h"
#include "msm_mmu.h"
#include "msm_gpu_trace.h"
-/*
- * Try to transition the preemption state from old to new. Return
- * true on success or false if the original state wasn't 'old'
- */
-static inline bool try_preempt_state(struct a6xx_gpu *a6xx_gpu,
- enum a6xx_preempt_state old, enum a6xx_preempt_state new)
-{
- enum a6xx_preempt_state cur = atomic_cmpxchg(&a6xx_gpu->preempt_state,
- old, new);
-
- return (cur == old);
-}
-
-/*
- * Force the preemption state to the specified state. This is used in cases
- * where the current state is known and won't change
- */
-static inline void set_preempt_state(struct a6xx_gpu *gpu,
- enum a6xx_preempt_state new)
-{
- /*
- * preempt_state may be read by other cores trying to trigger a
- * preemption or in the interrupt handler so barriers are needed
- * before...
- */
- smp_mb__before_atomic();
- atomic_set(&gpu->preempt_state, new);
- /* ... and after*/
- smp_mb__after_atomic();
-}
-
-/* Write the most recent wptr for the given ring into the hardware */
-static inline void update_wptr(struct a6xx_gpu *a6xx_gpu, struct msm_ringbuffer *ring)
-{
- unsigned long flags;
- uint32_t wptr;
-
- spin_lock_irqsave(&ring->preempt_lock, flags);
-
- if (ring->restore_wptr) {
- wptr = get_wptr(ring);
-
- a6xx_fenced_write(a6xx_gpu, REG_A6XX_CP_RB_WPTR, wptr, BIT(0), false);
-
- ring->restore_wptr = false;
- }
-
- spin_unlock_irqrestore(&ring->preempt_lock, flags);
-}
-
-/* Return the highest priority ringbuffer with something in it */
-static struct msm_ringbuffer *get_next_ring(struct msm_gpu *gpu)
-{
- struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
- struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
-
- unsigned long flags;
- int i;
-
- for (i = 0; i < gpu->nr_rings; i++) {
- bool empty;
- struct msm_ringbuffer *ring = gpu->rb[i];
-
- spin_lock_irqsave(&ring->preempt_lock, flags);
- empty = (get_wptr(ring) == gpu->funcs->get_rptr(gpu, ring));
- if (!empty && ring == a6xx_gpu->cur_ring)
- empty = ring->memptrs->fence == a6xx_gpu->last_seqno[i];
- spin_unlock_irqrestore(&ring->preempt_lock, flags);
-
- if (!empty)
- return ring;
- }
-
- return NULL;
-}
-
static void a6xx_preempt_timer(struct timer_list *t)
{
struct a6xx_gpu *a6xx_gpu = timer_container_of(a6xx_gpu, t,
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_preempt.h b/drivers/gpu/drm/msm/adreno/a6xx_preempt.h
new file mode 100644
index 000000000000..df36c945b836
--- /dev/null
+++ b/drivers/gpu/drm/msm/adreno/a6xx_preempt.h
@@ -0,0 +1,82 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved. */
+/* Copyright (c) 2023 Collabora, Ltd. */
+/* Copyright (c) 2024 Valve Corporation */
+/* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */
+
+/*
+ * Try to transition the preemption state from old to new. Return
+ * true on success or false if the original state wasn't 'old'
+ */
+static inline bool try_preempt_state(struct a6xx_gpu *a6xx_gpu,
+ enum a6xx_preempt_state old, enum a6xx_preempt_state new)
+{
+ enum a6xx_preempt_state cur = atomic_cmpxchg(&a6xx_gpu->preempt_state,
+ old, new);
+
+ return (cur == old);
+}
+
+/*
+ * Force the preemption state to the specified state. This is used in cases
+ * where the current state is known and won't change
+ */
+static inline void set_preempt_state(struct a6xx_gpu *gpu,
+ enum a6xx_preempt_state new)
+{
+ /*
+ * preempt_state may be read by other cores trying to trigger a
+ * preemption or in the interrupt handler so barriers are needed
+ * before...
+ */
+ smp_mb__before_atomic();
+ atomic_set(&gpu->preempt_state, new);
+ /* ... and after */
+ smp_mb__after_atomic();
+}
+
+/* Write the most recent wptr for the given ring into the hardware */
+static inline void update_wptr(struct a6xx_gpu *a6xx_gpu, struct msm_ringbuffer *ring)
+{
+ unsigned long flags;
+ uint32_t wptr;
+
+ spin_lock_irqsave(&ring->preempt_lock, flags);
+
+ if (ring->restore_wptr) {
+ wptr = get_wptr(ring);
+
+ a6xx_fenced_write(a6xx_gpu, REG_A6XX_CP_RB_WPTR, wptr, BIT(0), false);
+
+ ring->restore_wptr = false;
+ }
+
+ spin_unlock_irqrestore(&ring->preempt_lock, flags);
+}
+
+/* Return the highest priority ringbuffer with something in it */
+static inline struct msm_ringbuffer *get_next_ring(struct msm_gpu *gpu)
+{
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
+
+ unsigned long flags;
+ int i;
+
+ for (i = 0; i < gpu->nr_rings; i++) {
+ bool empty;
+ struct msm_ringbuffer *ring = gpu->rb[i];
+
+ spin_lock_irqsave(&ring->preempt_lock, flags);
+ empty = (get_wptr(ring) == gpu->funcs->get_rptr(gpu, ring));
+ if (!empty && ring == a6xx_gpu->cur_ring)
+ empty = ring->memptrs->fence == a6xx_gpu->last_seqno[i];
+ spin_unlock_irqrestore(&ring->preempt_lock, flags);
+
+ if (!empty)
+ return ring;
+ }
+
+ return NULL;
+}
+
diff --git a/drivers/gpu/drm/msm/adreno/a8xx_gpu.c b/drivers/gpu/drm/msm/adreno/a8xx_gpu.c
index 5a320f5bde41..ccfccc45133f 100644
--- a/drivers/gpu/drm/msm/adreno/a8xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a8xx_gpu.c
@@ -87,6 +87,7 @@ void a8xx_gpu_get_slice_info(struct msm_gpu *gpu)
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
const struct a6xx_info *info = adreno_gpu->info->a6xx;
+ struct device *dev = &gpu->pdev->dev;
u32 slice_mask;
if (adreno_gpu->info->family < ADRENO_8XX_GEN1)
@@ -110,6 +111,15 @@ void a8xx_gpu_get_slice_info(struct msm_gpu *gpu)
/* Chip ID depends on the number of slices available. So update it */
adreno_gpu->chip_id |= FIELD_PREP(GENMASK(7, 4), hweight32(slice_mask));
+
+ /* Update the gpu-name to reflect the slice config: */
+ const char *name = devm_kasprintf(dev, GFP_KERNEL,
+ "%"ADRENO_CHIPID_FMT,
+ ADRENO_CHIPID_ARGS(adreno_gpu->chip_id));
+ if (name) {
+ devm_kfree(dev, adreno_gpu->base.name);
+ adreno_gpu->base.name = name;
+ }
}
static u32 a8xx_get_first_slice(struct a6xx_gpu *a6xx_gpu)
@@ -173,7 +183,7 @@ void a8xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
/* Update HW if this is the current ring and we are not in preempt*/
if (!a6xx_in_preempt(a6xx_gpu)) {
if (a6xx_gpu->cur_ring == ring)
- gpu_write(gpu, REG_A6XX_CP_RB_WPTR, wptr);
+ a6xx_fenced_write(a6xx_gpu, REG_A6XX_CP_RB_WPTR, wptr, BIT(0), false);
else
ring->restore_wptr = true;
} else {
@@ -310,11 +320,21 @@ static void a8xx_set_ubwc_config(struct msm_gpu *gpu)
hbb = cfg->highest_bank_bit - 13;
hbb_hi = hbb >> 2;
hbb_lo = hbb & 3;
- a8xx_write_pipe(gpu, PIPE_BV, REG_A8XX_GRAS_NC_MODE_CNTL, hbb << 5);
- a8xx_write_pipe(gpu, PIPE_BR, REG_A8XX_GRAS_NC_MODE_CNTL, hbb << 5);
+
+ a8xx_write_pipe(gpu, PIPE_BV, REG_A8XX_GRAS_NC_MODE_CNTL,
+ hbb << 5 |
+ level3_swizzling_dis << 4 |
+ level2_swizzling_dis << 3);
+
+ a8xx_write_pipe(gpu, PIPE_BR, REG_A8XX_GRAS_NC_MODE_CNTL,
+ hbb << 5 |
+ level3_swizzling_dis << 4 |
+ level2_swizzling_dis << 3);
a8xx_write_pipe(gpu, PIPE_BR, REG_A8XX_RB_CCU_NC_MODE_CNTL,
yuvnotcomptofc << 6 |
+ level3_swizzling_dis << 5 |
+ level2_swizzling_dis << 4 |
hbb_hi << 3 |
hbb_lo << 1);
@@ -376,8 +396,115 @@ static void a8xx_nonctxt_config(struct msm_gpu *gpu, u32 *gmem_protect)
a8xx_aperture_clear(gpu);
}
+static void a8xx_patch_pwrup_reglist(struct msm_gpu *gpu)
+{
+ const struct adreno_reglist_pipe_list *dyn_pwrup_reglist;
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
+ const struct adreno_reglist_list *reglist;
+ void *ptr = a6xx_gpu->pwrup_reglist_ptr;
+ struct cpu_gpu_lock *lock = ptr;
+ u32 *dest = (u32 *)&lock->regs[0];
+ u32 dyn_pwrup_reglist_count = 0;
+ int i;
+
+ lock->gpu_req = lock->cpu_req = lock->turn = 0;
+
+ reglist = adreno_gpu->info->a6xx->ifpc_reglist;
+ if (reglist) {
+ lock->ifpc_list_len = reglist->count;
+
+ /*
+ * For each entry in each of the lists, write the offset and the current
+ * register value into the GPU buffer
+ */
+ for (i = 0; i < reglist->count; i++) {
+ *dest++ = reglist->regs[i];
+ *dest++ = gpu_read(gpu, reglist->regs[i]);
+ }
+ }
+
+ reglist = adreno_gpu->info->a6xx->pwrup_reglist;
+ if (reglist) {
+ lock->preemption_list_len = reglist->count;
+
+ for (i = 0; i < reglist->count; i++) {
+ *dest++ = reglist->regs[i];
+ *dest++ = gpu_read(gpu, reglist->regs[i]);
+ }
+ }
+
+ /*
+ * The overall register list is composed of
+ * 1. Static IFPC-only registers
+ * 2. Static IFPC + preemption registers
+ * 3. Dynamic IFPC + preemption registers (ex: perfcounter selects)
+ *
+ * The first two lists are static. Size of these lists are stored as
+ * number of pairs in ifpc_list_len and preemption_list_len
+ * respectively. With concurrent binning, Some of the perfcounter
+ * registers being virtualized, CP needs to know the pipe id to program
+ * the aperture inorder to restore the same. Thus, third list is a
+ * dynamic list with triplets as
+ * (<aperture, shifted 12 bits> <address> <data>), and the length is
+ * stored as number for triplets in dynamic_list_len.
+ */
+ dyn_pwrup_reglist = adreno_gpu->info->a6xx->dyn_pwrup_reglist;
+ if (!dyn_pwrup_reglist)
+ goto done;
+
+ for (u32 pipe_id = PIPE_BR; pipe_id <= PIPE_DDE_BV; pipe_id++) {
+ for (i = 0; i < dyn_pwrup_reglist->count; i++) {
+ if (!(dyn_pwrup_reglist->regs[i].pipe & BIT(pipe_id)))
+ continue;
+ *dest++ = A8XX_CP_APERTURE_CNTL_HOST_PIPEID(pipe_id);
+ *dest++ = dyn_pwrup_reglist->regs[i].offset;
+ *dest++ = a8xx_read_pipe_slice(gpu,
+ pipe_id,
+ a8xx_get_first_slice(a6xx_gpu),
+ dyn_pwrup_reglist->regs[i].offset);
+ dyn_pwrup_reglist_count++;
+ }
+ }
+
+ lock->dynamic_list_len = dyn_pwrup_reglist_count;
+
+done:
+ a8xx_aperture_clear(gpu);
+}
+
+static int a8xx_preempt_start(struct msm_gpu *gpu)
+{
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
+ struct msm_ringbuffer *ring = gpu->rb[0];
+
+ if (gpu->nr_rings <= 1)
+ return 0;
+
+ /* Turn CP protection off */
+ OUT_PKT7(ring, CP_SET_PROTECTED_MODE, 1);
+ OUT_RING(ring, 0);
+
+ a6xx_emit_set_pseudo_reg(ring, a6xx_gpu, NULL);
+
+ /* Yield the floor on command completion */
+ OUT_PKT7(ring, CP_CONTEXT_SWITCH_YIELD, 4);
+ OUT_RING(ring, 0x00);
+ OUT_RING(ring, 0x00);
+ OUT_RING(ring, 0x00);
+ /* Generate interrupt on preemption completion */
+ OUT_RING(ring, 0x00);
+
+ a6xx_flush(gpu, ring);
+
+ return a8xx_idle(gpu, ring) ? 0 : -EINVAL;
+}
+
static int a8xx_cp_init(struct msm_gpu *gpu)
{
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
struct msm_ringbuffer *ring = gpu->rb[0];
u32 mask;
@@ -385,7 +512,7 @@ static int a8xx_cp_init(struct msm_gpu *gpu)
OUT_PKT7(ring, CP_THREAD_CONTROL, 1);
OUT_RING(ring, BIT(27));
- OUT_PKT7(ring, CP_ME_INIT, 4);
+ OUT_PKT7(ring, CP_ME_INIT, 7);
/* Use multiple HW contexts */
mask = BIT(0);
@@ -399,6 +526,9 @@ static int a8xx_cp_init(struct msm_gpu *gpu)
/* Disable save/restore of performance counters across preemption */
mask |= BIT(6);
+ /* Enable the register init list with the spinlock */
+ mask |= BIT(8);
+
OUT_RING(ring, mask);
/* Enable multiple hardware contexts */
@@ -410,6 +540,14 @@ static int a8xx_cp_init(struct msm_gpu *gpu)
/* Operation mode mask */
OUT_RING(ring, 0x00000002);
+ /* Lo address */
+ OUT_RING(ring, lower_32_bits(a6xx_gpu->pwrup_reglist_iova));
+ /* Hi address */
+ OUT_RING(ring, upper_32_bits(a6xx_gpu->pwrup_reglist_iova));
+
+ /* Enable dyn pwrup list with triplets (offset, value, pipe) */
+ OUT_RING(ring, BIT(31));
+
a6xx_flush(gpu, ring);
return a8xx_idle(gpu, ring) ? 0 : -EINVAL;
}
@@ -638,6 +776,8 @@ static int hw_init(struct msm_gpu *gpu)
gpu_write64(gpu, REG_A6XX_CP_RB_RPTR_ADDR, shadowptr(a6xx_gpu, gpu->rb[0]));
gpu_write64(gpu, REG_A8XX_CP_RB_RPTR_ADDR_BV, rbmemptr(gpu->rb[0], bv_rptr));
+ a8xx_preempt_hw_init(gpu);
+
for (i = 0; i < gpu->nr_rings; i++)
a6xx_gpu->shadow[i] = 0;
@@ -692,15 +832,29 @@ static int hw_init(struct msm_gpu *gpu)
WARN_ON(!gmem_protect);
a8xx_aperture_clear(gpu);
+ if (!a6xx_gpu->pwrup_reglist_emitted) {
+ a8xx_patch_pwrup_reglist(gpu);
+ a6xx_gpu->pwrup_reglist_emitted = true;
+ }
+
/* Enable hardware clockgating */
a8xx_set_hwcg(gpu, true);
out:
+ /* Last step - yield the ringbuffer */
+ a8xx_preempt_start(gpu);
+
/*
* Tell the GMU that we are done touching the GPU and it can start power
* management
*/
a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET);
+ if (!ret && (refcount_read(&gpu->sysprof_active) > 1)) {
+ ret = a6xx_gmu_set_oob(gmu, GMU_OOB_PERFCOUNTER_SET);
+ if (!ret)
+ set_bit(GMU_STATUS_OOB_PERF_SET, &gmu->status);
+ }
+
return ret;
}
@@ -1098,11 +1252,11 @@ irqreturn_t a8xx_irq(struct msm_gpu *gpu)
if (status & A6XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS) {
msm_gpu_retire(gpu);
- a6xx_preempt_trigger(gpu);
+ a8xx_preempt_trigger(gpu);
}
if (status & A6XX_RBBM_INT_0_MASK_CP_SW)
- a6xx_preempt_irq(gpu);
+ a8xx_preempt_irq(gpu);
return IRQ_HANDLED;
}
@@ -1164,23 +1318,19 @@ void a8xx_bus_clear_pending_transactions(struct adreno_gpu *adreno_gpu, bool gx_
gpu_write(gpu, REG_A6XX_GBIF_HALT, 0x0);
}
-int a8xx_gmu_get_timestamp(struct msm_gpu *gpu, uint64_t *value)
+u64 a8xx_gmu_get_timestamp(struct msm_gpu *gpu)
{
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
+ u64 count_hi, count_lo, temp;
- mutex_lock(&a6xx_gpu->gmu.lock);
-
- /* Force the GPU power on so we can read this register */
- a6xx_gmu_set_oob(&a6xx_gpu->gmu, GMU_OOB_PERFCOUNTER_SET);
-
- *value = gpu_read64(gpu, REG_A8XX_CP_ALWAYS_ON_COUNTER);
-
- a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_PERFCOUNTER_SET);
-
- mutex_unlock(&a6xx_gpu->gmu.lock);
+ do {
+ count_hi = gmu_read(&a6xx_gpu->gmu, REG_A8XX_GMU_ALWAYS_ON_COUNTER_H);
+ count_lo = gmu_read(&a6xx_gpu->gmu, REG_A8XX_GMU_ALWAYS_ON_COUNTER_L);
+ temp = gmu_read(&a6xx_gpu->gmu, REG_A8XX_GMU_ALWAYS_ON_COUNTER_H);
+ } while (unlikely(count_hi != temp));
- return 0;
+ return (count_hi << 32) | count_lo;
}
u64 a8xx_gpu_busy(struct msm_gpu *gpu, unsigned long *out_sample_rate)
diff --git a/drivers/gpu/drm/msm/adreno/a8xx_preempt.c b/drivers/gpu/drm/msm/adreno/a8xx_preempt.c
new file mode 100644
index 000000000000..3d8c33ba722e
--- /dev/null
+++ b/drivers/gpu/drm/msm/adreno/a8xx_preempt.c
@@ -0,0 +1,259 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */
+
+#include "msm_gem.h"
+#include "a6xx_gpu.h"
+#include "a6xx_gmu.xml.h"
+#include "a6xx_preempt.h"
+#include "msm_mmu.h"
+#include "msm_gpu_trace.h"
+
+static void preempt_prepare_postamble(struct a6xx_gpu *a6xx_gpu)
+{
+ u32 *postamble = a6xx_gpu->preempt_postamble_ptr;
+ u32 count = 0;
+
+ postamble[count++] = PKT7(CP_REG_RMW, 3);
+ postamble[count++] = REG_A8XX_RBBM_PERFCTR_SRAM_INIT_CMD;
+ postamble[count++] = 0;
+ postamble[count++] = 1;
+
+ postamble[count++] = PKT7(CP_WAIT_REG_MEM, 6);
+ postamble[count++] = CP_WAIT_REG_MEM_0_FUNCTION(WRITE_EQ);
+ postamble[count++] = CP_WAIT_REG_MEM_POLL_ADDR_LO(
+ REG_A8XX_RBBM_PERFCTR_SRAM_INIT_STATUS);
+ postamble[count++] = CP_WAIT_REG_MEM_POLL_ADDR_HI(0);
+ postamble[count++] = CP_WAIT_REG_MEM_3_REF(0x1);
+ postamble[count++] = CP_WAIT_REG_MEM_4_MASK(0x1);
+ postamble[count++] = CP_WAIT_REG_MEM_5_DELAY_LOOP_CYCLES(0);
+
+ a6xx_gpu->preempt_postamble_len = count;
+
+ a6xx_gpu->postamble_enabled = true;
+}
+
+static void preempt_disable_postamble(struct a6xx_gpu *a6xx_gpu)
+{
+ u32 *postamble = a6xx_gpu->preempt_postamble_ptr;
+
+ /*
+ * Disable the postamble by replacing the first packet header with a NOP
+ * that covers the whole buffer.
+ */
+ *postamble = PKT7(CP_NOP, (a6xx_gpu->preempt_postamble_len - 1));
+
+ a6xx_gpu->postamble_enabled = false;
+}
+
+/*
+ * Set preemption keepalive vote. Please note that this vote is different from the one used in
+ * a8xx_irq()
+ */
+static void a8xx_preempt_keepalive_vote(struct msm_gpu *gpu, bool on)
+{
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
+
+ gmu_write(&a6xx_gpu->gmu, REG_A8XX_GMU_PWR_COL_PREEMPT_KEEPALIVE, on);
+}
+
+void a8xx_preempt_irq(struct msm_gpu *gpu)
+{
+ uint32_t status;
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
+ struct drm_device *dev = gpu->dev;
+
+ if (!try_preempt_state(a6xx_gpu, PREEMPT_TRIGGERED, PREEMPT_PENDING))
+ return;
+
+ /* Delete the preemption watchdog timer */
+ timer_delete(&a6xx_gpu->preempt_timer);
+
+ /*
+ * The hardware should be setting the stop bit of CP_CONTEXT_SWITCH_CNTL
+ * to zero before firing the interrupt, but there is a non zero chance
+ * of a hardware condition or a software race that could set it again
+ * before we have a chance to finish. If that happens, log and go for
+ * recovery
+ */
+ status = gpu_read(gpu, REG_A8XX_CP_CONTEXT_SWITCH_CNTL);
+ if (unlikely(status & A8XX_CP_CONTEXT_SWITCH_CNTL_STOP)) {
+ DRM_DEV_ERROR(&gpu->pdev->dev,
+ "!!!!!!!!!!!!!!!! preemption faulted !!!!!!!!!!!!!! irq\n");
+ set_preempt_state(a6xx_gpu, PREEMPT_FAULTED);
+ dev_err(dev->dev, "%s: Preemption failed to complete\n",
+ gpu->name);
+ kthread_queue_work(gpu->worker, &gpu->recover_work);
+ return;
+ }
+
+ a6xx_gpu->cur_ring = a6xx_gpu->next_ring;
+ a6xx_gpu->next_ring = NULL;
+
+ set_preempt_state(a6xx_gpu, PREEMPT_FINISH);
+
+ update_wptr(a6xx_gpu, a6xx_gpu->cur_ring);
+
+ set_preempt_state(a6xx_gpu, PREEMPT_NONE);
+
+ a8xx_preempt_keepalive_vote(gpu, false);
+
+ trace_msm_gpu_preemption_irq(a6xx_gpu->cur_ring->id);
+
+ /*
+ * Retrigger preemption to avoid a deadlock that might occur when preemption
+ * is skipped due to it being already in flight when requested.
+ */
+ a8xx_preempt_trigger(gpu);
+}
+
+void a8xx_preempt_hw_init(struct msm_gpu *gpu)
+{
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
+ int i;
+
+ /* No preemption if we only have one ring */
+ if (gpu->nr_rings == 1)
+ return;
+
+ for (i = 0; i < gpu->nr_rings; i++) {
+ struct a6xx_preempt_record *record_ptr = a6xx_gpu->preempt[i];
+
+ record_ptr->wptr = 0;
+ record_ptr->rptr = 0;
+ record_ptr->rptr_addr = shadowptr(a6xx_gpu, gpu->rb[i]);
+ record_ptr->info = 0;
+ record_ptr->data = 0;
+ record_ptr->rbase = gpu->rb[i]->iova;
+ }
+
+ /* Write a 0 to signal that we aren't switching pagetables */
+ gpu_write64(gpu, REG_A8XX_CP_CONTEXT_SWITCH_SMMU_INFO, 0);
+
+ /* Enable the GMEM save/restore feature for preemption */
+ gpu_write(gpu, REG_A6XX_RB_CONTEXT_SWITCH_GMEM_SAVE_RESTORE_ENABLE, 0x1);
+
+ /* Reset the preemption state */
+ set_preempt_state(a6xx_gpu, PREEMPT_NONE);
+
+ spin_lock_init(&a6xx_gpu->eval_lock);
+
+ /* Always come up on rb 0 */
+ a6xx_gpu->cur_ring = gpu->rb[0];
+}
+
+void a8xx_preempt_trigger(struct msm_gpu *gpu)
+{
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
+ unsigned long flags;
+ struct msm_ringbuffer *ring;
+ unsigned int cntl;
+ bool sysprof;
+
+ if (gpu->nr_rings == 1)
+ return;
+
+ /*
+ * Lock to make sure another thread attempting preemption doesn't skip it
+ * while we are still evaluating the next ring. This makes sure the other
+ * thread does start preemption if we abort it and avoids a soft lock.
+ */
+ spin_lock_irqsave(&a6xx_gpu->eval_lock, flags);
+
+ /*
+ * Try to start preemption by moving from NONE to START. If
+ * unsuccessful, a preemption is already in flight
+ */
+ if (!try_preempt_state(a6xx_gpu, PREEMPT_NONE, PREEMPT_START)) {
+ spin_unlock_irqrestore(&a6xx_gpu->eval_lock, flags);
+ return;
+ }
+
+ cntl = A8XX_CP_CONTEXT_SWITCH_CNTL_LEVEL(a6xx_gpu->preempt_level);
+
+ if (a6xx_gpu->skip_save_restore)
+ cntl |= A8XX_CP_CONTEXT_SWITCH_CNTL_SKIP_SAVE_RESTORE;
+
+ if (a6xx_gpu->uses_gmem)
+ cntl |= A8XX_CP_CONTEXT_SWITCH_CNTL_USES_GMEM;
+
+ cntl |= A8XX_CP_CONTEXT_SWITCH_CNTL_STOP;
+
+ /* Get the next ring to preempt to */
+ ring = get_next_ring(gpu);
+
+ /*
+ * If no ring is populated or the highest priority ring is the current
+ * one do nothing except to update the wptr to the latest and greatest
+ */
+ if (!ring || (a6xx_gpu->cur_ring == ring)) {
+ set_preempt_state(a6xx_gpu, PREEMPT_FINISH);
+ update_wptr(a6xx_gpu, a6xx_gpu->cur_ring);
+ set_preempt_state(a6xx_gpu, PREEMPT_NONE);
+ spin_unlock_irqrestore(&a6xx_gpu->eval_lock, flags);
+ return;
+ }
+
+ spin_unlock_irqrestore(&a6xx_gpu->eval_lock, flags);
+
+ spin_lock_irqsave(&ring->preempt_lock, flags);
+
+ struct a7xx_cp_smmu_info *smmu_info_ptr =
+ a6xx_gpu->preempt_smmu[ring->id];
+ struct a6xx_preempt_record *record_ptr = a6xx_gpu->preempt[ring->id];
+ u64 ttbr0 = ring->memptrs->ttbr0;
+ u32 context_idr = ring->memptrs->context_idr;
+
+ smmu_info_ptr->ttbr0 = ttbr0;
+ smmu_info_ptr->context_idr = context_idr;
+ record_ptr->wptr = get_wptr(ring);
+
+ /*
+ * The GPU will write the wptr we set above when we preempt. Reset
+ * restore_wptr to make sure that we don't write WPTR to the same
+ * thing twice. It's still possible subsequent submissions will update
+ * wptr again, in which case they will set the flag to true. This has
+ * to be protected by the lock for setting the flag and updating wptr
+ * to be atomic.
+ */
+ ring->restore_wptr = false;
+
+ trace_msm_gpu_preemption_trigger(a6xx_gpu->cur_ring->id, ring->id);
+
+ spin_unlock_irqrestore(&ring->preempt_lock, flags);
+
+ /* Set the keepalive bit to keep the GPU ON until preemption is complete */
+ a8xx_preempt_keepalive_vote(gpu, true);
+
+ a6xx_fenced_write(a6xx_gpu,
+ REG_A8XX_CP_CONTEXT_SWITCH_SMMU_INFO, a6xx_gpu->preempt_smmu_iova[ring->id],
+ BIT(1), true);
+
+ a6xx_fenced_write(a6xx_gpu,
+ REG_A8XX_CP_CONTEXT_SWITCH_PRIV_NON_SECURE_RESTORE_ADDR,
+ a6xx_gpu->preempt_iova[ring->id], BIT(1), true);
+
+ a6xx_gpu->next_ring = ring;
+
+ /* Start a timer to catch a stuck preemption */
+ mod_timer(&a6xx_gpu->preempt_timer, jiffies + msecs_to_jiffies(10000));
+
+ /* Enable or disable postamble as needed */
+ sysprof = refcount_read(&a6xx_gpu->base.base.sysprof_active) > 1;
+
+ if (!sysprof && !a6xx_gpu->postamble_enabled)
+ preempt_prepare_postamble(a6xx_gpu);
+
+ if (sysprof && a6xx_gpu->postamble_enabled)
+ preempt_disable_postamble(a6xx_gpu);
+
+ /* Set the preemption state to triggered */
+ set_preempt_state(a6xx_gpu, PREEMPT_TRIGGERED);
+
+ /* Trigger the preemption */
+ a6xx_fenced_write(a6xx_gpu, REG_A8XX_CP_CONTEXT_SWITCH_CNTL, cntl, BIT(1), false);
+}
+
diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c
index 554d746f115b..4edfe80c5be7 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_device.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
@@ -302,6 +302,7 @@ static const struct of_device_id dt_match[] = {
{ .compatible = "qcom,kgsl-3d0" },
{}
};
+MODULE_DEVICE_TABLE(of, dt_match);
static int adreno_runtime_resume(struct device *dev)
{
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index d5fe6f6f0dec..66f80f2d12f9 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -45,8 +45,8 @@ static int zap_shader_load_mdt(struct msm_gpu *gpu, const char *fwname,
return -EINVAL;
}
- np = of_get_child_by_name(dev->of_node, "zap-shader");
- if (!of_device_is_available(np)) {
+ np = of_get_available_child_by_name(dev->of_node, "zap-shader");
+ if (!np) {
zap_available = false;
return -ENODEV;
}
@@ -391,13 +391,11 @@ int adreno_get_param(struct msm_gpu *gpu, struct msm_context *ctx,
return 0;
case MSM_PARAM_TIMESTAMP:
if (adreno_gpu->funcs->get_timestamp) {
- int ret;
-
pm_runtime_get_sync(&gpu->pdev->dev);
- ret = adreno_gpu->funcs->get_timestamp(gpu, value);
+ *value = adreno_gpu->funcs->get_timestamp(gpu);
pm_runtime_put_autosuspend(&gpu->pdev->dev);
- return ret;
+ return 0;
}
return -EINVAL;
case MSM_PARAM_PRIORITIES:
@@ -443,6 +441,10 @@ int adreno_get_param(struct msm_gpu *gpu, struct msm_context *ctx,
case MSM_PARAM_HAS_PRR:
*value = adreno_smmu_has_prr(gpu);
return 0;
+ case MSM_PARAM_AQE:
+ *value = !!(adreno_gpu->funcs->aqe_is_enabled &&
+ adreno_gpu->funcs->aqe_is_enabled(adreno_gpu));
+ return 0;
default:
return UERR(EINVAL, drm, "%s: invalid param: %u", gpu->name, param);
}
@@ -1184,7 +1186,6 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
struct msm_gpu_config adreno_gpu_config = { 0 };
struct msm_gpu *gpu = &adreno_gpu->base;
const char *gpu_name;
- u32 speedbin;
int ret;
adreno_gpu->funcs = funcs;
@@ -1213,10 +1214,6 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
devm_pm_opp_set_clkname(dev, "core");
}
- if (adreno_read_speedbin(dev, &speedbin) || !speedbin)
- speedbin = 0xffff;
- adreno_gpu->speedbin = (uint16_t) (0xffff & speedbin);
-
gpu_name = devm_kasprintf(dev, GFP_KERNEL, "%"ADRENO_CHIPID_FMT,
ADRENO_CHIPID_ARGS(config->chip_id));
if (!gpu_name)
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
index 1d0145f8b3ec..ec643b84646b 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
@@ -63,25 +63,24 @@ enum adreno_family {
#define ADRENO_QUIRK_PREEMPTION BIT(5)
#define ADRENO_QUIRK_4GB_VA BIT(6)
#define ADRENO_QUIRK_IFPC BIT(7)
+#define ADRENO_QUIRK_SOFTFUSE BIT(8)
/* Helper for formating the chip_id in the way that userspace tools like
* crashdec expect.
*/
-#define ADRENO_CHIPID_FMT "u.%u.%u.%u"
-#define ADRENO_CHIPID_ARGS(_c) \
- (((_c) >> 24) & 0xff), \
- (((_c) >> 16) & 0xff), \
- (((_c) >> 8) & 0xff), \
- ((_c) & 0xff)
+#define ADRENO_CHIPID_FMT "08x"
+#define ADRENO_CHIPID_ARGS(_c) (_c)
struct adreno_gpu;
struct adreno_gpu_funcs {
struct msm_gpu_funcs base;
struct msm_gpu *(*init)(struct drm_device *dev);
- int (*get_timestamp)(struct msm_gpu *gpu, uint64_t *value);
+ u64 (*get_timestamp)(struct msm_gpu *gpu);
void (*bus_halt)(struct adreno_gpu *adreno_gpu, bool gx_off);
int (*mmu_fault_handler)(void *arg, unsigned long iova, int flags, void *data);
+ bool (*gx_is_on)(struct adreno_gpu *adreno_gpu);
+ bool (*aqe_is_enabled)(struct adreno_gpu *adreno_gpu);
};
struct adreno_reglist {
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_10_0_sm8650.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_10_0_sm8650.h
index 56d3c38c8778..2eef5f69832f 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_10_0_sm8650.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_10_0_sm8650.h
@@ -322,7 +322,6 @@ static const struct dpu_wb_cfg sm8650_wb[] = {
.format_list = wb2_formats_rgb_yuv,
.num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv),
.xin_id = 6,
- .vbif_idx = VBIF_RT,
.maxlinewidth = 4096,
.intr_wb_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 4),
},
@@ -378,7 +377,7 @@ static const struct dpu_intf_cfg sm8650_intf[] = {
.name = "intf_3", .id = INTF_3,
.base = 0x37000, .len = 0x280,
.type = INTF_DP,
- .controller_id = MSM_DP_CONTROLLER_1,
+ .controller_id = MSM_DP_CONTROLLER_0, /* pair with intf_0 for DP MST */
.prog_fetch_lines_worst_case = 24,
.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30),
.intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31),
@@ -445,8 +444,7 @@ const struct dpu_mdss_cfg dpu_sm8650_cfg = {
.cwb = sm8650_cwb,
.intf_count = ARRAY_SIZE(sm8650_intf),
.intf = sm8650_intf,
- .vbif_count = ARRAY_SIZE(sm8650_vbif),
- .vbif = sm8650_vbif,
+ .vbif = &sm8650_vbif,
.perf = &sm8650_perf_data,
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_0_sm8750.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_0_sm8750.h
index db8cc2d0112c..3889eb8a5428 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_0_sm8750.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_0_sm8750.h
@@ -364,7 +364,6 @@ static const struct dpu_wb_cfg sm8750_wb[] = {
.format_list = wb2_formats_rgb_yuv,
.num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv),
.xin_id = 6,
- .vbif_idx = VBIF_RT,
.maxlinewidth = 4096,
.intr_wb_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 4),
},
@@ -420,7 +419,7 @@ static const struct dpu_intf_cfg sm8750_intf[] = {
.name = "intf_3", .id = INTF_3,
.base = 0x37000, .len = 0x4bc,
.type = INTF_DP,
- .controller_id = MSM_DP_CONTROLLER_1,
+ .controller_id = MSM_DP_CONTROLLER_0, /* pair with intf_0 for DP MST */
.prog_fetch_lines_worst_case = 24,
.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30),
.intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31),
@@ -486,8 +485,7 @@ const struct dpu_mdss_cfg dpu_sm8750_cfg = {
.cwb = sm8650_cwb,
.intf_count = ARRAY_SIZE(sm8750_intf),
.intf = sm8750_intf,
- .vbif_count = ARRAY_SIZE(sm8650_vbif),
- .vbif = sm8650_vbif,
+ .vbif = &sm8650_vbif,
.perf = &sm8750_perf_data,
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_2_glymur.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_2_glymur.h
index 13bb43ba67d3..4eb4a0e9803e 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_2_glymur.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_2_glymur.h
@@ -371,7 +371,6 @@ static const struct dpu_wb_cfg glymur_wb[] = {
.format_list = wb2_formats_rgb_yuv,
.num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv),
.xin_id = 6,
- .vbif_idx = VBIF_RT,
.maxlinewidth = 4096,
.intr_wb_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 4),
},
@@ -426,7 +425,7 @@ static const struct dpu_intf_cfg glymur_intf[] = {
}, {
.name = "intf_3", .id = INTF_3,
.base = 0x37000, .len = 0x400,
- .type = INTF_NONE,
+ .type = INTF_DP,
.controller_id = MSM_DP_CONTROLLER_0, /* pair with intf_0 for DP MST */
.prog_fetch_lines_worst_case = 24,
.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30),
@@ -458,7 +457,7 @@ static const struct dpu_intf_cfg glymur_intf[] = {
}, {
.name = "intf_7", .id = INTF_7,
.base = 0x3b000, .len = 0x400,
- .type = INTF_NONE,
+ .type = INTF_DP,
.controller_id = MSM_DP_CONTROLLER_2, /* pair with intf_6 for DP MST */
.prog_fetch_lines_worst_case = 24,
.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 18),
@@ -466,7 +465,7 @@ static const struct dpu_intf_cfg glymur_intf[] = {
}, {
.name = "intf_8", .id = INTF_8,
.base = 0x3c000, .len = 0x400,
- .type = INTF_NONE,
+ .type = INTF_DP,
.controller_id = MSM_DP_CONTROLLER_1, /* pair with intf_4 for DP MST */
.prog_fetch_lines_worst_case = 24,
.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12),
@@ -533,8 +532,7 @@ const struct dpu_mdss_cfg dpu_glymur_cfg = {
.cwb = sm8650_cwb,
.intf_count = ARRAY_SIZE(glymur_intf),
.intf = glymur_intf,
- .vbif_count = ARRAY_SIZE(sm8650_vbif),
- .vbif = sm8650_vbif,
+ .vbif = &sm8650_vbif,
.perf = &glymur_perf_data,
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_4_eliza.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_4_eliza.h
new file mode 100644
index 000000000000..b93d32888972
--- /dev/null
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_4_eliza.h
@@ -0,0 +1,363 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef _DPU_12_4_ELIZA_H
+#define _DPU_12_4_ELIZA_H
+
+static const struct dpu_caps eliza_dpu_caps = {
+ .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
+ .max_mixer_blendstages = 0xb,
+ .has_src_split = true,
+ .has_dim_layer = true,
+ .has_idle_pc = true,
+ .has_3d_merge = true,
+ .max_linewidth = 8192,
+ .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
+};
+
+static const struct dpu_mdp_cfg eliza_mdp = {
+ .name = "top_0",
+ .base = 0, .len = 0x494,
+ .clk_ctrls = {
+ [DPU_CLK_CTRL_REG_DMA] = { .reg_off = 0x2bc, .bit_off = 20 },
+ },
+};
+
+static const struct dpu_ctl_cfg eliza_ctl[] = {
+ {
+ .name = "ctl_0", .id = CTL_0,
+ .base = 0x15000, .len = 0x1000,
+ .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9),
+ }, {
+ .name = "ctl_1", .id = CTL_1,
+ .base = 0x16000, .len = 0x1000,
+ .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10),
+ }, {
+ .name = "ctl_2", .id = CTL_2,
+ .base = 0x17000, .len = 0x1000,
+ .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11),
+ }, {
+ .name = "ctl_3", .id = CTL_3,
+ .base = 0x18000, .len = 0x1000,
+ .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12),
+ },
+};
+
+static const struct dpu_sspp_cfg eliza_sspp[] = {
+ {
+ .name = "sspp_0", .id = SSPP_VIG0,
+ .base = 0x4000, .len = 0x344,
+ .features = VIG_SDM845_MASK_SDMA,
+ .sblk = &dpu_vig_sblk_qseed3_3_4,
+ .xin_id = 0,
+ .type = SSPP_TYPE_VIG,
+ }, {
+ .name = "sspp_1", .id = SSPP_VIG1,
+ .base = 0x6000, .len = 0x344,
+ .features = VIG_SDM845_MASK_SDMA,
+ .sblk = &dpu_vig_sblk_qseed3_3_4,
+ .xin_id = 4,
+ .type = SSPP_TYPE_VIG,
+ }, {
+ .name = "sspp_8", .id = SSPP_DMA0,
+ .base = 0x24000, .len = 0x344,
+ .features = DMA_SDM845_MASK_SDMA,
+ .sblk = &dpu_dma_sblk,
+ .xin_id = 1,
+ .type = SSPP_TYPE_DMA,
+ }, {
+ .name = "sspp_9", .id = SSPP_DMA1,
+ .base = 0x26000, .len = 0x344,
+ .features = DMA_SDM845_MASK_SDMA,
+ .sblk = &dpu_dma_sblk,
+ .xin_id = 5,
+ .type = SSPP_TYPE_DMA,
+ }, {
+ .name = "sspp_10", .id = SSPP_DMA2,
+ .base = 0x28000, .len = 0x344,
+ .features = DMA_SDM845_MASK_SDMA,
+ .sblk = &dpu_dma_sblk,
+ .xin_id = 9,
+ .type = SSPP_TYPE_DMA,
+ }, {
+ .name = "sspp_11", .id = SSPP_DMA3,
+ .base = 0x2a000, .len = 0x344,
+ .features = DMA_SDM845_MASK_SDMA,
+ .sblk = &dpu_dma_sblk,
+ .xin_id = 13,
+ .type = SSPP_TYPE_DMA,
+ },
+};
+
+static const struct dpu_lm_cfg eliza_lm[] = {
+ {
+ .name = "lm_0", .id = LM_0,
+ .base = 0x44000, .len = 0x400,
+ .features = MIXER_MSM8998_MASK,
+ .sblk = &sm8750_lm_sblk,
+ .lm_pair = LM_1,
+ .pingpong = PINGPONG_0,
+ .dspp = DSPP_0,
+ }, {
+ .name = "lm_1", .id = LM_1,
+ .base = 0x45000, .len = 0x400,
+ .features = MIXER_MSM8998_MASK,
+ .sblk = &sm8750_lm_sblk,
+ .lm_pair = LM_0,
+ .pingpong = PINGPONG_1,
+ .dspp = DSPP_1,
+ }, {
+ .name = "lm_2", .id = LM_2,
+ .base = 0x46000, .len = 0x400,
+ .features = MIXER_MSM8998_MASK,
+ .sblk = &sm8750_lm_sblk,
+ .lm_pair = LM_3,
+ .pingpong = PINGPONG_2,
+ .dspp = DSPP_2,
+ }, {
+ .name = "lm_3", .id = LM_3,
+ .base = 0x47000, .len = 0x400,
+ .features = MIXER_MSM8998_MASK,
+ .sblk = &sm8750_lm_sblk,
+ .lm_pair = LM_2,
+ .pingpong = PINGPONG_3,
+ },
+};
+
+static const struct dpu_dspp_cfg eliza_dspp[] = {
+ {
+ .name = "dspp_0", .id = DSPP_0,
+ .base = 0x54000, .len = 0x1800,
+ .sblk = &sm8750_dspp_sblk,
+ }, {
+ .name = "dspp_1", .id = DSPP_1,
+ .base = 0x56000, .len = 0x1800,
+ .sblk = &sm8750_dspp_sblk,
+ }, {
+ .name = "dspp_2", .id = DSPP_2,
+ .base = 0x58000, .len = 0x1800,
+ .sblk = &sm8750_dspp_sblk,
+ },
+};
+
+static const struct dpu_pingpong_cfg eliza_pp[] = {
+ {
+ .name = "pingpong_0", .id = PINGPONG_0,
+ .base = 0x69000, .len = 0,
+ .sblk = &sc7280_pp_sblk,
+ .merge_3d = MERGE_3D_0,
+ .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8),
+ }, {
+ .name = "pingpong_1", .id = PINGPONG_1,
+ .base = 0x6a000, .len = 0,
+ .sblk = &sc7280_pp_sblk,
+ .merge_3d = MERGE_3D_0,
+ .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9),
+ }, {
+ .name = "pingpong_2", .id = PINGPONG_2,
+ .base = 0x6b000, .len = 0,
+ .sblk = &sc7280_pp_sblk,
+ .merge_3d = MERGE_3D_1,
+ .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10),
+ }, {
+ .name = "pingpong_3", .id = PINGPONG_3,
+ .base = 0x6c000, .len = 0,
+ .sblk = &sc7280_pp_sblk,
+ .merge_3d = MERGE_3D_1,
+ .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11),
+ }, {
+ .name = "pingpong_cwb_0", .id = PINGPONG_CWB_0,
+ .base = 0x66000, .len = 0,
+ .sblk = &sc7280_pp_sblk,
+ .merge_3d = MERGE_3D_2,
+ }, {
+ .name = "pingpong_cwb_1", .id = PINGPONG_CWB_1,
+ .base = 0x66400, .len = 0,
+ .sblk = &sc7280_pp_sblk,
+ .merge_3d = MERGE_3D_2,
+ }, {
+ .name = "pingpong_cwb_2", .id = PINGPONG_CWB_2,
+ .base = 0x7e000, .len = 0,
+ .sblk = &sc7280_pp_sblk,
+ .merge_3d = MERGE_3D_3,
+ }, {
+ .name = "pingpong_cwb_3", .id = PINGPONG_CWB_3,
+ .base = 0x7e400, .len = 0,
+ .sblk = &sc7280_pp_sblk,
+ .merge_3d = MERGE_3D_3,
+ },
+};
+
+static const struct dpu_merge_3d_cfg eliza_merge_3d[] = {
+ {
+ .name = "merge_3d_0", .id = MERGE_3D_0,
+ .base = 0x4e000, .len = 0x1c,
+ }, {
+ .name = "merge_3d_1", .id = MERGE_3D_1,
+ .base = 0x4f000, .len = 0x1c,
+ }, {
+ .name = "merge_3d_2", .id = MERGE_3D_2,
+ .base = 0x66700, .len = 0x1c,
+ }, {
+ .name = "merge_3d_3", .id = MERGE_3D_3,
+ .base = 0x7e700, .len = 0x1c,
+ },
+};
+
+/*
+ * NOTE: Each display compression engine (DCE) contains dual hard
+ * slice DSC encoders so both share same base address but with
+ * its own different sub block address.
+ */
+static const struct dpu_dsc_cfg eliza_dsc[] = {
+ {
+ .name = "dce_0_0", .id = DSC_0,
+ .base = 0x80000, .len = 0x8,
+ .features = BIT(DPU_DSC_NATIVE_42x_EN),
+ .sblk = &sm8750_dsc_sblk_0,
+ }, {
+ .name = "dce_0_1", .id = DSC_1,
+ .base = 0x80000, .len = 0x8,
+ .features = BIT(DPU_DSC_NATIVE_42x_EN),
+ .sblk = &sm8750_dsc_sblk_1,
+ }, {
+ .name = "dce_1_0", .id = DSC_2,
+ .base = 0x81000, .len = 0x8,
+ .features = BIT(DPU_DSC_NATIVE_42x_EN),
+ .sblk = &sm8750_dsc_sblk_0,
+ },
+};
+
+static const struct dpu_wb_cfg eliza_wb[] = {
+ {
+ .name = "wb_2", .id = WB_2,
+ .base = 0x65000, .len = 0x2c8,
+ .features = WB_SDM845_MASK,
+ .format_list = wb2_formats_rgb_yuv,
+ .num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv),
+ .xin_id = 6,
+ .maxlinewidth = 4096,
+ .intr_wb_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 4),
+ },
+};
+
+static const struct dpu_cwb_cfg eliza_cwb[] = {
+ {
+ .name = "cwb_0", .id = CWB_0,
+ .base = 0x66200, .len = 0x20,
+ },
+ {
+ .name = "cwb_1", .id = CWB_1,
+ .base = 0x66600, .len = 0x20,
+ },
+ {
+ .name = "cwb_2", .id = CWB_2,
+ .base = 0x7e200, .len = 0x20,
+ },
+ {
+ .name = "cwb_3", .id = CWB_3,
+ .base = 0x7e600, .len = 0x20,
+ },
+};
+
+static const struct dpu_intf_cfg eliza_intf[] = {
+ {
+ .name = "intf_0", .id = INTF_0,
+ .base = 0x34000, .len = 0x4bc,
+ .type = INTF_DP,
+ .controller_id = MSM_DP_CONTROLLER_0,
+ .prog_fetch_lines_worst_case = 24,
+ .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24),
+ .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25),
+ }, {
+ .name = "intf_1", .id = INTF_1,
+ .base = 0x35000, .len = 0x4bc,
+ .type = INTF_DSI,
+ .controller_id = MSM_DSI_CONTROLLER_0,
+ .prog_fetch_lines_worst_case = 24,
+ .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26),
+ .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27),
+ .intr_tear_rd_ptr = DPU_IRQ_IDX(MDP_INTF1_TEAR_INTR, 2),
+ }, {
+ .name = "intf_2", .id = INTF_2,
+ .base = 0x36000, .len = 0x4bc,
+ .type = INTF_DSI,
+ .controller_id = MSM_DSI_CONTROLLER_1,
+ .prog_fetch_lines_worst_case = 24,
+ .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 28),
+ .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 29),
+ .intr_tear_rd_ptr = DPU_IRQ_IDX(MDP_INTF2_TEAR_INTR, 2),
+ }, {
+ .name = "intf_3", .id = INTF_3,
+ .base = 0x37000, .len = 0x4bc,
+ .type = INTF_DP,
+ .controller_id = MSM_DP_CONTROLLER_0, /* pair with intf_0 for DP MST */
+ .prog_fetch_lines_worst_case = 24,
+ .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30),
+ .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31),
+ }
+};
+
+static const struct dpu_perf_cfg eliza_perf_data = {
+ .max_bw_low = 6800000,
+ .max_bw_high = 14200000,
+ .min_core_ib = 2500000,
+ .min_llcc_ib = 0,
+ .min_dram_ib = 1600000,
+ .min_prefill_lines = 35,
+ .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_mdss_version eliza_mdss_ver = {
+ .core_major_ver = 12,
+ .core_minor_ver = 4,
+};
+
+const struct dpu_mdss_cfg dpu_eliza_cfg = {
+ .mdss_ver = &eliza_mdss_ver,
+ .caps = &eliza_dpu_caps,
+ .mdp = &eliza_mdp,
+ .cdm = &dpu_cdm_5_x,
+ .ctl_count = ARRAY_SIZE(eliza_ctl),
+ .ctl = eliza_ctl,
+ .sspp_count = ARRAY_SIZE(eliza_sspp),
+ .sspp = eliza_sspp,
+ .mixer_count = ARRAY_SIZE(eliza_lm),
+ .mixer = eliza_lm,
+ .dspp_count = ARRAY_SIZE(eliza_dspp),
+ .dspp = eliza_dspp,
+ .pingpong_count = ARRAY_SIZE(eliza_pp),
+ .pingpong = eliza_pp,
+ .dsc_count = ARRAY_SIZE(eliza_dsc),
+ .dsc = eliza_dsc,
+ .merge_3d_count = ARRAY_SIZE(eliza_merge_3d),
+ .merge_3d = eliza_merge_3d,
+ .wb_count = ARRAY_SIZE(eliza_wb),
+ .wb = eliza_wb,
+ .cwb_count = ARRAY_SIZE(eliza_cwb),
+ .cwb = eliza_cwb,
+ .intf_count = ARRAY_SIZE(eliza_intf),
+ .intf = eliza_intf,
+ .vbif = &sm8650_vbif,
+ .perf = &eliza_perf_data,
+};
+
+#endif
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_13_0_kaanapali.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_13_0_kaanapali.h
index 0b20401b04cf..b7b06e45b529 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_13_0_kaanapali.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_13_0_kaanapali.h
@@ -362,7 +362,6 @@ static const struct dpu_wb_cfg kaanapali_wb[] = {
.format_list = wb2_formats_rgb_yuv,
.num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv),
.xin_id = 6,
- .vbif_idx = VBIF_RT,
.maxlinewidth = 4096,
.intr_wb_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 4),
},
@@ -418,7 +417,7 @@ static const struct dpu_intf_cfg kaanapali_intf[] = {
.name = "intf_3", .id = INTF_3,
.base = 0x190000, .len = 0x4bc,
.type = INTF_DP,
- .controller_id = MSM_DP_CONTROLLER_1,
+ .controller_id = MSM_DP_CONTROLLER_0, /* pair with intf_0 for DP MST */
.prog_fetch_lines_worst_case = 24,
.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30),
.intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31),
@@ -484,8 +483,7 @@ const struct dpu_mdss_cfg dpu_kaanapali_cfg = {
.cwb = sm8650_cwb,
.intf_count = ARRAY_SIZE(kaanapali_intf),
.intf = kaanapali_intf,
- .vbif_count = ARRAY_SIZE(sm8650_vbif),
- .vbif = sm8650_vbif,
+ .vbif = &sm8650_vbif,
.perf = &kaanapali_perf_data,
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_14_msm8937.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_14_msm8937.h
index 29e0eba91930..4ff7b397f808 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_14_msm8937.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_14_msm8937.h
@@ -197,8 +197,7 @@ const struct dpu_mdss_cfg dpu_msm8937_cfg = {
.pingpong = msm8937_pp,
.intf_count = ARRAY_SIZE(msm8937_intf),
.intf = msm8937_intf,
- .vbif_count = ARRAY_SIZE(msm8996_vbif),
- .vbif = msm8996_vbif,
+ .vbif = &msm8996_vbif,
.perf = &msm8937_perf_data,
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_15_msm8917.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_15_msm8917.h
index cb1ee4b63f9f..1518c3d39ce8 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_15_msm8917.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_15_msm8917.h
@@ -176,8 +176,7 @@ const struct dpu_mdss_cfg dpu_msm8917_cfg = {
.pingpong = msm8917_pp,
.intf_count = ARRAY_SIZE(msm8917_intf),
.intf = msm8917_intf,
- .vbif_count = ARRAY_SIZE(msm8996_vbif),
- .vbif = msm8996_vbif,
+ .vbif = &msm8996_vbif,
.perf = &msm8917_perf_data,
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_16_msm8953.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_16_msm8953.h
index b44d02b48418..859a97e8c07e 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_16_msm8953.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_16_msm8953.h
@@ -121,13 +121,6 @@ static const struct dpu_dspp_cfg msm8953_dspp[] = {
static const struct dpu_intf_cfg msm8953_intf[] = {
{
- .name = "intf_0", .id = INTF_0,
- .base = 0x6a000, .len = 0x268,
- .type = INTF_NONE,
- .prog_fetch_lines_worst_case = 14,
- .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24),
- .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25),
- }, {
.name = "intf_1", .id = INTF_1,
.base = 0x6a800, .len = 0x268,
.type = INTF_DSI,
@@ -204,8 +197,7 @@ const struct dpu_mdss_cfg dpu_msm8953_cfg = {
.pingpong = msm8953_pp,
.intf_count = ARRAY_SIZE(msm8953_intf),
.intf = msm8953_intf,
- .vbif_count = ARRAY_SIZE(msm8996_vbif),
- .vbif = msm8996_vbif,
+ .vbif = &msm8996_vbif,
.perf = &msm8953_perf_data,
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_7_msm8996.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_7_msm8996.h
index 8af63db315b4..67910a2f6880 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_7_msm8996.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_7_msm8996.h
@@ -320,8 +320,7 @@ const struct dpu_mdss_cfg dpu_msm8996_cfg = {
.dsc = msm8996_dsc,
.intf_count = ARRAY_SIZE(msm8996_intf),
.intf = msm8996_intf,
- .vbif_count = ARRAY_SIZE(msm8996_vbif),
- .vbif = msm8996_vbif,
+ .vbif = &msm8996_vbif,
.perf = &msm8996_perf_data,
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h
index b1b03d8b30fa..67c1463d3bd6 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h
@@ -305,8 +305,7 @@ const struct dpu_mdss_cfg dpu_msm8998_cfg = {
.dsc = msm8998_dsc,
.intf_count = ARRAY_SIZE(msm8998_intf),
.intf = msm8998_intf,
- .vbif_count = ARRAY_SIZE(msm8998_vbif),
- .vbif = msm8998_vbif,
+ .vbif = &msm8998_vbif,
.perf = &msm8998_perf_data,
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_2_sdm660.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_2_sdm660.h
index 64df4e80ea43..84344029819f 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_2_sdm660.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_2_sdm660.h
@@ -269,8 +269,7 @@ const struct dpu_mdss_cfg dpu_sdm660_cfg = {
.dsc = sdm660_dsc,
.intf_count = ARRAY_SIZE(sdm660_intf),
.intf = sdm660_intf,
- .vbif_count = ARRAY_SIZE(msm8998_vbif),
- .vbif = msm8998_vbif,
+ .vbif = &msm8998_vbif,
.perf = &sdm660_perf_data,
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_3_sdm630.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_3_sdm630.h
index b409af899918..ef5777aee587 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_3_sdm630.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_3_sdm630.h
@@ -207,8 +207,7 @@ const struct dpu_mdss_cfg dpu_sdm630_cfg = {
.pingpong = sdm630_pp,
.intf_count = ARRAY_SIZE(sdm630_intf),
.intf = sdm630_intf,
- .vbif_count = ARRAY_SIZE(msm8998_vbif),
- .vbif = msm8998_vbif,
+ .vbif = &msm8998_vbif,
.perf = &sdm630_perf_data,
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h
index 5cc9f55d542b..b608d2bb6d48 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h
@@ -258,7 +258,7 @@ static const struct dpu_intf_cfg sdm845_intf[] = {
.name = "intf_3", .id = INTF_3,
.base = 0x6b800, .len = 0x280,
.type = INTF_DP,
- .controller_id = MSM_DP_CONTROLLER_1,
+ .controller_id = MSM_DP_CONTROLLER_0, /* pair with intf_0 for DP MST */
.prog_fetch_lines_worst_case = 24,
.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30),
.intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31),
@@ -325,8 +325,7 @@ const struct dpu_mdss_cfg dpu_sdm845_cfg = {
.dsc = sdm845_dsc,
.intf_count = ARRAY_SIZE(sdm845_intf),
.intf = sdm845_intf,
- .vbif_count = ARRAY_SIZE(sdm845_vbif),
- .vbif = sdm845_vbif,
+ .vbif = &sdm845_vbif,
.perf = &sdm845_perf_data,
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_1_sdm670.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_1_sdm670.h
index 0f5e9babdeea..54b4a83ee16e 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_1_sdm670.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_1_sdm670.h
@@ -144,8 +144,7 @@ const struct dpu_mdss_cfg dpu_sdm670_cfg = {
.dsc = sdm670_dsc,
.intf_count = ARRAY_SIZE(sdm845_intf),
.intf = sdm845_intf,
- .vbif_count = ARRAY_SIZE(sdm845_vbif),
- .vbif = sdm845_vbif,
+ .vbif = &sdm845_vbif,
.perf = &sdm845_perf_data,
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h
index ae1b2ed96e9f..9729a65d3e3a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h
@@ -280,7 +280,6 @@ static const struct dpu_wb_cfg sm8150_wb[] = {
.num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv),
.clk_ctrl = DPU_CLK_CTRL_WB2,
.xin_id = 6,
- .vbif_idx = VBIF_RT,
.maxlinewidth = 4096,
.intr_wb_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 4),
},
@@ -317,7 +316,7 @@ static const struct dpu_intf_cfg sm8150_intf[] = {
.name = "intf_3", .id = INTF_3,
.base = 0x6b800, .len = 0x280,
.type = INTF_DP,
- .controller_id = MSM_DP_CONTROLLER_1,
+ .controller_id = MSM_DP_CONTROLLER_0, /* pair with intf_0 for DP MST */
.prog_fetch_lines_worst_case = 24,
.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30),
.intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31),
@@ -381,8 +380,7 @@ const struct dpu_mdss_cfg dpu_sm8150_cfg = {
.wb = sm8150_wb,
.intf_count = ARRAY_SIZE(sm8150_intf),
.intf = sm8150_intf,
- .vbif_count = ARRAY_SIZE(sdm845_vbif),
- .vbif = sdm845_vbif,
+ .vbif = &sdm845_vbif,
.perf = &sm8150_perf_data,
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h
index b572cfa7ed35..fb18de029e80 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h
@@ -286,7 +286,6 @@ static const struct dpu_wb_cfg sc8180x_wb[] = {
.num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv),
.clk_ctrl = DPU_CLK_CTRL_WB2,
.xin_id = 6,
- .vbif_idx = VBIF_RT,
.maxlinewidth = 4096,
.intr_wb_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 4),
},
@@ -405,8 +404,7 @@ const struct dpu_mdss_cfg dpu_sc8180x_cfg = {
.wb = sc8180x_wb,
.intf_count = ARRAY_SIZE(sc8180x_intf),
.intf = sc8180x_intf,
- .vbif_count = ARRAY_SIZE(sdm845_vbif),
- .vbif = sdm845_vbif,
+ .vbif = &sdm845_vbif,
.perf = &sc8180x_perf_data,
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_2_sm7150.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_2_sm7150.h
index a56c288ac10c..92a614686cb6 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_2_sm7150.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_2_sm7150.h
@@ -230,7 +230,7 @@ static const struct dpu_intf_cfg sm7150_intf[] = {
.name = "intf_3", .id = INTF_3,
.base = 0x6b800, .len = 0x280,
.type = INTF_DP,
- .controller_id = MSM_DP_CONTROLLER_1,
+ .controller_id = MSM_DP_CONTROLLER_0, /* pair with intf_0 for DP MST */
.prog_fetch_lines_worst_case = 24,
.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30),
.intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31),
@@ -246,7 +246,6 @@ static const struct dpu_wb_cfg sm7150_wb[] = {
.num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv),
.clk_ctrl = DPU_CLK_CTRL_WB2,
.xin_id = 6,
- .vbif_idx = VBIF_RT,
.maxlinewidth = 4096,
.intr_wb_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 4),
},
@@ -309,8 +308,7 @@ const struct dpu_mdss_cfg dpu_sm7150_cfg = {
.intf = sm7150_intf,
.wb_count = ARRAY_SIZE(sm7150_wb),
.wb = sm7150_wb,
- .vbif_count = ARRAY_SIZE(sdm845_vbif),
- .vbif = sdm845_vbif,
+ .vbif = &sdm845_vbif,
.perf = &sm7150_perf_data,
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_3_sm6150.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_3_sm6150.h
index 26883f6b66b3..87488d3ed95f 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_3_sm6150.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_3_sm6150.h
@@ -158,7 +158,6 @@ static const struct dpu_wb_cfg sm6150_wb[] = {
.num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv),
.clk_ctrl = DPU_CLK_CTRL_WB2,
.xin_id = 6,
- .vbif_idx = VBIF_RT,
.maxlinewidth = 2160,
.intr_wb_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 4),
},
@@ -186,7 +185,7 @@ static const struct dpu_intf_cfg sm6150_intf[] = {
.name = "intf_3", .id = INTF_3,
.base = 0x6b800, .len = 0x280,
.type = INTF_DP,
- .controller_id = MSM_DP_CONTROLLER_1,
+ .controller_id = MSM_DP_CONTROLLER_0, /* pair with intf_0 for DP MST */
.prog_fetch_lines_worst_case = 24,
.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30),
.intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31),
@@ -246,8 +245,7 @@ const struct dpu_mdss_cfg dpu_sm6150_cfg = {
.wb = sm6150_wb,
.intf_count = ARRAY_SIZE(sm6150_intf),
.intf = sm6150_intf,
- .vbif_count = ARRAY_SIZE(sdm845_vbif),
- .vbif = sdm845_vbif,
+ .vbif = &sdm845_vbif,
.perf = &sm6150_perf_data,
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_4_sm6125.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_4_sm6125.h
index fbf50f279e66..64be51e30159 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_4_sm6125.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_4_sm6125.h
@@ -137,7 +137,6 @@ static const struct dpu_wb_cfg sm6125_wb[] = {
.num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv),
.clk_ctrl = DPU_CLK_CTRL_WB2,
.xin_id = 6,
- .vbif_idx = VBIF_RT,
.maxlinewidth = 2160,
.intr_wb_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 4),
},
@@ -217,8 +216,7 @@ const struct dpu_mdss_cfg dpu_sm6125_cfg = {
.wb = sm6125_wb,
.intf_count = ARRAY_SIZE(sm6125_intf),
.intf = sm6125_intf,
- .vbif_count = ARRAY_SIZE(sdm845_vbif),
- .vbif = sdm845_vbif,
+ .vbif = &sdm845_vbif,
.perf = &sm6125_perf_data,
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h
index 7b8b7a1c2d76..0e311d54ef18 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h
@@ -301,7 +301,7 @@ static const struct dpu_intf_cfg sm8250_intf[] = {
.name = "intf_3", .id = INTF_3,
.base = 0x6b800, .len = 0x280,
.type = INTF_DP,
- .controller_id = MSM_DP_CONTROLLER_1,
+ .controller_id = MSM_DP_CONTROLLER_0, /* pair with intf_0 for DP MST */
.prog_fetch_lines_worst_case = 24,
.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30),
.intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31),
@@ -317,7 +317,6 @@ static const struct dpu_wb_cfg sm8250_wb[] = {
.num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv),
.clk_ctrl = DPU_CLK_CTRL_WB2,
.xin_id = 6,
- .vbif_idx = VBIF_RT,
.maxlinewidth = 4096,
.intr_wb_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 4),
},
@@ -378,8 +377,7 @@ const struct dpu_mdss_cfg dpu_sm8250_cfg = {
.merge_3d = sm8250_merge_3d,
.intf_count = ARRAY_SIZE(sm8250_intf),
.intf = sm8250_intf,
- .vbif_count = ARRAY_SIZE(sdm845_vbif),
- .vbif = sdm845_vbif,
+ .vbif = &sdm845_vbif,
.wb_count = ARRAY_SIZE(sm8250_wb),
.wb = sm8250_wb,
.perf = &sm8250_perf_data,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_2_sc7180.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_2_sc7180.h
index c990ba3b5db0..d6f7ee24ca93 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_2_sc7180.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_2_sc7180.h
@@ -153,7 +153,6 @@ static const struct dpu_wb_cfg sc7180_wb[] = {
.num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv),
.clk_ctrl = DPU_CLK_CTRL_WB2,
.xin_id = 6,
- .vbif_idx = VBIF_RT,
.maxlinewidth = 4096,
.intr_wb_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 4),
},
@@ -211,8 +210,7 @@ const struct dpu_mdss_cfg dpu_sc7180_cfg = {
.intf = sc7180_intf,
.wb_count = ARRAY_SIZE(sc7180_wb),
.wb = sc7180_wb,
- .vbif_count = ARRAY_SIZE(sdm845_vbif),
- .vbif = sdm845_vbif,
+ .vbif = &sdm845_vbif,
.perf = &sc7180_perf_data,
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_3_sm6115.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_3_sm6115.h
index 343ff5482382..20a2e9ff5cc9 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_3_sm6115.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_3_sm6115.h
@@ -144,8 +144,7 @@ const struct dpu_mdss_cfg dpu_sm6115_cfg = {
.pingpong = sm6115_pp,
.intf_count = ARRAY_SIZE(sm6115_intf),
.intf = sm6115_intf,
- .vbif_count = ARRAY_SIZE(sdm845_vbif),
- .vbif = sdm845_vbif,
+ .vbif = &sdm845_vbif,
.perf = &sm6115_perf_data,
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_4_sm6350.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_4_sm6350.h
index 093d16bdc450..dd891703e35f 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_4_sm6350.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_4_sm6350.h
@@ -147,7 +147,6 @@ static const struct dpu_wb_cfg sm6350_wb[] = {
.num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv),
.clk_ctrl = DPU_CLK_CTRL_WB2,
.xin_id = 6,
- .vbif_idx = VBIF_RT,
.maxlinewidth = 1920,
.intr_wb_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 4),
},
@@ -229,8 +228,7 @@ const struct dpu_mdss_cfg dpu_sm6350_cfg = {
.wb = sm6350_wb,
.intf_count = ARRAY_SIZE(sm6350_intf),
.intf = sm6350_intf,
- .vbif_count = ARRAY_SIZE(sdm845_vbif),
- .vbif = sdm845_vbif,
+ .vbif = &sdm845_vbif,
.perf = &sm6350_perf_data,
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_5_qcm2290.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_5_qcm2290.h
index 47053bf9b0a2..7ae7530aa3b0 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_5_qcm2290.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_5_qcm2290.h
@@ -137,8 +137,7 @@ const struct dpu_mdss_cfg dpu_qcm2290_cfg = {
.pingpong = qcm2290_pp,
.intf_count = ARRAY_SIZE(qcm2290_intf),
.intf = qcm2290_intf,
- .vbif_count = ARRAY_SIZE(sdm845_vbif),
- .vbif = sdm845_vbif,
+ .vbif = &sdm845_vbif,
.perf = &qcm2290_perf_data,
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_9_sm6375.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_9_sm6375.h
index 98190ee7ec7a..fc7ceac859be 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_9_sm6375.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_9_sm6375.h
@@ -155,8 +155,7 @@ const struct dpu_mdss_cfg dpu_sm6375_cfg = {
.pingpong = sm6375_pp,
.intf_count = ARRAY_SIZE(sm6375_intf),
.intf = sm6375_intf,
- .vbif_count = ARRAY_SIZE(sdm845_vbif),
- .vbif = sdm845_vbif,
+ .vbif = &sdm845_vbif,
.perf = &sm6375_perf_data,
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_0_sm8350.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_0_sm8350.h
index 85aae40c210f..d06c14f05faf 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_0_sm8350.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_0_sm8350.h
@@ -290,7 +290,6 @@ static const struct dpu_wb_cfg sm8350_wb[] = {
.num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv),
.clk_ctrl = DPU_CLK_CTRL_WB2,
.xin_id = 6,
- .vbif_idx = VBIF_RT,
.maxlinewidth = 4096,
.intr_wb_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 4),
},
@@ -327,7 +326,7 @@ static const struct dpu_intf_cfg sm8350_intf[] = {
.name = "intf_3", .id = INTF_3,
.base = 0x37000, .len = 0x280,
.type = INTF_DP,
- .controller_id = MSM_DP_CONTROLLER_1,
+ .controller_id = MSM_DP_CONTROLLER_0, /* pair with intf_0 for DP MST */
.prog_fetch_lines_worst_case = 24,
.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30),
.intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31),
@@ -392,8 +391,7 @@ const struct dpu_mdss_cfg dpu_sm8350_cfg = {
.wb = sm8350_wb,
.intf_count = ARRAY_SIZE(sm8350_intf),
.intf = sm8350_intf,
- .vbif_count = ARRAY_SIZE(sdm845_vbif),
- .vbif = sdm845_vbif,
+ .vbif = &sdm845_vbif,
.perf = &sm8350_perf_data,
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h
index 2f8688224f34..99b8a890fddc 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h
@@ -172,7 +172,6 @@ static const struct dpu_wb_cfg sc7280_wb[] = {
.num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv),
.clk_ctrl = DPU_CLK_CTRL_WB2,
.xin_id = 6,
- .vbif_idx = VBIF_RT,
.maxlinewidth = 4096,
.intr_wb_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 4),
},
@@ -263,8 +262,7 @@ const struct dpu_mdss_cfg dpu_sc7280_cfg = {
.wb = sc7280_wb,
.intf_count = ARRAY_SIZE(sc7280_intf),
.intf = sc7280_intf,
- .vbif_count = ARRAY_SIZE(sdm845_vbif),
- .vbif = sdm845_vbif,
+ .vbif = &sdm845_vbif,
.perf = &sc7280_perf_data,
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h
index 303d33dc7783..0ba907711d36 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h
@@ -133,7 +133,7 @@ static const struct dpu_sspp_cfg sc8280xp_sspp[] = {
static const struct dpu_lm_cfg sc8280xp_lm[] = {
{
.name = "lm_0", .id = LM_0,
- .base = 0x44000, .len = 0x320,
+ .base = 0x44000, .len = 0x400,
.features = MIXER_MSM8998_MASK,
.sblk = &sdm845_lm_sblk,
.lm_pair = LM_1,
@@ -141,7 +141,7 @@ static const struct dpu_lm_cfg sc8280xp_lm[] = {
.dspp = DSPP_0,
}, {
.name = "lm_1", .id = LM_1,
- .base = 0x45000, .len = 0x320,
+ .base = 0x45000, .len = 0x400,
.features = MIXER_MSM8998_MASK,
.sblk = &sdm845_lm_sblk,
.lm_pair = LM_0,
@@ -149,7 +149,7 @@ static const struct dpu_lm_cfg sc8280xp_lm[] = {
.dspp = DSPP_1,
}, {
.name = "lm_2", .id = LM_2,
- .base = 0x46000, .len = 0x320,
+ .base = 0x46000, .len = 0x400,
.features = MIXER_MSM8998_MASK,
.sblk = &sdm845_lm_sblk,
.lm_pair = LM_3,
@@ -157,7 +157,7 @@ static const struct dpu_lm_cfg sc8280xp_lm[] = {
.dspp = DSPP_2,
}, {
.name = "lm_3", .id = LM_3,
- .base = 0x47000, .len = 0x320,
+ .base = 0x47000, .len = 0x400,
.features = MIXER_MSM8998_MASK,
.sblk = &sdm845_lm_sblk,
.lm_pair = LM_2,
@@ -165,14 +165,14 @@ static const struct dpu_lm_cfg sc8280xp_lm[] = {
.dspp = DSPP_3,
}, {
.name = "lm_4", .id = LM_4,
- .base = 0x48000, .len = 0x320,
+ .base = 0x48000, .len = 0x400,
.features = MIXER_MSM8998_MASK,
.sblk = &sdm845_lm_sblk,
.lm_pair = LM_5,
.pingpong = PINGPONG_4,
}, {
.name = "lm_5", .id = LM_5,
- .base = 0x49000, .len = 0x320,
+ .base = 0x49000, .len = 0x400,
.features = MIXER_MSM8998_MASK,
.sblk = &sdm845_lm_sblk,
.lm_pair = LM_4,
@@ -288,7 +288,6 @@ static const struct dpu_dsc_cfg sc8280xp_dsc[] = {
},
};
-/* TODO: INTF 3, 8 and 7 are used for MST, marked as INTF_NONE for now */
static const struct dpu_intf_cfg sc8280xp_intf[] = {
{
.name = "intf_0", .id = INTF_0,
@@ -319,8 +318,8 @@ static const struct dpu_intf_cfg sc8280xp_intf[] = {
}, {
.name = "intf_3", .id = INTF_3,
.base = 0x37000, .len = 0x280,
- .type = INTF_NONE,
- .controller_id = MSM_DP_CONTROLLER_0,
+ .type = INTF_DP,
+ .controller_id = MSM_DP_CONTROLLER_0, /* pair with intf_0 for DP MST */
.prog_fetch_lines_worst_case = 24,
.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30),
.intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31),
@@ -351,16 +350,16 @@ static const struct dpu_intf_cfg sc8280xp_intf[] = {
}, {
.name = "intf_7", .id = INTF_7,
.base = 0x3b000, .len = 0x280,
- .type = INTF_NONE,
- .controller_id = MSM_DP_CONTROLLER_2,
+ .type = INTF_DP,
+ .controller_id = MSM_DP_CONTROLLER_2, /* pair with intf_6 for DP MST */
.prog_fetch_lines_worst_case = 24,
.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 18),
.intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 19),
}, {
.name = "intf_8", .id = INTF_8,
.base = 0x3c000, .len = 0x280,
- .type = INTF_NONE,
- .controller_id = MSM_DP_CONTROLLER_1,
+ .type = INTF_DP,
+ .controller_id = MSM_DP_CONTROLLER_1, /* pair with intf_8 for DP MST */
.prog_fetch_lines_worst_case = 24,
.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12),
.intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13),
@@ -421,8 +420,7 @@ const struct dpu_mdss_cfg dpu_sc8280xp_cfg = {
.merge_3d = sc8280xp_merge_3d,
.intf_count = ARRAY_SIZE(sc8280xp_intf),
.intf = sc8280xp_intf,
- .vbif_count = ARRAY_SIZE(sdm845_vbif),
- .vbif = sdm845_vbif,
+ .vbif = &sdm845_vbif,
.perf = &sc8280xp_perf_data,
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h
index b09a6af4c474..170a709f987c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h
@@ -134,7 +134,7 @@ static const struct dpu_sspp_cfg sm8450_sspp[] = {
static const struct dpu_lm_cfg sm8450_lm[] = {
{
.name = "lm_0", .id = LM_0,
- .base = 0x44000, .len = 0x320,
+ .base = 0x44000, .len = 0x400,
.features = MIXER_MSM8998_MASK,
.sblk = &sdm845_lm_sblk,
.lm_pair = LM_1,
@@ -142,7 +142,7 @@ static const struct dpu_lm_cfg sm8450_lm[] = {
.dspp = DSPP_0,
}, {
.name = "lm_1", .id = LM_1,
- .base = 0x45000, .len = 0x320,
+ .base = 0x45000, .len = 0x400,
.features = MIXER_MSM8998_MASK,
.sblk = &sdm845_lm_sblk,
.lm_pair = LM_0,
@@ -150,7 +150,7 @@ static const struct dpu_lm_cfg sm8450_lm[] = {
.dspp = DSPP_1,
}, {
.name = "lm_2", .id = LM_2,
- .base = 0x46000, .len = 0x320,
+ .base = 0x46000, .len = 0x400,
.features = MIXER_MSM8998_MASK,
.sblk = &sdm845_lm_sblk,
.lm_pair = LM_3,
@@ -158,7 +158,7 @@ static const struct dpu_lm_cfg sm8450_lm[] = {
.dspp = DSPP_2,
}, {
.name = "lm_3", .id = LM_3,
- .base = 0x47000, .len = 0x320,
+ .base = 0x47000, .len = 0x400,
.features = MIXER_MSM8998_MASK,
.sblk = &sdm845_lm_sblk,
.lm_pair = LM_2,
@@ -166,14 +166,14 @@ static const struct dpu_lm_cfg sm8450_lm[] = {
.dspp = DSPP_3,
}, {
.name = "lm_4", .id = LM_4,
- .base = 0x48000, .len = 0x320,
+ .base = 0x48000, .len = 0x400,
.features = MIXER_MSM8998_MASK,
.sblk = &sdm845_lm_sblk,
.lm_pair = LM_5,
.pingpong = PINGPONG_4,
}, {
.name = "lm_5", .id = LM_5,
- .base = 0x49000, .len = 0x320,
+ .base = 0x49000, .len = 0x400,
.features = MIXER_MSM8998_MASK,
.sblk = &sdm845_lm_sblk,
.lm_pair = LM_4,
@@ -303,7 +303,6 @@ static const struct dpu_wb_cfg sm8450_wb[] = {
.num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv),
.clk_ctrl = DPU_CLK_CTRL_WB2,
.xin_id = 6,
- .vbif_idx = VBIF_RT,
.maxlinewidth = 4096,
.intr_wb_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 4),
},
@@ -340,7 +339,7 @@ static const struct dpu_intf_cfg sm8450_intf[] = {
.name = "intf_3", .id = INTF_3,
.base = 0x37000, .len = 0x280,
.type = INTF_DP,
- .controller_id = MSM_DP_CONTROLLER_1,
+ .controller_id = MSM_DP_CONTROLLER_0, /* pair with intf_0 for DP MST */
.prog_fetch_lines_worst_case = 24,
.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30),
.intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31),
@@ -405,8 +404,7 @@ const struct dpu_mdss_cfg dpu_sm8450_cfg = {
.wb = sm8450_wb,
.intf_count = ARRAY_SIZE(sm8450_intf),
.intf = sm8450_intf,
- .vbif_count = ARRAY_SIZE(sdm845_vbif),
- .vbif = sdm845_vbif,
+ .vbif = &sdm845_vbif,
.perf = &sm8450_perf_data,
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_4_sa8775p.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_4_sa8775p.h
index 0f7b4a224e4c..9cc5e22e1228 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_4_sa8775p.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_4_sa8775p.h
@@ -310,13 +310,11 @@ static const struct dpu_wb_cfg sa8775p_wb[] = {
.num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv),
.clk_ctrl = DPU_CLK_CTRL_WB2,
.xin_id = 6,
- .vbif_idx = VBIF_RT,
.maxlinewidth = 4096,
.intr_wb_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 4),
},
};
-/* TODO: INTF 3, 6, 7 and 8 are used for MST, marked as INTF_NONE for now */
static const struct dpu_intf_cfg sa8775p_intf[] = {
{
.name = "intf_0", .id = INTF_0,
@@ -347,7 +345,7 @@ static const struct dpu_intf_cfg sa8775p_intf[] = {
}, {
.name = "intf_3", .id = INTF_3,
.base = 0x37000, .len = 0x280,
- .type = INTF_NONE,
+ .type = INTF_DP,
.controller_id = MSM_DP_CONTROLLER_0, /* pair with intf_0 for DP MST */
.prog_fetch_lines_worst_case = 24,
.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30),
@@ -363,15 +361,15 @@ static const struct dpu_intf_cfg sa8775p_intf[] = {
}, {
.name = "intf_6", .id = INTF_6,
.base = 0x3A000, .len = 0x280,
- .type = INTF_NONE,
+ .type = INTF_DP,
.controller_id = MSM_DP_CONTROLLER_0, /* pair with intf_0 for DP MST */
.prog_fetch_lines_worst_case = 24,
- .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 17),
- .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 16),
+ .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 16),
+ .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 17),
}, {
.name = "intf_7", .id = INTF_7,
.base = 0x3b000, .len = 0x280,
- .type = INTF_NONE,
+ .type = INTF_DP,
.controller_id = MSM_DP_CONTROLLER_0, /* pair with intf_0 for DP MST */
.prog_fetch_lines_worst_case = 24,
.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 18),
@@ -379,7 +377,7 @@ static const struct dpu_intf_cfg sa8775p_intf[] = {
}, {
.name = "intf_8", .id = INTF_8,
.base = 0x3c000, .len = 0x280,
- .type = INTF_NONE,
+ .type = INTF_DP,
.controller_id = MSM_DP_CONTROLLER_1, /* pair with intf_4 for DP MST */
.prog_fetch_lines_worst_case = 24,
.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12),
@@ -445,8 +443,7 @@ const struct dpu_mdss_cfg dpu_sa8775p_cfg = {
.wb = sa8775p_wb,
.intf_count = ARRAY_SIZE(sa8775p_intf),
.intf = sa8775p_intf,
- .vbif_count = ARRAY_SIZE(sdm845_vbif),
- .vbif = sdm845_vbif,
+ .vbif = &sdm845_vbif,
.perf = &sa8775p_perf_data,
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h
index 465b6460f875..b3d0f221807b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h
@@ -131,7 +131,7 @@ static const struct dpu_sspp_cfg sm8550_sspp[] = {
static const struct dpu_lm_cfg sm8550_lm[] = {
{
.name = "lm_0", .id = LM_0,
- .base = 0x44000, .len = 0x320,
+ .base = 0x44000, .len = 0x400,
.features = MIXER_MSM8998_MASK,
.sblk = &sdm845_lm_sblk,
.lm_pair = LM_1,
@@ -139,7 +139,7 @@ static const struct dpu_lm_cfg sm8550_lm[] = {
.dspp = DSPP_0,
}, {
.name = "lm_1", .id = LM_1,
- .base = 0x45000, .len = 0x320,
+ .base = 0x45000, .len = 0x400,
.features = MIXER_MSM8998_MASK,
.sblk = &sdm845_lm_sblk,
.lm_pair = LM_0,
@@ -147,7 +147,7 @@ static const struct dpu_lm_cfg sm8550_lm[] = {
.dspp = DSPP_1,
}, {
.name = "lm_2", .id = LM_2,
- .base = 0x46000, .len = 0x320,
+ .base = 0x46000, .len = 0x400,
.features = MIXER_MSM8998_MASK,
.sblk = &sdm845_lm_sblk,
.lm_pair = LM_3,
@@ -155,7 +155,7 @@ static const struct dpu_lm_cfg sm8550_lm[] = {
.dspp = DSPP_2,
}, {
.name = "lm_3", .id = LM_3,
- .base = 0x47000, .len = 0x320,
+ .base = 0x47000, .len = 0x400,
.features = MIXER_MSM8998_MASK,
.sblk = &sdm845_lm_sblk,
.lm_pair = LM_2,
@@ -163,14 +163,14 @@ static const struct dpu_lm_cfg sm8550_lm[] = {
.dspp = DSPP_3,
}, {
.name = "lm_4", .id = LM_4,
- .base = 0x48000, .len = 0x320,
+ .base = 0x48000, .len = 0x400,
.features = MIXER_MSM8998_MASK,
.sblk = &sdm845_lm_sblk,
.lm_pair = LM_5,
.pingpong = PINGPONG_4,
}, {
.name = "lm_5", .id = LM_5,
- .base = 0x49000, .len = 0x320,
+ .base = 0x49000, .len = 0x400,
.features = MIXER_MSM8998_MASK,
.sblk = &sdm845_lm_sblk,
.lm_pair = LM_4,
@@ -298,7 +298,6 @@ static const struct dpu_wb_cfg sm8550_wb[] = {
.format_list = wb2_formats_rgb_yuv,
.num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv),
.xin_id = 6,
- .vbif_idx = VBIF_RT,
.maxlinewidth = 4096,
.intr_wb_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 4),
},
@@ -335,7 +334,7 @@ static const struct dpu_intf_cfg sm8550_intf[] = {
.name = "intf_3", .id = INTF_3,
.base = 0x37000, .len = 0x280,
.type = INTF_DP,
- .controller_id = MSM_DP_CONTROLLER_1,
+ .controller_id = MSM_DP_CONTROLLER_0, /* pair with intf_0 for DP MST */
.prog_fetch_lines_worst_case = 24,
.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30),
.intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31),
@@ -400,8 +399,7 @@ const struct dpu_mdss_cfg dpu_sm8550_cfg = {
.wb = sm8550_wb,
.intf_count = ARRAY_SIZE(sm8550_intf),
.intf = sm8550_intf,
- .vbif_count = ARRAY_SIZE(sm8550_vbif),
- .vbif = sm8550_vbif,
+ .vbif = &sm8550_vbif,
.perf = &sm8550_perf_data,
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_1_sar2130p.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_1_sar2130p.h
index 6caa7d40f368..7effe7120a56 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_1_sar2130p.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_1_sar2130p.h
@@ -131,7 +131,7 @@ static const struct dpu_sspp_cfg sar2130p_sspp[] = {
static const struct dpu_lm_cfg sar2130p_lm[] = {
{
.name = "lm_0", .id = LM_0,
- .base = 0x44000, .len = 0x320,
+ .base = 0x44000, .len = 0x400,
.features = MIXER_MSM8998_MASK,
.sblk = &sdm845_lm_sblk,
.lm_pair = LM_1,
@@ -139,7 +139,7 @@ static const struct dpu_lm_cfg sar2130p_lm[] = {
.dspp = DSPP_0,
}, {
.name = "lm_1", .id = LM_1,
- .base = 0x45000, .len = 0x320,
+ .base = 0x45000, .len = 0x400,
.features = MIXER_MSM8998_MASK,
.sblk = &sdm845_lm_sblk,
.lm_pair = LM_0,
@@ -147,7 +147,7 @@ static const struct dpu_lm_cfg sar2130p_lm[] = {
.dspp = DSPP_1,
}, {
.name = "lm_2", .id = LM_2,
- .base = 0x46000, .len = 0x320,
+ .base = 0x46000, .len = 0x400,
.features = MIXER_MSM8998_MASK,
.sblk = &sdm845_lm_sblk,
.lm_pair = LM_3,
@@ -155,7 +155,7 @@ static const struct dpu_lm_cfg sar2130p_lm[] = {
.dspp = DSPP_2,
}, {
.name = "lm_3", .id = LM_3,
- .base = 0x47000, .len = 0x320,
+ .base = 0x47000, .len = 0x400,
.features = MIXER_MSM8998_MASK,
.sblk = &sdm845_lm_sblk,
.lm_pair = LM_2,
@@ -163,14 +163,14 @@ static const struct dpu_lm_cfg sar2130p_lm[] = {
.dspp = DSPP_3,
}, {
.name = "lm_4", .id = LM_4,
- .base = 0x48000, .len = 0x320,
+ .base = 0x48000, .len = 0x400,
.features = MIXER_MSM8998_MASK,
.sblk = &sdm845_lm_sblk,
.lm_pair = LM_5,
.pingpong = PINGPONG_4,
}, {
.name = "lm_5", .id = LM_5,
- .base = 0x49000, .len = 0x320,
+ .base = 0x49000, .len = 0x400,
.features = MIXER_MSM8998_MASK,
.sblk = &sdm845_lm_sblk,
.lm_pair = LM_4,
@@ -298,7 +298,6 @@ static const struct dpu_wb_cfg sar2130p_wb[] = {
.format_list = wb2_formats_rgb_yuv,
.num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv),
.xin_id = 6,
- .vbif_idx = VBIF_RT,
.maxlinewidth = 4096,
.intr_wb_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 4),
},
@@ -335,7 +334,7 @@ static const struct dpu_intf_cfg sar2130p_intf[] = {
.name = "intf_3", .id = INTF_3,
.base = 0x37000, .len = 0x280,
.type = INTF_DP,
- .controller_id = MSM_DP_CONTROLLER_1,
+ .controller_id = MSM_DP_CONTROLLER_0, /* pair with intf_0 for DP MST */
.prog_fetch_lines_worst_case = 24,
.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30),
.intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31),
@@ -400,8 +399,7 @@ const struct dpu_mdss_cfg dpu_sar2130p_cfg = {
.wb = sar2130p_wb,
.intf_count = ARRAY_SIZE(sar2130p_intf),
.intf = sar2130p_intf,
- .vbif_count = ARRAY_SIZE(sm8550_vbif),
- .vbif = sm8550_vbif,
+ .vbif = &sm8550_vbif,
.perf = &sar2130p_perf_data,
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h
index 7243eebb85f3..7b3febf8742d 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h
@@ -130,7 +130,7 @@ static const struct dpu_sspp_cfg x1e80100_sspp[] = {
static const struct dpu_lm_cfg x1e80100_lm[] = {
{
.name = "lm_0", .id = LM_0,
- .base = 0x44000, .len = 0x320,
+ .base = 0x44000, .len = 0x400,
.features = MIXER_MSM8998_MASK,
.sblk = &sdm845_lm_sblk,
.lm_pair = LM_1,
@@ -138,7 +138,7 @@ static const struct dpu_lm_cfg x1e80100_lm[] = {
.dspp = DSPP_0,
}, {
.name = "lm_1", .id = LM_1,
- .base = 0x45000, .len = 0x320,
+ .base = 0x45000, .len = 0x400,
.features = MIXER_MSM8998_MASK,
.sblk = &sdm845_lm_sblk,
.lm_pair = LM_0,
@@ -146,7 +146,7 @@ static const struct dpu_lm_cfg x1e80100_lm[] = {
.dspp = DSPP_1,
}, {
.name = "lm_2", .id = LM_2,
- .base = 0x46000, .len = 0x320,
+ .base = 0x46000, .len = 0x400,
.features = MIXER_MSM8998_MASK,
.sblk = &sdm845_lm_sblk,
.lm_pair = LM_3,
@@ -154,7 +154,7 @@ static const struct dpu_lm_cfg x1e80100_lm[] = {
.dspp = DSPP_2,
}, {
.name = "lm_3", .id = LM_3,
- .base = 0x47000, .len = 0x320,
+ .base = 0x47000, .len = 0x400,
.features = MIXER_MSM8998_MASK,
.sblk = &sdm845_lm_sblk,
.lm_pair = LM_2,
@@ -162,14 +162,14 @@ static const struct dpu_lm_cfg x1e80100_lm[] = {
.dspp = DSPP_3,
}, {
.name = "lm_4", .id = LM_4,
- .base = 0x48000, .len = 0x320,
+ .base = 0x48000, .len = 0x400,
.features = MIXER_MSM8998_MASK,
.sblk = &sdm845_lm_sblk,
.lm_pair = LM_5,
.pingpong = PINGPONG_4,
}, {
.name = "lm_5", .id = LM_5,
- .base = 0x49000, .len = 0x320,
+ .base = 0x49000, .len = 0x400,
.features = MIXER_MSM8998_MASK,
.sblk = &sdm845_lm_sblk,
.lm_pair = LM_4,
@@ -298,13 +298,11 @@ static const struct dpu_wb_cfg x1e80100_wb[] = {
.format_list = wb2_formats_rgb_yuv,
.num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv),
.xin_id = 6,
- .vbif_idx = VBIF_RT,
.maxlinewidth = 4096,
.intr_wb_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 4),
},
};
-/* TODO: INTF 3, 8 and 7 are used for MST, marked as INTF_NONE for now */
static const struct dpu_intf_cfg x1e80100_intf[] = {
{
.name = "intf_0", .id = INTF_0,
@@ -335,7 +333,7 @@ static const struct dpu_intf_cfg x1e80100_intf[] = {
}, {
.name = "intf_3", .id = INTF_3,
.base = 0x37000, .len = 0x280,
- .type = INTF_NONE,
+ .type = INTF_DP,
.controller_id = MSM_DP_CONTROLLER_0, /* pair with intf_0 for DP MST */
.prog_fetch_lines_worst_case = 24,
.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30),
@@ -367,7 +365,7 @@ static const struct dpu_intf_cfg x1e80100_intf[] = {
}, {
.name = "intf_7", .id = INTF_7,
.base = 0x3b000, .len = 0x280,
- .type = INTF_NONE,
+ .type = INTF_DP,
.controller_id = MSM_DP_CONTROLLER_2, /* pair with intf_6 for DP MST */
.prog_fetch_lines_worst_case = 24,
.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 18),
@@ -375,7 +373,7 @@ static const struct dpu_intf_cfg x1e80100_intf[] = {
}, {
.name = "intf_8", .id = INTF_8,
.base = 0x3c000, .len = 0x280,
- .type = INTF_NONE,
+ .type = INTF_DP,
.controller_id = MSM_DP_CONTROLLER_1, /* pair with intf_4 for DP MST */
.prog_fetch_lines_worst_case = 24,
.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12),
@@ -441,8 +439,7 @@ const struct dpu_mdss_cfg dpu_x1e80100_cfg = {
.wb = x1e80100_wb,
.intf_count = ARRAY_SIZE(x1e80100_intf),
.intf = x1e80100_intf,
- .vbif_count = ARRAY_SIZE(sm8550_vbif),
- .vbif = sm8550_vbif,
+ .vbif = &sm8550_vbif,
.perf = &x1e80100_perf_data,
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 0f4921b1a892..411a6fa832b5 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -326,43 +326,39 @@ static void _dpu_crtc_setup_blend_cfg(struct dpu_crtc_mixer *mixer,
{
struct dpu_hw_mixer *lm = mixer->hw_lm;
u32 blend_op;
- u32 fg_alpha, bg_alpha, max_alpha;
+ u32 fg_alpha, bg_alpha;
- if (mdss_ver->core_major_ver < 12) {
- max_alpha = 0xff;
- fg_alpha = pstate->base.alpha >> 8;
- } else {
- max_alpha = 0x3ff;
- fg_alpha = pstate->base.alpha >> 6;
- }
- bg_alpha = max_alpha - fg_alpha;
+ fg_alpha = pstate->base.alpha;
/* default to opaque blending */
if (pstate->base.pixel_blend_mode == DRM_MODE_BLEND_PIXEL_NONE ||
!format->alpha_enable) {
blend_op = DPU_BLEND_FG_ALPHA_FG_CONST |
DPU_BLEND_BG_ALPHA_BG_CONST;
+ bg_alpha = DRM_BLEND_ALPHA_OPAQUE - fg_alpha;
} else if (pstate->base.pixel_blend_mode == DRM_MODE_BLEND_PREMULTI) {
blend_op = DPU_BLEND_FG_ALPHA_FG_CONST |
DPU_BLEND_BG_ALPHA_FG_PIXEL;
- if (fg_alpha != max_alpha) {
+ if (fg_alpha != DRM_BLEND_ALPHA_OPAQUE) {
bg_alpha = fg_alpha;
blend_op |= DPU_BLEND_BG_MOD_ALPHA |
DPU_BLEND_BG_INV_MOD_ALPHA;
} else {
+ bg_alpha = 0;
blend_op |= DPU_BLEND_BG_INV_ALPHA;
}
} else {
/* coverage blending */
blend_op = DPU_BLEND_FG_ALPHA_FG_PIXEL |
DPU_BLEND_BG_ALPHA_FG_PIXEL;
- if (fg_alpha != max_alpha) {
+ if (fg_alpha != DRM_BLEND_ALPHA_OPAQUE) {
bg_alpha = fg_alpha;
blend_op |= DPU_BLEND_FG_MOD_ALPHA |
DPU_BLEND_FG_INV_MOD_ALPHA |
DPU_BLEND_BG_MOD_ALPHA |
DPU_BLEND_BG_INV_MOD_ALPHA;
} else {
+ bg_alpha = 0;
blend_op |= DPU_BLEND_BG_INV_ALPHA;
}
}
@@ -1325,7 +1321,7 @@ static bool dpu_crtc_needs_dirtyfb(struct drm_crtc_state *cstate)
return false;
}
-static int dpu_crtc_reassign_planes(struct drm_crtc *crtc, struct drm_crtc_state *crtc_state)
+static int dpu_crtc_assign_planes(struct drm_crtc *crtc, struct drm_crtc_state *crtc_state)
{
int total_planes = crtc->dev->mode_config.num_total_plane;
struct drm_atomic_state *state = crtc_state->state;
@@ -1338,8 +1334,6 @@ static int dpu_crtc_reassign_planes(struct drm_crtc *crtc, struct drm_crtc_state
if (IS_ERR(global_state))
return PTR_ERR(global_state);
- dpu_rm_release_all_sspp(global_state, crtc);
-
if (!crtc_state->enable)
return 0;
@@ -1366,6 +1360,19 @@ done:
return ret;
}
+static int dpu_crtc_reassign_planes(struct drm_crtc *crtc, struct drm_crtc_state *crtc_state)
+{
+ struct dpu_global_state *global_state;
+
+ global_state = dpu_kms_get_global_state(crtc_state->state);
+ if (IS_ERR(global_state))
+ return PTR_ERR(global_state);
+
+ dpu_rm_release_all_sspp(global_state, crtc);
+
+ return dpu_crtc_assign_planes(crtc, crtc_state);
+}
+
#define MAX_CHANNELS_PER_CRTC PIPES_PER_PLANE
#define MAX_HDISPLAY_SPLIT 1080
@@ -1410,7 +1417,8 @@ static struct msm_display_topology dpu_crtc_get_topology(
topology.num_lm = 2;
else if (topology.num_dsc == 2)
topology.num_lm = 2;
- else if (dpu_kms->catalog->caps->has_3d_merge)
+ else if (dpu_kms->catalog->caps->has_3d_merge &&
+ topology.num_dsc == 0)
topology.num_lm = (mode->hdisplay > MAX_HDISPLAY_SPLIT) ? 2 : 1;
else
topology.num_lm = 1;
@@ -1534,9 +1542,11 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
return rc;
}
- if (dpu_use_virtual_planes &&
- (crtc_state->planes_changed || crtc_state->zpos_changed)) {
- rc = dpu_crtc_reassign_planes(crtc, crtc_state);
+ if (crtc_state->planes_changed || crtc_state->zpos_changed) {
+ if (dpu_use_virtual_planes)
+ rc = dpu_crtc_reassign_planes(crtc, crtc_state);
+ else
+ rc = dpu_crtc_assign_planes(crtc, crtc_state);
if (rc < 0)
return rc;
}
@@ -1657,6 +1667,17 @@ int dpu_crtc_vblank(struct drm_crtc *crtc, bool en)
return 0;
}
+/**
+ * dpu_crtc_get_num_lm - Get mixer number in this CRTC pipeline
+ * @state: Pointer to drm crtc state object
+ */
+unsigned int dpu_crtc_get_num_lm(const struct drm_crtc_state *state)
+{
+ struct dpu_crtc_state *cstate = to_dpu_crtc_state(state);
+
+ return cstate->num_mixers;
+}
+
#ifdef CONFIG_DEBUG_FS
static int _dpu_debugfs_status_show(struct seq_file *s, void *data)
{
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
index 94392b9b9245..6eaba5696e8e 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
@@ -267,4 +267,6 @@ static inline enum dpu_crtc_client_type dpu_crtc_get_client_type(
void dpu_crtc_frame_event_cb(struct drm_crtc *crtc, u32 event);
+unsigned int dpu_crtc_get_num_lm(const struct drm_crtc_state *state);
+
#endif /* _DPU_CRTC_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 93db1484f606..45079ee59cf6 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
@@ -257,6 +257,12 @@ static int dpu_encoder_phys_cmd_control_vblank_irq(
if (!dpu_encoder_phys_cmd_is_master(phys_enc))
goto end;
+ /* IRQ not yet initialized */
+ if (!phys_enc->irq[INTR_IDX_RDPTR]) {
+ ret = -EINVAL;
+ goto end;
+ }
+
/* protect against negative */
if (!enable && refcount == 0) {
ret = -EINVAL;
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 0ba777bda253..ba810f26ea30 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
@@ -10,6 +10,7 @@
#include "dpu_formats.h"
#include "dpu_trace.h"
#include "disp/msm_disp_snapshot.h"
+#include "msm_dsc_helper.h"
#include <drm/display/drm_dsc_helper.h>
#include <drm/drm_managed.h>
@@ -136,6 +137,7 @@ static void drm_mode_to_intf_timing_params(
timing->width = timing->width * drm_dsc_get_bpp_int(dsc) /
(dsc->bits_per_component * 3);
timing->xres = timing->width;
+ timing->dce_bytes_per_line = msm_dsc_get_bytes_per_line(dsc);
}
}
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 6d28f2281c76..22433bfbea1e 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
@@ -70,7 +70,7 @@ static void dpu_encoder_phys_wb_set_ot_limit(
ot_params.height = phys_enc->cached_mode.vdisplay;
ot_params.is_wfd = !dpu_encoder_helper_get_cwb_mask(phys_enc);
ot_params.frame_rate = drm_mode_vrefresh(&phys_enc->cached_mode);
- ot_params.vbif_idx = hw_wb->caps->vbif_idx;
+ /* XXX: WB on MSM8996 should use VBIF_NRT */
ot_params.rd = false;
if (!_dpu_encoder_phys_wb_clk_force_ctrl(hw_wb, phys_enc->dpu_kms->hw_mdp,
@@ -108,14 +108,13 @@ static void dpu_encoder_phys_wb_set_qos_remap(
hw_wb = phys_enc->hw_wb;
memset(&qos_params, 0, sizeof(qos_params));
- qos_params.vbif_idx = hw_wb->caps->vbif_idx;
+ /* XXX: WB on MSM8996 should use VBIF_NRT */
qos_params.xin_id = hw_wb->caps->xin_id;
qos_params.num = hw_wb->idx - WB_0;
qos_params.is_rt = dpu_encoder_helper_get_cwb_mask(phys_enc);
- DPU_DEBUG("[qos_remap] wb:%d vbif:%d xin:%d is_rt:%d\n",
+ DPU_DEBUG("[qos_remap] wb:%d xin:%d is_rt:%d\n",
qos_params.num,
- qos_params.vbif_idx,
qos_params.xin_id, qos_params.is_rt);
if (!_dpu_encoder_phys_wb_clk_force_ctrl(hw_wb, phys_enc->dpu_kms->hw_mdp,
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 c4e1f6b7345d..bb4fd5fa4b22 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
@@ -513,10 +513,8 @@ static const struct dpu_vbif_dynamic_ot_cfg msm8998_ot_rdwr_cfg[] = {
},
};
-static const struct dpu_vbif_cfg msm8996_vbif[] = {
- {
- .name = "vbif_rt", .id = VBIF_RT,
- .base = 0, .len = 0x1040,
+static const struct dpu_vbif_cfg msm8996_vbif = {
+ .len = 0x1040,
.default_ot_rd_limit = 32,
.default_ot_wr_limit = 16,
.features = BIT(DPU_VBIF_QOS_REMAP) | BIT(DPU_VBIF_QOS_OTLIM),
@@ -538,13 +536,10 @@ static const struct dpu_vbif_cfg msm8996_vbif[] = {
.npriority_lvl = ARRAY_SIZE(msm8998_nrt_pri_lvl),
.priority_lvl = msm8998_nrt_pri_lvl,
},
- },
};
-static const struct dpu_vbif_cfg msm8998_vbif[] = {
- {
- .name = "vbif_rt", .id = VBIF_RT,
- .base = 0, .len = 0x1040,
+static const struct dpu_vbif_cfg msm8998_vbif = {
+ .len = 0x1040,
.default_ot_rd_limit = 32,
.default_ot_wr_limit = 32,
.features = BIT(DPU_VBIF_QOS_REMAP) | BIT(DPU_VBIF_QOS_OTLIM),
@@ -568,13 +563,10 @@ static const struct dpu_vbif_cfg msm8998_vbif[] = {
},
.memtype_count = 14,
.memtype = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2},
- },
};
-static const struct dpu_vbif_cfg sdm845_vbif[] = {
- {
- .name = "vbif_rt", .id = VBIF_RT,
- .base = 0, .len = 0x1040,
+static const struct dpu_vbif_cfg sdm845_vbif = {
+ .len = 0x1040,
.features = BIT(DPU_VBIF_QOS_REMAP),
.xin_halt_timeout = 0x4000,
.qos_rp_remap_size = 0x40,
@@ -588,13 +580,10 @@ static const struct dpu_vbif_cfg sdm845_vbif[] = {
},
.memtype_count = 14,
.memtype = {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3},
- },
};
-static const struct dpu_vbif_cfg sm8550_vbif[] = {
- {
- .name = "vbif_rt", .id = VBIF_RT,
- .base = 0, .len = 0x1040,
+static const struct dpu_vbif_cfg sm8550_vbif = {
+ .len = 0x1040,
.features = BIT(DPU_VBIF_QOS_REMAP),
.xin_halt_timeout = 0x4000,
.qos_rp_remap_size = 0x40,
@@ -608,13 +597,10 @@ static const struct dpu_vbif_cfg sm8550_vbif[] = {
},
.memtype_count = 16,
.memtype = {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3},
- },
};
-static const struct dpu_vbif_cfg sm8650_vbif[] = {
- {
- .name = "vbif_rt", .id = VBIF_RT,
- .base = 0, .len = 0x1074,
+static const struct dpu_vbif_cfg sm8650_vbif = {
+ .len = 0x1074,
.features = BIT(DPU_VBIF_QOS_REMAP),
.xin_halt_timeout = 0x4000,
.qos_rp_remap_size = 0x40,
@@ -628,7 +614,6 @@ static const struct dpu_vbif_cfg sm8650_vbif[] = {
},
.memtype_count = 16,
.memtype = {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3},
- },
};
/*************************************************************
@@ -771,4 +756,5 @@ static const struct dpu_qos_lut_entry sc7180_qos_nrt[] = {
#include "catalog/dpu_10_0_sm8650.h"
#include "catalog/dpu_12_0_sm8750.h"
#include "catalog/dpu_12_2_glymur.h"
+#include "catalog/dpu_12_4_eliza.h"
#include "catalog/dpu_13_0_kaanapali.h"
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 70d5ed4732f2..ba04ac24d5a9 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
@@ -524,7 +524,6 @@ struct dpu_intf_cfg {
/**
* struct dpu_wb_cfg - information of writeback blocks
* @DPU_HW_BLK_INFO: refer to the description above for DPU_HW_BLK_INFO
- * @vbif_idx: vbif client index
* @maxlinewidth: max line width supported by writeback block
* @xin_id: bus client identifier
* @intr_wb_done: interrupt index for WB_DONE
@@ -535,7 +534,6 @@ struct dpu_intf_cfg {
struct dpu_wb_cfg {
DPU_HW_BLK_INFO;
unsigned long features;
- u8 vbif_idx;
u32 maxlinewidth;
u32 xin_id;
unsigned int intr_wb_done;
@@ -587,8 +585,7 @@ struct dpu_vbif_qos_tbl {
/**
* struct dpu_vbif_cfg - information of VBIF blocks
- * @id enum identifying this block
- * @base register offset of this block
+ * @len: length of hardware block
* @features bit mask identifying sub-blocks/features
* @ot_rd_limit default OT read limit
* @ot_wr_limit default OT write limit
@@ -602,7 +599,7 @@ struct dpu_vbif_qos_tbl {
* @memtype array of xin memtype definitions
*/
struct dpu_vbif_cfg {
- DPU_HW_BLK_INFO;
+ u32 len;
unsigned long features;
u32 default_ot_rd_limit;
u32 default_ot_wr_limit;
@@ -743,7 +740,6 @@ struct dpu_mdss_cfg {
u32 intf_count;
const struct dpu_intf_cfg *intf;
- u32 vbif_count;
const struct dpu_vbif_cfg *vbif;
u32 wb_count;
@@ -767,6 +763,7 @@ struct dpu_mdss_cfg {
const struct dpu_format_extended *vig_formats;
};
+extern const struct dpu_mdss_cfg dpu_eliza_cfg;
extern const struct dpu_mdss_cfg dpu_glymur_cfg;
extern const struct dpu_mdss_cfg dpu_kaanapali_cfg;
extern const struct dpu_mdss_cfg dpu_msm8917_cfg;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c
index 188ee0af2c90..23dcbe1ce1b8 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c
@@ -89,7 +89,7 @@ static void dpu_setup_dspp_gc(struct dpu_hw_dspp *ctx,
base = ctx->cap->sblk->gc.base;
if (!base) {
- DRM_ERROR("invalid ctx %pK gc base\n", ctx);
+ DRM_ERROR("invalid ctx %p gc base\n", ctx);
return;
}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
index 7e620f590984..ac82b69aedf6 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
@@ -173,13 +173,29 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *intf,
data_width = p->width;
/*
- * If widebus is enabled, data is valid for only half the active window
- * since the data rate is doubled in this mode. But for the compression
- * mode in DP case, the p->width is already adjusted in
- * drm_mode_to_intf_timing_params()
+ * If widebus is disabled:
+ * For uncompressed stream, the data is valid for the entire active
+ * window period.
+ * For compressed stream, data is valid for a shorter time period
+ * inside the active window depending on the compression ratio.
+ *
+ * If widebus is enabled:
+ * For uncompressed stream, data is valid for only half the active
+ * window, since the data rate is doubled in this mode.
+ * For compressed stream, data validity window needs to be adjusted for
+ * compression ratio and then further halved.
+ *
+ * For the compression mode in DP case, the p->width is already
+ * adjusted in drm_mode_to_intf_timing_params().
*/
- if (p->wide_bus_en && !dp_intf)
+ if (p->compression_en && !dp_intf) {
+ if (p->wide_bus_en)
+ data_width = DIV_ROUND_UP(p->dce_bytes_per_line, 6);
+ else
+ data_width = DIV_ROUND_UP(p->dce_bytes_per_line, 3);
+ } else if (p->wide_bus_en && !dp_intf) {
data_width = p->width >> 1;
+ }
/* TODO: handle DSC+DP case, we only handle DSC+DSI case so far */
if (p->compression_en && !dp_intf &&
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h
index f6ef2c21b66d..badd26305fc9 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h
@@ -35,6 +35,7 @@ struct dpu_hw_intf_timing_params {
bool wide_bus_en;
bool compression_en;
+ u32 dce_bytes_per_line;
};
struct dpu_hw_intf_prog_fetch {
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c
index e8a76d5192c2..b7779726bf10 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c
@@ -126,7 +126,9 @@ static int dpu_hw_lm_collect_misr(struct dpu_hw_mixer *ctx, u32 *misr_value)
}
static void dpu_hw_lm_setup_blend_config_combined_alpha(struct dpu_hw_mixer *ctx,
- u32 stage, u32 fg_alpha, u32 bg_alpha, u32 blend_op)
+ u32 stage,
+ u16 fg_alpha, u16 bg_alpha,
+ u32 blend_op)
{
struct dpu_hw_blk_reg_map *c = &ctx->hw;
int stage_off;
@@ -139,15 +141,16 @@ static void dpu_hw_lm_setup_blend_config_combined_alpha(struct dpu_hw_mixer *ctx
if (WARN_ON(stage_off < 0))
return;
- const_alpha = (bg_alpha & 0xFF) | ((fg_alpha & 0xFF) << 16);
+ const_alpha = (bg_alpha >> 8) | ((fg_alpha >> 8) << 16);
DPU_REG_WRITE(c, LM_BLEND0_CONST_ALPHA + stage_off, const_alpha);
DPU_REG_WRITE(c, LM_BLEND0_OP + stage_off, blend_op);
}
static void
dpu_hw_lm_setup_blend_config_combined_alpha_v12(struct dpu_hw_mixer *ctx,
- u32 stage, u32 fg_alpha,
- u32 bg_alpha, u32 blend_op)
+ u32 stage,
+ u16 fg_alpha, u16 bg_alpha,
+ u32 blend_op)
{
struct dpu_hw_blk_reg_map *c = &ctx->hw;
int stage_off;
@@ -160,13 +163,15 @@ dpu_hw_lm_setup_blend_config_combined_alpha_v12(struct dpu_hw_mixer *ctx,
if (WARN_ON(stage_off < 0))
return;
- const_alpha = (bg_alpha & 0x3ff) | ((fg_alpha & 0x3ff) << 16);
+ const_alpha = (bg_alpha >> 6) | ((fg_alpha >> 6) << 16);
DPU_REG_WRITE(c, LM_BLEND0_CONST_ALPHA_V12 + stage_off, const_alpha);
DPU_REG_WRITE(c, LM_BLEND0_OP + stage_off, blend_op);
}
static void dpu_hw_lm_setup_blend_config(struct dpu_hw_mixer *ctx,
- u32 stage, u32 fg_alpha, u32 bg_alpha, u32 blend_op)
+ u32 stage,
+ u16 fg_alpha, u16 bg_alpha,
+ u32 blend_op)
{
struct dpu_hw_blk_reg_map *c = &ctx->hw;
int stage_off;
@@ -178,8 +183,8 @@ static void dpu_hw_lm_setup_blend_config(struct dpu_hw_mixer *ctx,
if (WARN_ON(stage_off < 0))
return;
- DPU_REG_WRITE(c, LM_BLEND0_FG_ALPHA + stage_off, fg_alpha);
- DPU_REG_WRITE(c, LM_BLEND0_BG_ALPHA + stage_off, bg_alpha);
+ DPU_REG_WRITE(c, LM_BLEND0_FG_ALPHA + stage_off, fg_alpha >> 8);
+ DPU_REG_WRITE(c, LM_BLEND0_BG_ALPHA + stage_off, bg_alpha >> 8);
DPU_REG_WRITE(c, LM_BLEND0_OP + stage_off, blend_op);
}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h
index ecbb77711d83..380ca673f6de 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h
@@ -41,7 +41,7 @@ struct dpu_hw_lm_ops {
* for the specified stage
*/
void (*setup_blend_config)(struct dpu_hw_mixer *ctx, uint32_t stage,
- uint32_t fg_alpha, uint32_t bg_alpha, uint32_t blend_op);
+ u16 fg_alpha, u16 bg_alpha, uint32_t blend_op);
/**
* @setup_alpha_out: Alpha color component selection from either fg or bg
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 046b683d4c66..0e65bf5ddc4a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
@@ -284,12 +284,6 @@ enum dpu_wd_timer {
WD_TIMER_MAX
};
-enum dpu_vbif {
- VBIF_RT,
- VBIF_NRT,
- VBIF_MAX,
-};
-
/**
* enum dpu_3d_blend_mode
* Desribes how the 3d data is blended
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp_v13.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp_v13.c
index e65f1fc026fd..f8f96ad971d7 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp_v13.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp_v13.c
@@ -156,11 +156,13 @@ static void dpu_hw_sspp_setup_pe_config_v13(struct dpu_hw_sspp *ctx,
u8 color;
u32 lr_pe[4], tb_pe[4];
const u32 bytemask = 0xff;
- u32 offset = ctx->cap->sblk->sspp_rec0_blk.base;
+ u32 offset;
if (!ctx || !pe_ext)
return;
+ offset = ctx->cap->sblk->sspp_rec0_blk.base;
+
c = &ctx->hw;
/* program SW pixel extension override for all pipes*/
for (color = 0; color < DPU_MAX_PLANES; color++) {
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c
index af76ad8a8103..112df3f31e2b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c
@@ -230,13 +230,12 @@ struct dpu_hw_vbif *dpu_hw_vbif_init(struct drm_device *dev,
if (!c)
return ERR_PTR(-ENOMEM);
- c->hw.blk_addr = addr + cfg->base;
+ c->hw.blk_addr = addr;
c->hw.log_mask = DPU_DBG_MASK_VBIF;
/*
* Assign ops
*/
- c->idx = cfg->id;
c->cap = cfg;
_setup_vbif_ops(&c->ops, c->cap->features);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h
index 9ac49448e432..96ec4e35e549 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h
@@ -98,7 +98,6 @@ struct dpu_hw_vbif {
struct dpu_hw_blk_reg_map hw;
/* vbif */
- enum dpu_vbif idx;
const struct dpu_vbif_cfg *cap;
/* ops */
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 449552513997..35f7af4743d7 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -52,7 +52,7 @@
#define DPU_DEBUGFS_DIR "msm_dpu"
#define DPU_DEBUGFS_HWMASKNAME "hw_log_mask"
-bool dpu_use_virtual_planes;
+bool dpu_use_virtual_planes = true;
module_param(dpu_use_virtual_planes, bool, 0);
static int dpu_kms_hw_init(struct msm_kms *kms);
@@ -888,16 +888,12 @@ static int _dpu_kms_drm_obj_init(struct dpu_kms *dpu_kms)
static void _dpu_kms_hw_destroy(struct dpu_kms *dpu_kms)
{
- int i;
-
dpu_kms->hw_intr = NULL;
/* safe to call these more than once during shutdown */
_dpu_kms_mmu_destroy(dpu_kms);
- for (i = 0; i < ARRAY_SIZE(dpu_kms->hw_vbif); i++) {
- dpu_kms->hw_vbif[i] = NULL;
- }
+ dpu_kms->hw_vbif = NULL;
dpu_kms_global_obj_fini(dpu_kms);
@@ -1061,13 +1057,11 @@ static void dpu_kms_mdp_snapshot(struct msm_disp_state *disp_state, struct msm_k
dpu_kms->mmio + cat->cdm->base,
"%s", cat->cdm->name);
- for (i = 0; i < dpu_kms->catalog->vbif_count; i++) {
- const struct dpu_vbif_cfg *vbif = &dpu_kms->catalog->vbif[i];
+ const struct dpu_vbif_cfg *vbif = dpu_kms->catalog->vbif;
- msm_disp_snapshot_add_block(disp_state, vbif->len,
- dpu_kms->vbif[vbif->id] + vbif->base,
- "%s", vbif->name);
- }
+ msm_disp_snapshot_add_block(disp_state, vbif->len,
+ dpu_kms->vbif,
+ "vbif");
pm_runtime_put_sync(&dpu_kms->pdev->dev);
}
@@ -1145,7 +1139,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
{
struct dpu_kms *dpu_kms;
struct drm_device *dev;
- int i, rc = -EINVAL;
+ int rc = -EINVAL;
unsigned long max_core_clk_rate;
u32 core_rev;
@@ -1161,7 +1155,6 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
dev->mode_config.cursor_height = 512;
drm_atomic_private_obj_init(dpu_kms->dev, &dpu_kms->global_state,
- NULL,
&dpu_kms_global_state_funcs);
atomic_set(&dpu_kms->bandwidth_ref, 0);
@@ -1221,20 +1214,18 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
goto err_pm_put;
}
- for (i = 0; i < dpu_kms->catalog->vbif_count; i++) {
- struct dpu_hw_vbif *hw;
- const struct dpu_vbif_cfg *vbif = &dpu_kms->catalog->vbif[i];
-
- hw = dpu_hw_vbif_init(dev, vbif, dpu_kms->vbif[vbif->id]);
- if (IS_ERR(hw)) {
- rc = PTR_ERR(hw);
- DPU_ERROR("failed to init vbif %d: %d\n", vbif->id, rc);
- goto err_pm_put;
- }
+ struct dpu_hw_vbif *hw;
+ const struct dpu_vbif_cfg *vbif = dpu_kms->catalog->vbif;
- dpu_kms->hw_vbif[vbif->id] = hw;
+ hw = dpu_hw_vbif_init(dev, vbif, dpu_kms->vbif);
+ if (IS_ERR(hw)) {
+ rc = PTR_ERR(hw);
+ DPU_ERROR("failed to init vbif: %d\n", rc);
+ goto err_pm_put;
}
+ dpu_kms->hw_vbif = hw;
+
/* TODO: use the same max_freq as in dpu_kms_hw_init */
max_core_clk_rate = dpu_kms_get_clk_rate(dpu_kms, "core");
if (!max_core_clk_rate) {
@@ -1349,24 +1340,14 @@ static int dpu_kms_mmap_mdp5(struct dpu_kms *dpu_kms)
}
DRM_DEBUG("mapped dpu address space @%p\n", dpu_kms->mmio);
- dpu_kms->vbif[VBIF_RT] = msm_ioremap_mdss(mdss_dev,
- dpu_kms->pdev,
- "vbif_phys");
- if (IS_ERR(dpu_kms->vbif[VBIF_RT])) {
- ret = PTR_ERR(dpu_kms->vbif[VBIF_RT]);
+ dpu_kms->vbif = msm_ioremap_mdss(mdss_dev, dpu_kms->pdev, "vbif_phys");
+ if (IS_ERR(dpu_kms->vbif)) {
+ ret = PTR_ERR(dpu_kms->vbif);
DPU_ERROR("vbif register memory map failed: %d\n", ret);
- dpu_kms->vbif[VBIF_RT] = NULL;
+ dpu_kms->vbif = NULL;
return ret;
}
- dpu_kms->vbif[VBIF_NRT] = msm_ioremap_mdss(mdss_dev,
- dpu_kms->pdev,
- "vbif_nrt_phys");
- if (IS_ERR(dpu_kms->vbif[VBIF_NRT])) {
- dpu_kms->vbif[VBIF_NRT] = NULL;
- DPU_DEBUG("VBIF NRT is not defined");
- }
-
return 0;
}
@@ -1384,20 +1365,14 @@ static int dpu_kms_mmap_dpu(struct dpu_kms *dpu_kms)
}
DRM_DEBUG("mapped dpu address space @%p\n", dpu_kms->mmio);
- dpu_kms->vbif[VBIF_RT] = msm_ioremap(pdev, "vbif");
- if (IS_ERR(dpu_kms->vbif[VBIF_RT])) {
- ret = PTR_ERR(dpu_kms->vbif[VBIF_RT]);
+ dpu_kms->vbif = msm_ioremap(pdev, "vbif");
+ if (IS_ERR(dpu_kms->vbif)) {
+ ret = PTR_ERR(dpu_kms->vbif);
DPU_ERROR("vbif register memory map failed: %d\n", ret);
- dpu_kms->vbif[VBIF_RT] = NULL;
+ dpu_kms->vbif = NULL;
return ret;
}
- dpu_kms->vbif[VBIF_NRT] = msm_ioremap_quiet(pdev, "vbif_nrt");
- if (IS_ERR(dpu_kms->vbif[VBIF_NRT])) {
- dpu_kms->vbif[VBIF_NRT] = NULL;
- DPU_DEBUG("VBIF NRT is not defined");
- }
-
return 0;
}
@@ -1463,8 +1438,6 @@ static int __maybe_unused dpu_runtime_suspend(struct device *dev)
struct msm_drm_private *priv = platform_get_drvdata(pdev);
struct dpu_kms *dpu_kms = to_dpu_kms(priv->kms);
- /* Drop the performance state vote */
- dev_pm_opp_set_rate(dev, 0);
clk_bulk_disable_unprepare(dpu_kms->num_clocks, dpu_kms->clocks);
for (i = 0; i < dpu_kms->num_paths; i++)
@@ -1507,6 +1480,7 @@ static const struct dev_pm_ops dpu_pm_ops = {
};
static const struct of_device_id dpu_dt_match[] = {
+ { .compatible = "qcom,eliza-dpu", .data = &dpu_eliza_cfg, },
{ .compatible = "qcom,glymur-dpu", .data = &dpu_glymur_cfg, },
{ .compatible = "qcom,kaanapali-dpu", .data = &dpu_kaanapali_cfg, },
{ .compatible = "qcom,msm8917-mdp5", .data = &dpu_msm8917_cfg, },
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
index 993cf512f8c5..bb3393bd102e 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
@@ -63,7 +63,7 @@ struct dpu_kms {
const struct qcom_ubwc_cfg_data *mdss;
/* io/register spaces: */
- void __iomem *mmio, *vbif[VBIF_MAX];
+ void __iomem *mmio, *vbif;
struct regulator *vdd;
struct regulator *mmagic;
@@ -81,7 +81,7 @@ struct dpu_kms {
struct dpu_rm rm;
- struct dpu_hw_vbif *hw_vbif[VBIF_MAX];
+ struct dpu_hw_vbif *hw_vbif;
struct dpu_hw_mdp *hw_mdp;
bool has_danger_ctrl;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index 547d084f2944..3c315d5805b8 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -374,7 +374,6 @@ static void _dpu_plane_set_ot_limit(struct drm_plane *plane,
ot_params.height = drm_rect_height(&pipe_cfg->src_rect);
ot_params.is_wfd = !pdpu->is_rt_pipe;
ot_params.frame_rate = frame_rate;
- ot_params.vbif_idx = VBIF_RT;
ot_params.rd = true;
if (!_dpu_plane_sspp_clk_force_ctrl(pipe->sspp, dpu_kms->hw_mdp,
@@ -402,14 +401,12 @@ static void _dpu_plane_set_qos_remap(struct drm_plane *plane,
bool forced_on = false;
memset(&qos_params, 0, sizeof(qos_params));
- qos_params.vbif_idx = VBIF_RT;
qos_params.xin_id = pipe->sspp->cap->xin_id;
qos_params.num = pipe->sspp->idx - SSPP_VIG0;
qos_params.is_rt = pdpu->is_rt_pipe;
- DPU_DEBUG_PLANE(pdpu, "pipe:%d vbif:%d xin:%d rt:%d\n",
+ DPU_DEBUG_PLANE(pdpu, "pipe:%d xin:%d rt:%d\n",
qos_params.num,
- qos_params.vbif_idx,
qos_params.xin_id, qos_params.is_rt);
if (!_dpu_plane_sspp_clk_force_ctrl(pipe->sspp, dpu_kms->hw_mdp,
@@ -821,13 +818,8 @@ static int dpu_plane_atomic_check_nosspp(struct drm_plane *plane,
{
int i, ret = 0, min_scale, max_scale;
struct dpu_plane *pdpu = to_dpu_plane(plane);
- struct dpu_kms *kms = _dpu_plane_get_kms(&pdpu->base);
- u64 max_mdp_clk_rate = kms->perf.max_core_clk_rate;
struct dpu_plane_state *pstate = to_dpu_plane_state(new_plane_state);
- struct dpu_sw_pipe_cfg *pipe_cfg;
- struct dpu_sw_pipe_cfg *r_pipe_cfg;
struct drm_rect fb_rect = { 0 };
- uint32_t max_linewidth;
min_scale = FRAC_16_16(1, MAX_UPSCALE_RATIO);
max_scale = MAX_DOWNSCALE_RATIO << 16;
@@ -850,14 +842,6 @@ static int dpu_plane_atomic_check_nosspp(struct drm_plane *plane,
return -EINVAL;
}
- /* move the assignment here, to ease handling to another pairs later */
- pipe_cfg = &pstate->pipe_cfg[0];
- r_pipe_cfg = &pstate->pipe_cfg[1];
- /* state->src is 16.16, src_rect is not */
- drm_rect_fp_to_int(&pipe_cfg->src_rect, &new_plane_state->src);
-
- pipe_cfg->dst_rect = new_plane_state->dst;
-
fb_rect.x2 = new_plane_state->fb->width;
fb_rect.y2 = new_plane_state->fb->height;
@@ -879,38 +863,125 @@ static int dpu_plane_atomic_check_nosspp(struct drm_plane *plane,
if (pstate->layout.plane_pitch[i] > DPU_SSPP_MAX_PITCH_SIZE)
return -E2BIG;
+ pstate->needs_qos_remap = drm_atomic_crtc_needs_modeset(crtc_state);
+
+ return 0;
+}
+
+static int dpu_plane_split(struct drm_plane *plane,
+ struct drm_plane_state *new_plane_state,
+ const struct drm_crtc_state *crtc_state)
+{
+ struct dpu_plane *pdpu = to_dpu_plane(plane);
+ struct dpu_kms *kms = _dpu_plane_get_kms(&pdpu->base);
+ u64 max_mdp_clk_rate = kms->perf.max_core_clk_rate;
+ struct dpu_plane_state *pstate = to_dpu_plane_state(new_plane_state);
+ struct dpu_sw_pipe_cfg *pipe_cfg;
+ struct dpu_sw_pipe_cfg *r_pipe_cfg;
+ const struct drm_display_mode *mode = &crtc_state->adjusted_mode;
+ uint32_t max_linewidth;
+ u32 num_lm;
+ int stage_id, num_stages;
+
max_linewidth = pdpu->catalog->caps->max_linewidth;
- drm_rect_rotate(&pipe_cfg->src_rect,
- new_plane_state->fb->width, new_plane_state->fb->height,
- new_plane_state->rotation);
+ /* In non-virtual plane case, one mixer pair is always needed. */
+ num_lm = dpu_crtc_get_num_lm(crtc_state);
+ if (dpu_use_virtual_planes)
+ num_stages = (num_lm + 1) / 2;
+ else
+ num_stages = 1;
- if ((drm_rect_width(&pipe_cfg->src_rect) > max_linewidth) ||
- _dpu_plane_calc_clk(&crtc_state->adjusted_mode, pipe_cfg) > max_mdp_clk_rate) {
- if (drm_rect_width(&pipe_cfg->src_rect) > 2 * max_linewidth) {
- DPU_DEBUG_PLANE(pdpu, "invalid src " DRM_RECT_FMT " line:%u\n",
- DRM_RECT_ARG(&pipe_cfg->src_rect), max_linewidth);
- return -E2BIG;
+ /*
+ * For wide plane that exceeds SSPP rectangle constrain, it needed to
+ * be split and mapped to 2 rectangles with 1 config for 2:2:1.
+ * For 2 interfaces cases, such as dual DSI, 2:2:2 topology is needed.
+ * If the width or clock exceeds hardware limitation in every half of
+ * screen, 4:4:2 topology is needed and virtual plane feature should
+ * be enabled to map plane to more than 1 SSPP. 2 stage configs are
+ * needed to serve 2 mixer pairs in this 4:4:2 case. So both left/right
+ * half of plane splitting, and splitting within the half of screen is
+ * needed in quad-pipe case. Check dest rectangle left/right clipping
+ * and iterate mixer configs for this plane first, then check wide
+ * rectangle splitting in every half next.
+ */
+ for (stage_id = 0; stage_id < num_stages; stage_id++) {
+ struct drm_rect mixer_rect = {
+ .x1 = stage_id * mode->hdisplay / num_stages,
+ .y1 = 0,
+ .x2 = (stage_id + 1) * mode->hdisplay / num_stages,
+ .y2 = mode->vdisplay
+ };
+ int cfg_idx = stage_id * PIPES_PER_STAGE;
+
+ pipe_cfg = &pstate->pipe_cfg[cfg_idx];
+ r_pipe_cfg = &pstate->pipe_cfg[cfg_idx + 1];
+
+ drm_rect_fp_to_int(&pipe_cfg->src_rect, &new_plane_state->src);
+
+ drm_rect_rotate(&pipe_cfg->src_rect,
+ new_plane_state->fb->width, new_plane_state->fb->height,
+ new_plane_state->rotation);
+
+ pipe_cfg->dst_rect = new_plane_state->dst;
+
+ DPU_DEBUG_PLANE(pdpu, "checking src " DRM_RECT_FMT
+ " vs clip window " DRM_RECT_FMT "\n",
+ DRM_RECT_ARG(&pipe_cfg->src_rect),
+ DRM_RECT_ARG(&mixer_rect));
+
+ /*
+ * If this plane does not fall into mixer rect, check next
+ * mixer rect.
+ */
+ if (!drm_rect_clip_scaled(&pipe_cfg->src_rect,
+ &pipe_cfg->dst_rect,
+ &mixer_rect)) {
+ memset(pipe_cfg, 0, 2 * sizeof(struct dpu_sw_pipe_cfg));
+
+ continue;
}
- *r_pipe_cfg = *pipe_cfg;
- pipe_cfg->src_rect.x2 = (pipe_cfg->src_rect.x1 + pipe_cfg->src_rect.x2) >> 1;
- pipe_cfg->dst_rect.x2 = (pipe_cfg->dst_rect.x1 + pipe_cfg->dst_rect.x2) >> 1;
- r_pipe_cfg->src_rect.x1 = pipe_cfg->src_rect.x2;
- r_pipe_cfg->dst_rect.x1 = pipe_cfg->dst_rect.x2;
- } else {
- memset(r_pipe_cfg, 0, sizeof(*r_pipe_cfg));
- }
+ pipe_cfg->dst_rect.x1 -= mixer_rect.x1;
+ pipe_cfg->dst_rect.x2 -= mixer_rect.x1;
+
+ DPU_DEBUG_PLANE(pdpu, "Got clip src:" DRM_RECT_FMT " dst: " DRM_RECT_FMT "\n",
+ DRM_RECT_ARG(&pipe_cfg->src_rect), DRM_RECT_ARG(&pipe_cfg->dst_rect));
+
+ /* Split wide rect into 2 rect */
+ if ((drm_rect_width(&pipe_cfg->src_rect) > max_linewidth) ||
+ _dpu_plane_calc_clk(mode, pipe_cfg) > max_mdp_clk_rate) {
+
+ if (drm_rect_width(&pipe_cfg->src_rect) > 2 * max_linewidth) {
+ DPU_DEBUG_PLANE(pdpu, "invalid src " DRM_RECT_FMT " line:%u\n",
+ DRM_RECT_ARG(&pipe_cfg->src_rect), max_linewidth);
+ return -E2BIG;
+ }
+
+ memcpy(r_pipe_cfg, pipe_cfg, sizeof(struct dpu_sw_pipe_cfg));
+ pipe_cfg->src_rect.x2 = (pipe_cfg->src_rect.x1 + pipe_cfg->src_rect.x2) >> 1;
+ pipe_cfg->dst_rect.x2 = (pipe_cfg->dst_rect.x1 + pipe_cfg->dst_rect.x2) >> 1;
+ r_pipe_cfg->src_rect.x1 = pipe_cfg->src_rect.x2;
+ r_pipe_cfg->dst_rect.x1 = pipe_cfg->dst_rect.x2;
+ DPU_DEBUG_PLANE(pdpu, "Split wide plane into:"
+ DRM_RECT_FMT " and " DRM_RECT_FMT "\n",
+ DRM_RECT_ARG(&pipe_cfg->src_rect),
+ DRM_RECT_ARG(&r_pipe_cfg->src_rect));
+ } else {
+ memset(r_pipe_cfg, 0, sizeof(struct dpu_sw_pipe_cfg));
+ }
- drm_rect_rotate_inv(&pipe_cfg->src_rect,
- new_plane_state->fb->width, new_plane_state->fb->height,
- new_plane_state->rotation);
- if (drm_rect_width(&r_pipe_cfg->src_rect) != 0)
- drm_rect_rotate_inv(&r_pipe_cfg->src_rect,
- new_plane_state->fb->width, new_plane_state->fb->height,
+ drm_rect_rotate_inv(&pipe_cfg->src_rect,
+ new_plane_state->fb->width,
+ new_plane_state->fb->height,
new_plane_state->rotation);
- pstate->needs_qos_remap = drm_atomic_crtc_needs_modeset(crtc_state);
+ if (drm_rect_width(&r_pipe_cfg->src_rect) != 0)
+ drm_rect_rotate_inv(&r_pipe_cfg->src_rect,
+ new_plane_state->fb->width,
+ new_plane_state->fb->height,
+ new_plane_state->rotation);
+ }
return 0;
}
@@ -985,20 +1056,18 @@ static int dpu_plane_atomic_check_sspp(struct drm_plane *plane,
drm_atomic_get_new_plane_state(state, plane);
struct dpu_plane *pdpu = to_dpu_plane(plane);
struct dpu_plane_state *pstate = to_dpu_plane_state(new_plane_state);
- struct dpu_sw_pipe *pipe = &pstate->pipe[0];
- struct dpu_sw_pipe *r_pipe = &pstate->pipe[1];
- struct dpu_sw_pipe_cfg *pipe_cfg = &pstate->pipe_cfg[0];
- struct dpu_sw_pipe_cfg *r_pipe_cfg = &pstate->pipe_cfg[1];
- int ret = 0;
- ret = dpu_plane_atomic_check_pipe(pdpu, pipe, pipe_cfg,
- &crtc_state->adjusted_mode,
- new_plane_state);
- if (ret)
- return ret;
+ struct dpu_sw_pipe *pipe;
+ struct dpu_sw_pipe_cfg *pipe_cfg;
+ int ret = 0, i;
- if (drm_rect_width(&r_pipe_cfg->src_rect) != 0) {
- ret = dpu_plane_atomic_check_pipe(pdpu, r_pipe, r_pipe_cfg,
+ for (i = 0; i < PIPES_PER_PLANE; i++) {
+ pipe = &pstate->pipe[i];
+ pipe_cfg = &pstate->pipe_cfg[i];
+ if (!drm_rect_width(&pipe_cfg->src_rect))
+ continue;
+ DPU_DEBUG_PLANE(pdpu, "pipe %d is in use, validate it\n", i);
+ ret = dpu_plane_atomic_check_pipe(pdpu, pipe, pipe_cfg,
&crtc_state->adjusted_mode,
new_plane_state);
if (ret)
@@ -1103,60 +1172,12 @@ static int dpu_plane_try_multirect_shared(struct dpu_plane_state *pstate,
static int dpu_plane_atomic_check(struct drm_plane *plane,
struct drm_atomic_state *state)
{
- struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
- plane);
- int ret = 0;
- struct dpu_plane *pdpu = to_dpu_plane(plane);
- struct dpu_plane_state *pstate = to_dpu_plane_state(new_plane_state);
- struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane);
- struct dpu_sw_pipe *pipe = &pstate->pipe[0];
- struct dpu_sw_pipe *r_pipe = &pstate->pipe[1];
- struct dpu_sw_pipe_cfg *pipe_cfg = &pstate->pipe_cfg[0];
- struct dpu_sw_pipe_cfg *r_pipe_cfg = &pstate->pipe_cfg[1];
- const struct drm_crtc_state *crtc_state = NULL;
- uint32_t max_linewidth = dpu_kms->catalog->caps->max_linewidth;
-
- if (new_plane_state->crtc)
- crtc_state = drm_atomic_get_new_crtc_state(state,
- new_plane_state->crtc);
-
- pipe->sspp = dpu_rm_get_sspp(&dpu_kms->rm, pdpu->pipe);
-
- if (!pipe->sspp)
- return -EINVAL;
-
- ret = dpu_plane_atomic_check_nosspp(plane, new_plane_state, crtc_state);
- if (ret)
- return ret;
-
- if (!new_plane_state->visible)
- return 0;
-
- if (!dpu_plane_try_multirect_parallel(pipe, pipe_cfg, r_pipe, r_pipe_cfg,
- pipe->sspp,
- msm_framebuffer_format(new_plane_state->fb),
- max_linewidth)) {
- DPU_DEBUG_PLANE(pdpu, "invalid " DRM_RECT_FMT " /" DRM_RECT_FMT
- " max_line:%u, can't use split source\n",
- DRM_RECT_ARG(&pipe_cfg->src_rect),
- DRM_RECT_ARG(&r_pipe_cfg->src_rect),
- max_linewidth);
- return -E2BIG;
- }
-
- return dpu_plane_atomic_check_sspp(plane, state, crtc_state);
-}
-
-static int dpu_plane_virtual_atomic_check(struct drm_plane *plane,
- struct drm_atomic_state *state)
-{
struct drm_plane_state *plane_state =
drm_atomic_get_plane_state(state, plane);
struct drm_plane_state *old_plane_state =
drm_atomic_get_old_plane_state(state, plane);
- struct dpu_plane_state *pstate = to_dpu_plane_state(plane_state);
+ int ret = 0;
struct drm_crtc_state *crtc_state = NULL;
- int ret, i;
if (IS_ERR(plane_state))
return PTR_ERR(plane_state);
@@ -1169,16 +1190,8 @@ static int dpu_plane_virtual_atomic_check(struct drm_plane *plane,
if (ret)
return ret;
- if (!plane_state->visible) {
- /*
- * resources are freed by dpu_crtc_assign_plane_resources(),
- * but clean them here.
- */
- for (i = 0; i < PIPES_PER_PLANE; i++)
- pstate->pipe[i].sspp = NULL;
-
+ if (!plane_state->visible)
return 0;
- }
/*
* Force resource reallocation if the format of FB or src/dst have
@@ -1193,7 +1206,6 @@ static int dpu_plane_virtual_atomic_check(struct drm_plane *plane,
msm_framebuffer_format(old_plane_state->fb) !=
msm_framebuffer_format(plane_state->fb))
crtc_state->planes_changed = true;
-
return 0;
}
@@ -1240,9 +1252,9 @@ static int dpu_plane_virtual_assign_resources(struct drm_crtc *crtc,
struct dpu_global_state *global_state,
struct drm_atomic_state *state,
struct drm_plane_state *plane_state,
+ const struct drm_crtc_state *crtc_state,
struct drm_plane_state **prev_adjacent_plane_state)
{
- const struct drm_crtc_state *crtc_state = NULL;
struct drm_plane *plane = plane_state->plane;
struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane);
struct dpu_rm_sspp_requirements reqs;
@@ -1252,10 +1264,6 @@ static int dpu_plane_virtual_assign_resources(struct drm_crtc *crtc,
const struct msm_format *fmt;
int i, ret;
- if (plane_state->crtc)
- crtc_state = drm_atomic_get_new_crtc_state(state,
- plane_state->crtc);
-
pstate = to_dpu_plane_state(plane_state);
for (i = 0; i < STAGES_PER_PLANE; i++)
prev_adjacent_pstate[i] = prev_adjacent_plane_state[i] ?
@@ -1267,6 +1275,10 @@ static int dpu_plane_virtual_assign_resources(struct drm_crtc *crtc,
if (!plane_state->fb)
return -EINVAL;
+ ret = dpu_plane_split(plane, plane_state, crtc_state);
+ if (ret)
+ return ret;
+
fmt = msm_framebuffer_format(plane_state->fb);
reqs.yuv = MSM_FORMAT_IS_YUV(fmt);
reqs.scale = (plane_state->src_w >> 16 != plane_state->crtc_w) ||
@@ -1297,14 +1309,55 @@ static int dpu_plane_virtual_assign_resources(struct drm_crtc *crtc,
return dpu_plane_atomic_check_sspp(plane, state, crtc_state);
}
+static int dpu_plane_assign_resources(struct drm_crtc *crtc,
+ struct dpu_global_state *global_state,
+ struct drm_atomic_state *state,
+ struct drm_plane_state *plane_state,
+ const struct drm_crtc_state *crtc_state)
+{
+ struct drm_plane *plane = plane_state->plane;
+ struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane);
+ struct dpu_plane_state *pstate = to_dpu_plane_state(plane_state);
+ struct dpu_sw_pipe *pipe = &pstate->pipe[0];
+ struct dpu_sw_pipe *r_pipe = &pstate->pipe[1];
+ struct dpu_sw_pipe_cfg *pipe_cfg = &pstate->pipe_cfg[0];
+ struct dpu_sw_pipe_cfg *r_pipe_cfg = &pstate->pipe_cfg[1];
+ struct dpu_plane *pdpu = to_dpu_plane(plane);
+ int ret;
+
+ pipe->sspp = dpu_rm_get_sspp(&dpu_kms->rm, pdpu->pipe);
+ if (!pipe->sspp)
+ return -EINVAL;
+
+ ret = dpu_plane_split(plane, plane_state, crtc_state);
+ if (ret)
+ return ret;
+
+ if (!dpu_plane_try_multirect_parallel(pipe, pipe_cfg, r_pipe, r_pipe_cfg,
+ pipe->sspp,
+ msm_framebuffer_format(plane_state->fb),
+ dpu_kms->catalog->caps->max_linewidth)) {
+ DPU_DEBUG_PLANE(pdpu, "invalid " DRM_RECT_FMT " /" DRM_RECT_FMT
+ " max_line:%u, can't use split source\n",
+ DRM_RECT_ARG(&pipe_cfg->src_rect),
+ DRM_RECT_ARG(&r_pipe_cfg->src_rect),
+ dpu_kms->catalog->caps->max_linewidth);
+ return -E2BIG;
+ }
+
+ return dpu_plane_atomic_check_sspp(plane, state, crtc_state);
+}
+
int dpu_assign_plane_resources(struct dpu_global_state *global_state,
struct drm_atomic_state *state,
struct drm_crtc *crtc,
struct drm_plane_state **states,
unsigned int num_planes)
{
- unsigned int i;
struct drm_plane_state *prev_adjacent_plane_state[STAGES_PER_PLANE] = { NULL };
+ const struct drm_crtc_state *crtc_state = NULL;
+ unsigned int i;
+ int ret;
for (i = 0; i < num_planes; i++) {
struct drm_plane_state *plane_state = states[i];
@@ -1313,8 +1366,18 @@ int dpu_assign_plane_resources(struct dpu_global_state *global_state,
!plane_state->visible)
continue;
- int ret = dpu_plane_virtual_assign_resources(crtc, global_state,
+ if (plane_state->crtc)
+ crtc_state = drm_atomic_get_new_crtc_state(state,
+ plane_state->crtc);
+
+ if (!dpu_use_virtual_planes)
+ ret = dpu_plane_assign_resources(crtc, global_state,
+ state, plane_state,
+ crtc_state);
+ else
+ ret = dpu_plane_virtual_assign_resources(crtc, global_state,
state, plane_state,
+ crtc_state,
prev_adjacent_plane_state);
if (ret)
return ret;
@@ -1751,7 +1814,7 @@ static const struct drm_plane_helper_funcs dpu_plane_helper_funcs = {
static const struct drm_plane_helper_funcs dpu_plane_virtual_helper_funcs = {
.prepare_fb = dpu_plane_prepare_fb,
.cleanup_fb = dpu_plane_cleanup_fb,
- .atomic_check = dpu_plane_virtual_atomic_check,
+ .atomic_check = dpu_plane_atomic_check,
.atomic_update = dpu_plane_atomic_update,
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
index 451a4fcf3e65..7e77d88f8959 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -350,26 +350,28 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
return true;
}
-static bool dpu_rm_find_lms(struct dpu_rm *rm,
- struct dpu_global_state *global_state,
- uint32_t crtc_id, bool skip_dspp,
- struct msm_display_topology *topology,
- int *lm_idx, int *pp_idx, int *dspp_idx)
+static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
+ struct dpu_global_state *global_state,
+ uint32_t crtc_id,
+ struct msm_display_topology *topology)
{
+ int lm_idx[MAX_BLOCKS];
+ int pp_idx[MAX_BLOCKS];
+ int dspp_idx[MAX_BLOCKS] = {0};
int i, lm_count = 0;
+ if (!topology->num_lm) {
+ DPU_ERROR("zero LMs in topology\n");
+ return -EINVAL;
+ }
+
/* Find a primary mixer */
for (i = 0; i < ARRAY_SIZE(rm->mixer_blks) &&
lm_count < topology->num_lm; i++) {
if (!rm->mixer_blks[i])
continue;
- if (skip_dspp && to_dpu_hw_mixer(rm->mixer_blks[i])->cap->dspp) {
- DPU_DEBUG("Skipping LM_%d, skipping LMs with DSPPs\n", i);
- continue;
- }
-
/*
* Reset lm_count to an even index. This will drop the previous
* primary mixer if failed to find its peer.
@@ -408,38 +410,12 @@ static bool dpu_rm_find_lms(struct dpu_rm *rm,
}
}
- return lm_count == topology->num_lm;
-}
-
-static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
- struct dpu_global_state *global_state,
- uint32_t crtc_id,
- struct msm_display_topology *topology)
-
-{
- int lm_idx[MAX_BLOCKS];
- int pp_idx[MAX_BLOCKS];
- int dspp_idx[MAX_BLOCKS] = {0};
- int i;
- bool found;
-
- if (!topology->num_lm) {
- DPU_ERROR("zero LMs in topology\n");
- return -EINVAL;
- }
-
- /* Try using non-DSPP LM blocks first */
- found = dpu_rm_find_lms(rm, global_state, crtc_id, !topology->num_dspp,
- topology, lm_idx, pp_idx, dspp_idx);
- if (!found && !topology->num_dspp)
- found = dpu_rm_find_lms(rm, global_state, crtc_id, false,
- topology, lm_idx, pp_idx, dspp_idx);
- if (!found) {
+ if (lm_count != topology->num_lm) {
DPU_DEBUG("unable to find appropriate mixers\n");
return -ENAVAIL;
}
- for (i = 0; i < topology->num_lm; i++) {
+ for (i = 0; i < lm_count; i++) {
global_state->mixer_to_crtc_id[lm_idx[i]] = crtc_id;
global_state->pingpong_to_crtc_id[pp_idx[i]] = crtc_id;
global_state->dspp_to_crtc_id[dspp_idx[i]] =
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h
index cb24ad2a6d8d..805d117493da 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h
@@ -72,23 +72,20 @@ TRACE_EVENT(dpu_perf_set_danger_luts,
);
TRACE_EVENT(dpu_perf_set_ot,
- TP_PROTO(u32 pnum, u32 xin_id, u32 rd_lim, u32 vbif_idx),
- TP_ARGS(pnum, xin_id, rd_lim, vbif_idx),
+ TP_PROTO(u32 pnum, u32 xin_id, u32 rd_lim),
+ TP_ARGS(pnum, xin_id, rd_lim),
TP_STRUCT__entry(
__field(u32, pnum)
__field(u32, xin_id)
__field(u32, rd_lim)
- __field(u32, vbif_idx)
),
TP_fast_assign(
__entry->pnum = pnum;
__entry->xin_id = xin_id;
__entry->rd_lim = rd_lim;
- __entry->vbif_idx = vbif_idx;
),
- TP_printk("pnum:%d xin_id:%d ot:%d vbif:%d",
- __entry->pnum, __entry->xin_id, __entry->rd_lim,
- __entry->vbif_idx)
+ TP_printk("pnum:%d xin_id:%d ot:%d",
+ __entry->pnum, __entry->xin_id, __entry->rd_lim)
)
TRACE_EVENT(dpu_cmd_release_bw,
@@ -861,17 +858,15 @@ TRACE_EVENT(dpu_rm_reserve_lms,
);
TRACE_EVENT(dpu_vbif_wait_xin_halt_fail,
- TP_PROTO(enum dpu_vbif index, u32 xin_id),
- TP_ARGS(index, xin_id),
+ TP_PROTO(u32 xin_id),
+ TP_ARGS(xin_id),
TP_STRUCT__entry(
- __field( enum dpu_vbif, index )
__field( u32, xin_id )
),
TP_fast_assign(
- __entry->index = index;
__entry->xin_id = xin_id;
),
- TP_printk("index:%d xin_id:%u", __entry->index, __entry->xin_id)
+ TP_printk("xin_id:%u", __entry->xin_id)
);
TRACE_EVENT(dpu_pp_connect_ext_te,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c
index 2a551e455aa3..0c6fa9bb0cb6 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c
@@ -11,26 +11,6 @@
#include "dpu_hw_vbif.h"
#include "dpu_trace.h"
-static struct dpu_hw_vbif *dpu_get_vbif(struct dpu_kms *dpu_kms, enum dpu_vbif vbif_idx)
-{
- if (vbif_idx < ARRAY_SIZE(dpu_kms->hw_vbif))
- return dpu_kms->hw_vbif[vbif_idx];
-
- return NULL;
-}
-
-static const char *dpu_vbif_name(enum dpu_vbif idx)
-{
- switch (idx) {
- case VBIF_RT:
- return "VBIF_RT";
- case VBIF_NRT:
- return "VBIF_NRT";
- default:
- return "??";
- }
-}
-
/**
* _dpu_vbif_wait_for_xin_halt - wait for the xin to halt
* @vbif: Pointer to hardware vbif driver
@@ -62,12 +42,10 @@ static int _dpu_vbif_wait_for_xin_halt(struct dpu_hw_vbif *vbif, u32 xin_id)
if (!status) {
rc = -ETIMEDOUT;
- DPU_ERROR("%s client %d not halting. TIMEDOUT.\n",
- dpu_vbif_name(vbif->idx), xin_id);
+ DPU_ERROR("VBIF client %d not halting. TIMEDOUT.\n", xin_id);
} else {
rc = 0;
- DRM_DEBUG_ATOMIC("%s client %d is halted\n",
- dpu_vbif_name(vbif->idx), xin_id);
+ DRM_DEBUG_ATOMIC("VBIF client %d is halted\n", xin_id);
}
return rc;
@@ -107,10 +85,10 @@ static void _dpu_vbif_apply_dynamic_ot_limit(struct dpu_hw_vbif *vbif,
}
}
- DRM_DEBUG_ATOMIC("%s xin:%d w:%d h:%d fps:%d pps:%llu ot:%u\n",
- dpu_vbif_name(vbif->idx), params->xin_id,
- params->width, params->height, params->frame_rate,
- pps, *ot_lim);
+ DRM_DEBUG_ATOMIC("VBIF xin:%d w:%d h:%d fps:%d pps:%llu ot:%u\n",
+ params->xin_id,
+ params->width, params->height, params->frame_rate,
+ pps, *ot_lim);
}
/**
@@ -153,8 +131,7 @@ static u32 _dpu_vbif_get_ot_limit(struct dpu_hw_vbif *vbif,
}
exit:
- DRM_DEBUG_ATOMIC("%s xin:%d ot_lim:%d\n",
- dpu_vbif_name(vbif->idx), params->xin_id, ot_lim);
+ DRM_DEBUG_ATOMIC("VBIF xin:%d ot_lim:%d\n", params->xin_id, ot_lim);
return ot_lim;
}
@@ -172,7 +149,7 @@ void dpu_vbif_set_ot_limit(struct dpu_kms *dpu_kms,
u32 ot_lim;
int ret;
- vbif = dpu_get_vbif(dpu_kms, params->vbif_idx);
+ vbif = dpu_kms->hw_vbif;
if (!vbif) {
DRM_DEBUG_ATOMIC("invalid arguments vbif %d\n", vbif != NULL);
return;
@@ -190,8 +167,7 @@ void dpu_vbif_set_ot_limit(struct dpu_kms *dpu_kms,
if (ot_lim == 0)
return;
- trace_dpu_perf_set_ot(params->num, params->xin_id, ot_lim,
- params->vbif_idx);
+ trace_dpu_perf_set_ot(params->num, params->xin_id, ot_lim);
vbif->ops.set_limit_conf(vbif, params->xin_id, params->rd, ot_lim);
@@ -199,7 +175,7 @@ void dpu_vbif_set_ot_limit(struct dpu_kms *dpu_kms,
ret = _dpu_vbif_wait_for_xin_halt(vbif, params->xin_id);
if (ret)
- trace_dpu_vbif_wait_xin_halt_fail(vbif->idx, params->xin_id);
+ trace_dpu_vbif_wait_xin_halt_fail(params->xin_id);
vbif->ops.set_halt_ctrl(vbif, params->xin_id, false);
}
@@ -221,10 +197,10 @@ void dpu_vbif_set_qos_remap(struct dpu_kms *dpu_kms,
return;
}
- vbif = dpu_get_vbif(dpu_kms, params->vbif_idx);
+ vbif = dpu_kms->hw_vbif;
if (!vbif || !vbif->cap) {
- DPU_ERROR("invalid vbif %d\n", params->vbif_idx);
+ DPU_ERROR("invalid vbif\n");
return;
}
@@ -242,8 +218,8 @@ void dpu_vbif_set_qos_remap(struct dpu_kms *dpu_kms,
}
for (i = 0; i < qos_tbl->npriority_lvl; i++) {
- DRM_DEBUG_ATOMIC("%s xin:%d lvl:%d/%d\n",
- dpu_vbif_name(params->vbif_idx), params->xin_id, i,
+ DRM_DEBUG_ATOMIC("VBIF xin:%d lvl:%d/%d\n",
+ params->xin_id, i,
qos_tbl->priority_lvl[i]);
vbif->ops.set_qos_remap(vbif, params->xin_id, i,
qos_tbl->priority_lvl[i]);
@@ -257,16 +233,13 @@ void dpu_vbif_set_qos_remap(struct dpu_kms *dpu_kms,
void dpu_vbif_clear_errors(struct dpu_kms *dpu_kms)
{
struct dpu_hw_vbif *vbif;
- u32 i, pnd, src;
-
- for (i = 0; i < ARRAY_SIZE(dpu_kms->hw_vbif); i++) {
- vbif = dpu_kms->hw_vbif[i];
- if (vbif && vbif->ops.clear_errors) {
- vbif->ops.clear_errors(vbif, &pnd, &src);
- if (pnd || src) {
- DRM_DEBUG_KMS("%s: pnd 0x%X, src 0x%X\n",
- dpu_vbif_name(vbif->idx), pnd, src);
- }
+ u32 pnd, src;
+
+ vbif = dpu_kms->hw_vbif;
+ if (vbif && vbif->ops.clear_errors) {
+ vbif->ops.clear_errors(vbif, &pnd, &src);
+ if (pnd || src) {
+ DRM_DEBUG_KMS("VBIF: pnd 0x%X, src 0x%X\n", pnd, src);
}
}
}
@@ -278,15 +251,12 @@ void dpu_vbif_clear_errors(struct dpu_kms *dpu_kms)
void dpu_vbif_init_memtypes(struct dpu_kms *dpu_kms)
{
struct dpu_hw_vbif *vbif;
- int i, j;
-
- for (i = 0; i < ARRAY_SIZE(dpu_kms->hw_vbif); i++) {
- vbif = dpu_kms->hw_vbif[i];
- if (vbif && vbif->cap && vbif->ops.set_mem_type) {
- for (j = 0; j < vbif->cap->memtype_count; j++)
- vbif->ops.set_mem_type(
- vbif, j, vbif->cap->memtype[j]);
- }
+ int j;
+
+ vbif = dpu_kms->hw_vbif;
+ if (vbif && vbif->cap && vbif->ops.set_mem_type) {
+ for (j = 0; j < vbif->cap->memtype_count; j++)
+ vbif->ops.set_mem_type(vbif, j, vbif->cap->memtype[j]);
}
}
@@ -294,58 +264,51 @@ void dpu_vbif_init_memtypes(struct dpu_kms *dpu_kms)
void dpu_debugfs_vbif_init(struct dpu_kms *dpu_kms, struct dentry *debugfs_root)
{
+ const struct dpu_vbif_cfg *vbif = dpu_kms->catalog->vbif;
char vbif_name[32];
- struct dentry *entry, *debugfs_vbif;
- int i, j;
-
- entry = debugfs_create_dir("vbif", debugfs_root);
-
- for (i = 0; i < dpu_kms->catalog->vbif_count; i++) {
- const struct dpu_vbif_cfg *vbif = &dpu_kms->catalog->vbif[i];
+ struct dentry *debugfs_vbif;
+ int j;
- snprintf(vbif_name, sizeof(vbif_name), "%d", vbif->id);
+ debugfs_vbif = debugfs_create_dir("vbif", debugfs_root);
- debugfs_vbif = debugfs_create_dir(vbif_name, entry);
+ debugfs_create_u32("features", 0600, debugfs_vbif,
+ (u32 *)&vbif->features);
- debugfs_create_u32("features", 0600, debugfs_vbif,
- (u32 *)&vbif->features);
+ debugfs_create_u32("xin_halt_timeout", 0400, debugfs_vbif,
+ (u32 *)&vbif->xin_halt_timeout);
- debugfs_create_u32("xin_halt_timeout", 0400, debugfs_vbif,
- (u32 *)&vbif->xin_halt_timeout);
+ debugfs_create_u32("default_rd_ot_limit", 0400, debugfs_vbif,
+ (u32 *)&vbif->default_ot_rd_limit);
- debugfs_create_u32("default_rd_ot_limit", 0400, debugfs_vbif,
- (u32 *)&vbif->default_ot_rd_limit);
+ debugfs_create_u32("default_wr_ot_limit", 0400, debugfs_vbif,
+ (u32 *)&vbif->default_ot_wr_limit);
- debugfs_create_u32("default_wr_ot_limit", 0400, debugfs_vbif,
- (u32 *)&vbif->default_ot_wr_limit);
+ for (j = 0; j < vbif->dynamic_ot_rd_tbl.count; j++) {
+ const struct dpu_vbif_dynamic_ot_cfg *cfg =
+ &vbif->dynamic_ot_rd_tbl.cfg[j];
- for (j = 0; j < vbif->dynamic_ot_rd_tbl.count; j++) {
- const struct dpu_vbif_dynamic_ot_cfg *cfg =
- &vbif->dynamic_ot_rd_tbl.cfg[j];
-
- snprintf(vbif_name, sizeof(vbif_name),
- "dynamic_ot_rd_%d_pps", j);
- debugfs_create_u64(vbif_name, 0400, debugfs_vbif,
- (u64 *)&cfg->pps);
- snprintf(vbif_name, sizeof(vbif_name),
- "dynamic_ot_rd_%d_ot_limit", j);
- debugfs_create_u32(vbif_name, 0400, debugfs_vbif,
- (u32 *)&cfg->ot_limit);
- }
+ snprintf(vbif_name, sizeof(vbif_name),
+ "dynamic_ot_rd_%d_pps", j);
+ debugfs_create_u64(vbif_name, 0400, debugfs_vbif,
+ (u64 *)&cfg->pps);
+ snprintf(vbif_name, sizeof(vbif_name),
+ "dynamic_ot_rd_%d_ot_limit", j);
+ debugfs_create_u32(vbif_name, 0400, debugfs_vbif,
+ (u32 *)&cfg->ot_limit);
+ }
- for (j = 0; j < vbif->dynamic_ot_wr_tbl.count; j++) {
- const struct dpu_vbif_dynamic_ot_cfg *cfg =
- &vbif->dynamic_ot_wr_tbl.cfg[j];
-
- snprintf(vbif_name, sizeof(vbif_name),
- "dynamic_ot_wr_%d_pps", j);
- debugfs_create_u64(vbif_name, 0400, debugfs_vbif,
- (u64 *)&cfg->pps);
- snprintf(vbif_name, sizeof(vbif_name),
- "dynamic_ot_wr_%d_ot_limit", j);
- debugfs_create_u32(vbif_name, 0400, debugfs_vbif,
- (u32 *)&cfg->ot_limit);
- }
+ for (j = 0; j < vbif->dynamic_ot_wr_tbl.count; j++) {
+ const struct dpu_vbif_dynamic_ot_cfg *cfg =
+ &vbif->dynamic_ot_wr_tbl.cfg[j];
+
+ snprintf(vbif_name, sizeof(vbif_name),
+ "dynamic_ot_wr_%d_pps", j);
+ debugfs_create_u64(vbif_name, 0400, debugfs_vbif,
+ (u64 *)&cfg->pps);
+ snprintf(vbif_name, sizeof(vbif_name),
+ "dynamic_ot_wr_%d_ot_limit", j);
+ debugfs_create_u32(vbif_name, 0400, debugfs_vbif,
+ (u32 *)&cfg->ot_limit);
}
}
#endif
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.h
index 62e47ae1e3ee..f47a89cb34ea 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.h
@@ -15,24 +15,20 @@ struct dpu_vbif_set_ot_params {
u32 frame_rate;
bool rd;
bool is_wfd;
- u32 vbif_idx;
};
struct dpu_vbif_set_memtype_params {
u32 xin_id;
- u32 vbif_idx;
bool is_cacheable;
};
/**
* struct dpu_vbif_set_qos_params - QoS remapper parameter
- * @vbif_idx: vbif identifier
* @xin_id: client interface identifier
* @num: pipe identifier (debug only)
* @is_rt: true if pipe is used in real-time use case
*/
struct dpu_vbif_set_qos_params {
- u32 vbif_idx;
u32 xin_id;
u32 num;
bool is_rt;
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c
index 69fef034d0df..7c91fc1915f3 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c
@@ -14,95 +14,6 @@ struct mdp5_cfg_handler {
/* mdp5_cfg must be exposed (used in mdp5.xml.h) */
const struct mdp5_cfg_hw *mdp5_cfg = NULL;
-static const struct mdp5_cfg_hw msm8x74v1_config = {
- .name = "msm8x74v1",
- .mdp = {
- .count = 1,
- .caps = MDP_CAP_SMP |
- 0,
- },
- .smp = {
- .mmb_count = 22,
- .mmb_size = 4096,
- .clients = {
- [SSPP_VIG0] = 1, [SSPP_VIG1] = 4, [SSPP_VIG2] = 7,
- [SSPP_DMA0] = 10, [SSPP_DMA1] = 13,
- [SSPP_RGB0] = 16, [SSPP_RGB1] = 17, [SSPP_RGB2] = 18,
- },
- },
- .ctl = {
- .count = 5,
- .base = { 0x00500, 0x00600, 0x00700, 0x00800, 0x00900 },
- .flush_hw_mask = 0x0003ffff,
- },
- .pipe_vig = {
- .count = 3,
- .base = { 0x01100, 0x01500, 0x01900 },
- .caps = MDP_PIPE_CAP_HFLIP |
- MDP_PIPE_CAP_VFLIP |
- MDP_PIPE_CAP_SCALE |
- MDP_PIPE_CAP_CSC |
- 0,
- },
- .pipe_rgb = {
- .count = 3,
- .base = { 0x01d00, 0x02100, 0x02500 },
- .caps = MDP_PIPE_CAP_HFLIP |
- MDP_PIPE_CAP_VFLIP |
- MDP_PIPE_CAP_SCALE |
- 0,
- },
- .pipe_dma = {
- .count = 2,
- .base = { 0x02900, 0x02d00 },
- .caps = MDP_PIPE_CAP_HFLIP |
- MDP_PIPE_CAP_VFLIP |
- 0,
- },
- .lm = {
- .count = 5,
- .base = { 0x03100, 0x03500, 0x03900, 0x03d00, 0x04100 },
- .instances = {
- { .id = 0, .pp = 0, .dspp = 0,
- .caps = MDP_LM_CAP_DISPLAY, },
- { .id = 1, .pp = 1, .dspp = 1,
- .caps = MDP_LM_CAP_DISPLAY, },
- { .id = 2, .pp = 2, .dspp = 2,
- .caps = MDP_LM_CAP_DISPLAY, },
- { .id = 3, .pp = -1, .dspp = -1,
- .caps = MDP_LM_CAP_WB },
- { .id = 4, .pp = -1, .dspp = -1,
- .caps = MDP_LM_CAP_WB },
- },
- .nb_stages = 5,
- .max_width = 2048,
- .max_height = 0xFFFF,
- },
- .dspp = {
- .count = 3,
- .base = { 0x04500, 0x04900, 0x04d00 },
- },
- .pp = {
- .count = 3,
- .base = { 0x21a00, 0x21b00, 0x21c00 },
- },
- .intf = {
- .base = { 0x21000, 0x21200, 0x21400, 0x21600 },
- .connect = {
- [0] = INTF_eDP,
- [1] = INTF_DSI,
- [2] = INTF_DSI,
- [3] = INTF_HDMI,
- },
- },
- .perf = {
- .ab_inefficiency = 200,
- .ib_inefficiency = 120,
- .clk_inefficiency = 125
- },
- .max_clk = 200000000,
-};
-
static const struct mdp5_cfg_hw msm8x26_config = {
.name = "msm8x26",
.mdp = {
@@ -184,7 +95,7 @@ static const struct mdp5_cfg_hw msm8x26_config = {
.max_clk = 200000000,
};
-static const struct mdp5_cfg_hw msm8x74v2_config = {
+static const struct mdp5_cfg_hw msm8x74_config = {
.name = "msm8x74",
.mdp = {
.count = 1,
@@ -1098,9 +1009,8 @@ static const struct mdp5_cfg_hw msm8937_config = {
};
static const struct mdp5_cfg_handler cfg_handlers_v1[] = {
- { .revision = 0, .config = { .hw = &msm8x74v1_config } },
{ .revision = 1, .config = { .hw = &msm8x26_config } },
- { .revision = 2, .config = { .hw = &msm8x74v2_config } },
+ { .revision = 2, .config = { .hw = &msm8x74_config } },
{ .revision = 3, .config = { .hw = &apq8084_config } },
{ .revision = 6, .config = { .hw = &msm8x16_config } },
{ .revision = 8, .config = { .hw = &msm8x36_config } },
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.c
index fc183fe37f56..1eca140616c6 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.c
@@ -17,9 +17,6 @@
* a specific data path ID - REG_MDP5_CTL_*(<id>, ...)
*
* Hardware capabilities determine the number of concurrent data paths
- *
- * In certain use cases (high-resolution dual pipe), one single CTL can be
- * shared across multiple CRTCs.
*/
#define CTL_STAT_BUSY 0x1
@@ -46,11 +43,6 @@ struct mdp5_ctl {
u32 pending_ctl_trigger;
bool cursor_on;
-
- /* True if the current CTL has FLUSH bits pending for single FLUSH. */
- bool flush_pending;
-
- struct mdp5_ctl *pair; /* Paired CTL to be flushed together */
};
struct mdp5_ctl_manager {
@@ -63,10 +55,6 @@ struct mdp5_ctl_manager {
/* to filter out non-present bits in the current hardware config */
u32 flush_hw_mask;
- /* status for single FLUSH */
- bool single_flush_supported;
- u32 single_flush_pending_mask;
-
/* pool of CTLs + lock to protect resource allocation (ctls[i].busy) */
spinlock_t pool_lock;
struct mdp5_ctl ctls[MAX_CTL];
@@ -485,31 +473,6 @@ static u32 fix_sw_flush(struct mdp5_ctl *ctl, struct mdp5_pipeline *pipeline,
return sw_mask;
}
-static void fix_for_single_flush(struct mdp5_ctl *ctl, u32 *flush_mask,
- u32 *flush_id)
-{
- struct mdp5_ctl_manager *ctl_mgr = ctl->ctlm;
-
- if (ctl->pair) {
- DBG("CTL %d FLUSH pending mask %x", ctl->id, *flush_mask);
- ctl->flush_pending = true;
- ctl_mgr->single_flush_pending_mask |= (*flush_mask);
- *flush_mask = 0;
-
- if (ctl->pair->flush_pending) {
- *flush_id = min_t(u32, ctl->id, ctl->pair->id);
- *flush_mask = ctl_mgr->single_flush_pending_mask;
-
- ctl->flush_pending = false;
- ctl->pair->flush_pending = false;
- ctl_mgr->single_flush_pending_mask = 0;
-
- DBG("Single FLUSH mask %x,ID %d", *flush_mask,
- *flush_id);
- }
- }
-}
-
/**
* mdp5_ctl_commit() - Register Flush
*
@@ -555,8 +518,6 @@ u32 mdp5_ctl_commit(struct mdp5_ctl *ctl,
curr_ctl_flush_mask = flush_mask;
- fix_for_single_flush(ctl, &flush_mask, &flush_id);
-
if (!start) {
ctl->flush_mask |= flush_mask;
return curr_ctl_flush_mask;
@@ -589,40 +550,6 @@ int mdp5_ctl_get_ctl_id(struct mdp5_ctl *ctl)
}
/*
- * mdp5_ctl_pair() - Associate 2 booked CTLs for single FLUSH
- */
-int mdp5_ctl_pair(struct mdp5_ctl *ctlx, struct mdp5_ctl *ctly, bool enable)
-{
- struct mdp5_ctl_manager *ctl_mgr = ctlx->ctlm;
- struct mdp5_kms *mdp5_kms = get_kms(ctl_mgr);
-
- /* do nothing silently if hw doesn't support */
- if (!ctl_mgr->single_flush_supported)
- return 0;
-
- if (!enable) {
- ctlx->pair = NULL;
- ctly->pair = NULL;
- mdp5_write(mdp5_kms, REG_MDP5_SPARE_0, 0);
- return 0;
- } else if ((ctlx->pair != NULL) || (ctly->pair != NULL)) {
- DRM_DEV_ERROR(ctl_mgr->dev->dev, "CTLs already paired\n");
- return -EINVAL;
- } else if (!(ctlx->status & ctly->status & CTL_STAT_BOOKED)) {
- DRM_DEV_ERROR(ctl_mgr->dev->dev, "Only pair booked CTLs\n");
- return -EINVAL;
- }
-
- ctlx->pair = ctly;
- ctly->pair = ctlx;
-
- mdp5_write(mdp5_kms, REG_MDP5_SPARE_0,
- MDP5_SPARE_0_SPLIT_DPL_SINGLE_FLUSH_EN);
-
- return 0;
-}
-
-/*
* mdp5_ctl_request() - CTL allocation
*
* Try to return booked CTL for @intf_num is 1 or 2, unbooked for other INTFs.
@@ -687,8 +614,6 @@ struct mdp5_ctl_manager *mdp5_ctlm_init(struct drm_device *dev,
{
struct mdp5_ctl_manager *ctl_mgr;
const struct mdp5_cfg_hw *hw_cfg = mdp5_cfg_get_hw_config(cfg_hnd);
- int rev = mdp5_cfg_get_hw_rev(cfg_hnd);
- unsigned dsi_cnt = 0;
const struct mdp5_ctl_block *ctl_cfg = &hw_cfg->ctl;
unsigned long flags;
int c, ret;
@@ -730,21 +655,6 @@ struct mdp5_ctl_manager *mdp5_ctlm_init(struct drm_device *dev,
spin_lock_init(&ctl->hw_lock);
}
- /*
- * In bonded DSI case, CTL0 and CTL1 are always assigned to two DSI
- * interfaces to support single FLUSH feature (Flush CTL0 and CTL1 when
- * only write into CTL0's FLUSH register) to keep two DSI pipes in sync.
- * Single FLUSH is supported from hw rev v3.0.
- */
- for (c = 0; c < ARRAY_SIZE(hw_cfg->intf.connect); c++)
- if (hw_cfg->intf.connect[c] == INTF_DSI)
- dsi_cnt++;
- if ((rev >= 3) && (dsi_cnt > 1)) {
- ctl_mgr->single_flush_supported = true;
- /* Reserve CTL0/1 for INTF1/2 */
- ctl_mgr->ctls[0].status |= CTL_STAT_BOOKED;
- ctl_mgr->ctls[1].status |= CTL_STAT_BOOKED;
- }
spin_unlock_irqrestore(&ctl_mgr->pool_lock, flags);
DBG("Pool of %d CTLs created.", ctl_mgr->nctl);
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.h b/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.h
index 9020e8efc4e4..0c45f7874c24 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.h
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.h
@@ -35,7 +35,6 @@ int mdp5_ctl_set_encoder_state(struct mdp5_ctl *ctl, struct mdp5_pipeline *p,
int mdp5_ctl_set_cursor(struct mdp5_ctl *ctl, struct mdp5_pipeline *pipeline,
int cursor_id, bool enable);
-int mdp5_ctl_pair(struct mdp5_ctl *ctlx, struct mdp5_ctl *ctly, bool enable);
#define MAX_PIPE_STAGE 2
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
index 1e3dc9bf9494..2d26b07b06f5 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
@@ -717,7 +717,6 @@ static int mdp5_init(struct platform_device *pdev, struct drm_device *dev)
mdp5_kms->dev = dev;
drm_atomic_private_obj_init(mdp5_kms->dev, &mdp5_kms->glob_state,
- NULL,
&mdp5_global_state_funcs);
/* we need to set a default rate before enabling. Set a safe
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c
index 500b7dc895d0..890d2f31510e 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c
@@ -118,8 +118,6 @@ uint32_t mdp5_smp_calculate(struct mdp5_smp *smp,
u32 width, bool hdecim)
{
const struct drm_format_info *info = drm_format_info(format->pixel_format);
- struct mdp5_kms *mdp5_kms = get_kms(smp);
- int rev = mdp5_cfg_get_hw_rev(mdp5_kms->cfg);
int i, hsub, nplanes, nlines;
uint32_t blkcfg = 0;
@@ -133,7 +131,7 @@ uint32_t mdp5_smp_calculate(struct mdp5_smp *smp,
* U and V components (splits them from Y if necessary) and packs
* them together, writes to SMP using a single client.
*/
- if ((rev > 0) && (format->chroma_sample > CHROMA_FULL)) {
+ if (format->chroma_sample > CHROMA_FULL) {
nplanes = 2;
/* if decimation is enabled, HW decimates less on the
@@ -151,10 +149,6 @@ uint32_t mdp5_smp_calculate(struct mdp5_smp *smp,
n = DIV_ROUND_UP(fetch_stride * nlines, smp->blk_size);
- /* for hw rev v1.00 */
- if (rev == 0)
- n = roundup_pow_of_two(n);
-
blkcfg |= (n << (8 * i));
}
diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
index ef298c7d3e5e..cba8a71a2561 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
@@ -1928,9 +1928,6 @@ void msm_dp_ctrl_phy_init(struct msm_dp_ctrl *msm_dp_ctrl)
msm_dp_ctrl_phy_reset(ctrl);
phy_init(phy);
-
- drm_dbg_dp(ctrl->drm_dev, "phy=%p init=%d power_on=%d\n",
- phy, phy->init_count, phy->power_count);
}
void msm_dp_ctrl_phy_exit(struct msm_dp_ctrl *msm_dp_ctrl)
@@ -1943,8 +1940,6 @@ void msm_dp_ctrl_phy_exit(struct msm_dp_ctrl *msm_dp_ctrl)
msm_dp_ctrl_phy_reset(ctrl);
phy_exit(phy);
- drm_dbg_dp(ctrl->drm_dev, "phy=%p init=%d power_on=%d\n",
- phy, phy->init_count, phy->power_count);
}
static int msm_dp_ctrl_reinitialize_mainlink(struct msm_dp_ctrl_private *ctrl)
@@ -1996,8 +1991,6 @@ static int msm_dp_ctrl_deinitialize_mainlink(struct msm_dp_ctrl_private *ctrl)
phy_exit(phy);
phy_init(phy);
- drm_dbg_dp(ctrl->drm_dev, "phy=%p init=%d power_on=%d\n",
- phy, phy->init_count, phy->power_count);
return 0;
}
@@ -2588,9 +2581,6 @@ void msm_dp_ctrl_off_link_stream(struct msm_dp_ctrl *msm_dp_ctrl)
/* aux channel down, reinit phy */
phy_exit(phy);
phy_init(phy);
-
- drm_dbg_dp(ctrl->drm_dev, "phy=%p init=%d power_on=%d\n",
- phy, phy->init_count, phy->power_count);
}
void msm_dp_ctrl_off_link(struct msm_dp_ctrl *msm_dp_ctrl)
@@ -2606,13 +2596,7 @@ void msm_dp_ctrl_off_link(struct msm_dp_ctrl *msm_dp_ctrl)
dev_pm_opp_set_rate(ctrl->dev, 0);
msm_dp_ctrl_link_clk_disable(&ctrl->msm_dp_ctrl);
- DRM_DEBUG_DP("Before, phy=%p init_count=%d power_on=%d\n",
- phy, phy->init_count, phy->power_count);
-
phy_power_off(phy);
-
- DRM_DEBUG_DP("After, phy=%p init_count=%d power_on=%d\n",
- phy, phy->init_count, phy->power_count);
}
void msm_dp_ctrl_off(struct msm_dp_ctrl *msm_dp_ctrl)
@@ -2638,8 +2622,6 @@ void msm_dp_ctrl_off(struct msm_dp_ctrl *msm_dp_ctrl)
msm_dp_ctrl_link_clk_disable(&ctrl->msm_dp_ctrl);
phy_power_off(phy);
- drm_dbg_dp(ctrl->drm_dev, "phy=%p init=%d power_on=%d\n",
- phy, phy->init_count, phy->power_count);
}
irqreturn_t msm_dp_ctrl_isr(struct msm_dp_ctrl *msm_dp_ctrl)
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index 476848bf8cd1..d2124d625485 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -210,6 +210,7 @@ static const struct of_device_id msm_dp_dt_match[] = {
{ .compatible = "qcom,x1e80100-dp", .data = &msm_dp_desc_x1e80100 },
{}
};
+MODULE_DEVICE_TABLE(of, msm_dp_dt_match);
static struct msm_dp_display_private *dev_get_dp_display_private(struct device *dev)
{
diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c
index d8bb40ef820e..3c9f01ed6271 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.c
+++ b/drivers/gpu/drm/msm/dsi/dsi.c
@@ -198,6 +198,7 @@ static const struct of_device_id dt_match[] = {
{ .compatible = "qcom,dsi-ctrl-6g-qcm2290" },
{}
};
+MODULE_DEVICE_TABLE(of, dt_match);
static const struct dev_pm_ops dsi_pm_ops = {
SET_RUNTIME_PM_OPS(msm_dsi_runtime_suspend, msm_dsi_runtime_resume, NULL)
diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.c b/drivers/gpu/drm/msm/dsi/dsi_cfg.c
index bd3c51c350e7..da3fe6824495 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_cfg.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.c
@@ -317,10 +317,10 @@ static const struct msm_dsi_cfg_handler dsi_cfg_handlers[] = {
&msm8996_dsi_cfg, &msm_dsi_6g_host_ops},
{MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V1_4_2,
&msm8976_dsi_cfg, &msm_dsi_6g_host_ops},
+ {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V2_0_0,
+ &msm8998_dsi_cfg, &msm_dsi_6g_v2_host_ops},
{MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V2_1_0,
&sdm660_dsi_cfg, &msm_dsi_6g_v2_host_ops},
- {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V2_2_0,
- &msm8998_dsi_cfg, &msm_dsi_6g_v2_host_ops},
{MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V2_2_1,
&sdm845_dsi_cfg, &msm_dsi_6g_v2_host_ops},
{MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V2_3_0,
diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.h b/drivers/gpu/drm/msm/dsi/dsi_cfg.h
index 5dc812028bd5..ccf06679608e 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_cfg.h
+++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.h
@@ -19,8 +19,8 @@
#define MSM_DSI_6G_VER_MINOR_V1_3_1 0x10030001
#define MSM_DSI_6G_VER_MINOR_V1_4_1 0x10040001
#define MSM_DSI_6G_VER_MINOR_V1_4_2 0x10040002
+#define MSM_DSI_6G_VER_MINOR_V2_0_0 0x20000000
#define MSM_DSI_6G_VER_MINOR_V2_1_0 0x20010000
-#define MSM_DSI_6G_VER_MINOR_V2_2_0 0x20000000
#define MSM_DSI_6G_VER_MINOR_V2_2_1 0x20020001
#define MSM_DSI_6G_VER_MINOR_V2_3_0 0x20030000
#define MSM_DSI_6G_VER_MINOR_V2_3_1 0x20030001
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
index e0de545d4077..565d425f88b8 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -569,6 +569,7 @@ void dsi_link_clk_disable_v2(struct msm_dsi_host *msm_host)
* dsi_adjust_pclk_for_compression() - Adjust the pclk rate for compression case
* @mode: The selected mode for the DSI output
* @dsc: DRM DSC configuration for this DSI output
+ * @is_bonded_dsi: True if two DSI controllers are bonded
*
* Adjust the pclk rate by calculating a new hdisplay proportional to
* the compression ratio such that:
@@ -584,13 +585,30 @@ void dsi_link_clk_disable_v2(struct msm_dsi_host *msm_host)
* FIXME: Reconsider this if/when CMD mode handling is rewritten to use
* transfer time and data overhead as a starting point of the calculations.
*/
-static unsigned long dsi_adjust_pclk_for_compression(const struct drm_display_mode *mode,
- const struct drm_dsc_config *dsc)
+static unsigned long
+dsi_adjust_pclk_for_compression(const struct drm_display_mode *mode,
+ const struct drm_dsc_config *dsc,
+ bool is_bonded_dsi)
{
- int new_hdisplay = DIV_ROUND_UP(mode->hdisplay * drm_dsc_get_bpp_int(dsc),
- dsc->bits_per_component * 3);
+ int hdisplay, new_hdisplay, new_htotal;
- int new_htotal = mode->htotal - mode->hdisplay + new_hdisplay;
+ /*
+ * For bonded DSI, split hdisplay across two links and round up each
+ * half separately, passing the full hdisplay would only round up once.
+ * This also aligns with the hdisplay we program later in
+ * dsi_timing_setup()
+ */
+ hdisplay = mode->hdisplay;
+ if (is_bonded_dsi)
+ hdisplay /= 2;
+
+ new_hdisplay = DIV_ROUND_UP(hdisplay * drm_dsc_get_bpp_int(dsc),
+ dsc->bits_per_component * 3);
+
+ if (is_bonded_dsi)
+ new_hdisplay *= 2;
+
+ new_htotal = mode->htotal - mode->hdisplay + new_hdisplay;
return mult_frac(mode->clock * 1000u, new_htotal, mode->htotal);
}
@@ -603,7 +621,7 @@ static unsigned long dsi_get_pclk_rate(const struct drm_display_mode *mode,
pclk_rate = mode->clock * 1000u;
if (dsc)
- pclk_rate = dsi_adjust_pclk_for_compression(mode, dsc);
+ pclk_rate = dsi_adjust_pclk_for_compression(mode, dsc, is_bonded_dsi);
/*
* For bonded DSI mode, the current DRM mode has the complete width of the
@@ -740,6 +758,7 @@ static inline enum dsi_vid_dst_format
dsi_get_vid_fmt(const enum mipi_dsi_pixel_format mipi_fmt)
{
switch (mipi_fmt) {
+ case MIPI_DSI_FMT_RGB101010: return VID_DST_FORMAT_RGB101010;
case MIPI_DSI_FMT_RGB888: return VID_DST_FORMAT_RGB888;
case MIPI_DSI_FMT_RGB666: return VID_DST_FORMAT_RGB666_LOOSE;
case MIPI_DSI_FMT_RGB666_PACKED: return VID_DST_FORMAT_RGB666;
@@ -752,6 +771,7 @@ static inline enum dsi_cmd_dst_format
dsi_get_cmd_fmt(const enum mipi_dsi_pixel_format mipi_fmt)
{
switch (mipi_fmt) {
+ case MIPI_DSI_FMT_RGB101010: return CMD_DST_FORMAT_RGB101010;
case MIPI_DSI_FMT_RGB888: return CMD_DST_FORMAT_RGB888;
case MIPI_DSI_FMT_RGB666_PACKED:
case MIPI_DSI_FMT_RGB666: return CMD_DST_FORMAT_RGB666;
@@ -765,13 +785,21 @@ static void dsi_ctrl_disable(struct msm_dsi_host *msm_host)
dsi_write(msm_host, REG_DSI_CTRL, 0);
}
+static bool msm_dsi_host_version_geq(struct msm_dsi_host *msm_host,
+ u32 major, u32 minor)
+{
+ return msm_host->cfg_hnd->major > major ||
+ (msm_host->cfg_hnd->major == major &&
+ msm_host->cfg_hnd->minor >= minor);
+}
+
bool msm_dsi_host_is_wide_bus_enabled(struct mipi_dsi_host *host)
{
struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
return msm_host->dsc &&
- (msm_host->cfg_hnd->major == MSM_DSI_VER_MAJOR_6G &&
- msm_host->cfg_hnd->minor >= MSM_DSI_6G_VER_MINOR_V2_5_0);
+ msm_dsi_host_version_geq(msm_host, MSM_DSI_VER_MAJOR_6G,
+ MSM_DSI_6G_VER_MINOR_V2_5_0);
}
static void dsi_ctrl_enable(struct msm_dsi_host *msm_host,
@@ -993,7 +1021,7 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_dsi)
if (msm_host->dsc) {
struct drm_dsc_config *dsc = msm_host->dsc;
- u32 bytes_per_pclk;
+ u32 bits_per_pclk;
/* update dsc params with timing params */
if (!dsc || !mode->hdisplay || !mode->vdisplay) {
@@ -1015,7 +1043,10 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_dsi)
/*
* DPU sends 3 bytes per pclk cycle to DSI. If widebus is
- * enabled, bus width is extended to 6 bytes.
+ * enabled, MDP always sends out 48-bit compressed data per
+ * pclk and on average, for video mode, DSI consumes only an
+ * amount of compressed data equivalent to the uncompressed
+ * pixel depth per pclk.
*
* Calculate the number of pclks needed to transmit one line of
* the compressed data.
@@ -1027,12 +1058,16 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_dsi)
* unused anyway.
*/
h_total -= hdisplay;
- if (wide_bus_enabled && !(msm_host->mode_flags & MIPI_DSI_MODE_VIDEO))
- bytes_per_pclk = 6;
- else
- bytes_per_pclk = 3;
+ if (wide_bus_enabled) {
+ if (msm_host->mode_flags & MIPI_DSI_MODE_VIDEO)
+ bits_per_pclk = dsc->bits_per_component * 3;
+ else
+ bits_per_pclk = 48;
+ } else {
+ bits_per_pclk = 24;
+ }
- hdisplay = DIV_ROUND_UP(msm_dsc_get_bytes_per_line(msm_host->dsc), bytes_per_pclk);
+ hdisplay = DIV_ROUND_UP(msm_dsc_get_bytes_per_line(msm_host->dsc) * 8, bits_per_pclk);
h_total += hdisplay;
ha_end = ha_start + hdisplay;
@@ -1686,6 +1721,26 @@ static int dsi_host_attach(struct mipi_dsi_host *host,
if (dsi->dsc)
msm_host->dsc = dsi->dsc;
+ if (msm_host->format == MIPI_DSI_FMT_RGB101010) {
+ if (!msm_dsi_host_version_geq(msm_host, MSM_DSI_VER_MAJOR_6G,
+ MSM_DSI_6G_VER_MINOR_V2_1_0)) {
+ DRM_DEV_ERROR(&msm_host->pdev->dev,
+ "RGB101010 not supported on this DSI controller\n");
+ return -EINVAL;
+ }
+
+ /*
+ * Downstream overrides RGB101010 back to RGB888 when DSC is enabled
+ * but widebus is not. Using RGB101010 in this case may require some
+ * extra changes.
+ */
+ if (msm_host->dsc &&
+ !msm_dsi_host_is_wide_bus_enabled(&msm_host->base)) {
+ dev_warn(&msm_host->pdev->dev,
+ "RGB101010 with DSC but without widebus, may need extra changes\n");
+ }
+ }
+
ret = dsi_dev_attach(msm_host->pdev);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
index 7937266de1d2..c59375aaae19 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
@@ -582,6 +582,7 @@ static const struct of_device_id dsi_phy_dt_match[] = {
#endif
{}
};
+MODULE_DEVICE_TABLE(of, dsi_phy_dt_match);
/*
* Currently, we only support one SoC for each PHY type. When we have multiple
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 8cb0db3a9880..8f4b03713f25 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
@@ -41,8 +41,8 @@
#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.0 */
+#define DSI_PHY_7NM_QUIRK_V4_0 BIT(0)
/* Hardware is V4.1 */
#define DSI_PHY_7NM_QUIRK_V4_1 BIT(1)
/* Hardware is V4.2 */
@@ -51,8 +51,8 @@
#define DSI_PHY_7NM_QUIRK_V4_3 BIT(3)
/* Hardware is V5.2 */
#define DSI_PHY_7NM_QUIRK_V5_2 BIT(4)
-/* Hardware is V7.0 */
-#define DSI_PHY_7NM_QUIRK_V7_0 BIT(5)
+/* Hardware is V7.2 */
+#define DSI_PHY_7NM_QUIRK_V7_2 BIT(5)
struct dsi_pll_config {
bool enable_ssc;
@@ -141,9 +141,9 @@ 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_PRE_V4_1) {
+ if (pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_0) {
config->pll_clock_inverters = 0x28;
- } else if ((pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_0)) {
+ } else if ((pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_2)) {
if (pll_freq < 163000000ULL)
config->pll_clock_inverters = 0xa0;
else if (pll_freq < 175000000ULL)
@@ -264,7 +264,7 @@ 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_PRE_V4_1))
+ if (!(pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_0))
if (pll->vco_current_rate >= 3100000000ULL)
analog_controls_five_1 = 0x03;
@@ -284,7 +284,7 @@ static void dsi_pll_config_hzindep_reg(struct dsi_pll_7nm *pll)
}
if ((pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2) ||
- (pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_0)) {
+ (pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_2)) {
if (pll->vco_current_rate < 1557000000ULL)
vco_config_1 = 0x08;
else
@@ -313,10 +313,10 @@ static void dsi_pll_config_hzindep_reg(struct dsi_pll_7nm *pll)
writel(0x29, base + REG_DSI_7nm_PHY_PLL_PFILT);
writel(0x2f, base + REG_DSI_7nm_PHY_PLL_PFILT);
writel(0x2a, base + REG_DSI_7nm_PHY_PLL_IFILT);
- writel(!(pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_PRE_V4_1) ? 0x3f : 0x22,
+ writel(!(pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_0) ? 0x3f : 0x22,
base + REG_DSI_7nm_PHY_PLL_IFILT);
- if (!(pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_PRE_V4_1)) {
+ if (!(pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_0)) {
writel(0x22, base + REG_DSI_7nm_PHY_PLL_PERF_OPTIMIZE);
if (pll->slave)
writel(0x22, pll->slave->phy->pll_base + REG_DSI_7nm_PHY_PLL_PERF_OPTIMIZE);
@@ -699,7 +699,7 @@ static int dsi_7nm_set_usecase(struct msm_dsi_phy *phy)
case MSM_DSI_PHY_MASTER:
pll_7nm->slave = pll_7nm_list[(pll_7nm->phy->id + 1) % DSI_MAX];
/* v7.0: Enable ATB_EN0 and alternate clock output to external phy */
- if (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_0)
+ if (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_2)
writel(0x07, base + REG_DSI_7nm_PHY_CMN_CTRL_5);
break;
case MSM_DSI_PHY_SLAVE:
@@ -928,7 +928,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_PRE_V4_1))
+ if (!(phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_0))
tx_dctrl = tx_dctrl_1;
/* Strength ctrl settings */
@@ -987,7 +987,7 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy,
/* Request for REFGEN READY */
if ((phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_3) ||
(phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2) ||
- (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_0)) {
+ (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_2)) {
writel(0x1, phy->base + REG_DSI_7nm_PHY_CMN_GLBL_DIGTOP_SPARE10);
udelay(500);
}
@@ -1021,7 +1021,7 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy,
lane_ctrl0 = 0x1f;
}
- if ((phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_0)) {
+ if ((phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_2)) {
if (phy->cphy_mode) {
/* TODO: different for second phy */
vreg_ctrl_0 = 0x57;
@@ -1097,7 +1097,7 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy,
/* program CMN_CTRL_4 for minor_ver 2 chipsets*/
if ((phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2) ||
- (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_0) ||
+ (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_2) ||
(readl(base + REG_DSI_7nm_PHY_CMN_REVISION_ID0) & (0xf0)) == 0x20)
writel(0x04, base + REG_DSI_7nm_PHY_CMN_CTRL_4);
@@ -1213,7 +1213,7 @@ static void dsi_7nm_phy_disable(struct msm_dsi_phy *phy)
/* Turn off REFGEN Vote */
if ((phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_3) ||
(phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2) ||
- (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_0)) {
+ (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_2)) {
writel(0x0, base + REG_DSI_7nm_PHY_CMN_GLBL_DIGTOP_SPARE10);
wmb();
/* Delay to ensure HW removes vote before PHY shut down */
@@ -1319,7 +1319,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,
+ .quirks = DSI_PHY_7NM_QUIRK_V4_0,
};
const struct msm_dsi_phy_cfg dsi_phy_7nm_7280_cfgs = {
@@ -1502,7 +1502,7 @@ const struct msm_dsi_phy_cfg dsi_phy_3nm_8750_cfgs = {
#endif
.io_start = { 0xae95000, 0xae97000 },
.num_dsi_phy = 2,
- .quirks = DSI_PHY_7NM_QUIRK_V7_0,
+ .quirks = DSI_PHY_7NM_QUIRK_V7_2,
};
const struct msm_dsi_phy_cfg dsi_phy_3nm_kaanapali_cfgs = {
@@ -1525,5 +1525,5 @@ const struct msm_dsi_phy_cfg dsi_phy_3nm_kaanapali_cfgs = {
#endif
.io_start = { 0x9ac1000, 0x9ac4000 },
.num_dsi_phy = 2,
- .quirks = DSI_PHY_7NM_QUIRK_V7_0,
+ .quirks = DSI_PHY_7NM_QUIRK_V7_2,
};
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
index 5afac09c0d33..852abb2466f0 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
@@ -20,7 +20,7 @@
void msm_hdmi_set_mode(struct hdmi *hdmi, bool power_on)
{
- uint32_t ctrl = 0;
+ u32 ctrl = 0;
unsigned long flags;
spin_lock_irqsave(&hdmi->reg_lock, flags);
@@ -91,7 +91,7 @@ static int msm_hdmi_get_phy(struct hdmi *hdmi)
struct platform_device *phy_pdev;
struct device_node *phy_node;
- phy_node = of_parse_phandle(pdev->dev.of_node, "phys", 0);
+ phy_node = of_parse_phandle(dev_of_node(&pdev->dev), "phys", 0);
if (!phy_node) {
DRM_DEV_ERROR(&pdev->dev, "cannot find phy device\n");
return -ENXIO;
@@ -278,7 +278,7 @@ static int msm_hdmi_dev_probe(struct platform_device *pdev)
if (!config)
return -EINVAL;
- hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
+ hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
if (!hdmi)
return -ENOMEM;
@@ -287,7 +287,7 @@ static int msm_hdmi_dev_probe(struct platform_device *pdev)
spin_lock_init(&hdmi->reg_lock);
mutex_init(&hdmi->state_mutex);
- ret = drm_of_find_panel_or_bridge(pdev->dev.of_node, 1, 0, NULL, &hdmi->next_bridge);
+ ret = drm_of_find_panel_or_bridge(dev_of_node(dev), 1, 0, NULL, &hdmi->next_bridge);
if (ret && ret != -ENODEV)
return ret;
@@ -304,7 +304,7 @@ static int msm_hdmi_dev_probe(struct platform_device *pdev)
hdmi->qfprom_mmio = msm_ioremap(pdev, "qfprom_physical");
if (IS_ERR(hdmi->qfprom_mmio)) {
- DRM_DEV_INFO(&pdev->dev, "can't find qfprom resource\n");
+ DRM_DEV_INFO(dev, "can't find qfprom resource\n");
hdmi->qfprom_mmio = NULL;
}
@@ -312,8 +312,7 @@ static int msm_hdmi_dev_probe(struct platform_device *pdev)
if (hdmi->irq < 0)
return hdmi->irq;
- hdmi->pwr_regs = devm_kcalloc(&pdev->dev,
- config->pwr_reg_cnt,
+ hdmi->pwr_regs = devm_kcalloc(dev, config->pwr_reg_cnt,
sizeof(hdmi->pwr_regs[0]),
GFP_KERNEL);
if (!hdmi->pwr_regs)
@@ -322,12 +321,11 @@ static int msm_hdmi_dev_probe(struct platform_device *pdev)
for (i = 0; i < config->pwr_reg_cnt; i++)
hdmi->pwr_regs[i].supply = config->pwr_reg_names[i];
- ret = devm_regulator_bulk_get(&pdev->dev, config->pwr_reg_cnt, hdmi->pwr_regs);
+ ret = devm_regulator_bulk_get(dev, config->pwr_reg_cnt, hdmi->pwr_regs);
if (ret)
return dev_err_probe(dev, ret, "failed to get pwr regulators\n");
- hdmi->pwr_clks = devm_kcalloc(&pdev->dev,
- config->pwr_clk_cnt,
+ hdmi->pwr_clks = devm_kcalloc(dev, config->pwr_clk_cnt,
sizeof(hdmi->pwr_clks[0]),
GFP_KERNEL);
if (!hdmi->pwr_clks)
@@ -336,16 +334,16 @@ static int msm_hdmi_dev_probe(struct platform_device *pdev)
for (i = 0; i < config->pwr_clk_cnt; i++)
hdmi->pwr_clks[i].id = config->pwr_clk_names[i];
- ret = devm_clk_bulk_get(&pdev->dev, config->pwr_clk_cnt, hdmi->pwr_clks);
+ ret = devm_clk_bulk_get(dev, config->pwr_clk_cnt, hdmi->pwr_clks);
if (ret)
return ret;
- hdmi->extp_clk = devm_clk_get_optional(&pdev->dev, "extp");
+ hdmi->extp_clk = devm_clk_get_optional(dev, "extp");
if (IS_ERR(hdmi->extp_clk))
return dev_err_probe(dev, PTR_ERR(hdmi->extp_clk),
"failed to get extp clock\n");
- hdmi->hpd_gpiod = devm_gpiod_get_optional(&pdev->dev, "hpd", GPIOD_IN);
+ hdmi->hpd_gpiod = devm_gpiod_get_optional(dev, "hpd", GPIOD_IN);
/* This will catch e.g. -EPROBE_DEFER */
if (IS_ERR(hdmi->hpd_gpiod))
return dev_err_probe(dev, PTR_ERR(hdmi->hpd_gpiod),
@@ -358,18 +356,16 @@ static int msm_hdmi_dev_probe(struct platform_device *pdev)
gpiod_set_consumer_name(hdmi->hpd_gpiod, "HDMI_HPD");
ret = msm_hdmi_get_phy(hdmi);
- if (ret) {
- DRM_DEV_ERROR(&pdev->dev, "failed to get phy\n");
+ if (ret)
return ret;
- }
- ret = devm_pm_runtime_enable(&pdev->dev);
+ ret = devm_pm_runtime_enable(dev);
if (ret)
goto err_put_phy;
platform_set_drvdata(pdev, hdmi);
- ret = component_add(&pdev->dev, &msm_hdmi_ops);
+ ret = component_add(dev, &msm_hdmi_ops);
if (ret)
goto err_put_phy;
@@ -429,7 +425,7 @@ fail:
return ret;
}
-DEFINE_RUNTIME_DEV_PM_OPS(msm_hdmi_pm_ops, msm_hdmi_runtime_suspend, msm_hdmi_runtime_resume, NULL);
+static DEFINE_RUNTIME_DEV_PM_OPS(msm_hdmi_pm_ops, msm_hdmi_runtime_suspend, msm_hdmi_runtime_resume, NULL);
static const struct of_device_id msm_hdmi_dt_match[] = {
{ .compatible = "qcom,hdmi-tx-8998", .data = &hdmi_tx_8974_config },
@@ -441,6 +437,7 @@ static const struct of_device_id msm_hdmi_dt_match[] = {
{ .compatible = "qcom,hdmi-tx-8660", .data = &hdmi_tx_8960_config },
{}
};
+MODULE_DEVICE_TABLE(of, msm_hdmi_dt_match);
static struct platform_driver msm_hdmi_driver = {
.probe = msm_hdmi_dev_probe,
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h
index 02cfd46df594..49433f7727c3 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.h
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.h
@@ -43,7 +43,7 @@ struct hdmi {
bool power_on;
bool hpd_enabled;
struct mutex state_mutex; /* protects two booleans */
- unsigned long int pixclock;
+ unsigned long pixclock;
void __iomem *mmio;
void __iomem *qfprom_mmio;
@@ -132,7 +132,7 @@ enum hdmi_phy_type {
struct hdmi_phy_cfg {
enum hdmi_phy_type type;
- void (*powerup)(struct hdmi_phy *phy, unsigned long int pixclock);
+ void (*powerup)(struct hdmi_phy *phy, unsigned long pixclock);
void (*powerdown)(struct hdmi_phy *phy);
const char * const *reg_names;
int num_regs;
@@ -167,7 +167,7 @@ static inline u32 hdmi_phy_read(struct hdmi_phy *phy, u32 reg)
int msm_hdmi_phy_resource_enable(struct hdmi_phy *phy);
void msm_hdmi_phy_resource_disable(struct hdmi_phy *phy);
-void msm_hdmi_phy_powerup(struct hdmi_phy *phy, unsigned long int pixclock);
+void msm_hdmi_phy_powerup(struct hdmi_phy *phy, unsigned long pixclock);
void msm_hdmi_phy_powerdown(struct hdmi_phy *phy);
void __init msm_hdmi_phy_driver_register(void);
void __exit msm_hdmi_phy_driver_unregister(void);
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_audio.c b/drivers/gpu/drm/msm/hdmi/hdmi_audio.c
index d9a8dc9dae8f..249c167ab04d 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_audio.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_audio.c
@@ -17,8 +17,7 @@ int msm_hdmi_audio_update(struct hdmi *hdmi)
{
struct hdmi_audio *audio = &hdmi->audio;
bool enabled = audio->enabled;
- uint32_t acr_pkt_ctrl, vbi_pkt_ctrl, aud_pkt_ctrl;
- uint32_t audio_config;
+ u32 acr_pkt_ctrl, vbi_pkt_ctrl, aud_pkt_ctrl, audio_config;
if (!hdmi->connector->display_info.is_hdmi)
return -EINVAL;
@@ -43,7 +42,7 @@ int msm_hdmi_audio_update(struct hdmi *hdmi)
acr_pkt_ctrl &= ~HDMI_ACR_PKT_CTRL_SELECT__MASK;
if (enabled) {
- uint32_t n, cts, multiplier;
+ u32 n, cts, multiplier;
enum hdmi_acr_cts select;
drm_hdmi_acr_get_n_cts(hdmi->pixclock, audio->rate, &n, &cts);
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
index 98cd490e7ab0..a9eb6489c520 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
@@ -153,7 +153,7 @@ static int msm_hdmi_bridge_write_avi_infoframe(struct drm_bridge *bridge,
for (i = 0; i < ARRAY_SIZE(buf); i++)
hdmi_write(hdmi, REG_HDMI_AVI_INFO(i), buf[i]);
- val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL1);
+ val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL0);
val |= HDMI_INFOFRAME_CTRL0_AVI_SEND |
HDMI_INFOFRAME_CTRL0_AVI_CONT;
hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL0, val);
@@ -193,7 +193,7 @@ static int msm_hdmi_bridge_write_audio_infoframe(struct drm_bridge *bridge,
buffer[9] << 16 |
buffer[10] << 24);
- val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL1);
+ val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL0);
val |= HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SEND |
HDMI_INFOFRAME_CTRL0_AUDIO_INFO_CONT |
HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SOURCE |
@@ -356,7 +356,7 @@ static void msm_hdmi_set_timings(struct hdmi *hdmi,
const struct drm_display_mode *mode)
{
int hstart, hend, vstart, vend;
- uint32_t frame_ctrl;
+ u32 frame_ctrl;
hstart = mode->htotal - mode->hsync_start;
hend = mode->htotal - mode->hsync_start + mode->hdisplay;
@@ -409,7 +409,7 @@ static const struct drm_edid *msm_hdmi_bridge_edid_read(struct drm_bridge *bridg
struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
struct hdmi *hdmi = hdmi_bridge->hdmi;
const struct drm_edid *drm_edid;
- uint32_t hdmi_ctrl;
+ u32 hdmi_ctrl;
hdmi_ctrl = hdmi_read(hdmi, REG_HDMI_CTRL);
hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl | HDMI_CTRL_ENABLE);
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c b/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c
index 114b0d507700..2cccd9062584 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c
@@ -65,7 +65,7 @@ void msm_hdmi_hpd_enable(struct drm_bridge *bridge)
struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
struct hdmi *hdmi = hdmi_bridge->hdmi;
struct device *dev = &hdmi->pdev->dev;
- uint32_t hpd_ctrl;
+ u32 hpd_ctrl;
int ret;
unsigned long flags;
@@ -125,7 +125,7 @@ void msm_hdmi_hpd_irq(struct drm_bridge *bridge)
{
struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
struct hdmi *hdmi = hdmi_bridge->hdmi;
- uint32_t hpd_int_status, hpd_int_ctrl;
+ u32 hpd_int_status, hpd_int_ctrl;
/* Process HPD: */
hpd_int_status = hdmi_read(hdmi, REG_HDMI_HPD_INT_STATUS);
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_i2c.c b/drivers/gpu/drm/msm/hdmi/hdmi_i2c.c
index 6b9265159195..4a4a2cf90234 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_i2c.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_i2c.c
@@ -40,8 +40,8 @@ static int ddc_clear_irq(struct hdmi_i2c_adapter *hdmi_i2c)
{
struct hdmi *hdmi = hdmi_i2c->hdmi;
struct drm_device *dev = hdmi->dev;
- uint32_t retry = 0xffff;
- uint32_t ddc_int_ctrl;
+ u32 retry = 0xffff;
+ u32 ddc_int_ctrl;
do {
--retry;
@@ -71,7 +71,7 @@ static bool sw_done(struct hdmi_i2c_adapter *hdmi_i2c)
struct hdmi *hdmi = hdmi_i2c->hdmi;
if (!hdmi_i2c->sw_done) {
- uint32_t ddc_int_ctrl;
+ u32 ddc_int_ctrl;
ddc_int_ctrl = hdmi_read(hdmi, REG_HDMI_DDC_INT_CTRL);
@@ -92,13 +92,13 @@ static int msm_hdmi_i2c_xfer(struct i2c_adapter *i2c,
struct hdmi_i2c_adapter *hdmi_i2c = to_hdmi_i2c_adapter(i2c);
struct hdmi *hdmi = hdmi_i2c->hdmi;
struct drm_device *dev = hdmi->dev;
- static const uint32_t nack[] = {
+ static const u32 nack[] = {
HDMI_DDC_SW_STATUS_NACK0, HDMI_DDC_SW_STATUS_NACK1,
HDMI_DDC_SW_STATUS_NACK2, HDMI_DDC_SW_STATUS_NACK3,
};
int indices[MAX_TRANSACTIONS];
int ret, i, j, index = 0;
- uint32_t ddc_status, ddc_data, i2c_trans;
+ u32 ddc_status, ddc_data, i2c_trans;
num = min(num, MAX_TRANSACTIONS);
@@ -119,7 +119,7 @@ static int msm_hdmi_i2c_xfer(struct i2c_adapter *i2c,
for (i = 0; i < num; i++) {
struct i2c_msg *p = &msgs[i];
- uint32_t raw_addr = p->addr << 1;
+ u32 raw_addr = p->addr << 1;
if (p->flags & I2C_M_RD)
raw_addr |= 1;
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_phy.c b/drivers/gpu/drm/msm/hdmi/hdmi_phy.c
index 667573f1db7c..eb1088755cb3 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_phy.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_phy.c
@@ -94,7 +94,7 @@ void msm_hdmi_phy_resource_disable(struct hdmi_phy *phy)
pm_runtime_put_sync(dev);
}
-void msm_hdmi_phy_powerup(struct hdmi_phy *phy, unsigned long int pixclock)
+void msm_hdmi_phy_powerup(struct hdmi_phy *phy, unsigned long pixclock)
{
if (!phy || !phy->cfg->powerup)
return;
@@ -204,6 +204,7 @@ static const struct of_device_id msm_hdmi_phy_dt_match[] = {
.data = &msm_hdmi_phy_8998_cfg },
{}
};
+MODULE_DEVICE_TABLE(of, msm_hdmi_phy_dt_match);
static struct platform_driver msm_hdmi_phy_platform_driver = {
.probe = msm_hdmi_phy_probe,
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c b/drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c
index cf90a0c1f822..cfa8fc494199 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c
@@ -7,7 +7,7 @@
#include "hdmi.h"
static void hdmi_phy_8960_powerup(struct hdmi_phy *phy,
- unsigned long int pixclock)
+ unsigned long pixclock)
{
DBG("pixclock: %lu", pixclock);
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8x60.c b/drivers/gpu/drm/msm/hdmi/hdmi_phy_8x60.c
index 1d97640d8c24..10ee91818364 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8x60.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_phy_8x60.c
@@ -9,7 +9,7 @@
#include "hdmi.h"
static void hdmi_phy_8x60_powerup(struct hdmi_phy *phy,
- unsigned long int pixclock)
+ unsigned long pixclock)
{
/* De-serializer delay D/C for non-lbk mode: */
hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG0,
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8x74.c b/drivers/gpu/drm/msm/hdmi/hdmi_phy_8x74.c
index a2a6940e195a..6f40820d9071 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8x74.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_phy_8x74.c
@@ -7,7 +7,7 @@
#include "hdmi.h"
static void hdmi_phy_8x74_powerup(struct hdmi_phy *phy,
- unsigned long int pixclock)
+ unsigned long pixclock)
{
hdmi_phy_write(phy, REG_HDMI_8x74_ANA_CFG0, 0x1b);
hdmi_phy_write(phy, REG_HDMI_8x74_ANA_CFG1, 0xf2);
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index e5ab1e28851d..195f40e331e5 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -536,6 +536,11 @@ static int msm_ioctl_gem_info_get_metadata(struct drm_gem_object *obj,
len = msm_obj->metadata_size;
buf = kmemdup(msm_obj->metadata, len, GFP_KERNEL);
+ if (!buf) {
+ msm_gem_unlock(obj);
+ return -ENOMEM;
+ }
+
msm_gem_unlock(obj);
if (*metadata_size < len) {
@@ -548,7 +553,7 @@ static int msm_ioctl_gem_info_get_metadata(struct drm_gem_object *obj,
kfree(buf);
- return 0;
+ return ret;
}
static int msm_ioctl_gem_info(struct drm_device *dev, void *data,
diff --git a/drivers/gpu/drm/msm/msm_fb.c b/drivers/gpu/drm/msm/msm_fb.c
index b3fdb83202ab..9b681e144c07 100644
--- a/drivers/gpu/drm/msm/msm_fb.c
+++ b/drivers/gpu/drm/msm/msm_fb.c
@@ -219,7 +219,12 @@ static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev,
+ mode_cmd->offsets[i];
if (bos[i]->size < min_size) {
- ret = -EINVAL;
+ ret = UERR(EINVAL, dev, "plane %d too small", i);
+ goto fail;
+ }
+
+ if (to_msm_bo(bos[i])->flags & MSM_BO_NO_SHARE) {
+ ret = UERR(EINVAL, dev, "Cannot map _NO_SHARE to kms vm");
goto fail;
}
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
index b27abaa13926..2cb3ab04f125 100644
--- a/drivers/gpu/drm/msm/msm_gem.c
+++ b/drivers/gpu/drm/msm/msm_gem.c
@@ -507,8 +507,11 @@ void msm_gem_unpin_locked(struct drm_gem_object *obj)
*/
void msm_gem_unpin_active(struct drm_gem_object *obj)
{
+ struct msm_drm_private *priv = obj->dev->dev_private;
struct msm_gem_object *msm_obj = to_msm_bo(obj);
+ GEM_WARN_ON(!mutex_is_locked(&priv->lru.lock));
+
msm_obj->pin_count--;
GEM_WARN_ON(msm_obj->pin_count < 0);
update_lru_active(obj);
diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h
index cb32093fda47..762e546d25ef 100644
--- a/drivers/gpu/drm/msm/msm_gem.h
+++ b/drivers/gpu/drm/msm/msm_gem.h
@@ -452,6 +452,7 @@ struct msm_gem_submit {
bool bos_pinned : 1;
bool fault_dumped:1;/* Limit devcoredump dumping to one per submit */
bool in_rb : 1; /* "sudo" mode, copy cmds into RB */
+ bool has_exec : 1; /* @exec is initialized. */
struct msm_ringbuffer *ring;
unsigned int nr_cmds;
unsigned int nr_bos;
diff --git a/drivers/gpu/drm/msm/msm_gem_shrinker.c b/drivers/gpu/drm/msm/msm_gem_shrinker.c
index 1039e3c0a47b..31fa51a44f86 100644
--- a/drivers/gpu/drm/msm/msm_gem_shrinker.c
+++ b/drivers/gpu/drm/msm/msm_gem_shrinker.c
@@ -26,9 +26,8 @@ static bool can_swap(void)
static bool can_block(struct shrink_control *sc)
{
- if (!(sc->gfp_mask & __GFP_DIRECT_RECLAIM))
- return false;
- return current_is_kswapd() || (sc->gfp_mask & __GFP_RECLAIM);
+ return (sc->gfp_mask & __GFP_DIRECT_RECLAIM) ||
+ (current_is_kswapd() && (sc->gfp_mask & __GFP_KSWAPD_RECLAIM));
}
static unsigned long
diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c
index 75d9f3574370..26ea8a28be47 100644
--- a/drivers/gpu/drm/msm/msm_gem_submit.c
+++ b/drivers/gpu/drm/msm/msm_gem_submit.c
@@ -278,6 +278,7 @@ static int submit_lock_objects_vmbind(struct msm_gem_submit *submit)
int ret = 0;
drm_exec_init(&submit->exec, flags, submit->nr_bos);
+ submit->has_exec = true;
drm_exec_until_all_locked (&submit->exec) {
ret = drm_gpuvm_prepare_vm(submit->vm, exec, 1);
@@ -304,6 +305,7 @@ static int submit_lock_objects(struct msm_gem_submit *submit)
return submit_lock_objects_vmbind(submit);
drm_exec_init(&submit->exec, flags, submit->nr_bos);
+ submit->has_exec = true;
drm_exec_until_all_locked (&submit->exec) {
ret = drm_exec_lock_obj(&submit->exec,
@@ -523,7 +525,7 @@ static void submit_cleanup(struct msm_gem_submit *submit, bool error)
if (error)
submit_unpin_objects(submit);
- if (submit->exec.objects)
+ if (submit->has_exec)
drm_exec_fini(&submit->exec);
/* if job wasn't enqueued to scheduler, early retirement: */
diff --git a/drivers/gpu/drm/msm/msm_gem_vma.c b/drivers/gpu/drm/msm/msm_gem_vma.c
index adf88cf8f41a..1a952b171ed7 100644
--- a/drivers/gpu/drm/msm/msm_gem_vma.c
+++ b/drivers/gpu/drm/msm/msm_gem_vma.c
@@ -373,6 +373,12 @@ msm_gem_vma_new(struct drm_gpuvm *gpuvm, struct drm_gem_object *obj,
struct msm_gem_vma *vma;
int ret;
+ /* _NO_SHARE objs cannot be mapped outside of their "host" vm: */
+ if (obj && (to_msm_bo(obj)->flags & MSM_BO_NO_SHARE) &&
+ GEM_WARN_ON(obj->resv != drm_gpuvm_resv(gpuvm))) {
+ return ERR_PTR(-EINVAL);
+ }
+
drm_gpuvm_resv_assert_held(&vm->base);
vma = kzalloc_obj(*vma);
@@ -696,6 +702,7 @@ static struct dma_fence *
msm_vma_job_run(struct drm_sched_job *_job)
{
struct msm_vm_bind_job *job = to_msm_vm_bind_job(_job);
+ struct msm_drm_private *priv = job->vm->drm->dev_private;
struct msm_gem_vm *vm = to_msm_vm(job->vm);
struct drm_gem_object *obj;
int ret = vm->unusable ? -EINVAL : 0;
@@ -738,12 +745,14 @@ msm_vma_job_run(struct drm_sched_job *_job)
if (ret)
msm_gem_vm_unusable(job->vm);
+ mutex_lock(&priv->lru.lock);
+
job_foreach_bo (obj, job) {
- msm_gem_lock(obj);
- msm_gem_unpin_locked(obj);
- msm_gem_unlock(obj);
+ msm_gem_unpin_active(obj);
}
+ mutex_unlock(&priv->lru.lock);
+
/* VM_BIND ops are synchronous, so no fence to wait on: */
return NULL;
}
@@ -1242,7 +1251,7 @@ vm_bind_job_lock_objects(struct msm_vm_bind_job *job, struct drm_exec *exec)
case MSM_VM_BIND_OP_UNMAP:
ret = drm_gpuvm_sm_unmap_exec_lock(job->vm, exec,
op->iova,
- op->obj_offset);
+ op->range);
break;
case MSM_VM_BIND_OP_MAP:
case MSM_VM_BIND_OP_MAP_NULL: {
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index 84d6c7f50c8d..930e54d1b0a7 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -17,6 +17,7 @@
#include <linux/string_helpers.h>
#include <linux/devcoredump.h>
#include <linux/sched/task.h>
+#include <linux/sched/mm.h>
/*
* Power Management:
@@ -468,6 +469,7 @@ static void recover_worker(struct kthread_work *work)
struct msm_gem_submit *submit;
struct msm_ringbuffer *cur_ring = gpu->funcs->active_ring(gpu);
char *comm = NULL, *cmd = NULL;
+ unsigned int noreclaim_flag;
struct task_struct *task;
int i;
@@ -505,6 +507,8 @@ static void recover_worker(struct kthread_work *work)
msm_gem_vm_unusable(submit->vm);
}
+ noreclaim_flag = memalloc_noreclaim_save();
+
get_comm_cmdline(submit, &comm, &cmd);
if (comm && cmd) {
@@ -523,6 +527,8 @@ static void recover_worker(struct kthread_work *work)
pm_runtime_get_sync(&gpu->pdev->dev);
msm_gpu_crashstate_capture(gpu, submit, NULL, comm, cmd);
+ memalloc_noreclaim_restore(noreclaim_flag);
+
kfree(cmd);
kfree(comm);
@@ -546,32 +552,30 @@ static void recover_worker(struct kthread_work *work)
msm_update_fence(ring->fctx, fence);
}
- if (msm_gpu_active(gpu)) {
- /* retire completed submits, plus the one that hung: */
- retire_submits(gpu);
+ /* retire completed submits, plus the one that hung: */
+ retire_submits(gpu);
- gpu->funcs->recover(gpu);
+ gpu->funcs->recover(gpu);
- /*
- * Replay all remaining submits starting with highest priority
- * ring
- */
- for (i = 0; i < gpu->nr_rings; i++) {
- struct msm_ringbuffer *ring = gpu->rb[i];
- unsigned long flags;
+ /*
+ * Replay all remaining submits starting with highest priority
+ * ring
+ */
+ for (i = 0; i < gpu->nr_rings; i++) {
+ struct msm_ringbuffer *ring = gpu->rb[i];
+ unsigned long flags;
- spin_lock_irqsave(&ring->submit_lock, flags);
- list_for_each_entry(submit, &ring->submits, node) {
- /*
- * If the submit uses an unusable vm make sure
- * we don't actually run it
- */
- if (to_msm_vm(submit->vm)->unusable)
- submit->nr_cmds = 0;
- gpu->funcs->submit(gpu, submit);
- }
- spin_unlock_irqrestore(&ring->submit_lock, flags);
+ spin_lock_irqsave(&ring->submit_lock, flags);
+ list_for_each_entry(submit, &ring->submits, node) {
+ /*
+ * If the submit uses an unusable vm make sure
+ * we don't actually run it
+ */
+ if (to_msm_vm(submit->vm)->unusable)
+ submit->nr_cmds = 0;
+ gpu->funcs->submit(gpu, submit);
}
+ spin_unlock_irqrestore(&ring->submit_lock, flags);
}
pm_runtime_put(&gpu->pdev->dev);
@@ -587,6 +591,7 @@ void msm_gpu_fault_crashstate_capture(struct msm_gpu *gpu, struct msm_gpu_fault_
struct msm_gem_submit *submit;
struct msm_ringbuffer *cur_ring = gpu->funcs->active_ring(gpu);
char *comm = NULL, *cmd = NULL;
+ unsigned int noreclaim_flag;
mutex_lock(&gpu->lock);
@@ -594,6 +599,8 @@ void msm_gpu_fault_crashstate_capture(struct msm_gpu *gpu, struct msm_gpu_fault_
if (submit && submit->fault_dumped)
goto resume_smmu;
+ noreclaim_flag = memalloc_noreclaim_save();
+
if (submit) {
get_comm_cmdline(submit, &comm, &cmd);
@@ -609,6 +616,8 @@ void msm_gpu_fault_crashstate_capture(struct msm_gpu *gpu, struct msm_gpu_fault_
msm_gpu_crashstate_capture(gpu, submit, fault_info, comm, cmd);
pm_runtime_put_sync(&gpu->pdev->dev);
+ memalloc_noreclaim_restore(noreclaim_flag);
+
kfree(cmd);
kfree(comm);
diff --git a/drivers/gpu/drm/msm/msm_mdss.c b/drivers/gpu/drm/msm/msm_mdss.c
index 9047e8d9ee89..90c3fa0681a0 100644
--- a/drivers/gpu/drm/msm/msm_mdss.c
+++ b/drivers/gpu/drm/msm/msm_mdss.c
@@ -262,6 +262,14 @@ static int msm_mdss_enable(struct msm_mdss *msm_mdss)
icc_set_bw(msm_mdss->reg_bus_path, 0,
msm_mdss->reg_bus_bw);
+ /*
+ * TODO:
+ * Previous users (e.g. the bootloader) may have left this clock at a high rate, which
+ * would remain set, as prepare_enable() doesn't reprogram it. This theoretically poses a
+ * risk of brownout, but realistically this path is almost exclusively excercised after the
+ * correct OPP has been set in one of the MDPn or DPU drivers, or during initial probe,
+ * before the RPM(H)PD sync_state is done.
+ */
ret = clk_bulk_prepare_enable(msm_mdss->num_clocks, msm_mdss->clocks);
if (ret) {
dev_err(msm_mdss->dev, "clock enable failed, ret:%d\n", ret);
@@ -560,6 +568,7 @@ static const struct msm_mdss_data data_153k6 = {
static const struct of_device_id mdss_dt_match[] = {
{ .compatible = "qcom,mdss", .data = &data_153k6 },
+ { .compatible = "qcom,eliza-mdss", .data = &data_57k },
{ .compatible = "qcom,glymur-mdss", .data = &data_57k },
{ .compatible = "qcom,kaanapali-mdss", .data = &data_57k },
{ .compatible = "qcom,msm8998-mdss", .data = &data_76k8 },
diff --git a/drivers/gpu/drm/msm/registers/adreno/a6xx.xml b/drivers/gpu/drm/msm/registers/adreno/a6xx.xml
index 3941e7510754..2309870f5031 100644
--- a/drivers/gpu/drm/msm/registers/adreno/a6xx.xml
+++ b/drivers/gpu/drm/msm/registers/adreno/a6xx.xml
@@ -5016,6 +5016,10 @@ by a particular renderpass/blit.
<bitfield pos="1" name="LPAC" type="boolean"/>
<bitfield pos="2" name="RAYTRACING" type="boolean"/>
</reg32>
+ <reg32 offset="0x0405" name="CX_MISC_SW_FUSE_FREQ_LIMIT_STATUS" variants="A8XX-">
+ <bitfield high="8" low="0" name="FINALFREQLIMIT"/>
+ <bitfield pos="24" name="SOFTSKUDISABLED" type="boolean"/>
+ </reg32>
</domain>
</database>
diff --git a/drivers/gpu/drm/msm/registers/adreno/a6xx_gmu.xml b/drivers/gpu/drm/msm/registers/adreno/a6xx_gmu.xml
index c4e00b1263cd..33404eb18fd0 100644
--- a/drivers/gpu/drm/msm/registers/adreno/a6xx_gmu.xml
+++ b/drivers/gpu/drm/msm/registers/adreno/a6xx_gmu.xml
@@ -141,8 +141,10 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
<reg32 offset="0x1f9f0" name="GMU_BOOT_KMD_LM_HANDSHAKE"/>
<reg32 offset="0x1f957" name="GMU_LLM_GLM_SLEEP_CTRL"/>
<reg32 offset="0x1f958" name="GMU_LLM_GLM_SLEEP_STATUS"/>
- <reg32 offset="0x1f888" name="GMU_ALWAYS_ON_COUNTER_L"/>
- <reg32 offset="0x1f889" name="GMU_ALWAYS_ON_COUNTER_H"/>
+ <reg32 offset="0x1f888" name="GMU_ALWAYS_ON_COUNTER_L" variants="A6XX-A7XX"/>
+ <reg32 offset="0x1f840" name="GMU_ALWAYS_ON_COUNTER_L" variants="A8XX-"/>
+ <reg32 offset="0x1f889" name="GMU_ALWAYS_ON_COUNTER_H" variants="A6XX-A7XX"/>
+ <reg32 offset="0x1f841" name="GMU_ALWAYS_ON_COUNTER_H" variants="A8XX-"/>
<reg32 offset="0x1f8c3" name="GMU_GMU_PWR_COL_KEEPALIVE" variants="A6XX-A7XX"/>
<reg32 offset="0x1f7e4" name="GMU_GMU_PWR_COL_KEEPALIVE" variants="A8XX-"/>
<reg32 offset="0x1f8c4" name="GMU_PWR_COL_PREEMPT_KEEPALIVE" variants="A6XX-A7XX"/>
diff --git a/drivers/gpu/drm/msm/registers/display/dsi.xml b/drivers/gpu/drm/msm/registers/display/dsi.xml
index c7a7b633d747..e40125f75175 100644
--- a/drivers/gpu/drm/msm/registers/display/dsi.xml
+++ b/drivers/gpu/drm/msm/registers/display/dsi.xml
@@ -15,6 +15,7 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
<value name="VID_DST_FORMAT_RGB666" value="1"/>
<value name="VID_DST_FORMAT_RGB666_LOOSE" value="2"/>
<value name="VID_DST_FORMAT_RGB888" value="3"/>
+ <value name="VID_DST_FORMAT_RGB101010" value="4"/>
</enum>
<enum name="dsi_rgb_swap">
<value name="SWAP_RGB" value="0"/>
@@ -39,6 +40,7 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
<value name="CMD_DST_FORMAT_RGB565" value="6"/>
<value name="CMD_DST_FORMAT_RGB666" value="7"/>
<value name="CMD_DST_FORMAT_RGB888" value="8"/>
+ <value name="CMD_DST_FORMAT_RGB101010" value="9"/>
</enum>
<enum name="dsi_lane_swap">
<value name="LANE_SWAP_0123" value="0"/>
@@ -142,7 +144,8 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
</reg32>
<reg32 offset="0x0000c" name="VID_CFG0">
<bitfield name="VIRT_CHANNEL" low="0" high="1" type="uint"/> <!-- always zero? -->
- <bitfield name="DST_FORMAT" low="4" high="5" type="dsi_vid_dst_format"/>
+ <!-- high was 5 before DSI 6G 2.1.0 -->
+ <bitfield name="DST_FORMAT" low="4" high="6" type="dsi_vid_dst_format"/>
<bitfield name="TRAFFIC_MODE" low="8" high="9" type="dsi_traffic_mode"/>
<bitfield name="BLLP_POWER_STOP" pos="12" type="boolean"/>
<bitfield name="EOF_BLLP_POWER_STOP" pos="15" type="boolean"/>
diff --git a/drivers/gpu/drm/nova/gem.rs b/drivers/gpu/drm/nova/gem.rs
index 6ccfa5da5761..e073e174e257 100644
--- a/drivers/gpu/drm/nova/gem.rs
+++ b/drivers/gpu/drm/nova/gem.rs
@@ -19,8 +19,9 @@ pub(crate) struct NovaObject {}
impl gem::DriverObject for NovaObject {
type Driver = NovaDriver;
+ type Args = ();
- fn new(_dev: &NovaDevice, _size: usize) -> impl PinInit<Self, Error> {
+ fn new(_dev: &NovaDevice, _size: usize, _args: Self::Args) -> impl PinInit<Self, Error> {
try_pin_init!(NovaObject {})
}
}
@@ -33,7 +34,7 @@ impl NovaObject {
}
let aligned_size = page::page_align(size).ok_or(EINVAL)?;
- gem::Object::new(dev, aligned_size)
+ gem::Object::new(dev, aligned_size, ())
}
/// Look up a GEM object handle for a `File` and return an `ObjectRef` for it.
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index bf0bad8c8cf1..ae678696fbac 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -275,7 +275,22 @@ static void omap_global_destroy_state(struct drm_private_obj *obj,
kfree(omap_state);
}
+static struct drm_private_state *
+omap_global_atomic_create_state(struct drm_private_obj *obj)
+{
+ struct omap_global_state *state;
+
+ state = kzalloc_obj(*state);
+ if (!state)
+ return ERR_PTR(-ENOMEM);
+
+ __drm_atomic_helper_private_obj_create_state(obj, &state->base);
+
+ return &state->base;
+}
+
static const struct drm_private_state_funcs omap_global_state_funcs = {
+ .atomic_create_state = omap_global_atomic_create_state,
.atomic_duplicate_state = omap_global_duplicate_state,
.atomic_destroy_state = omap_global_destroy_state,
};
@@ -283,13 +298,8 @@ static const struct drm_private_state_funcs omap_global_state_funcs = {
static int omap_global_obj_init(struct drm_device *dev)
{
struct omap_drm_private *priv = dev->dev_private;
- struct omap_global_state *state;
-
- state = kzalloc_obj(*state);
- if (!state)
- return -ENOMEM;
- drm_atomic_private_obj_init(dev, &priv->glob_obj, &state->base,
+ drm_atomic_private_obj_init(dev, &priv->glob_obj,
&omap_global_state_funcs);
return 0;
}
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index a99f2e2a49fe..d6863b28ddc5 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -203,6 +203,17 @@ config DRM_PANEL_HIMAX_HX83112B
Say Y here if you want to enable support for Himax HX83112B-based
display panels, such as the one found in the Fairphone 3 smartphone.
+config DRM_PANEL_HIMAX_HX83121A
+ tristate "Himax HX83121A-based DSI panel"
+ depends on OF
+ depends on DRM_MIPI_DSI
+ depends on BACKLIGHT_CLASS_DEVICE
+ select DRM_KMS_HELPER
+ help
+ Say Y here if you want to enable support for Himax HX83121A-based
+ display panels, such as the one found in the HUAWEI Matebook E Go
+ series.
+
config DRM_PANEL_HIMAX_HX8394
tristate "HIMAX HX8394 MIPI-DSI LCD panels"
depends on OF
@@ -257,14 +268,30 @@ config DRM_PANEL_ILITEK_ILI9805
Say Y if you want to enable support for panels based on the
Ilitek ILI9805 controller.
-config DRM_PANEL_ILITEK_ILI9806E
- tristate "Ilitek ILI9806E-based panels"
+config DRM_PANEL_ILITEK_ILI9806E_CORE
+ tristate
+
+config DRM_PANEL_ILITEK_ILI9806E_DSI
+ tristate "Ilitek ILI9806E-based DSI panels"
depends on OF
depends on DRM_MIPI_DSI
depends on BACKLIGHT_CLASS_DEVICE
+ select DRM_PANEL_ILITEK_ILI9806E_CORE
+ help
+ Say Y if you want to enable support for panels based on the
+ Ilitek ILI9806E controller using DSI.
+
+config DRM_PANEL_ILITEK_ILI9806E_SPI
+ tristate "Ilitek ILI9806E-based RGB SPI panel"
+ depends on OF
+ depends on SPI
+ depends on BACKLIGHT_CLASS_DEVICE
+ select DRM_MIPI_DBI
+ select VIDEOMODE_HELPERS
+ select DRM_PANEL_ILITEK_ILI9806E_CORE
help
Say Y if you want to enable support for panels based on the
- Ilitek ILI9806E controller.
+ Ilitek ILI9806E controller using SPI.
config DRM_PANEL_ILITEK_ILI9881C
tristate "Ilitek ILI9881C-based panels"
@@ -939,6 +966,19 @@ config DRM_PANEL_SAMSUNG_S6E8AA5X01_AMS561RA01
~5.6 inch AMOLED display, and the controller is driven by the MIPI
DSI protocol with 4 lanes.
+config DRM_PANEL_SAMSUNG_S6E8FC0
+ tristate "Samsung S6E8FC0 DSI controller"
+ depends on OF
+ depends on BACKLIGHT_CLASS_DEVICE
+ select DRM_MIPI_DSI
+ help
+ Say Y or M here if you want to enable support for the Samsung
+ S6E8FC0 DSI controller and connected panel.
+ Currently supported panels:
+
+ M1906F9 (M1906F9SH or M1906F9SI), 6.09 inch 720x1560, found
+ in the Xiaomi Mi A3 smartphone (xiaomi-laurel).
+
config DRM_PANEL_SAMSUNG_SOFEF00
tristate "Samsung SOFEF00 DSI panel controller"
depends on OF
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index 3336a2c0cd86..a4291dc3905b 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -21,12 +21,15 @@ obj-$(CONFIG_DRM_PANEL_HIMAX_HX8279) += panel-himax-hx8279.o
obj-$(CONFIG_DRM_PANEL_HIMAX_HX83102) += panel-himax-hx83102.o
obj-$(CONFIG_DRM_PANEL_HIMAX_HX83112A) += panel-himax-hx83112a.o
obj-$(CONFIG_DRM_PANEL_HIMAX_HX83112B) += panel-himax-hx83112b.o
+obj-$(CONFIG_DRM_PANEL_HIMAX_HX83121A) += panel-himax-hx83121a.o
obj-$(CONFIG_DRM_PANEL_HIMAX_HX8394) += panel-himax-hx8394.o
obj-$(CONFIG_DRM_PANEL_HYDIS_HV101HD1) += panel-hydis-hv101hd1.o
obj-$(CONFIG_DRM_PANEL_ILITEK_IL9322) += panel-ilitek-ili9322.o
obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9341) += panel-ilitek-ili9341.o
obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9805) += panel-ilitek-ili9805.o
-obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9806E) += panel-ilitek-ili9806e.o
+obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9806E_CORE) += panel-ilitek-ili9806e-core.o
+obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9806E_DSI) += panel-ilitek-ili9806e-dsi.o
+obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9806E_SPI) += panel-ilitek-ili9806e-spi.o
obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9881C) += panel-ilitek-ili9881c.o
obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9882T) += panel-ilitek-ili9882t.o
obj-$(CONFIG_DRM_PANEL_INNOLUX_EJ030NA) += panel-innolux-ej030na.o
@@ -95,6 +98,7 @@ obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E88A0_AMS427AP24) += panel-samsung-s6e88a0-ams4
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E88A0_AMS452EF01) += panel-samsung-s6e88a0-ams452ef01.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0) += panel-samsung-s6e8aa0.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E8AA5X01_AMS561RA01) += panel-samsung-s6e8aa5x01-ams561ra01.o
+obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E8FC0) += panel-samsung-s6e8fc0-m1906f9.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_SOFEF00) += panel-samsung-sofef00.o
obj-$(CONFIG_DRM_PANEL_SEIKO_43WVF1G) += panel-seiko-43wvf1g.o
obj-$(CONFIG_DRM_PANEL_SHARP_LQ079L1SX01) += panel-sharp-lq079l1sx01.o
diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c
index 0fce4452dbe7..497dcd48f57b 100644
--- a/drivers/gpu/drm/panel/panel-edp.c
+++ b/drivers/gpu/drm/panel/panel-edp.c
@@ -2025,6 +2025,7 @@ static const struct edp_panel_entry edp_panels[] = {
EDP_PANEL_ENTRY('B', 'O', 'E', 0x0cfa, &delay_200_500_e50, "NV116WHM-A4D"),
EDP_PANEL_ENTRY('B', 'O', 'E', 0x0d45, &delay_200_500_e80, "NV116WHM-N4B"),
EDP_PANEL_ENTRY('B', 'O', 'E', 0x0d73, &delay_200_500_e80, "NE140WUM-N6S"),
+ EDP_PANEL_ENTRY('B', 'O', 'E', 0x0db3, &delay_200_500_e80, "NV153WUM-N42"),
EDP_PANEL_ENTRY('B', 'O', 'E', 0x0ddf, &delay_200_500_e80, "NV116WHM-T01"),
EDP_PANEL_ENTRY('C', 'M', 'N', 0x1130, &delay_200_500_e50, "N116BGE-EB2"),
@@ -2061,6 +2062,7 @@ static const struct edp_panel_entry edp_panels[] = {
EDP_PANEL_ENTRY('C', 'M', 'N', 0x14d6, &delay_200_500_e80_d50, "N140BGA-EA4"),
EDP_PANEL_ENTRY('C', 'M', 'N', 0x14e5, &delay_200_500_e80_d50, "N140HGA-EA1"),
EDP_PANEL_ENTRY('C', 'M', 'N', 0x1565, &delay_200_500_e80, "N156HCA-EAB"),
+ EDP_PANEL_ENTRY('C', 'M', 'N', 0x156b, &delay_200_500_e80_d50, "N153JCA-ELK"),
EDP_PANEL_ENTRY('C', 'M', 'N', 0x162b, &delay_200_500_e80_d50, "N160JCE-ELL"),
EDP_PANEL_ENTRY('C', 'M', 'N', 0x7402, &delay_200_500_e200_d50, "N116BCA-EAK"),
@@ -2079,6 +2081,7 @@ static const struct edp_panel_entry edp_panels[] = {
EDP_PANEL_ENTRY('C', 'S', 'W', 0x146e, &delay_80_500_e50_d50, "MNE007QB3-1"),
EDP_PANEL_ENTRY('C', 'S', 'W', 0x147c, &delay_200_500_e50_d100, "MNE007QB3-1"),
EDP_PANEL_ENTRY('C', 'S', 'W', 0x1519, &delay_200_500_e80_d50, "MNF601BS1-3"),
+ EDP_PANEL_ENTRY('C', 'S', 'W', 0x1529, &delay_200_500_e80_d50, "MNF307QS3-2"),
EDP_PANEL_ENTRY('E', 'T', 'C', 0x0000, &delay_50_500_e200_d200_po2e335, "LP079QX1-SP0V"),
diff --git a/drivers/gpu/drm/panel/panel-himax-hx83102.c b/drivers/gpu/drm/panel/panel-himax-hx83102.c
index 1d3bb5dca559..8b2a68ee851e 100644
--- a/drivers/gpu/drm/panel/panel-himax-hx83102.c
+++ b/drivers/gpu/drm/panel/panel-himax-hx83102.c
@@ -7,6 +7,7 @@
* Based on drivers/gpu/drm/panel/panel-himax-hx8394.c
*/
+#include <linux/backlight.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h>
@@ -76,6 +77,8 @@ struct hx83102_panel_desc {
unsigned int height_mm;
} size;
+ bool has_backlight;
+
int (*init)(struct hx83102 *ctx);
};
@@ -701,6 +704,67 @@ static int starry_2082109qfh040022_50e_init(struct hx83102 *ctx)
return dsi_ctx.accum_err;
}
+static int holitech_htf065h045_init(struct hx83102 *ctx)
+{
+ struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi };
+
+ msleep(50);
+
+ hx83102_enable_extended_cmds(&dsi_ctx, true);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x22, 0x44, 0x27, 0x27, 0x32,
+ 0x52, 0x57, 0x39, 0x08, 0x08, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETDISP, 0x00, 0x00, 0x06, 0x40, 0x00,
+ 0x0e, 0xae, 0x38, 0x00, 0x00, 0x00, 0x00, 0xf4, 0xa0);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x01, 0x58, 0x01, 0x58, 0x01,
+ 0x58, 0x03, 0x58, 0x03, 0xff, 0x01, 0x20, 0x00, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPANEL, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x17, 0x00, 0x63, 0x37, 0x0e, 0x0e, 0x00, 0x00,
+ 0x32, 0x10, 0x08, 0x00, 0x08, 0x32, 0x16, 0x4e, 0x06, 0x4e);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPWM, 0x04, 0x0c, 0xb2, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP1, 0x24, 0x25, 0x18, 0x18, 0x19,
+ 0x19, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x06, 0x07, 0x04, 0x05, 0x18, 0x18, 0x18,
+ 0x18, 0x02, 0x03, 0x00, 0x01, 0x20, 0x21, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP2, 0x00, 0x09, 0x16, 0x1f, 0x28,
+ 0x4b, 0x65, 0x6d, 0x74, 0x70, 0x89, 0x8d, 0x91, 0xa0, 0x9e,
+ 0xa8, 0xb2, 0xc8, 0xc9, 0x65, 0x6d, 0x78, 0x7f, 0x00, 0x09,
+ 0x16, 0x1f, 0x28, 0x4b, 0x65, 0x6d, 0x74, 0x70, 0x89, 0x8d,
+ 0x91, 0xa0, 0x9e, 0xa8, 0xb2, 0xc8, 0xc9, 0x65, 0x6d, 0x78,
+ 0x7f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0xff, 0x14, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xa0, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xa0, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x70, 0x23, 0xa8, 0x93, 0xb2,
+ 0xc0, 0xc0, 0x01, 0x10, 0x00, 0x00, 0x00, 0x0d, 0x3d, 0x82,
+ 0x77, 0x04, 0x01, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x00, 0x53, 0x00, 0x02, 0x59);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPTBA, 0xfc, 0x00, 0x04, 0x9e, 0xf6,
+ 0x00, 0x5d);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x42, 0x00, 0x33, 0x00, 0x33,
+ 0x88, 0xb3, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPCTRL, 0x20, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x7f, 0x03, 0xf5);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00);
+
+ return dsi_ctx.accum_err;
+}
+
static const struct drm_display_mode starry_mode = {
.clock = 162680,
.hdisplay = 1200,
@@ -833,6 +897,29 @@ static const struct hx83102_panel_desc starry_2082109qfh040022_50e_desc = {
.init = starry_2082109qfh040022_50e_init,
};
+static const struct drm_display_mode holitech_htf065h045_default_mode = {
+ .clock = 90720,
+ .hdisplay = 720,
+ .hsync_start = 720 + 40,
+ .hsync_end = 720 + 40 + 40,
+ .htotal = 720 + 40 + 40 + 40,
+ .vdisplay = 1600,
+ .vsync_start = 1600 + 186,
+ .vsync_end = 1600 + 186 + 2,
+ .vtotal = 1600 + 186 + 2 + 12,
+ .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+};
+
+static const struct hx83102_panel_desc holitech_htf065h045_desc = {
+ .modes = &holitech_htf065h045_default_mode,
+ .size = {
+ .width_mm = 68,
+ .height_mm = 151,
+ },
+ .has_backlight = true,
+ .init = holitech_htf065h045_init,
+};
+
static int hx83102_enable(struct drm_panel *panel)
{
msleep(130);
@@ -966,6 +1053,59 @@ static const struct drm_panel_funcs hx83102_drm_funcs = {
.get_orientation = hx83102_get_orientation,
};
+static int hx83102_bl_update_status(struct backlight_device *bl)
+{
+ struct mipi_dsi_device *dsi = bl_get_data(bl);
+ u16 brightness = backlight_get_brightness(bl);
+ int ret;
+
+ dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+ ret = mipi_dsi_dcs_set_display_brightness_large(dsi, brightness);
+ if (ret < 0)
+ return ret;
+
+ dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+ return 0;
+}
+
+static int hx83102_bl_get_brightness(struct backlight_device *bl)
+{
+ struct mipi_dsi_device *dsi = bl_get_data(bl);
+ u16 brightness;
+ int ret;
+
+ dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+ ret = mipi_dsi_dcs_get_display_brightness_large(dsi, &brightness);
+ if (ret < 0)
+ return ret;
+
+ dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+ return brightness;
+}
+
+static const struct backlight_ops hx83102_bl_ops = {
+ .update_status = hx83102_bl_update_status,
+ .get_brightness = hx83102_bl_get_brightness,
+};
+
+static struct backlight_device *
+hx83102_create_dcs_backlight(struct mipi_dsi_device *dsi)
+{
+ struct device *dev = &dsi->dev;
+ const struct backlight_properties props = {
+ .type = BACKLIGHT_RAW,
+ .brightness = 4095,
+ .max_brightness = 4095,
+ };
+
+ return devm_backlight_device_register(dev, dev_name(dev), dev, dsi,
+ &hx83102_bl_ops, &props);
+}
+
static int hx83102_panel_add(struct hx83102 *ctx)
{
struct device *dev = &ctx->dsi->dev;
@@ -997,6 +1137,14 @@ static int hx83102_panel_add(struct hx83102 *ctx)
if (err)
return err;
+ /* Use DSI-based backlight as fallback if available */
+ if (ctx->desc->has_backlight && !ctx->base.backlight) {
+ ctx->base.backlight = hx83102_create_dcs_backlight(ctx->dsi);
+ if (IS_ERR(ctx->base.backlight))
+ return dev_err_probe(dev, PTR_ERR(ctx->base.backlight),
+ "Failed to create backlight\n");
+ }
+
ctx->base.funcs = &hx83102_drm_funcs;
ctx->base.dev = &ctx->dsi->dev;
@@ -1069,6 +1217,9 @@ static const struct of_device_id hx83102_of_match[] = {
{ .compatible = "starry,himax83102-j02",
.data = &starry_desc
},
+ { .compatible = "holitech,htf065h045",
+ .data = &holitech_htf065h045_desc
+ },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, hx83102_of_match);
diff --git a/drivers/gpu/drm/panel/panel-himax-hx83121a.c b/drivers/gpu/drm/panel/panel-himax-hx83121a.c
new file mode 100644
index 000000000000..ebe643ba4184
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-himax-hx83121a.c
@@ -0,0 +1,749 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Himax HX83121A DriverIC panels driver
+ * Copyright (c) 2024-2026 Pengyu Luo <mitltlatltl@gmail.com>
+ *
+ * Multiple panels handling based on panel-novatek-nt36523.c
+ */
+
+#include <linux/backlight.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_graph.h>
+#include <linux/regulator/consumer.h>
+
+#include <drm/display/drm_dsc.h>
+#include <drm/display/drm_dsc_helper.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+#include <video/mipi_display.h>
+
+static bool enable_dsc;
+module_param(enable_dsc, bool, 0);
+MODULE_PARM_DESC(enable_dsc, "enable DSC on the panel (default: false)");
+
+struct himax {
+ struct drm_panel panel;
+ struct mipi_dsi_device *dsi[2];
+ const struct panel_desc *desc;
+ struct drm_dsc_config dsc;
+ struct gpio_desc *reset_gpio;
+ struct regulator_bulk_data *supplies;
+ struct backlight_device *backlight;
+};
+
+struct panel_desc {
+ unsigned int width_mm;
+ unsigned int height_mm;
+ unsigned int bpc;
+ unsigned int lanes;
+ enum mipi_dsi_pixel_format format;
+ unsigned long mode_flags;
+ const struct drm_dsc_config *dsc_cfg;
+ const struct drm_display_mode *dsc_modes;
+ unsigned int num_dsc_modes;
+
+ const struct drm_display_mode *modes;
+ unsigned int num_modes;
+
+ int (*init_sequence_dsc)(struct mipi_dsi_multi_context *dsi_ctx);
+ int (*init_sequence)(struct mipi_dsi_multi_context *dsi_ctx);
+
+ bool is_dual_dsi;
+ bool has_dcs_backlight;
+};
+
+static const struct regulator_bulk_data himax_supplies[] = {
+ { .supply = "vddi" },
+ { .supply = "avdd" },
+ { .supply = "avee" },
+};
+
+static inline struct himax *to_himax(struct drm_panel *panel)
+{
+ return container_of(panel, struct himax, panel);
+}
+
+static inline struct mipi_dsi_device *to_primary_dsi(struct himax *ctx)
+{
+ /* Sync on DSI1 for dual dsi */
+ return ctx->desc->is_dual_dsi ? ctx->dsi[1] : ctx->dsi[0];
+}
+
+static void himax_reset(struct himax *ctx)
+{
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+ usleep_range(4000, 4100);
+ gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+ msleep(20);
+}
+
+static int himax_prepare(struct drm_panel *panel)
+{
+ struct himax *ctx = to_himax(panel);
+ struct mipi_dsi_device *dsi = to_primary_dsi(ctx);
+ struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
+ struct drm_dsc_picture_parameter_set pps;
+ int ret;
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(himax_supplies),
+ ctx->supplies);
+ if (ret < 0)
+ return ret;
+
+ himax_reset(ctx);
+
+ if (enable_dsc && ctx->desc->init_sequence_dsc)
+ ret = ctx->desc->init_sequence_dsc(&dsi_ctx);
+ else if (ctx->desc->init_sequence)
+ ret = ctx->desc->init_sequence(&dsi_ctx);
+ else
+ ret = -EOPNOTSUPP;
+
+ if (ret < 0) {
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+ regulator_bulk_disable(ARRAY_SIZE(himax_supplies),
+ ctx->supplies);
+ return ret;
+ }
+
+ if (enable_dsc) {
+ drm_dsc_pps_payload_pack(&pps, &ctx->dsc);
+ mipi_dsi_picture_parameter_set_multi(&dsi_ctx, &pps);
+ mipi_dsi_compression_mode_multi(&dsi_ctx, true);
+ }
+
+ return backlight_enable(ctx->backlight);
+}
+
+static int himax_off(struct mipi_dsi_multi_context *dsi_ctx)
+{
+ mipi_dsi_dcs_enter_sleep_mode_multi(dsi_ctx);
+ mipi_dsi_msleep(dsi_ctx, 120);
+
+ return dsi_ctx->accum_err;
+}
+
+static int himax_unprepare(struct drm_panel *panel)
+{
+ struct himax *ctx = to_himax(panel);
+ struct mipi_dsi_device *dsi = to_primary_dsi(ctx);
+ struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
+ struct device *dev = &dsi->dev;
+ int ret;
+
+ ret = himax_off(&dsi_ctx);
+ if (ret < 0)
+ dev_err(dev, "panel failed to off: %d\n", ret);
+
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+ regulator_bulk_disable(ARRAY_SIZE(himax_supplies), ctx->supplies);
+
+ return 0;
+}
+
+static int himax_get_modes(struct drm_panel *panel,
+ struct drm_connector *connector)
+{
+ struct himax *ctx = to_himax(panel);
+ const struct panel_desc *desc = ctx->desc;
+ const struct drm_display_mode *modes;
+ int num_modes;
+ int i;
+
+ modes = enable_dsc ? desc->dsc_modes : desc->modes;
+ num_modes = enable_dsc ? desc->num_dsc_modes : desc->num_modes;
+
+ for (i = 0; i < num_modes; i++) {
+ const struct drm_display_mode *m = &modes[i];
+ struct drm_display_mode *mode;
+
+ mode = drm_mode_duplicate(connector->dev, m);
+ if (!mode) {
+ dev_err(panel->dev, "failed to add mode %ux%u@%u\n",
+ m->hdisplay, m->vdisplay, drm_mode_vrefresh(m));
+ return -ENOMEM;
+ }
+
+ mode->type = DRM_MODE_TYPE_DRIVER;
+ if (i == 0)
+ mode->type |= DRM_MODE_TYPE_PREFERRED;
+
+ drm_mode_set_name(mode);
+ drm_mode_probed_add(connector, mode);
+ }
+
+ connector->display_info.width_mm = desc->width_mm;
+ connector->display_info.height_mm = desc->height_mm;
+ connector->display_info.bpc = desc->bpc;
+
+ return num_modes;
+}
+
+static const struct drm_panel_funcs himax_panel_funcs = {
+ .prepare = himax_prepare,
+ .unprepare = himax_unprepare,
+ .get_modes = himax_get_modes,
+};
+
+static int himax_bl_update_status(struct backlight_device *bl)
+{
+ struct mipi_dsi_device *dsi = bl_get_data(bl);
+ u16 brightness = backlight_get_brightness(bl);
+ /* TODO: brightness to raw map table */
+ return mipi_dsi_dcs_set_display_brightness_large(dsi, brightness);
+}
+
+static const struct backlight_ops himax_bl_ops = {
+ .options = BL_CORE_SUSPENDRESUME,
+ .update_status = himax_bl_update_status,
+};
+
+static struct backlight_device *
+himax_create_backlight(struct mipi_dsi_device *dsi)
+{
+ struct device *dev = &dsi->dev;
+ const struct backlight_properties props = {
+ .type = BACKLIGHT_RAW,
+ .brightness = 512,
+ .max_brightness = 4095,
+ .scale = BACKLIGHT_SCALE_NON_LINEAR,
+ };
+
+ return devm_backlight_device_register(dev, dev_name(dev), dev, dsi,
+ &himax_bl_ops, &props);
+}
+
+static int boe_ppc357db1_4_dsc_init_seq(struct mipi_dsi_multi_context *dsi_ctx)
+{
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb9, 0x83, 0x12, 0x1a, 0x55, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x24);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe2, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x03);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe1, 0x01);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0xc7);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb2, 0x98);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x02);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe7,
+ 0x01, 0x07, 0x01, 0x07, 0x01, 0x07, 0x06, 0x06,
+ 0x06, 0x16, 0x00, 0x16, 0x81, 0x02, 0x40, 0x00,
+ 0x1a, 0x4a, 0x05, 0x04, 0x03, 0x02, 0x01);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x01);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0xc6);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xd2, 0x00, 0x30);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0xc9);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xd3, 0x04);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0xc6);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe2, 0x42);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0xd0);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb2, 0xf5);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xcd,
+ 0x81, 0x00, 0x80, 0x77, 0x00, 0x01, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x01);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe4,
+ 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1,
+ 0xc7, 0xb2, 0xa0, 0x90, 0x81, 0x75, 0x69, 0x5f,
+ 0x55, 0x4c, 0x44, 0x3d, 0x36, 0x2f, 0x2a, 0x24,
+ 0x1e, 0x19, 0x14, 0x10, 0x09, 0x08, 0x07, 0x54,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x03);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe4,
+ 0xaa, 0xd4, 0xff, 0x2a, 0x55, 0x7f, 0xaa, 0xd4,
+ 0xff, 0xea, 0xff, 0x03);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0xc8);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb1, 0x25);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbe, 0x01, 0x35, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xd9, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb9, 0x00, 0x00, 0x00);
+
+ mipi_dsi_dcs_exit_sleep_mode_multi(dsi_ctx);
+ mipi_dsi_msleep(dsi_ctx, 140);
+ mipi_dsi_dcs_set_display_on_multi(dsi_ctx);
+
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, MIPI_DCS_WRITE_POWER_SAVE, 0x01);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x24);
+ mipi_dsi_msleep(dsi_ctx, 20);
+
+ return dsi_ctx->accum_err;
+}
+
+static int boe_ppc357db1_4_init_seq(struct mipi_dsi_multi_context *dsi_ctx)
+{
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb9, 0x83, 0x12, 0x1a, 0x55, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x24);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xd1, 0x37, 0x03, 0x0c, 0xfd);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe2, 0x20);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x03);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe1, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0xc7);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb2, 0xa6);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x02);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe7,
+ 0x01, 0x07, 0x01, 0x07, 0x01, 0x07, 0x06, 0x06,
+ 0x06, 0x16, 0x00, 0x16, 0x81, 0x02, 0x40, 0x00,
+ 0x1a, 0x4a, 0x05, 0x04, 0x03, 0x02, 0x01);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe2,
+ 0x02, 0x68, 0x02, 0x68, 0x02, 0x68, 0x02, 0x68,
+ 0x02, 0x6f, 0x03, 0x04, 0x2d, 0x09, 0x09, 0x00,
+ 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x10, 0x1c, 0x25, 0x3c, 0x00, 0x23,
+ 0x5d, 0x02, 0x02, 0x00, 0x00, 0x58, 0x01, 0xac,
+ 0x0f, 0xa9, 0x10, 0x00, 0x2d, 0x6f, 0x00, 0x70,
+ 0x00, 0x0a, 0xcb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x01);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0xc6);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xd2, 0x09, 0x85);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0xc9);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xd3, 0x04);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0xd0);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb2, 0xf5);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x01);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe4,
+ 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1,
+ 0xc7, 0xb2, 0xa0, 0x90, 0x81, 0x75, 0x69, 0x5f,
+ 0x55, 0x4c, 0x44, 0x3d, 0x36, 0x2f, 0x2a, 0x24,
+ 0x1e, 0x19, 0x14, 0x10, 0x09, 0x08, 0x07, 0x54,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x03);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe4,
+ 0xaa, 0xd4, 0xff, 0x2a, 0x55, 0x7f, 0xaa, 0xd4,
+ 0xff, 0xea, 0xff, 0x03);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0xc8);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb1, 0x25);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbe, 0x01, 0x35, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xd9, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb9, 0x00, 0x00, 0x00);
+
+ mipi_dsi_dcs_exit_sleep_mode_multi(dsi_ctx);
+ mipi_dsi_msleep(dsi_ctx, 140);
+ mipi_dsi_dcs_set_display_on_multi(dsi_ctx);
+
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, MIPI_DCS_WRITE_POWER_SAVE, 0x01);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x24);
+ mipi_dsi_msleep(dsi_ctx, 31);
+
+ return dsi_ctx->accum_err;
+}
+
+static int csot_ppc357db1_4_dsc_init_seq(struct mipi_dsi_multi_context *dsi_ctx)
+{
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb9, 0x83, 0x12, 0x1a, 0x55, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x24);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb1,
+ 0x1c, 0x6b, 0x6b, 0x27, 0xe7, 0x00, 0x1b, 0x25,
+ 0x21, 0x21, 0x2d, 0x2d, 0x17, 0x33, 0x31, 0x40,
+ 0xcd, 0xff, 0x1a, 0x05, 0x15, 0x98, 0x00, 0x88,
+ 0x7f, 0xff, 0xff, 0xcf, 0x1a, 0xcc, 0x02, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xd1, 0x37, 0x03, 0x0c, 0xfd);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb2,
+ 0x00, 0x6a, 0x40, 0x00, 0x00, 0x14, 0x98, 0x60,
+ 0x3c, 0x02, 0x80, 0x21, 0x21, 0x00, 0x00, 0xf0,
+ 0x27);
+ /*
+ * NOTE: Register 0xE2 configuration (based on downstream reference):
+ * - 0x00: 120Hz with DSC enabled
+ * - 0x10: 60Hz with DSC enabled
+ * - 0x20: 60Hz with DSC disabled
+ *
+ * Both 0x00 and 0x10 are compatible with 60Hz/120Hz when DSC is active.
+ * We use a fixed DSC-on value to remain refresh-rate agnostic.
+ */
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe2, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xc0, 0x23, 0x23, 0xcc, 0x22, 0x99, 0xd8);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb4,
+ 0x46, 0x06, 0x0c, 0xbe, 0x0c, 0xbe, 0x09, 0x46,
+ 0x0f, 0x57, 0x0f, 0x57, 0x03, 0x4a, 0x00, 0x00,
+ 0x04, 0x0c, 0x00, 0x18, 0x01, 0x06, 0x08, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xff, 0x00, 0xff, 0x10, 0x00, 0x02,
+ 0x14, 0x14, 0x14, 0x14);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x03);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe1, 0x01, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0xe2);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe7, 0x49);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xd3,
+ 0x00, 0xc0, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04,
+ 0x16, 0x02, 0x07, 0x07, 0x07, 0x31, 0x13, 0x19,
+ 0x12, 0x12, 0x03, 0x03, 0x03, 0x32, 0x10, 0x18,
+ 0x00, 0x11, 0x32, 0x10, 0x03, 0x00, 0x03, 0x32,
+ 0x10, 0x03, 0x00, 0x03, 0x00, 0x00, 0xff, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe1,
+ 0x11, 0x00, 0x00, 0x89, 0x30, 0x80, 0x0a, 0x00,
+ 0x03, 0x20, 0x00, 0x14, 0x03, 0x20, 0x03, 0x20,
+ 0x02, 0x00, 0x02, 0x91, 0x00, 0x20, 0x02, 0x47,
+ 0x00, 0x0b, 0x00, 0x0c, 0x05, 0x0e, 0x03, 0x68,
+ 0x18, 0x00, 0x10, 0xe0, 0x03, 0x0c, 0x20, 0x00,
+ 0x06, 0x0b, 0x0b, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
+ 0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
+ 0x7d, 0x7e, 0x01, 0x02, 0x01, 0x00, 0x09);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe7,
+ 0x17, 0x08, 0x08, 0x2c, 0x46, 0x1e, 0x02, 0x23,
+ 0x5d, 0x02, 0xc9, 0x00, 0x00, 0x00, 0x00, 0x12,
+ 0x05, 0x02, 0x02, 0x07, 0x10, 0x10, 0x00, 0x1d,
+ 0xb9, 0x23, 0xb9, 0x00, 0x33, 0x02, 0x88);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x01);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe7,
+ 0x02, 0x00, 0xb2, 0x01, 0x56, 0x07, 0x56, 0x08,
+ 0x48, 0x14, 0xfd, 0x26);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x02);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe7,
+ 0x08, 0x08, 0x01, 0x03, 0x01, 0x03, 0x07, 0x02,
+ 0x02, 0x47, 0x00, 0x47, 0x81, 0x02, 0x40, 0x00,
+ 0x18, 0x4a, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01,
+ 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbf,
+ 0xfd, 0x00, 0x80, 0x9c, 0x36, 0x00, 0x81, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xcd,
+ 0x81, 0x00, 0x80, 0x77, 0x00, 0x01, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x01);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe4,
+ 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1,
+ 0xc7, 0xb2, 0xa0, 0x90, 0x81, 0x75, 0x69, 0x5f,
+ 0x55, 0x4c, 0x44, 0x3d, 0x36, 0x2f, 0x2a, 0x24,
+ 0x1e, 0x19, 0x14, 0x10, 0x09, 0x08, 0x07, 0x54,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x03);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe4,
+ 0xaa, 0xd4, 0xff, 0x2a, 0x55, 0x7f, 0xaa, 0xd4,
+ 0xff, 0xea, 0xff, 0x03);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbe, 0x01, 0x35, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xd9, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb9, 0x00, 0x00, 0x00);
+
+ mipi_dsi_dcs_exit_sleep_mode_multi(dsi_ctx);
+ mipi_dsi_msleep(dsi_ctx, 140);
+ mipi_dsi_dcs_set_display_on_multi(dsi_ctx);
+
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, MIPI_DCS_WRITE_POWER_SAVE, 0x01);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x24);
+ mipi_dsi_msleep(dsi_ctx, 20);
+
+ return dsi_ctx->accum_err;
+}
+
+static int csot_ppc357db1_4_init_seq(struct mipi_dsi_multi_context *dsi_ctx)
+{
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb9, 0x83, 0x12, 0x1a, 0x55, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x24);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb1,
+ 0x1c, 0x6b, 0x6b, 0x27, 0xe7, 0x00, 0x1b, 0x11,
+ 0x21, 0x21, 0x2d, 0x2d, 0x17, 0x33, 0x31, 0x40,
+ 0xcd, 0xff, 0x1a, 0x05, 0x15, 0x98, 0x00, 0x88,
+ 0x7f, 0xff, 0xff, 0xcf, 0x1a, 0xcc, 0x02, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xd1, 0x37, 0x03, 0x0c, 0xfd);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe2, 0x20);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb2,
+ 0x00, 0x6a, 0x40, 0x00, 0x00, 0x14, 0x98, 0x60,
+ 0x3c, 0x02, 0x80, 0x21, 0x21, 0x00, 0x00, 0x10,
+ 0x27);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x03);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe1, 0x00, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0xe2);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe7, 0x49);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xd3,
+ 0x00, 0xc0, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04,
+ 0x16, 0x02, 0x07, 0x07, 0x07, 0x31, 0x13, 0x16,
+ 0x12, 0x12, 0x03, 0x03, 0x03, 0x32, 0x10, 0x15,
+ 0x00, 0x11, 0x32, 0x10, 0x03, 0x00, 0x03, 0x32,
+ 0x10, 0x03, 0x00, 0x03, 0x00, 0x00, 0xff, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x02);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe2,
+ 0x80, 0x05, 0x1c, 0xbe, 0x09, 0x8d, 0x0f, 0x57,
+ 0x03, 0x87, 0x06, 0x10, 0x32, 0x06, 0x15, 0x00,
+ 0x00, 0x14, 0x14, 0x14, 0x14, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x10, 0x16, 0x28, 0x3c, 0x03, 0x23,
+ 0x5d, 0x02, 0x02, 0x00, 0x00, 0x48, 0x01, 0xac,
+ 0x0f, 0xab, 0x10, 0x00, 0x32, 0x87, 0x00, 0xa1,
+ 0x00, 0x0a, 0xcb, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x01);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe7,
+ 0x02, 0x00, 0xb2, 0x01, 0x56, 0x07, 0x56, 0x08,
+ 0x48, 0x14, 0x00, 0x26);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x02);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe7,
+ 0x05, 0x05, 0x01, 0x05, 0x01, 0x05, 0x04, 0x04,
+ 0x04, 0x24, 0x00, 0x24, 0x81, 0x02, 0x40, 0x00,
+ 0x32, 0x87, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0xd0);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb2, 0xf0);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbf,
+ 0xfd, 0x00, 0x80, 0x9c, 0x10, 0x00, 0x81, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x01);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe4,
+ 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1,
+ 0xc7, 0xb2, 0xa0, 0x90, 0x81, 0x75, 0x69, 0x5f,
+ 0x55, 0x4c, 0x44, 0x3d, 0x36, 0x2f, 0x2a, 0x24,
+ 0x1e, 0x19, 0x14, 0x10, 0x09, 0x08, 0x07, 0x54,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x03);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe4,
+ 0xaa, 0xd4, 0xff, 0x2a, 0x55, 0x7f, 0xaa, 0xd4,
+ 0xff, 0xea, 0xff, 0x03);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbd, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0xc8);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb1, 0x25);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe9, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xbe, 0x01, 0x35, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xd9, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb9, 0x00, 0x00, 0x00);
+
+ mipi_dsi_dcs_exit_sleep_mode_multi(dsi_ctx);
+ mipi_dsi_msleep(dsi_ctx, 140);
+ mipi_dsi_dcs_set_display_on_multi(dsi_ctx);
+
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, MIPI_DCS_WRITE_POWER_SAVE, 0x01);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x24);
+ mipi_dsi_msleep(dsi_ctx, 31);
+
+ return dsi_ctx->accum_err;
+}
+
+static struct drm_dsc_config ppc357db1_4_dsc_cfg = {
+ .dsc_version_major = 1,
+ .dsc_version_minor = 1,
+ .slice_height = 20,
+ .slice_width = 800,
+ .slice_count = 1,
+ .bits_per_component = 8,
+ .bits_per_pixel = 8 << 4,
+ .block_pred_enable = true,
+};
+
+static const struct drm_display_mode ppc357db1_4_dsc_modes[] = {
+ {
+ .clock = (800 + 60 + 40 + 40) * 2 * (2560 + 154 + 4 + 18) * 120 / 1000,
+ .hdisplay = 800 * 2,
+ .hsync_start = (800 + 60) * 2,
+ .hsync_end = (800 + 60 + 40) * 2,
+ .htotal = (800 + 60 + 40 + 40) * 2,
+ .vdisplay = 2560,
+ .vsync_start = 2560 + 154,
+ .vsync_end = 2560 + 154 + 4,
+ .vtotal = 2560 + 154 + 4 + 18,
+ },
+ {
+ .clock = (800 + 60 + 40 + 40) * 2 * (2560 + 2890 + 4 + 18) * 60 / 1000,
+ .hdisplay = 800 * 2,
+ .hsync_start = (800 + 60) * 2,
+ .hsync_end = (800 + 60 + 40) * 2,
+ .htotal = (800 + 60 + 40 + 40) * 2,
+ .vdisplay = 2560,
+ .vsync_start = 2560 + 2890,
+ .vsync_end = 2560 + 2890 + 4,
+ .vtotal = 2560 + 2890 + 4 + 18,
+ },
+};
+
+static const struct drm_display_mode ppc357db1_4_modes[] = {
+ {
+ .clock = (800 + 60 + 20 + 40) * 2 * (2560 + 154 + 4 + 18) * 60 / 1000,
+ .hdisplay = 800 * 2,
+ .hsync_start = (800 + 60) * 2,
+ .hsync_end = (800 + 60 + 20) * 2,
+ .htotal = (800 + 60 + 20 + 40) * 2,
+ .vdisplay = 2560,
+ .vsync_start = 2560 + 168,
+ .vsync_end = 2560 + 168 + 4,
+ .vtotal = 2560 + 168 + 4 + 18,
+ },
+};
+
+static int himax_probe(struct mipi_dsi_device *dsi)
+{
+ struct mipi_dsi_device_info dsi_info = {"dsi-secondary", 0, NULL};
+ struct mipi_dsi_host *dsi1_host;
+ struct device *dev = &dsi->dev;
+ const struct panel_desc *desc;
+ struct device_node *dsi1;
+ struct himax *ctx;
+ int num_dsi = 1;
+ int ret, i;
+
+ ctx = devm_drm_panel_alloc(dev, struct himax, panel, &himax_panel_funcs,
+ DRM_MODE_CONNECTOR_DSI);
+ if (!ctx)
+ return -ENOMEM;
+
+ ret = devm_regulator_bulk_get_const(&dsi->dev,
+ ARRAY_SIZE(himax_supplies),
+ himax_supplies, &ctx->supplies);
+ if (ret < 0)
+ return ret;
+
+ ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(ctx->reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
+ "Failed to get reset-gpios\n");
+
+ desc = of_device_get_match_data(dev);
+ if (!desc)
+ return -ENODEV;
+ ctx->desc = desc;
+ ctx->dsc = *desc->dsc_cfg;
+
+ if (desc->is_dual_dsi) {
+ num_dsi = 2;
+ dsi1 = of_graph_get_remote_node(dsi->dev.of_node, 1, -1);
+ if (!dsi1) {
+ dev_err(dev, "cannot get secondary DSI node.\n");
+ return -ENODEV;
+ }
+
+ dsi1_host = of_find_mipi_dsi_host_by_node(dsi1);
+ of_node_put(dsi1);
+ if (!dsi1_host)
+ return dev_err_probe(dev, -EPROBE_DEFER,
+ "cannot get secondary DSI host\n");
+
+ ctx->dsi[1] = devm_mipi_dsi_device_register_full(dev, dsi1_host,
+ &dsi_info);
+ if (IS_ERR(ctx->dsi[1])) {
+ dev_err(dev, "cannot get secondary DSI device\n");
+ return PTR_ERR(ctx->dsi[1]);
+ }
+
+ mipi_dsi_set_drvdata(ctx->dsi[1], ctx);
+ }
+
+ ctx->dsi[0] = dsi;
+ mipi_dsi_set_drvdata(dsi, ctx);
+
+ ctx->panel.prepare_prev_first = true;
+
+ if (desc->has_dcs_backlight) {
+ ctx->backlight = himax_create_backlight(to_primary_dsi(ctx));
+ if (IS_ERR(ctx->backlight))
+ return dev_err_probe(dev, PTR_ERR(ctx->backlight),
+ "Failed to create backlight\n");
+ } else {
+ ret = drm_panel_of_backlight(&ctx->panel);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to get backlight\n");
+ }
+
+ drm_panel_add(&ctx->panel);
+
+ for (i = 0; i < num_dsi; i++) {
+ ctx->dsi[i]->lanes = desc->lanes;
+ ctx->dsi[i]->format = desc->format;
+ ctx->dsi[i]->mode_flags = desc->mode_flags;
+ ctx->dsi[i]->dsc = enable_dsc ? &ctx->dsc : NULL;
+ ret = devm_mipi_dsi_attach(dev, ctx->dsi[i]);
+ if (ret < 0) {
+ drm_panel_remove(&ctx->panel);
+ return dev_err_probe(dev, ret,
+ "Failed to attach to DSI host\n");
+ }
+ }
+
+ return 0;
+}
+
+static void himax_remove(struct mipi_dsi_device *dsi)
+{
+ struct himax *ctx = mipi_dsi_get_drvdata(dsi);
+
+ drm_panel_remove(&ctx->panel);
+}
+
+/* Model name: BOE PPC357DB1-4 */
+static const struct panel_desc boe_ppc357db1_4_desc = {
+ .width_mm = 266,
+ .height_mm = 166,
+ .lanes = 4,
+ .format = MIPI_DSI_FMT_RGB888,
+ .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_CLOCK_NON_CONTINUOUS |
+ MIPI_DSI_MODE_LPM,
+ .dsc_cfg = &ppc357db1_4_dsc_cfg,
+ .dsc_modes = ppc357db1_4_dsc_modes,
+ .num_dsc_modes = ARRAY_SIZE(ppc357db1_4_dsc_modes),
+ .modes = ppc357db1_4_modes,
+ .num_modes = ARRAY_SIZE(ppc357db1_4_modes),
+ .init_sequence_dsc = boe_ppc357db1_4_dsc_init_seq,
+ .init_sequence = boe_ppc357db1_4_init_seq,
+ .is_dual_dsi = true,
+ .has_dcs_backlight = true,
+};
+
+/* Model name: CSOT PPC357DB1-4 */
+static const struct panel_desc csot_ppc357db1_4_desc = {
+ .width_mm = 266,
+ .height_mm = 166,
+ .lanes = 4,
+ .format = MIPI_DSI_FMT_RGB888,
+ .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_CLOCK_NON_CONTINUOUS |
+ MIPI_DSI_MODE_LPM,
+ .dsc_cfg = &ppc357db1_4_dsc_cfg,
+ .dsc_modes = ppc357db1_4_dsc_modes,
+ .num_dsc_modes = ARRAY_SIZE(ppc357db1_4_dsc_modes),
+ .modes = ppc357db1_4_modes,
+ .num_modes = ARRAY_SIZE(ppc357db1_4_modes),
+ .init_sequence_dsc = csot_ppc357db1_4_dsc_init_seq,
+ .init_sequence = csot_ppc357db1_4_init_seq,
+ .is_dual_dsi = true,
+ .has_dcs_backlight = true,
+};
+
+/*
+ * Known panels with HX83121A:
+ * CSOT PNC357DB1-4: on MI Book S 12.4
+ * CSOT PPC357DB1-1: on SAMSUNG Galaxy Tab S7 FE
+ * BOE/CSOT PPC357DB1-4: on HUAWEI Matebook E Go
+ * CSOT PPC357DB1-5: on MI Pad 5 Pro 12.4
+ */
+
+static const struct of_device_id himax_of_match[] = {
+ { .compatible = "boe,ppc357db1-4", .data = &boe_ppc357db1_4_desc },
+ { .compatible = "csot,ppc357db1-4", .data = &csot_ppc357db1_4_desc },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, himax_of_match);
+
+static struct mipi_dsi_driver himax_driver = {
+ .probe = himax_probe,
+ .remove = himax_remove,
+ .driver = {
+ .name = "panel-himax-hx83121a",
+ .of_match_table = himax_of_match,
+ },
+};
+module_mipi_dsi_driver(himax_driver);
+
+MODULE_AUTHOR("Pengyu Luo <mitltlatltl0@gmail.com>");
+MODULE_DESCRIPTION("Himax HX83121A DriverIC panels driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9806e-core.c b/drivers/gpu/drm/panel/panel-ilitek-ili9806e-core.c
new file mode 100644
index 000000000000..be2cf1440155
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-ilitek-ili9806e-core.c
@@ -0,0 +1,134 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Ilitek ILI9806E core driver.
+ *
+ * Copyright (c) 2026 Amarula Solutions, Dario Binacchi <dario.binacchi@amarulasolutions.com>
+ */
+
+#include <drm/drm_panel.h>
+
+#include <linux/delay.h>
+#include <linux/export.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/property.h>
+#include <linux/regulator/consumer.h>
+
+#include "panel-ilitek-ili9806e-core.h"
+
+struct ili9806e {
+ void *transport;
+ struct drm_panel panel;
+
+ unsigned int num_supplies;
+ struct regulator_bulk_data supplies[2];
+ struct gpio_desc *reset_gpio;
+};
+
+void *ili9806e_get_transport(struct drm_panel *panel)
+{
+ struct ili9806e *ctx = container_of(panel, struct ili9806e, panel);
+
+ return ctx->transport;
+}
+EXPORT_SYMBOL_GPL(ili9806e_get_transport);
+
+int ili9806e_power_on(struct device *dev)
+{
+ struct ili9806e *ctx = dev_get_drvdata(dev);
+ int ret;
+
+ gpiod_set_value(ctx->reset_gpio, 1);
+
+ ret = regulator_bulk_enable(ctx->num_supplies, ctx->supplies);
+ if (ret) {
+ dev_err(dev, "regulator bulk enable failed: %d\n", ret);
+ return ret;
+ }
+
+ usleep_range(10000, 20000);
+ gpiod_set_value(ctx->reset_gpio, 0);
+ usleep_range(10000, 20000);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ili9806e_power_on);
+
+int ili9806e_power_off(struct device *dev)
+{
+ struct ili9806e *ctx = dev_get_drvdata(dev);
+ int ret;
+
+ gpiod_set_value(ctx->reset_gpio, 1);
+
+ ret = regulator_bulk_disable(ctx->num_supplies, ctx->supplies);
+ if (ret)
+ dev_err(dev, "regulator bulk disable failed: %d\n", ret);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(ili9806e_power_off);
+
+int ili9806e_probe(struct device *dev, void *transport,
+ const struct drm_panel_funcs *funcs,
+ int connector_type)
+{
+ struct ili9806e *ctx;
+ bool set_prepare_prev_first = false;
+ int ret;
+
+ ctx = devm_kzalloc(dev, sizeof(struct ili9806e), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ dev_set_drvdata(dev, ctx);
+ ctx->transport = transport;
+
+ ctx->supplies[ctx->num_supplies++].supply = "vdd";
+ if (of_device_is_compatible(dev->of_node,
+ "densitron,dmt028vghmcmi-1d") ||
+ of_device_is_compatible(dev->of_node,
+ "ortustech,com35h3p70ulc")) {
+ ctx->supplies[ctx->num_supplies++].supply = "vccio";
+ set_prepare_prev_first = true;
+ }
+
+ ret = devm_regulator_bulk_get(dev, ctx->num_supplies, ctx->supplies);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to get regulators\n");
+
+ ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(ctx->reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
+ "Failed to get reset-gpios\n");
+
+ drm_panel_init(&ctx->panel, dev, funcs, connector_type);
+
+ ret = drm_panel_of_backlight(&ctx->panel);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to get backlight\n");
+
+ if (set_prepare_prev_first)
+ ctx->panel.prepare_prev_first = true;
+
+ drm_panel_add(&ctx->panel);
+
+ return 0;
+
+}
+EXPORT_SYMBOL_GPL(ili9806e_probe);
+
+void ili9806e_remove(struct device *dev)
+{
+ struct ili9806e *ctx = dev_get_drvdata(dev);
+
+ drm_panel_remove(&ctx->panel);
+}
+EXPORT_SYMBOL_GPL(ili9806e_remove);
+
+MODULE_AUTHOR("Dario Binacchi <dario.binacchi@amarulasolutions.com>");
+MODULE_AUTHOR("Gunnar Dibbern <gunnar.dibbern@lht.dlh.de>");
+MODULE_AUTHOR("Michael Walle <mwalle@kernel.org>");
+MODULE_DESCRIPTION("Ilitek ILI9806E Controller Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9806e-core.h b/drivers/gpu/drm/panel/panel-ilitek-ili9806e-core.h
new file mode 100644
index 000000000000..dddece62cf42
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-ilitek-ili9806e-core.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _PANEL_ILITEK_ILI9806E_CORE_H
+#define _PANEL_ILITEK_ILI9806E_CORE_H
+
+void *ili9806e_get_transport(struct drm_panel *panel);
+int ili9806e_power_off(struct device *dev);
+int ili9806e_power_on(struct device *dev);
+
+int ili9806e_probe(struct device *dev, void *transport,
+ const struct drm_panel_funcs *funcs,
+ int connector_type);
+void ili9806e_remove(struct device *dev);
+
+#endif /* _PANEL_ILITEK_ILI9806E_CORE_H */
diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9806e.c b/drivers/gpu/drm/panel/panel-ilitek-ili9806e-dsi.c
index 18aa6222b0c5..ecdbed8d4a3a 100644
--- a/drivers/gpu/drm/panel/panel-ilitek-ili9806e.c
+++ b/drivers/gpu/drm/panel/panel-ilitek-ili9806e-dsi.c
@@ -1,15 +1,12 @@
// SPDX-License-Identifier: GPL-2.0
-#include <linux/delay.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/errno.h>
-#include <linux/gpio/consumer.h>
#include <linux/kernel.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/property.h>
-#include <linux/regulator/consumer.h>
#include <drm/drm_mipi_dsi.h>
#include <drm/drm_modes.h>
@@ -18,7 +15,9 @@
#include <video/mipi_display.h>
-struct panel_desc {
+#include "panel-ilitek-ili9806e-core.h"
+
+struct ili9806e_dsi_panel_desc {
const struct drm_display_mode *display_mode;
unsigned long mode_flags;
enum mipi_dsi_pixel_format format;
@@ -26,60 +25,13 @@ struct panel_desc {
void (*init_sequence)(struct mipi_dsi_multi_context *ctx);
};
-struct ili9806e_panel {
- struct drm_panel panel;
+struct ili9806e_dsi_panel {
struct mipi_dsi_device *dsi;
- struct gpio_desc *reset_gpio;
- struct regulator_bulk_data supplies[2];
- const struct panel_desc *desc;
+ const struct ili9806e_dsi_panel_desc *desc;
enum drm_panel_orientation orientation;
};
-static const char * const regulator_names[] = {
- "vdd",
- "vccio",
-};
-
-static inline struct ili9806e_panel *to_ili9806e_panel(struct drm_panel *panel)
-{
- return container_of(panel, struct ili9806e_panel, panel);
-}
-
-static int ili9806e_power_on(struct ili9806e_panel *ctx)
-{
- struct mipi_dsi_device *dsi = ctx->dsi;
- int ret;
-
- gpiod_set_value(ctx->reset_gpio, 1);
-
- ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
- if (ret < 0) {
- dev_err(&dsi->dev, "regulator bulk enable failed: %d\n", ret);
- return ret;
- }
-
- usleep_range(10000, 20000);
- gpiod_set_value(ctx->reset_gpio, 0);
- usleep_range(10000, 20000);
-
- return 0;
-}
-
-static int ili9806e_power_off(struct ili9806e_panel *ctx)
-{
- struct mipi_dsi_device *dsi = ctx->dsi;
- int ret;
-
- gpiod_set_value(ctx->reset_gpio, 1);
-
- ret = regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
- if (ret)
- dev_err(&dsi->dev, "regulator bulk disable failed: %d\n", ret);
-
- return ret;
-}
-
-static int ili9806e_on(struct ili9806e_panel *ili9806e)
+static int ili9806e_dsi_on(struct ili9806e_dsi_panel *ili9806e)
{
struct mipi_dsi_multi_context ctx = { .dsi = ili9806e->dsi };
@@ -93,7 +45,7 @@ static int ili9806e_on(struct ili9806e_panel *ili9806e)
return ctx.accum_err;
}
-static int ili9806e_off(struct ili9806e_panel *panel)
+static int ili9806e_dsi_off(struct ili9806e_dsi_panel *panel)
{
struct mipi_dsi_multi_context ctx = { .dsi = panel->dsi };
@@ -104,88 +56,75 @@ static int ili9806e_off(struct ili9806e_panel *panel)
return ctx.accum_err;
}
-static int ili9806e_prepare(struct drm_panel *panel)
+static int ili9806e_dsi_prepare(struct drm_panel *panel)
{
- struct ili9806e_panel *ctx = to_ili9806e_panel(panel);
+ struct ili9806e_dsi_panel *ctx = ili9806e_get_transport(panel);
+ struct device *dev = &ctx->dsi->dev;
int ret;
- ret = ili9806e_power_on(ctx);
+ ret = ili9806e_power_on(dev);
if (ret < 0)
return ret;
- ret = ili9806e_on(ctx);
+ ret = ili9806e_dsi_on(ctx);
if (ret < 0) {
- ili9806e_power_off(ctx);
+ ili9806e_power_off(dev);
return ret;
}
return 0;
}
-static int ili9806e_unprepare(struct drm_panel *panel)
+static int ili9806e_dsi_unprepare(struct drm_panel *panel)
{
- struct ili9806e_panel *ctx = to_ili9806e_panel(panel);
- struct mipi_dsi_device *dsi = ctx->dsi;
+ struct ili9806e_dsi_panel *ctx = ili9806e_get_transport(panel);
+ struct device *dev = &ctx->dsi->dev;
int ret;
- ili9806e_off(ctx);
+ ili9806e_dsi_off(ctx);
- ret = ili9806e_power_off(ctx);
+ ret = ili9806e_power_off(dev);
if (ret < 0)
- dev_err(&dsi->dev, "power off failed: %d\n", ret);
+ dev_err(dev, "power off failed: %d\n", ret);
return ret;
}
-static int ili9806e_get_modes(struct drm_panel *panel,
+static int ili9806e_dsi_get_modes(struct drm_panel *panel,
struct drm_connector *connector)
{
- struct ili9806e_panel *ctx = to_ili9806e_panel(panel);
+ struct ili9806e_dsi_panel *ctx = ili9806e_get_transport(panel);
const struct drm_display_mode *mode = ctx->desc->display_mode;
return drm_connector_helper_get_modes_fixed(connector, mode);
}
-static enum drm_panel_orientation ili9806e_get_orientation(struct drm_panel *panel)
+static enum drm_panel_orientation ili9806e_dsi_get_orientation(struct drm_panel *panel)
{
- struct ili9806e_panel *ctx = to_ili9806e_panel(panel);
+ struct ili9806e_dsi_panel *ctx = ili9806e_get_transport(panel);
return ctx->orientation;
}
-static const struct drm_panel_funcs ili9806e_funcs = {
- .prepare = ili9806e_prepare,
- .unprepare = ili9806e_unprepare,
- .get_modes = ili9806e_get_modes,
- .get_orientation = ili9806e_get_orientation,
+static const struct drm_panel_funcs ili9806e_dsi_funcs = {
+ .prepare = ili9806e_dsi_prepare,
+ .unprepare = ili9806e_dsi_unprepare,
+ .get_modes = ili9806e_dsi_get_modes,
+ .get_orientation = ili9806e_dsi_get_orientation,
};
static int ili9806e_dsi_probe(struct mipi_dsi_device *dsi)
{
struct device *dev = &dsi->dev;
- struct ili9806e_panel *ctx;
- int i, ret;
+ struct ili9806e_dsi_panel *ctx;
+ int ret;
- ctx = devm_drm_panel_alloc(dev, struct ili9806e_panel, panel, &ili9806e_funcs,
- DRM_MODE_CONNECTOR_DSI);
- if (IS_ERR(ctx))
- return PTR_ERR(ctx);
+ ctx = devm_kzalloc(dev, sizeof(struct ili9806e_dsi_panel), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
ctx->desc = device_get_match_data(dev);
- for (i = 0; i < ARRAY_SIZE(ctx->supplies); i++)
- ctx->supplies[i].supply = regulator_names[i];
-
- ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
- ctx->supplies);
- if (ret < 0)
- return ret;
-
- ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
- if (IS_ERR(ctx->reset_gpio))
- return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
- "Failed to get reset-gpios\n");
-
mipi_dsi_set_drvdata(dsi, ctx);
ctx->dsi = dsi;
@@ -197,17 +136,15 @@ static int ili9806e_dsi_probe(struct mipi_dsi_device *dsi)
if (ret)
return dev_err_probe(dev, ret, "Failed to get orientation\n");
- ret = drm_panel_of_backlight(&ctx->panel);
+ ret = ili9806e_probe(dev, ctx, &ili9806e_dsi_funcs,
+ DRM_MODE_CONNECTOR_DSI);
if (ret)
- return dev_err_probe(dev, ret, "Failed to get backlight\n");
-
- ctx->panel.prepare_prev_first = true;
- drm_panel_add(&ctx->panel);
+ return ret;
ret = mipi_dsi_attach(dsi);
if (ret < 0) {
dev_err_probe(dev, ret, "Failed to attach to DSI host\n");
- drm_panel_remove(&ctx->panel);
+ ili9806e_remove(dev);
return ret;
}
@@ -216,10 +153,8 @@ static int ili9806e_dsi_probe(struct mipi_dsi_device *dsi)
static void ili9806e_dsi_remove(struct mipi_dsi_device *dsi)
{
- struct ili9806e_panel *ctx = mipi_dsi_get_drvdata(dsi);
-
mipi_dsi_detach(dsi);
- drm_panel_remove(&ctx->panel);
+ ili9806e_remove(&dsi->dev);
}
static void com35h3p70ulc_init(struct mipi_dsi_multi_context *ctx)
@@ -369,7 +304,7 @@ static const struct drm_display_mode com35h3p70ulc_default_mode = {
.height_mm = 71,
};
-static const struct panel_desc com35h3p70ulc_desc = {
+static const struct ili9806e_dsi_panel_desc com35h3p70ulc_desc = {
.init_sequence = com35h3p70ulc_init,
.display_mode = &com35h3p70ulc_default_mode,
.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
@@ -533,7 +468,7 @@ static const struct drm_display_mode dmt028vghmcmi_1d_default_mode = {
.type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
};
-static const struct panel_desc dmt028vghmcmi_1d_desc = {
+static const struct ili9806e_dsi_panel_desc dmt028vghmcmi_1d_desc = {
.init_sequence = dmt028vghmcmi_1d_init,
.display_mode = &dmt028vghmcmi_1d_default_mode,
.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
@@ -542,17 +477,17 @@ static const struct panel_desc dmt028vghmcmi_1d_desc = {
.lanes = 2,
};
-static const struct of_device_id ili9806e_of_match[] = {
+static const struct of_device_id ili9806e_dsi_of_match[] = {
{ .compatible = "densitron,dmt028vghmcmi-1d", .data = &dmt028vghmcmi_1d_desc },
{ .compatible = "ortustech,com35h3p70ulc", .data = &com35h3p70ulc_desc },
{ }
};
-MODULE_DEVICE_TABLE(of, ili9806e_of_match);
+MODULE_DEVICE_TABLE(of, ili9806e_dsi_of_match);
static struct mipi_dsi_driver ili9806e_dsi_driver = {
.driver = {
.name = "ili9806e-dsi",
- .of_match_table = ili9806e_of_match,
+ .of_match_table = ili9806e_dsi_of_match,
},
.probe = ili9806e_dsi_probe,
.remove = ili9806e_dsi_remove,
@@ -561,5 +496,5 @@ module_mipi_dsi_driver(ili9806e_dsi_driver);
MODULE_AUTHOR("Gunnar Dibbern <gunnar.dibbern@lht.dlh.de>");
MODULE_AUTHOR("Michael Walle <mwalle@kernel.org>");
-MODULE_DESCRIPTION("Ilitek ILI9806E Controller Driver");
+MODULE_DESCRIPTION("Ilitek ILI9806E Controller DSI Driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9806e-spi.c b/drivers/gpu/drm/panel/panel-ilitek-ili9806e-spi.c
new file mode 100644
index 000000000000..9d10b0d28f52
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-ilitek-ili9806e-spi.c
@@ -0,0 +1,323 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SPI interface to the Ilitek ILI9806E panel.
+ *
+ * Copyright (c) 2026 Amarula Solutions, Dario Binacchi <dario.binacchi@amarulasolutions.com>
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/media-bus-format.h>
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+
+#include <drm/drm_mipi_dbi.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_print.h>
+
+#include <video/mipi_display.h>
+
+#include "panel-ilitek-ili9806e-core.h"
+
+struct ili9806e_spi_panel {
+ struct spi_device *spi;
+ struct mipi_dbi dbi;
+ const struct ili9806e_spi_panel_desc *desc;
+};
+
+struct ili9806e_spi_panel_desc {
+ const struct drm_display_mode *display_mode;
+ u32 bus_format;
+ u32 bus_flags;
+ void (*init_sequence)(struct ili9806e_spi_panel *ctx);
+};
+
+static int ili9806e_spi_off(struct ili9806e_spi_panel *ctx)
+{
+ struct mipi_dbi *dbi = &ctx->dbi;
+
+ mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_OFF, 0x00);
+ mipi_dbi_command(dbi, MIPI_DCS_ENTER_SLEEP_MODE, 0x00);
+
+ return 0;
+}
+
+static int ili9806e_spi_unprepare(struct drm_panel *panel)
+{
+ struct ili9806e_spi_panel *ctx = ili9806e_get_transport(panel);
+ struct device *dev = &ctx->spi->dev;
+ int ret;
+
+ ili9806e_spi_off(ctx);
+
+ ret = ili9806e_power_off(dev);
+ if (ret)
+ dev_err(dev, "power off failed: %d\n", ret);
+
+ return 0;
+}
+
+static int ili9806e_spi_prepare(struct drm_panel *panel)
+{
+ struct ili9806e_spi_panel *ctx = ili9806e_get_transport(panel);
+ struct device *dev = &ctx->spi->dev;
+ int ret;
+
+ ret = ili9806e_power_on(dev);
+ if (ret)
+ return ret;
+
+ if (ctx->desc->init_sequence)
+ ctx->desc->init_sequence(ctx);
+
+ return 0;
+}
+
+static int ili9806e_spi_get_modes(struct drm_panel *panel,
+ struct drm_connector *connector)
+{
+ struct ili9806e_spi_panel *ctx = ili9806e_get_transport(panel);
+ const struct ili9806e_spi_panel_desc *desc = ctx->desc;
+ struct drm_display_mode *mode;
+
+ mode = drm_mode_duplicate(connector->dev, desc->display_mode);
+ if (!mode)
+ return -ENOMEM;
+
+ drm_mode_set_name(mode);
+
+ connector->display_info.width_mm = mode->width_mm;
+ connector->display_info.height_mm = mode->height_mm;
+ connector->display_info.bus_flags = desc->bus_flags;
+ drm_display_info_set_bus_formats(&connector->display_info,
+ &desc->bus_format, 1);
+
+ drm_mode_probed_add(connector, mode);
+
+ return 1;
+}
+
+static const struct drm_panel_funcs ili9806e_spi_funcs = {
+ .unprepare = ili9806e_spi_unprepare,
+ .prepare = ili9806e_spi_prepare,
+ .get_modes = ili9806e_spi_get_modes,
+};
+
+static int ili9806e_spi_probe(struct spi_device *spi)
+{
+ struct device *dev = &spi->dev;
+ struct ili9806e_spi_panel *ctx;
+ int err;
+
+ ctx = devm_kzalloc(dev, sizeof(struct ili9806e_spi_panel), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ ctx->spi = spi;
+ ctx->desc = device_get_match_data(dev);
+
+ err = mipi_dbi_spi_init(spi, &ctx->dbi, NULL);
+ if (err)
+ return dev_err_probe(dev, err, "MIPI DBI init failed\n");
+
+ return ili9806e_probe(dev, ctx, &ili9806e_spi_funcs,
+ DRM_MODE_CONNECTOR_DPI);
+}
+
+static void ili9806e_spi_remove(struct spi_device *spi)
+{
+ ili9806e_remove(&spi->dev);
+}
+
+static void rk050hr345_ct106a_init(struct ili9806e_spi_panel *ctx)
+{
+ struct mipi_dbi *dbi = &ctx->dbi;
+
+ /* Switch to page 1 */
+ mipi_dbi_command(dbi, 0xff, 0xff, 0x98, 0x06, 0x04, 0x01);
+ /* Interface Settings */
+ mipi_dbi_command(dbi, 0x08, 0x10);
+ mipi_dbi_command(dbi, 0x21, 0x01);
+ /* Panel Settings */
+ mipi_dbi_command(dbi, 0x30, 0x01);
+ mipi_dbi_command(dbi, 0x31, 0x00);
+ /* Power Control */
+ mipi_dbi_command(dbi, 0x40, 0x15);
+ mipi_dbi_command(dbi, 0x41, 0x44);
+ mipi_dbi_command(dbi, 0x42, 0x03);
+ mipi_dbi_command(dbi, 0x43, 0x09);
+ mipi_dbi_command(dbi, 0x44, 0x09);
+ mipi_dbi_command(dbi, 0x50, 0x78);
+ mipi_dbi_command(dbi, 0x51, 0x78);
+ mipi_dbi_command(dbi, 0x52, 0x00);
+ mipi_dbi_command(dbi, 0x53, 0x3a);
+ mipi_dbi_command(dbi, 0x57, 0x50);
+ /* Timing Control */
+ mipi_dbi_command(dbi, 0x60, 0x07);
+ mipi_dbi_command(dbi, 0x61, 0x00);
+ mipi_dbi_command(dbi, 0x62, 0x08);
+ mipi_dbi_command(dbi, 0x63, 0x00);
+ /* Gamma Settings */
+ mipi_dbi_command(dbi, 0xa0, 0x00);
+ mipi_dbi_command(dbi, 0xa1, 0x03);
+ mipi_dbi_command(dbi, 0xa2, 0x0b);
+ mipi_dbi_command(dbi, 0xa3, 0x0f);
+ mipi_dbi_command(dbi, 0xa4, 0x0b);
+ mipi_dbi_command(dbi, 0xa5, 0x1b);
+ mipi_dbi_command(dbi, 0xa6, 0x0a);
+ mipi_dbi_command(dbi, 0xa7, 0x0a);
+ mipi_dbi_command(dbi, 0xa8, 0x02);
+ mipi_dbi_command(dbi, 0xa9, 0x07);
+ mipi_dbi_command(dbi, 0xaa, 0x05);
+ mipi_dbi_command(dbi, 0xab, 0x03);
+ mipi_dbi_command(dbi, 0xac, 0x0e);
+ mipi_dbi_command(dbi, 0xad, 0x32);
+ mipi_dbi_command(dbi, 0xae, 0x2d);
+ mipi_dbi_command(dbi, 0xaf, 0x00);
+ mipi_dbi_command(dbi, 0xc0, 0x00);
+ mipi_dbi_command(dbi, 0xc1, 0x03);
+ mipi_dbi_command(dbi, 0xc2, 0x0e);
+ mipi_dbi_command(dbi, 0xc3, 0x10);
+ mipi_dbi_command(dbi, 0xc4, 0x09);
+ mipi_dbi_command(dbi, 0xc5, 0x17);
+ mipi_dbi_command(dbi, 0xc6, 0x09);
+ mipi_dbi_command(dbi, 0xc7, 0x07);
+ mipi_dbi_command(dbi, 0xc8, 0x04);
+ mipi_dbi_command(dbi, 0xc9, 0x09);
+ mipi_dbi_command(dbi, 0xca, 0x06);
+ mipi_dbi_command(dbi, 0xcb, 0x06);
+ mipi_dbi_command(dbi, 0xcc, 0x0c);
+ mipi_dbi_command(dbi, 0xcd, 0x25);
+ mipi_dbi_command(dbi, 0xce, 0x20);
+ mipi_dbi_command(dbi, 0xcf, 0x00);
+
+ /* Switch to page 6 */
+ mipi_dbi_command(dbi, 0xff, 0xff, 0x98, 0x06, 0x04, 0x06);
+ /* GIP settings */
+ mipi_dbi_command(dbi, 0x00, 0x21);
+ mipi_dbi_command(dbi, 0x01, 0x09);
+ mipi_dbi_command(dbi, 0x02, 0x00);
+ mipi_dbi_command(dbi, 0x03, 0x00);
+ mipi_dbi_command(dbi, 0x04, 0x01);
+ mipi_dbi_command(dbi, 0x05, 0x01);
+ mipi_dbi_command(dbi, 0x06, 0x80);
+ mipi_dbi_command(dbi, 0x07, 0x05);
+ mipi_dbi_command(dbi, 0x08, 0x02);
+ mipi_dbi_command(dbi, 0x09, 0x80);
+ mipi_dbi_command(dbi, 0x0a, 0x00);
+ mipi_dbi_command(dbi, 0x0b, 0x00);
+ mipi_dbi_command(dbi, 0x0c, 0x0a);
+ mipi_dbi_command(dbi, 0x0d, 0x0a);
+ mipi_dbi_command(dbi, 0x0e, 0x00);
+ mipi_dbi_command(dbi, 0x0f, 0x00);
+ mipi_dbi_command(dbi, 0x10, 0xe0);
+ mipi_dbi_command(dbi, 0x11, 0xe4);
+ mipi_dbi_command(dbi, 0x12, 0x04);
+ mipi_dbi_command(dbi, 0x13, 0x00);
+ mipi_dbi_command(dbi, 0x14, 0x00);
+ mipi_dbi_command(dbi, 0x15, 0xc0);
+ mipi_dbi_command(dbi, 0x16, 0x08);
+ mipi_dbi_command(dbi, 0x17, 0x00);
+ mipi_dbi_command(dbi, 0x18, 0x00);
+ mipi_dbi_command(dbi, 0x19, 0x00);
+ mipi_dbi_command(dbi, 0x1a, 0x00);
+ mipi_dbi_command(dbi, 0x1b, 0x00);
+ mipi_dbi_command(dbi, 0x1c, 0x00);
+ mipi_dbi_command(dbi, 0x1d, 0x00);
+ mipi_dbi_command(dbi, 0x20, 0x01);
+ mipi_dbi_command(dbi, 0x21, 0x23);
+ mipi_dbi_command(dbi, 0x22, 0x45);
+ mipi_dbi_command(dbi, 0x23, 0x67);
+ mipi_dbi_command(dbi, 0x24, 0x01);
+ mipi_dbi_command(dbi, 0x25, 0x23);
+ mipi_dbi_command(dbi, 0x26, 0x45);
+ mipi_dbi_command(dbi, 0x27, 0x67);
+ mipi_dbi_command(dbi, 0x30, 0x01);
+ mipi_dbi_command(dbi, 0x31, 0x11);
+ mipi_dbi_command(dbi, 0x32, 0x00);
+ mipi_dbi_command(dbi, 0x33, 0xee);
+ mipi_dbi_command(dbi, 0x34, 0xff);
+ mipi_dbi_command(dbi, 0x35, 0xbb);
+ mipi_dbi_command(dbi, 0x36, 0xca);
+ mipi_dbi_command(dbi, 0x37, 0xdd);
+ mipi_dbi_command(dbi, 0x38, 0xac);
+ mipi_dbi_command(dbi, 0x39, 0x76);
+ mipi_dbi_command(dbi, 0x3a, 0x67);
+ mipi_dbi_command(dbi, 0x3b, 0x22);
+ mipi_dbi_command(dbi, 0x3c, 0x22);
+ mipi_dbi_command(dbi, 0x3d, 0x22);
+ mipi_dbi_command(dbi, 0x3e, 0x22);
+ mipi_dbi_command(dbi, 0x3f, 0x22);
+ mipi_dbi_command(dbi, 0x40, 0x22);
+ mipi_dbi_command(dbi, 0x52, 0x10);
+ mipi_dbi_command(dbi, 0x53, 0x10);
+
+ /* Switch to page 7 */
+ mipi_dbi_command(dbi, 0xff, 0xff, 0x98, 0x06, 0x04, 0x07);
+ mipi_dbi_command(dbi, 0x17, 0x22);
+ mipi_dbi_command(dbi, 0x02, 0x77);
+ mipi_dbi_command(dbi, 0xe1, 0x79);
+ mipi_dbi_command(dbi, 0xb3, 0x10);
+
+ /* Switch to page 0 */
+ mipi_dbi_command(dbi, 0xff, 0xff, 0x98, 0x06, 0x04, 0x00);
+ mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, 0x00); // 0x36
+ mipi_dbi_command(dbi, MIPI_DCS_EXIT_SLEEP_MODE); // 0x11
+
+ msleep(120);
+
+ mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_ON);
+
+ msleep(120);
+}
+
+static const struct drm_display_mode rk050hr345_ct106a_mode = {
+ .width_mm = 62,
+ .height_mm = 110,
+ .clock = 27000,
+ .hdisplay = 480,
+ .hsync_start = 480 + 10,
+ .hsync_end = 480 + 10 + 10,
+ .htotal = 480 + 10 + 10 + 10,
+ .vdisplay = 854,
+ .vsync_start = 854 + 10,
+ .vsync_end = 854 + 10 + 10,
+ .vtotal = 854 + 10 + 10 + 10,
+ .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
+ .type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER,
+};
+
+static const struct ili9806e_spi_panel_desc rk050hr345_ct106a_desc = {
+ .init_sequence = rk050hr345_ct106a_init,
+ .display_mode = &rk050hr345_ct106a_mode,
+ .bus_format = MEDIA_BUS_FMT_RGB888_1X24,
+ .bus_flags = DRM_BUS_FLAG_DE_HIGH |
+ DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE,
+};
+
+static const struct of_device_id ili9806e_spi_of_match[] = {
+ { .compatible = "rocktech,rk050hr345-ct106a", .data = &rk050hr345_ct106a_desc },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ili9806e_spi_of_match);
+
+static const struct spi_device_id ili9806e_spi_ids[] = {
+ { "rk050hr345-ct106a", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(spi, ili9806e_spi_ids);
+
+static struct spi_driver ili9806e_spi_driver = {
+ .driver = {
+ .name = "ili9806e-spi",
+ .of_match_table = ili9806e_spi_of_match,
+ },
+ .probe = ili9806e_spi_probe,
+ .remove = ili9806e_spi_remove,
+ .id_table = ili9806e_spi_ids,
+};
+module_spi_driver(ili9806e_spi_driver);
+
+MODULE_AUTHOR("Dario Binacchi <dario.binacchi@amarulasolutions.com>");
+MODULE_DESCRIPTION("Ilitek ILI9806E LCD SPI Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/panel/panel-novatek-nt36672a.c b/drivers/gpu/drm/panel/panel-novatek-nt36672a.c
index 29e1f6aea480..7e8b5e059575 100644
--- a/drivers/gpu/drm/panel/panel-novatek-nt36672a.c
+++ b/drivers/gpu/drm/panel/panel-novatek-nt36672a.c
@@ -79,70 +79,57 @@ static inline struct nt36672a_panel *to_nt36672a_panel(struct drm_panel *panel)
return container_of(panel, struct nt36672a_panel, base);
}
-static int nt36672a_send_cmds(struct drm_panel *panel, const struct nt36672a_panel_cmd *cmds,
- int num)
+static void nt36672a_send_cmds(struct mipi_dsi_multi_context *dsi_ctx,
+ const struct nt36672a_panel_cmd *cmds, int num)
{
- struct nt36672a_panel *pinfo = to_nt36672a_panel(panel);
unsigned int i;
- int err;
for (i = 0; i < num; i++) {
const struct nt36672a_panel_cmd *cmd = &cmds[i];
- err = mipi_dsi_dcs_write(pinfo->link, cmd->data[0], cmd->data + 1, 1);
-
- if (err < 0)
- return err;
+ /* cmd->data[0] is the DCS command, cmd->data[1] is the parameter */
+ mipi_dsi_dcs_write_buffer_multi(dsi_ctx, cmd->data, sizeof(cmd->data));
}
-
- return 0;
}
-static int nt36672a_panel_power_off(struct drm_panel *panel)
+static void nt36672a_panel_power_off(struct drm_panel *panel)
{
struct nt36672a_panel *pinfo = to_nt36672a_panel(panel);
- int ret = 0;
+ int ret;
gpiod_set_value(pinfo->reset_gpio, 1);
ret = regulator_bulk_disable(ARRAY_SIZE(pinfo->supplies), pinfo->supplies);
if (ret)
dev_err(panel->dev, "regulator_bulk_disable failed %d\n", ret);
-
- return ret;
}
static int nt36672a_panel_unprepare(struct drm_panel *panel)
{
struct nt36672a_panel *pinfo = to_nt36672a_panel(panel);
- int ret;
+ struct mipi_dsi_multi_context dsi_ctx = { .dsi = pinfo->link };
/* send off cmds */
- ret = nt36672a_send_cmds(panel, pinfo->desc->off_cmds,
- pinfo->desc->num_off_cmds);
+ nt36672a_send_cmds(&dsi_ctx, pinfo->desc->off_cmds,
+ pinfo->desc->num_off_cmds);
- if (ret < 0)
- dev_err(panel->dev, "failed to send DCS off cmds: %d\n", ret);
-
- ret = mipi_dsi_dcs_set_display_off(pinfo->link);
- if (ret < 0)
- dev_err(panel->dev, "set_display_off cmd failed ret = %d\n", ret);
+ /* Reset error to continue with display off even if send_cmds failed */
+ dsi_ctx.accum_err = 0;
+ mipi_dsi_dcs_set_display_off_multi(&dsi_ctx);
+ /* Reset error to continue power-down even if display off failed */
+ dsi_ctx.accum_err = 0;
/* 120ms delay required here as per DCS spec */
msleep(120);
- ret = mipi_dsi_dcs_enter_sleep_mode(pinfo->link);
- if (ret < 0)
- dev_err(panel->dev, "enter_sleep cmd failed ret = %d\n", ret);
+ mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx);
/* 0x3C = 60ms delay */
msleep(60);
- ret = nt36672a_panel_power_off(panel);
- if (ret < 0)
- dev_err(panel->dev, "power_off failed ret = %d\n", ret);
+ nt36672a_panel_power_off(panel);
- return ret;
+ return 0;
}
static int nt36672a_panel_power_on(struct nt36672a_panel *pinfo)
@@ -170,52 +157,31 @@ static int nt36672a_panel_power_on(struct nt36672a_panel *pinfo)
static int nt36672a_panel_prepare(struct drm_panel *panel)
{
struct nt36672a_panel *pinfo = to_nt36672a_panel(panel);
- int err;
+ struct mipi_dsi_multi_context dsi_ctx = { .dsi = pinfo->link };
- err = nt36672a_panel_power_on(pinfo);
- if (err < 0)
- goto poweroff;
+ dsi_ctx.accum_err = nt36672a_panel_power_on(pinfo);
/* send first part of init cmds */
- err = nt36672a_send_cmds(panel, pinfo->desc->on_cmds_1,
- pinfo->desc->num_on_cmds_1);
+ nt36672a_send_cmds(&dsi_ctx, pinfo->desc->on_cmds_1,
+ pinfo->desc->num_on_cmds_1);
- if (err < 0) {
- dev_err(panel->dev, "failed to send DCS Init 1st Code: %d\n", err);
- goto poweroff;
- }
-
- err = mipi_dsi_dcs_exit_sleep_mode(pinfo->link);
- if (err < 0) {
- dev_err(panel->dev, "failed to exit sleep mode: %d\n", err);
- goto poweroff;
- }
+ mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);
/* 0x46 = 70 ms delay */
- msleep(70);
+ mipi_dsi_msleep(&dsi_ctx, 70);
- err = mipi_dsi_dcs_set_display_on(pinfo->link);
- if (err < 0) {
- dev_err(panel->dev, "failed to Set Display ON: %d\n", err);
- goto poweroff;
- }
+ mipi_dsi_dcs_set_display_on_multi(&dsi_ctx);
/* Send rest of the init cmds */
- err = nt36672a_send_cmds(panel, pinfo->desc->on_cmds_2,
- pinfo->desc->num_on_cmds_2);
+ nt36672a_send_cmds(&dsi_ctx, pinfo->desc->on_cmds_2,
+ pinfo->desc->num_on_cmds_2);
- if (err < 0) {
- dev_err(panel->dev, "failed to send DCS Init 2nd Code: %d\n", err);
- goto poweroff;
- }
+ mipi_dsi_msleep(&dsi_ctx, 120);
- msleep(120);
+ if (dsi_ctx.accum_err < 0)
+ gpiod_set_value(pinfo->reset_gpio, 0);
- return 0;
-
-poweroff:
- gpiod_set_value(pinfo->reset_gpio, 0);
- return err;
+ return dsi_ctx.accum_err;
}
static int nt36672a_panel_get_modes(struct drm_panel *panel,
diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e8fc0-m1906f9.c b/drivers/gpu/drm/panel/panel-samsung-s6e8fc0-m1906f9.c
new file mode 100644
index 000000000000..199ff99efd78
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-samsung-s6e8fc0-m1906f9.c
@@ -0,0 +1,301 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (c) Kamil Gołda <kamil.golda@protonmail.com>
+// Copyright (c) Yedaya Katsman <yedaya.ka@gmail.com>
+// Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree:
+// Copyright (c) The Linux Foundation. All rights reserved.
+
+#include <linux/backlight.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/regulator/consumer.h>
+
+#include <video/mipi_display.h>
+
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_probe_helper.h>
+
+struct s6e8fc0_ctx {
+ struct drm_panel panel;
+ struct mipi_dsi_device *dsi;
+ struct regulator_bulk_data *supplies;
+ struct gpio_desc *reset_gpio;
+};
+
+static const struct regulator_bulk_data s6e8fc0_supplies[] = {
+ { .supply = "vdd" },
+ { .supply = "vci" },
+};
+
+static inline
+struct s6e8fc0_ctx *to_s6e8fc0_ctx(struct drm_panel *panel)
+{
+ return container_of_const(panel, struct s6e8fc0_ctx, panel);
+}
+
+static void s6e8fc0_m1906f9_reset(struct s6e8fc0_ctx *ctx)
+{
+ gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+ usleep_range(12000, 13000);
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+ usleep_range(2000, 3000);
+ gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+ usleep_range(10000, 11000);
+}
+
+#define s6e8fc0_test_key_on_lvl2(ctx) \
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xf0, 0x5a, 0x5a)
+#define s6e8fc0_test_key_off_lvl2(ctx) \
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xf0, 0xa5, 0xa5)
+#define s6e8fc0_test_key_on_lvl3(ctx) \
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xfc, 0x5a, 0x5a)
+#define s6e8fc0_test_key_off_lvl3(ctx) \
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xfc, 0xa5, 0xa5)
+
+static int s6e8fc0_m1906f9_on(struct s6e8fc0_ctx *ctx)
+{
+ struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi };
+
+ s6e8fc0_test_key_on_lvl3(&dsi_ctx);
+
+ mipi_dsi_dcs_set_display_brightness_multi(&dsi_ctx, 0x0000);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_WRITE_CONTROL_DISPLAY,
+ 0x20);
+ mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);
+ mipi_dsi_msleep(&dsi_ctx, 50);
+ mipi_dsi_dcs_set_display_on_multi(&dsi_ctx);
+
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, 0x04, 0xed);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xed,
+ 0xe4, 0x08, 0x96, 0xa4, 0x2a, 0x72, 0xe2,
+ 0xca, 0x00);
+ s6e8fc0_test_key_off_lvl3(&dsi_ctx);
+ s6e8fc0_test_key_on_lvl2(&dsi_ctx);
+ s6e8fc0_test_key_on_lvl3(&dsi_ctx);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe1, 0x93);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, 0x05, 0xf4);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf4, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xed, 0x01, 0x81, 0x04);
+ s6e8fc0_test_key_off_lvl2(&dsi_ctx);
+ s6e8fc0_test_key_off_lvl3(&dsi_ctx);
+
+ return dsi_ctx.accum_err;
+}
+
+static int s6e8fc0_m1906f9_off(struct s6e8fc0_ctx *ctx)
+{
+ struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi };
+
+ mipi_dsi_dcs_set_display_off_multi(&dsi_ctx);
+ mipi_dsi_msleep(&dsi_ctx, 20);
+ mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx);
+ mipi_dsi_msleep(&dsi_ctx, 120);
+
+ return dsi_ctx.accum_err;
+}
+
+static int s6e8fc0_m1906f9_prepare(struct drm_panel *panel)
+{
+ struct s6e8fc0_ctx *ctx = to_s6e8fc0_ctx(panel);
+ struct device *dev = &ctx->dsi->dev;
+ int ret;
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(s6e8fc0_supplies), ctx->supplies);
+ if (ret < 0) {
+ dev_err(dev, "Failed to enable regulators: %d\n", ret);
+ return ret;
+ }
+
+ s6e8fc0_m1906f9_reset(ctx);
+
+ ret = s6e8fc0_m1906f9_on(ctx);
+ if (ret < 0) {
+ dev_err(dev, "Failed to initialize panel: %d\n", ret);
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+ regulator_bulk_disable(ARRAY_SIZE(s6e8fc0_supplies), ctx->supplies);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int s6e8fc0_m1906f9_unprepare(struct drm_panel *panel)
+{
+ struct s6e8fc0_ctx *ctx = to_s6e8fc0_ctx(panel);
+ struct device *dev = &ctx->dsi->dev;
+ int ret;
+
+ ret = s6e8fc0_m1906f9_off(ctx);
+ if (ret < 0)
+ dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
+
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+ regulator_bulk_disable(ARRAY_SIZE(s6e8fc0_supplies), ctx->supplies);
+
+ return 0;
+}
+
+static const struct drm_display_mode s6e8fc0_m1906f9_samsungp_mode = {
+ .clock = (720 + 350 + 40 + 294) * (1560 + 17 + 2 + 5) * 60 / 1000,
+ .hdisplay = 720,
+ .hsync_start = 720 + 350,
+ .hsync_end = 720 + 350 + 40,
+ .htotal = 720 + 350 + 40 + 294,
+ .vdisplay = 1560,
+ .vsync_start = 1560 + 17,
+ .vsync_end = 1560 + 17 + 2,
+ .vtotal = 1560 + 17 + 2 + 5,
+ .width_mm = 65,
+ .height_mm = 140,
+ .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+};
+
+static int s6e8fc0_m1906f9_get_modes(struct drm_panel *panel,
+ struct drm_connector *connector)
+{
+ return drm_connector_helper_get_modes_fixed(connector, &s6e8fc0_m1906f9_samsungp_mode);
+}
+
+static const struct drm_panel_funcs s6e8fc0_m1906f9_panel_funcs = {
+ .prepare = s6e8fc0_m1906f9_prepare,
+ .unprepare = s6e8fc0_m1906f9_unprepare,
+ .get_modes = s6e8fc0_m1906f9_get_modes,
+};
+
+static int s6e8fc0_bl_update_status(struct backlight_device *bl)
+{
+ struct mipi_dsi_device *dsi = bl_get_data(bl);
+ u16 brightness = backlight_get_brightness(bl);
+ int ret;
+
+ dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+ ret = mipi_dsi_dcs_set_display_brightness_large(dsi, brightness);
+ if (ret < 0)
+ return ret;
+
+ dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+ return 0;
+}
+
+static int s6e8fc0_bl_get_brightness(struct backlight_device *bl)
+{
+ struct mipi_dsi_device *dsi = bl_get_data(bl);
+ u16 brightness;
+ int ret;
+
+ dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+ ret = mipi_dsi_dcs_get_display_brightness_large(dsi, &brightness);
+ if (ret < 0)
+ return ret;
+
+ dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+ return brightness;
+}
+
+static const struct backlight_ops s6e8fc0_bl_ops = {
+ .update_status = s6e8fc0_bl_update_status,
+ .get_brightness = s6e8fc0_bl_get_brightness,
+};
+
+static struct backlight_device *
+s6e8fc0_m1906f9_create_backlight(struct mipi_dsi_device *dsi)
+{
+ struct device *dev = &dsi->dev;
+ const struct backlight_properties props = {
+ .type = BACKLIGHT_RAW,
+ .brightness = 512,
+ .max_brightness = 1023,
+ };
+
+ return devm_backlight_device_register(dev, dev_name(dev), dev, dsi,
+ &s6e8fc0_bl_ops, &props);
+}
+
+static int s6e8fc0_m1906f9_probe(struct mipi_dsi_device *dsi)
+{
+ struct device *dev = &dsi->dev;
+ struct s6e8fc0_ctx *ctx;
+ int ret;
+
+ ctx = devm_drm_panel_alloc(dev, struct s6e8fc0_ctx, panel,
+ &s6e8fc0_m1906f9_panel_funcs,
+ DRM_MODE_CONNECTOR_DSI);
+ if (IS_ERR(ctx))
+ return PTR_ERR(ctx);
+
+ ret = devm_regulator_bulk_get_const(dev,
+ ARRAY_SIZE(s6e8fc0_supplies),
+ s6e8fc0_supplies,
+ &ctx->supplies);
+ if (ret < 0)
+ return ret;
+
+ ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(ctx->reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
+ "Failed to get reset-gpios\n");
+
+ ctx->dsi = dsi;
+ mipi_dsi_set_drvdata(dsi, ctx);
+
+ dsi->lanes = 4;
+ dsi->format = MIPI_DSI_FMT_RGB888;
+ dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
+ MIPI_DSI_CLOCK_NON_CONTINUOUS;
+
+ ctx->panel.prepare_prev_first = true;
+
+ ctx->panel.backlight = s6e8fc0_m1906f9_create_backlight(dsi);
+ if (IS_ERR(ctx->panel.backlight))
+ return dev_err_probe(dev, PTR_ERR(ctx->panel.backlight),
+ "Failed to create backlight\n");
+
+ drm_panel_add(&ctx->panel);
+
+ ret = mipi_dsi_attach(dsi);
+ if (ret < 0) {
+ drm_panel_remove(&ctx->panel);
+ return dev_err_probe(dev, ret, "Failed to attach to DSI host\n");
+ }
+
+ return 0;
+}
+
+static void s6e8fc0_remove(struct mipi_dsi_device *dsi)
+{
+ struct s6e8fc0_ctx *ctx = mipi_dsi_get_drvdata(dsi);
+ int ret;
+
+ ret = mipi_dsi_detach(dsi);
+ if (ret < 0)
+ dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
+
+ drm_panel_remove(&ctx->panel);
+}
+
+static const struct of_device_id samsung_s6e8fc0_of_match[] = {
+ { .compatible = "samsung,s6e8fc0-m1906f9" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, samsung_s6e8fc0_of_match);
+
+static struct mipi_dsi_driver s6e8fc0_driver = {
+ .probe = s6e8fc0_m1906f9_probe,
+ .remove = s6e8fc0_remove,
+ .driver = {
+ .name = "panel-samsung-s6e8fc0-m1906f9",
+ .of_match_table = samsung_s6e8fc0_of_match,
+ },
+};
+module_mipi_dsi_driver(s6e8fc0_driver);
+
+MODULE_AUTHOR("Kamil Gołda <kamil.golda@protonmail.com>");
+MODULE_DESCRIPTION("DRM driver for Samsung s6e8fc0 DSI controller");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c b/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c
index 36abfa2e65e9..dd1eaba23ad3 100644
--- a/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c
+++ b/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c
@@ -201,6 +201,7 @@ static int sharp_nt_panel_add(struct sharp_nt_panel *sharp_nt)
drm_panel_init(&sharp_nt->base, &sharp_nt->dsi->dev,
&sharp_nt_panel_funcs, DRM_MODE_CONNECTOR_DSI);
+ sharp_nt->base.prepare_prev_first = true;
ret = drm_panel_of_backlight(&sharp_nt->base);
if (ret)
diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
index e1d15434ea54..236bd56208cc 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -1295,7 +1295,7 @@ static const struct panel_desc auo_g190ean01 = {
.height = 301,
},
.delay = {
- .prepare = 50,
+ .prepare = 30,
.enable = 200,
.disable = 110,
.unprepare = 1000,
@@ -2947,6 +2947,35 @@ static const struct panel_desc innolux_zj070na_01p = {
},
};
+static const struct display_timing jutouch_jt070tm041_timing = {
+ .pixelclock = { 40800000, 51200000, 67200000 },
+ .hactive = { 1024, 1024, 1024 },
+ .hfront_porch = { 16, 160, 216 },
+ .hback_porch = { 160, 160, 160 },
+ .hsync_len = { 1, 1, 140 },
+ .vactive = { 600, 600, 600 },
+ .vfront_porch = { 1, 12, 127 },
+ .vback_porch = { 23, 23, 23 },
+ .vsync_len = { 1, 1, 20 },
+};
+
+static const struct panel_desc jutouch_jt070tm041 = {
+ .timings = &jutouch_jt070tm041_timing,
+ .num_timings = 1,
+ .bpc = 8,
+ .size = {
+ .width = 154,
+ .height = 86,
+ },
+ .delay = {
+ .enable = 50,
+ .disable = 50,
+ },
+ .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+ .bus_flags = DRM_BUS_FLAG_DE_HIGH,
+ .connector_type = DRM_MODE_CONNECTOR_LVDS,
+};
+
static const struct display_timing jutouch_jt101tm023_timing = {
.pixelclock = { 66300000, 72400000, 78900000 },
.hactive = { 1280, 1280, 1280 },
@@ -5414,6 +5443,9 @@ static const struct of_device_id platform_of_match[] = {
.compatible = "innolux,zj070na-01p",
.data = &innolux_zj070na_01p,
}, {
+ .compatible = "jutouch,jt070tm041",
+ .data = &jutouch_jt070tm041,
+ }, {
.compatible = "jutouch,jt101tm023",
.data = &jutouch_jt101tm023,
}, {
@@ -5609,6 +5641,9 @@ static const struct of_device_id platform_of_match[] = {
.compatible = "tianma,p0700wxf1mbaa",
.data = &tianma_p0700wxf1mbaa,
}, {
+ .compatible = "tianma,tm050rdh03",
+ .data = &ontat_kd50g21_40nt_a1,
+ }, {
.compatible = "tianma,tm070jdhg30",
.data = &tianma_tm070jdhg30,
}, {
diff --git a/drivers/gpu/drm/panthor/panthor_drv.c b/drivers/gpu/drm/panthor/panthor_drv.c
index 1bcec6a2e3e0..87d27c3c1456 100644
--- a/drivers/gpu/drm/panthor/panthor_drv.c
+++ b/drivers/gpu/drm/panthor/panthor_drv.c
@@ -13,7 +13,9 @@
#include <linux/pagemap.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
+#include <linux/sched/clock.h>
#include <linux/time64.h>
+#include <linux/time_namespace.h>
#include <drm/drm_auth.h>
#include <drm/drm_debugfs.h>
@@ -761,22 +763,135 @@ static void panthor_submit_ctx_cleanup(struct panthor_submit_ctx *ctx,
kvfree(ctx->jobs);
}
+#define VALID_TIMESTAMP_QUERY_FLAGS \
+ (DRM_PANTHOR_TIMESTAMP_GPU | \
+ DRM_PANTHOR_TIMESTAMP_CPU_TYPE_MASK | \
+ DRM_PANTHOR_TIMESTAMP_GPU_OFFSET | \
+ DRM_PANTHOR_TIMESTAMP_GPU_CYCLE_COUNT | \
+ DRM_PANTHOR_TIMESTAMP_FREQ | \
+ DRM_PANTHOR_TIMESTAMP_DURATION)
+
static int panthor_query_timestamp_info(struct panthor_device *ptdev,
struct drm_panthor_timestamp_info *arg)
{
int ret;
+ u32 flags;
+ unsigned long irq_flags;
+ struct timespec64 cpu_ts;
+ u64 query_start_time;
+ bool minimize_interruption;
+ u32 timestamp_types = 0;
+
+ if (arg->flags != 0) {
+ flags = arg->flags;
+ } else {
+ /*
+ * If flags are 0, then ask for the same things that we asked
+ * for before flags were added.
+ */
+ flags = DRM_PANTHOR_TIMESTAMP_GPU |
+ DRM_PANTHOR_TIMESTAMP_GPU_OFFSET |
+ DRM_PANTHOR_TIMESTAMP_FREQ;
+ }
+
+ switch (flags & DRM_PANTHOR_TIMESTAMP_CPU_TYPE_MASK) {
+ case DRM_PANTHOR_TIMESTAMP_CPU_NONE:
+ break;
+ case DRM_PANTHOR_TIMESTAMP_CPU_MONOTONIC:
+ case DRM_PANTHOR_TIMESTAMP_CPU_MONOTONIC_RAW:
+ timestamp_types++;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (flags & ~VALID_TIMESTAMP_QUERY_FLAGS)
+ return -EINVAL;
+
+ if (flags & DRM_PANTHOR_TIMESTAMP_GPU)
+ timestamp_types++;
+ if (flags & DRM_PANTHOR_TIMESTAMP_GPU_CYCLE_COUNT)
+ timestamp_types++;
+
+ /* If user asked to obtain timestamps from more than one source,
+ * then it very likely means they want them to be as close as possible.
+ * If they asked for duration, then that likely means that they
+ * want to know how long obtaining timestamp takes, without random
+ * events, like process scheduling or interrupts.
+ */
+ minimize_interruption =
+ (flags & DRM_PANTHOR_TIMESTAMP_DURATION) ||
+ (timestamp_types >= 2);
ret = panthor_device_resume_and_get(ptdev);
if (ret)
return ret;
+ if (flags & DRM_PANTHOR_TIMESTAMP_FREQ) {
#ifdef CONFIG_ARM_ARCH_TIMER
- arg->timestamp_frequency = arch_timer_get_cntfrq();
+ arg->timestamp_frequency = arch_timer_get_cntfrq();
#else
- arg->timestamp_frequency = 0;
+ arg->timestamp_frequency = 0;
#endif
- arg->current_timestamp = gpu_read64_counter(ptdev, GPU_TIMESTAMP);
- arg->timestamp_offset = gpu_read64(ptdev, GPU_TIMESTAMP_OFFSET);
+ } else {
+ arg->timestamp_frequency = 0;
+ }
+
+ if (flags & DRM_PANTHOR_TIMESTAMP_GPU_OFFSET)
+ arg->timestamp_offset = gpu_read64(ptdev, GPU_TIMESTAMP_OFFSET);
+ else
+ arg->timestamp_offset = 0;
+
+ if (minimize_interruption) {
+ preempt_disable();
+ local_irq_save(irq_flags);
+ }
+
+ if (flags & DRM_PANTHOR_TIMESTAMP_DURATION)
+ query_start_time = local_clock();
+ else
+ query_start_time = 0;
+
+ if (flags & DRM_PANTHOR_TIMESTAMP_GPU)
+ arg->current_timestamp = gpu_read64_counter(ptdev, GPU_TIMESTAMP);
+ else
+ arg->current_timestamp = 0;
+
+ switch (flags & DRM_PANTHOR_TIMESTAMP_CPU_TYPE_MASK) {
+ case DRM_PANTHOR_TIMESTAMP_CPU_MONOTONIC:
+ ktime_get_ts64(&cpu_ts);
+ break;
+ case DRM_PANTHOR_TIMESTAMP_CPU_MONOTONIC_RAW:
+ ktime_get_raw_ts64(&cpu_ts);
+ break;
+ default:
+ break;
+ }
+
+ if (flags & DRM_PANTHOR_TIMESTAMP_GPU_CYCLE_COUNT)
+ arg->cycle_count = gpu_read64_counter(ptdev, GPU_CYCLE_COUNT);
+ else
+ arg->cycle_count = 0;
+
+ if (flags & DRM_PANTHOR_TIMESTAMP_DURATION)
+ arg->duration_nsec = local_clock() - query_start_time;
+ else
+ arg->duration_nsec = 0;
+
+ if (minimize_interruption) {
+ local_irq_restore(irq_flags);
+ preempt_enable();
+ }
+
+ if (flags & DRM_PANTHOR_TIMESTAMP_CPU_TYPE_MASK) {
+ timens_add_monotonic(&cpu_ts);
+
+ arg->cpu_timestamp_sec = cpu_ts.tv_sec;
+ arg->cpu_timestamp_nsec = cpu_ts.tv_nsec;
+ } else {
+ arg->cpu_timestamp_sec = 0;
+ arg->cpu_timestamp_nsec = 0;
+ }
pm_runtime_put(ptdev->base.dev);
return 0;
@@ -851,8 +966,14 @@ static int panthor_ioctl_dev_query(struct drm_device *ddev, void *data, struct d
return PANTHOR_UOBJ_SET(args->pointer, args->size, ptdev->csif_info);
case DRM_PANTHOR_DEV_QUERY_TIMESTAMP_INFO:
- ret = panthor_query_timestamp_info(ptdev, &timestamp_info);
+ ret = copy_struct_from_user(&timestamp_info,
+ sizeof(timestamp_info),
+ u64_to_user_ptr(args->pointer),
+ args->size);
+ if (ret)
+ return ret;
+ ret = panthor_query_timestamp_info(ptdev, &timestamp_info);
if (ret)
return ret;
@@ -1680,6 +1801,7 @@ static void panthor_debugfs_init(struct drm_minor *minor)
* - adds DRM_IOCTL_PANTHOR_BO_SYNC ioctl
* - adds DRM_IOCTL_PANTHOR_BO_QUERY_INFO ioctl
* - adds drm_panthor_gpu_info::selected_coherency
+ * - 1.8 - extends DEV_QUERY_TIMESTAMP_INFO with flags
*/
static const struct drm_driver panthor_drm_driver = {
.driver_features = DRIVER_RENDER | DRIVER_GEM | DRIVER_SYNCOBJ |
@@ -1693,7 +1815,7 @@ static const struct drm_driver panthor_drm_driver = {
.name = "panthor",
.desc = "Panthor DRM driver",
.major = 1,
- .minor = 7,
+ .minor = 8,
.gem_create_object = panthor_gem_create_object,
.gem_prime_import_sg_table = drm_gem_shmem_prime_import_sg_table,
diff --git a/drivers/gpu/drm/panthor/panthor_fw.c b/drivers/gpu/drm/panthor/panthor_fw.c
index 5a904ca64525..8886002e1d31 100644
--- a/drivers/gpu/drm/panthor/panthor_fw.c
+++ b/drivers/gpu/drm/panthor/panthor_fw.c
@@ -581,7 +581,7 @@ static int panthor_fw_load_section_entry(struct panthor_device *ptdev,
if (hdr.flags & CSF_FW_BINARY_IFACE_ENTRY_PROT) {
drm_warn(&ptdev->base,
- "Firmware protected mode entry not be supported, ignoring");
+ "Firmware protected mode entry is not supported, ignoring");
return 0;
}
@@ -750,7 +750,7 @@ static int panthor_fw_load_entry(struct panthor_device *ptdev,
if ((iter->offset % sizeof(u32)) ||
(CSF_FW_BINARY_ENTRY_SIZE(ehdr) % sizeof(u32))) {
- drm_err(&ptdev->base, "Firmware entry isn't 32 bit aligned, offset=0x%x size=0x%x\n",
+ drm_err(&ptdev->base, "Firmware entry is not 32-bit aligned, offset=0x%x size=0x%x\n",
(u32)(iter->offset - sizeof(u32)), CSF_FW_BINARY_ENTRY_SIZE(ehdr));
return -EINVAL;
}
diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c
index b4aa49b1ac63..4b10715f951c 100644
--- a/drivers/gpu/drm/radeon/si_dpm.c
+++ b/drivers/gpu/drm/radeon/si_dpm.c
@@ -2915,9 +2915,11 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
if (rdev->family == CHIP_HAINAN) {
if ((rdev->pdev->revision == 0x81) ||
(rdev->pdev->revision == 0xC3) ||
+ (rdev->pdev->device == 0x6660) ||
(rdev->pdev->device == 0x6664) ||
(rdev->pdev->device == 0x6665) ||
- (rdev->pdev->device == 0x6667)) {
+ (rdev->pdev->device == 0x6667) ||
+ (rdev->pdev->device == 0x666F)) {
max_sclk = 75000;
}
if ((rdev->pdev->revision == 0xC3) ||
diff --git a/drivers/gpu/drm/renesas/rcar-du/rcar_cmm.c b/drivers/gpu/drm/renesas/rcar-du/rcar_cmm.c
index 93ba115d654f..5bced9d778e8 100644
--- a/drivers/gpu/drm/renesas/rcar-du/rcar_cmm.c
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_cmm.c
@@ -59,7 +59,7 @@ static void rcar_cmm_lut_write(struct rcar_cmm *rcmm,
/*
* rcar_cmm_setup() - Configure the CMM unit
- * @pdev: The platform device associated with the CMM instance
+ * @dev: The device associated with the CMM instance
* @config: The CMM unit configuration
*
* Configure the CMM unit with the given configuration. Currently enabling,
@@ -73,10 +73,10 @@ static void rcar_cmm_lut_write(struct rcar_cmm *rcmm,
* TODO: Add support for LUT double buffer operations to avoid updating the
* LUT table entries while a frame is being displayed.
*/
-int rcar_cmm_setup(struct platform_device *pdev,
+int rcar_cmm_setup(struct device *dev,
const struct rcar_cmm_config *config)
{
- struct rcar_cmm *rcmm = platform_get_drvdata(pdev);
+ struct rcar_cmm *rcmm = dev_get_drvdata(dev);
/* Disable LUT if no table is provided. */
if (!config->lut.table) {
@@ -102,7 +102,7 @@ EXPORT_SYMBOL_GPL(rcar_cmm_setup);
/*
* rcar_cmm_enable() - Enable the CMM unit
- * @pdev: The platform device associated with the CMM instance
+ * @dev: The device associated with the CMM instance
*
* When the output of the corresponding DU channel is routed to the CMM unit,
* the unit shall be enabled before the DU channel is started, and remain
@@ -113,11 +113,11 @@ EXPORT_SYMBOL_GPL(rcar_cmm_setup);
* It is an error to attempt to enable an already enabled CMM unit, or to
* attempt to disable a disabled unit.
*/
-int rcar_cmm_enable(struct platform_device *pdev)
+int rcar_cmm_enable(struct device *dev)
{
int ret;
- ret = pm_runtime_resume_and_get(&pdev->dev);
+ ret = pm_runtime_resume_and_get(dev);
if (ret < 0)
return ret;
@@ -127,7 +127,7 @@ EXPORT_SYMBOL_GPL(rcar_cmm_enable);
/*
* rcar_cmm_disable() - Disable the CMM unit
- * @pdev: The platform device associated with the CMM instance
+ * @dev: The device associated with the CMM instance
*
* See rcar_cmm_enable() for usage information.
*
@@ -135,27 +135,27 @@ EXPORT_SYMBOL_GPL(rcar_cmm_enable);
* state shall thus be restored with rcar_cmm_setup() when re-enabling the CMM
* unit after the next rcar_cmm_enable() call.
*/
-void rcar_cmm_disable(struct platform_device *pdev)
+void rcar_cmm_disable(struct device *dev)
{
- struct rcar_cmm *rcmm = platform_get_drvdata(pdev);
+ struct rcar_cmm *rcmm = dev_get_drvdata(dev);
rcar_cmm_write(rcmm, CM2_LUT_CTRL, 0);
rcmm->lut.enabled = false;
- pm_runtime_put(&pdev->dev);
+ pm_runtime_put(dev);
}
EXPORT_SYMBOL_GPL(rcar_cmm_disable);
/*
* rcar_cmm_init() - Initialize the CMM unit
- * @pdev: The platform device associated with the CMM instance
+ * @dev: The device associated with the CMM instance
*
* Return: 0 on success, -EPROBE_DEFER if the CMM is not available yet,
* -ENODEV if the DRM_RCAR_CMM config option is disabled
*/
-int rcar_cmm_init(struct platform_device *pdev)
+int rcar_cmm_init(struct device *dev)
{
- struct rcar_cmm *rcmm = platform_get_drvdata(pdev);
+ struct rcar_cmm *rcmm = dev_get_drvdata(dev);
if (!rcmm)
return -EPROBE_DEFER;
diff --git a/drivers/gpu/drm/renesas/rcar-du/rcar_cmm.h b/drivers/gpu/drm/renesas/rcar-du/rcar_cmm.h
index 628072acc98b..c420113430b9 100644
--- a/drivers/gpu/drm/renesas/rcar-du/rcar_cmm.h
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_cmm.h
@@ -10,8 +10,8 @@
#define CM2_LUT_SIZE 256
+struct device;
struct drm_color_lut;
-struct platform_device;
/**
* struct rcar_cmm_config - CMM configuration
@@ -26,29 +26,29 @@ struct rcar_cmm_config {
};
#if IS_ENABLED(CONFIG_DRM_RCAR_CMM)
-int rcar_cmm_init(struct platform_device *pdev);
+int rcar_cmm_init(struct device *dev);
-int rcar_cmm_enable(struct platform_device *pdev);
-void rcar_cmm_disable(struct platform_device *pdev);
+int rcar_cmm_enable(struct device *dev);
+void rcar_cmm_disable(struct device *dev);
-int rcar_cmm_setup(struct platform_device *pdev,
+int rcar_cmm_setup(struct device *dev,
const struct rcar_cmm_config *config);
#else
-static inline int rcar_cmm_init(struct platform_device *pdev)
+static inline int rcar_cmm_init(struct device *dev)
{
return -ENODEV;
}
-static inline int rcar_cmm_enable(struct platform_device *pdev)
+static inline int rcar_cmm_enable(struct device *dev)
{
return 0;
}
-static inline void rcar_cmm_disable(struct platform_device *pdev)
+static inline void rcar_cmm_disable(struct device *dev)
{
}
-static inline int rcar_cmm_setup(struct platform_device *pdev,
+static inline int rcar_cmm_setup(struct device *dev,
const struct rcar_cmm_config *config)
{
return 0;
diff --git a/drivers/gpu/drm/renesas/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/renesas/rcar-du/rcar_du_crtc.c
index 28a5aa5a14d8..7c36c30a75b6 100644
--- a/drivers/gpu/drm/renesas/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_du_crtc.c
@@ -513,13 +513,13 @@ static void rcar_du_cmm_setup(struct drm_crtc *crtc)
struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
struct rcar_cmm_config cmm_config = {};
- if (!rcrtc->cmm)
+ if (!rcrtc->cmm->dev)
return;
if (drm_lut)
cmm_config.lut.table = (struct drm_color_lut *)drm_lut->data;
- rcar_cmm_setup(rcrtc->cmm, &cmm_config);
+ rcar_cmm_setup(rcrtc->cmm->dev, &cmm_config);
}
/* -----------------------------------------------------------------------------
@@ -667,8 +667,8 @@ static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc)
if (rcar_du_has(rcrtc->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
rcar_du_vsp_disable(rcrtc);
- if (rcrtc->cmm)
- rcar_cmm_disable(rcrtc->cmm);
+ if (rcrtc->cmm->dev)
+ rcar_cmm_disable(rcrtc->cmm->dev);
/*
* Select switch sync mode. This stops display operation and configures
@@ -726,8 +726,8 @@ static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc,
struct rcar_du_crtc_state *rstate = to_rcar_crtc_state(crtc->state);
struct rcar_du_device *rcdu = rcrtc->dev;
- if (rcrtc->cmm)
- rcar_cmm_enable(rcrtc->cmm);
+ if (rcrtc->cmm->dev)
+ rcar_cmm_enable(rcrtc->cmm->dev);
rcar_du_crtc_get(rcrtc);
/*
@@ -1300,8 +1300,8 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int swindex,
return ret;
/* CMM might be disabled for this CRTC. */
- if (rcdu->cmms[swindex]) {
- rcrtc->cmm = rcdu->cmms[swindex];
+ if (rcdu->cmms[swindex].dev) {
+ rcrtc->cmm = &rcdu->cmms[swindex];
rgrp->cmms_mask |= BIT(hwindex % 2);
drm_mode_crtc_set_gamma_size(crtc, CM2_LUT_SIZE);
diff --git a/drivers/gpu/drm/renesas/rcar-du/rcar_du_crtc.h b/drivers/gpu/drm/renesas/rcar-du/rcar_du_crtc.h
index d0f38a8b3561..8857926e109a 100644
--- a/drivers/gpu/drm/renesas/rcar-du/rcar_du_crtc.h
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_du_crtc.h
@@ -19,6 +19,7 @@
#include <media/vsp1.h>
+struct rcar_du_cmm;
struct rcar_du_group;
struct rcar_du_vsp;
@@ -65,7 +66,7 @@ struct rcar_du_crtc {
unsigned int vblank_count;
struct rcar_du_group *group;
- struct platform_device *cmm;
+ struct rcar_du_cmm *cmm;
struct rcar_du_vsp *vsp;
unsigned int vsp_pipe;
diff --git a/drivers/gpu/drm/renesas/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/renesas/rcar-du/rcar_du_drv.h
index 5cfa2bb7ad93..de9c6617a2d4 100644
--- a/drivers/gpu/drm/renesas/rcar-du/rcar_du_drv.h
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_du_drv.h
@@ -22,6 +22,7 @@
struct clk;
struct device;
+struct device_link;
struct drm_bridge;
struct drm_property;
struct rcar_du_device;
@@ -88,6 +89,11 @@ struct rcar_du_device_info {
unsigned int lvds_clk_mask;
};
+struct rcar_du_cmm {
+ struct device *dev;
+ struct device_link *link;
+};
+
#define RCAR_DU_MAX_CRTCS 4
#define RCAR_DU_MAX_GROUPS DIV_ROUND_UP(RCAR_DU_MAX_CRTCS, 2)
#define RCAR_DU_MAX_VSPS 4
@@ -106,7 +112,7 @@ struct rcar_du_device {
unsigned int num_crtcs;
struct rcar_du_group groups[RCAR_DU_MAX_GROUPS];
- struct platform_device *cmms[RCAR_DU_MAX_CRTCS];
+ struct rcar_du_cmm cmms[RCAR_DU_MAX_CRTCS];
struct rcar_du_vsp vsps[RCAR_DU_MAX_VSPS];
struct drm_bridge *lvds[RCAR_DU_MAX_LVDS];
struct drm_bridge *dsi[RCAR_DU_MAX_DSI];
diff --git a/drivers/gpu/drm/renesas/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/renesas/rcar-du/rcar_du_kms.c
index 60e6f43b8ab2..b2d0e4651e35 100644
--- a/drivers/gpu/drm/renesas/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_du_kms.c
@@ -19,6 +19,7 @@
#include <drm/drm_probe_helper.h>
#include <drm/drm_vblank.h>
+#include <linux/cleanup.h>
#include <linux/device.h>
#include <linux/dma-buf.h>
#include <linux/of.h>
@@ -573,7 +574,7 @@ static int rcar_du_encoders_init_one(struct rcar_du_device *rcdu,
enum rcar_du_output output,
struct of_endpoint *ep)
{
- struct device_node *entity;
+ struct device_node *entity __free(device_node) = NULL;
int ret;
/* Locate the connected entity and initialize the encoder. */
@@ -588,7 +589,6 @@ static int rcar_du_encoders_init_one(struct rcar_du_device *rcdu,
dev_dbg(rcdu->dev,
"connected entity %pOF is disabled, skipping\n",
entity);
- of_node_put(entity);
return -ENODEV;
}
@@ -598,15 +598,13 @@ static int rcar_du_encoders_init_one(struct rcar_du_device *rcdu,
"failed to initialize encoder %pOF on output %s (%d), skipping\n",
entity, rcar_du_output_name(output), ret);
- of_node_put(entity);
-
return ret;
}
static int rcar_du_encoders_init(struct rcar_du_device *rcdu)
{
+ struct device_node *ep_node __free(device_node) = NULL;
struct device_node *np = rcdu->dev->of_node;
- struct device_node *ep_node;
unsigned int num_encoders = 0;
/*
@@ -620,10 +618,8 @@ static int rcar_du_encoders_init(struct rcar_du_device *rcdu)
int ret;
ret = of_graph_parse_endpoint(ep_node, &ep);
- if (ret < 0) {
- of_node_put(ep_node);
+ if (ret < 0)
return ret;
- }
/* Find the output route corresponding to the port number. */
for (i = 0; i < RCAR_DU_OUTPUT_MAX; ++i) {
@@ -644,10 +640,8 @@ static int rcar_du_encoders_init(struct rcar_du_device *rcdu)
/* Process the output pipeline. */
ret = rcar_du_encoders_init_one(rcdu, output, &ep);
if (ret < 0) {
- if (ret == -EPROBE_DEFER) {
- of_node_put(ep_node);
+ if (ret == -EPROBE_DEFER)
return ret;
- }
continue;
}
@@ -775,51 +769,47 @@ static int rcar_du_cmm_init(struct rcar_du_device *rcdu)
}
for (i = 0; i < cells; ++i) {
+ struct device_node *cmm_node __free(device_node) = NULL;
+ struct rcar_du_cmm *cmm = &rcdu->cmms[i];
struct platform_device *pdev;
- struct device_link *link;
- struct device_node *cmm;
int ret;
- cmm = of_parse_phandle(np, "renesas,cmms", i);
- if (!cmm) {
+ cmm_node = of_parse_phandle(np, "renesas,cmms", i);
+ if (!cmm_node) {
dev_err(rcdu->dev,
"Failed to parse 'renesas,cmms' property\n");
return -EINVAL;
}
- if (!of_device_is_available(cmm)) {
+ if (!of_device_is_available(cmm_node))
/* It's fine to have a phandle to a non-enabled CMM. */
- of_node_put(cmm);
continue;
- }
- pdev = of_find_device_by_node(cmm);
+ pdev = of_find_device_by_node(cmm_node);
if (!pdev) {
dev_err(rcdu->dev, "No device found for CMM%u\n", i);
- of_node_put(cmm);
return -EINVAL;
}
- of_node_put(cmm);
-
/*
* -ENODEV is used to report that the CMM config option is
* disabled: return 0 and let the DU continue probing.
*/
- ret = rcar_cmm_init(pdev);
+ ret = rcar_cmm_init(&pdev->dev);
if (ret) {
platform_device_put(pdev);
return ret == -ENODEV ? 0 : ret;
}
- rcdu->cmms[i] = pdev;
+ cmm->dev = &pdev->dev;
/*
* Enforce suspend/resume ordering by making the CMM a provider
* of the DU: CMM is suspended after and resumed before the DU.
*/
- link = device_link_add(rcdu->dev, &pdev->dev, DL_FLAG_STATELESS);
- if (!link) {
+ cmm->link = device_link_add(rcdu->dev, cmm->dev,
+ DL_FLAG_STATELESS);
+ if (!cmm->link) {
dev_err(rcdu->dev,
"Failed to create device link to CMM%u\n", i);
return -EINVAL;
@@ -834,8 +824,14 @@ static void rcar_du_modeset_cleanup(struct drm_device *dev, void *res)
struct rcar_du_device *rcdu = to_rcar_du_device(dev);
unsigned int i;
- for (i = 0; i < ARRAY_SIZE(rcdu->cmms); ++i)
- platform_device_put(rcdu->cmms[i]);
+ for (i = 0; i < ARRAY_SIZE(rcdu->cmms); ++i) {
+ struct rcar_du_cmm *cmm = &rcdu->cmms[i];
+
+ if (cmm->link)
+ device_link_del(cmm->link);
+
+ put_device(cmm->dev);
+ }
}
int rcar_du_modeset_init(struct rcar_du_device *rcdu)
diff --git a/drivers/gpu/drm/renesas/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/renesas/rcar-du/rcar_du_vsp.c
index 94c22d2db197..a4a49dcd8233 100644
--- a/drivers/gpu/drm/renesas/rcar-du/rcar_du_vsp.c
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_du_vsp.c
@@ -20,6 +20,7 @@
#include <drm/drm_vblank.h>
#include <linux/bitops.h>
+#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
@@ -458,6 +459,9 @@ static void rcar_du_vsp_cleanup(struct drm_device *dev, void *res)
kfree(vsp->planes);
+ if (vsp->link)
+ device_link_del(vsp->link);
+
put_device(vsp->vsp);
}
@@ -482,6 +486,18 @@ int rcar_du_vsp_init(struct rcar_du_vsp *vsp, struct device_node *np,
if (ret < 0)
return ret;
+ /*
+ * Enforce suspend/resume ordering between the DU (consumer) and the
+ * VSP (supplier). The DU will be suspended before and resume after the
+ * VSP.
+ */
+ vsp->link = device_link_add(rcdu->dev, vsp->vsp, DL_FLAG_STATELESS);
+ if (!vsp->link) {
+ dev_err(rcdu->dev, "Failed to create device link to VSP %s\n",
+ dev_name(vsp->vsp));
+ return -EINVAL;
+ }
+
ret = vsp1_du_init(vsp->vsp);
if (ret < 0)
return ret;
diff --git a/drivers/gpu/drm/renesas/rcar-du/rcar_du_vsp.h b/drivers/gpu/drm/renesas/rcar-du/rcar_du_vsp.h
index 67630f0b6599..a6731249db34 100644
--- a/drivers/gpu/drm/renesas/rcar-du/rcar_du_vsp.h
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_du_vsp.h
@@ -12,6 +12,7 @@
#include <drm/drm_plane.h>
+struct device_link;
struct drm_framebuffer;
struct rcar_du_format_info;
struct rcar_du_vsp;
@@ -26,6 +27,7 @@ struct rcar_du_vsp_plane {
struct rcar_du_vsp {
unsigned int index;
struct device *vsp;
+ struct device_link *link;
struct rcar_du_device *dev;
struct rcar_du_vsp_plane *planes;
unsigned int num_planes;
diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
index 29f2b7d24fe5..a87a301326c7 100644
--- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
+++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
@@ -808,8 +808,7 @@ static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi,
* commands payload not being saved to memory.
*/
dsisetr = rzg2l_mipi_dsi_link_read(dsi, DSISETR);
- dsisetr &= ~DSISETR_MRPSZ;
- dsisetr |= FIELD_PREP(DSISETR_MRPSZ, RZG2L_DCS_BUF_SIZE);
+ FIELD_MODIFY(DSISETR_MRPSZ, &dsisetr, RZG2L_DCS_BUF_SIZE);
rzg2l_mipi_dsi_link_write(dsi, DSISETR, dsisetr);
return 0;
diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index fdab71d51e2a..96bd3dd239d2 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -171,12 +171,12 @@ static int rockchip_dp_get_modes(struct analogix_dp_plat_data *plat_data,
{
struct drm_display_info *di = &connector->display_info;
/* VOP couldn't output YUV video format for eDP rightly */
- u32 mask = DRM_COLOR_FORMAT_YCBCR444 | DRM_COLOR_FORMAT_YCBCR422;
+ u32 mask = BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444) | BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422);
if ((di->color_formats & mask)) {
DRM_DEBUG_KMS("Swapping display color format from YUV to RGB\n");
di->color_formats &= ~mask;
- di->color_formats |= DRM_COLOR_FORMAT_RGB444;
+ di->color_formats |= BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444);
di->bpc = 8;
}
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
index a195f5c819a2..843c7ef979b2 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
@@ -1080,6 +1080,13 @@ static int vop2_plane_atomic_check(struct drm_plane *plane,
return -EINVAL;
}
+ if ((cstate->background_color << 16) &&
+ (fb->format->has_alpha || pstate->alpha != 0xffff)) {
+ drm_dbg_kms(vop2->drm,
+ "Alpha-blending with background color is unsupported\n");
+ return -EINVAL;
+ }
+
return 0;
}
@@ -1552,6 +1559,7 @@ static void vop2_post_config(struct drm_crtc *crtc)
struct vop2_video_port *vp = to_vop2_video_port(crtc);
struct vop2 *vop2 = vp->vop2;
struct drm_display_mode *mode = &crtc->state->adjusted_mode;
+ u64 bgcolor = crtc->state->background_color;
u16 vtotal = mode->crtc_vtotal;
u16 hdisplay = mode->crtc_hdisplay;
u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
@@ -1597,7 +1605,15 @@ static void vop2_post_config(struct drm_crtc *crtc)
vop2_vp_write(vp, RK3568_VP_POST_DSP_VACT_INFO_F1, val);
}
- vop2_vp_write(vp, RK3568_VP_DSP_BG, 0);
+ /*
+ * Background color is programmed with 10 bits of precision.
+ * Since performance is more important than accuracy here,
+ * make use of the DRM_ARGB64_GET*_BPCS() helpers.
+ */
+ val = FIELD_PREP(RK3568_VP_DSP_BG__DSP_BG_RED, DRM_ARGB64_GETR_BPCS(bgcolor, 10));
+ FIELD_MODIFY(RK3568_VP_DSP_BG__DSP_BG_GREEN, &val, DRM_ARGB64_GETG_BPCS(bgcolor, 10));
+ FIELD_MODIFY(RK3568_VP_DSP_BG__DSP_BG_BLUE, &val, DRM_ARGB64_GETB_BPCS(bgcolor, 10));
+ vop2_vp_write(vp, RK3568_VP_DSP_BG, val);
}
static int us_to_vertical_line(struct drm_display_mode *mode, int us)
@@ -1983,6 +1999,10 @@ static int vop2_crtc_state_dump(struct drm_crtc *crtc, struct seq_file *s)
drm_get_bus_format_name(vcstate->bus_format));
seq_printf(s, "\toutput_mode[%x]", vcstate->output_mode);
seq_printf(s, " color_space[%d]\n", vcstate->color_space);
+ seq_printf(s, "\tbackground color (10bpc): r=0x%x g=0x%x b=0x%x\n",
+ DRM_ARGB64_GETR_BPCS(cstate->background_color, 10),
+ DRM_ARGB64_GETG_BPCS(cstate->background_color, 10),
+ DRM_ARGB64_GETB_BPCS(cstate->background_color, 10));
seq_printf(s, " Display mode: %dx%d%s%d\n",
mode->hdisplay, mode->vdisplay, interlaced ? "i" : "p",
drm_mode_vrefresh(mode));
@@ -2471,6 +2491,8 @@ static int vop2_create_crtcs(struct vop2 *vop2)
return dev_err_probe(drm->dev, ret,
"crtc init for video_port%d failed\n", i);
+ drm_crtc_attach_background_color_property(&vp->crtc);
+
drm_crtc_helper_add(&vp->crtc, &vop2_crtc_helper_funcs);
if (vop2->lut_regs) {
const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h
index 9124191899ba..37722652844a 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h
@@ -658,6 +658,10 @@ enum dst_factor_mode {
#define RK3588_VP_CLK_CTRL__DCLK_OUT_DIV GENMASK(3, 2)
#define RK3588_VP_CLK_CTRL__DCLK_CORE_DIV GENMASK(1, 0)
+#define RK3568_VP_DSP_BG__DSP_BG_RED GENMASK(29, 20)
+#define RK3568_VP_DSP_BG__DSP_BG_GREEN GENMASK(19, 10)
+#define RK3568_VP_DSP_BG__DSP_BG_BLUE GENMASK(9, 0)
+
#define RK3568_VP_POST_SCL_CTRL__VSCALEDOWN BIT(1)
#define RK3568_VP_POST_SCL_CTRL__HSCALEDOWN BIT(0)
diff --git a/drivers/gpu/drm/sitronix/st7586.c b/drivers/gpu/drm/sitronix/st7586.c
index b57ebf37a664..fa58b3d83564 100644
--- a/drivers/gpu/drm/sitronix/st7586.c
+++ b/drivers/gpu/drm/sitronix/st7586.c
@@ -13,6 +13,7 @@
#include <video/mipi_display.h>
#include <drm/clients/drm_client_setup.h>
+#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_damage_helper.h>
#include <drm/drm_drv.h>
@@ -48,6 +49,20 @@
#define ST7586_DISP_CTRL_MX BIT(6)
#define ST7586_DISP_CTRL_MY BIT(7)
+struct st7586_device {
+ struct mipi_dbi_dev dbidev;
+
+ struct drm_plane plane;
+ struct drm_crtc crtc;
+ struct drm_encoder encoder;
+ struct drm_connector connector;
+};
+
+static struct st7586_device *to_st7586_device(struct drm_device *dev)
+{
+ return container_of(drm_to_mipi_dbi_dev(dev), struct st7586_device, dbidev);
+}
+
/*
* The ST7586 controller has an unusual pixel format where 2bpp grayscale is
* packed 3 pixels per byte with the first two pixels using 3 bits and the 3rd
@@ -147,46 +162,59 @@ err_msg:
dev_err_once(fb->dev->dev, "Failed to update display %d\n", ret);
}
-static void st7586_pipe_update(struct drm_simple_display_pipe *pipe,
- struct drm_plane_state *old_state)
+static const u32 st7586_plane_formats[] = {
+ DRM_FORMAT_XRGB8888,
+};
+
+static const u64 st7586_plane_format_modifiers[] = {
+ DRM_MIPI_DBI_PLANE_FORMAT_MODIFIERS,
+};
+
+static void st7586_plane_helper_atomic_update(struct drm_plane *plane,
+ struct drm_atomic_state *state)
{
- struct drm_plane_state *state = pipe->plane.state;
- struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(state);
- struct drm_framebuffer *fb = state->fb;
+ struct drm_plane_state *plane_state = plane->state;
+ struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
+ struct drm_framebuffer *fb = plane_state->fb;
+ struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
struct drm_rect rect;
int idx;
- if (!pipe->crtc.state->active)
+ if (!fb)
return;
- if (!drm_dev_enter(fb->dev, &idx))
+ if (!drm_dev_enter(plane->dev, &idx))
return;
- if (drm_atomic_helper_damage_merged(old_state, state, &rect))
+ if (drm_atomic_helper_damage_merged(old_plane_state, plane_state, &rect))
st7586_fb_dirty(&shadow_plane_state->data[0], fb, &rect,
&shadow_plane_state->fmtcnv_state);
drm_dev_exit(idx);
}
-static void st7586_pipe_enable(struct drm_simple_display_pipe *pipe,
- struct drm_crtc_state *crtc_state,
- struct drm_plane_state *plane_state)
+static const struct drm_plane_helper_funcs st7586_plane_helper_funcs = {
+ DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
+ .atomic_check = drm_mipi_dbi_plane_helper_atomic_check,
+ .atomic_update = st7586_plane_helper_atomic_update
+};
+
+static const struct drm_plane_funcs st7586_plane_funcs = {
+ DRM_MIPI_DBI_PLANE_FUNCS,
+ .destroy = drm_plane_cleanup,
+};
+
+static void st7586_crtc_helper_atomic_enable(struct drm_crtc *crtc,
+ struct drm_atomic_state *state)
{
- struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev);
- struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
- struct drm_framebuffer *fb = plane_state->fb;
+ struct drm_device *drm = crtc->dev;
+ struct st7586_device *st7586 = to_st7586_device(drm);
+ struct mipi_dbi_dev *dbidev = &st7586->dbidev;
struct mipi_dbi *dbi = &dbidev->dbi;
- struct drm_rect rect = {
- .x1 = 0,
- .x2 = fb->width,
- .y1 = 0,
- .y2 = fb->height,
- };
int idx, ret;
u8 addr_mode;
- if (!drm_dev_enter(pipe->crtc.dev, &idx))
+ if (!drm_dev_enter(drm, &idx))
return;
DRM_DEBUG_KMS("\n");
@@ -242,17 +270,17 @@ static void st7586_pipe_enable(struct drm_simple_display_pipe *pipe,
msleep(100);
- st7586_fb_dirty(&shadow_plane_state->data[0], fb, &rect,
- &shadow_plane_state->fmtcnv_state);
-
mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_ON);
out_exit:
drm_dev_exit(idx);
}
-static void st7586_pipe_disable(struct drm_simple_display_pipe *pipe)
+static void st7586_crtc_helper_atomic_disable(struct drm_crtc *crtc,
+ struct drm_atomic_state *state)
{
- struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev);
+ struct drm_device *drm = crtc->dev;
+ struct st7586_device *st7586 = to_st7586_device(drm);
+ struct mipi_dbi_dev *dbidev = &st7586->dbidev;
/*
* This callback is not protected by drm_dev_enter/exit since we want to
@@ -266,20 +294,37 @@ static void st7586_pipe_disable(struct drm_simple_display_pipe *pipe)
mipi_dbi_command(&dbidev->dbi, MIPI_DCS_SET_DISPLAY_OFF);
}
-static const u32 st7586_formats[] = {
- DRM_FORMAT_XRGB8888,
+static const struct drm_crtc_helper_funcs st7586_crtc_helper_funcs = {
+ .mode_valid = drm_mipi_dbi_crtc_helper_mode_valid,
+ .atomic_check = drm_mipi_dbi_crtc_helper_atomic_check,
+ .atomic_enable = st7586_crtc_helper_atomic_enable,
+ .atomic_disable = st7586_crtc_helper_atomic_disable,
+};
+
+static const struct drm_crtc_funcs st7586_crtc_funcs = {
+ DRM_MIPI_DBI_CRTC_FUNCS,
+ .destroy = drm_crtc_cleanup,
+};
+
+static const struct drm_encoder_funcs st7586_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
+static const struct drm_connector_helper_funcs st7586_connector_helper_funcs = {
+ DRM_MIPI_DBI_CONNECTOR_HELPER_FUNCS,
};
-static const struct drm_simple_display_pipe_funcs st7586_pipe_funcs = {
- .mode_valid = mipi_dbi_pipe_mode_valid,
- .enable = st7586_pipe_enable,
- .disable = st7586_pipe_disable,
- .update = st7586_pipe_update,
- .begin_fb_access = mipi_dbi_pipe_begin_fb_access,
- .end_fb_access = mipi_dbi_pipe_end_fb_access,
- .reset_plane = mipi_dbi_pipe_reset_plane,
- .duplicate_plane_state = mipi_dbi_pipe_duplicate_plane_state,
- .destroy_plane_state = mipi_dbi_pipe_destroy_plane_state,
+static const struct drm_connector_funcs st7586_connector_funcs = {
+ DRM_MIPI_DBI_CONNECTOR_FUNCS,
+ .destroy = drm_connector_cleanup,
+};
+
+static const struct drm_mode_config_helper_funcs st7586_mode_config_helper_funcs = {
+ DRM_MIPI_DBI_MODE_CONFIG_HELPER_FUNCS,
+};
+
+static const struct drm_mode_config_funcs st7586_mode_config_funcs = {
+ DRM_MIPI_DBI_MODE_CONFIG_FUNCS,
};
static const struct drm_display_mode st7586_mode = {
@@ -315,19 +360,23 @@ MODULE_DEVICE_TABLE(spi, st7586_id);
static int st7586_probe(struct spi_device *spi)
{
struct device *dev = &spi->dev;
+ struct st7586_device *st7586;
struct mipi_dbi_dev *dbidev;
struct drm_device *drm;
struct mipi_dbi *dbi;
struct gpio_desc *a0;
+ struct drm_plane *plane;
+ struct drm_crtc *crtc;
+ struct drm_encoder *encoder;
+ struct drm_connector *connector;
u32 rotation = 0;
size_t bufsize;
int ret;
- dbidev = devm_drm_dev_alloc(dev, &st7586_driver,
- struct mipi_dbi_dev, drm);
- if (IS_ERR(dbidev))
- return PTR_ERR(dbidev);
-
+ st7586 = devm_drm_dev_alloc(dev, &st7586_driver, struct st7586_device, dbidev.drm);
+ if (IS_ERR(st7586))
+ return PTR_ERR(st7586);
+ dbidev = &st7586->dbidev;
dbi = &dbidev->dbi;
drm = &dbidev->drm;
@@ -347,23 +396,64 @@ static int st7586_probe(struct spi_device *spi)
if (ret)
return ret;
+ /*
+ * Override value set by mipi_dbi_spi_init(). This driver is a bit
+ * non-standard, so best to set it explicitly here.
+ */
+ dbi->write_memory_bpw = 8;
+
/* Cannot read from this controller via SPI */
dbi->read_commands = NULL;
- ret = mipi_dbi_dev_init_with_formats(dbidev, &st7586_pipe_funcs,
- st7586_formats, ARRAY_SIZE(st7586_formats),
- &st7586_mode, rotation, bufsize);
+ ret = drm_mipi_dbi_dev_init(dbidev, &st7586_mode, st7586_plane_formats[0],
+ rotation, bufsize);
if (ret)
return ret;
- /*
- * we are using 8-bit data, so we are not actually swapping anything,
- * but setting mipi->swap_bytes makes mipi_dbi_typec3_command() do the
- * right thing and not use 16-bit transfers (which results in swapped
- * bytes on little-endian systems and causes out of order data to be
- * sent to the display).
- */
- dbi->swap_bytes = true;
+ ret = drmm_mode_config_init(drm);
+ if (ret)
+ return ret;
+
+ drm->mode_config.min_width = dbidev->mode.hdisplay;
+ drm->mode_config.max_width = dbidev->mode.hdisplay;
+ drm->mode_config.min_height = dbidev->mode.vdisplay;
+ drm->mode_config.max_height = dbidev->mode.vdisplay;
+ drm->mode_config.funcs = &st7586_mode_config_funcs;
+ drm->mode_config.preferred_depth = 24;
+ drm->mode_config.helper_private = &st7586_mode_config_helper_funcs;
+
+ plane = &st7586->plane;
+ ret = drm_universal_plane_init(drm, plane, 0, &st7586_plane_funcs,
+ st7586_plane_formats, ARRAY_SIZE(st7586_plane_formats),
+ st7586_plane_format_modifiers,
+ DRM_PLANE_TYPE_PRIMARY, NULL);
+ if (ret)
+ return ret;
+ drm_plane_helper_add(plane, &st7586_plane_helper_funcs);
+ drm_plane_enable_fb_damage_clips(plane);
+
+ crtc = &st7586->crtc;
+ ret = drm_crtc_init_with_planes(drm, crtc, plane, NULL, &st7586_crtc_funcs, NULL);
+ if (ret)
+ return ret;
+ drm_crtc_helper_add(crtc, &st7586_crtc_helper_funcs);
+
+ encoder = &st7586->encoder;
+ ret = drm_encoder_init(drm, encoder, &st7586_encoder_funcs, DRM_MODE_ENCODER_NONE, NULL);
+ if (ret)
+ return ret;
+ encoder->possible_crtcs = drm_crtc_mask(crtc);
+
+ connector = &st7586->connector;
+ ret = drm_connector_init(drm, connector, &st7586_connector_funcs,
+ DRM_MODE_CONNECTOR_SPI);
+ if (ret)
+ return ret;
+ drm_connector_helper_add(connector, &st7586_connector_helper_funcs);
+
+ ret = drm_connector_attach_encoder(connector, encoder);
+ if (ret)
+ return ret;
drm_mode_config_reset(drm);
diff --git a/drivers/gpu/drm/sitronix/st7735r.c b/drivers/gpu/drm/sitronix/st7735r.c
index c1f8228495f6..5a75716ed5ff 100644
--- a/drivers/gpu/drm/sitronix/st7735r.c
+++ b/drivers/gpu/drm/sitronix/st7735r.c
@@ -52,23 +52,49 @@ struct st7735r_cfg {
unsigned int rgb:1; /* RGB (vs. BGR) */
};
-struct st7735r_priv {
+struct st7735r_device {
struct mipi_dbi_dev dbidev; /* Must be first for .release() */
const struct st7735r_cfg *cfg;
+
+ struct drm_plane plane;
+ struct drm_crtc crtc;
+ struct drm_encoder encoder;
+ struct drm_connector connector;
};
-static void st7735r_pipe_enable(struct drm_simple_display_pipe *pipe,
- struct drm_crtc_state *crtc_state,
- struct drm_plane_state *plane_state)
+static struct st7735r_device *to_st7735r_device(struct drm_device *drm)
{
- struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev);
- struct st7735r_priv *priv = container_of(dbidev, struct st7735r_priv,
- dbidev);
+ return container_of(drm_to_mipi_dbi_dev(drm), struct st7735r_device, dbidev);
+}
+
+static const u32 st7735r_plane_formats[] = {
+ DRM_MIPI_DBI_PLANE_FORMATS,
+};
+
+static const u64 st7735r_plane_format_modifiers[] = {
+ DRM_MIPI_DBI_PLANE_FORMAT_MODIFIERS,
+};
+
+static const struct drm_plane_helper_funcs st7735r_plane_helper_funcs = {
+ DRM_MIPI_DBI_PLANE_HELPER_FUNCS,
+};
+
+static const struct drm_plane_funcs st7735r_plane_funcs = {
+ DRM_MIPI_DBI_PLANE_FUNCS,
+ .destroy = drm_plane_cleanup,
+};
+
+static void st7735r_crtc_helper_atomic_enable(struct drm_crtc *crtc,
+ struct drm_atomic_state *state)
+{
+ struct drm_device *drm = crtc->dev;
+ struct st7735r_device *st7735r = to_st7735r_device(drm);
+ struct mipi_dbi_dev *dbidev = &st7735r->dbidev;
struct mipi_dbi *dbi = &dbidev->dbi;
int ret, idx;
u8 addr_mode;
- if (!drm_dev_enter(pipe->crtc.dev, &idx))
+ if (!drm_dev_enter(drm, &idx))
return;
DRM_DEBUG_KMS("\n");
@@ -109,7 +135,7 @@ static void st7735r_pipe_enable(struct drm_simple_display_pipe *pipe,
break;
}
- if (priv->cfg->rgb)
+ if (st7735r->cfg->rgb)
addr_mode |= ST7735R_RGB;
mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode);
@@ -129,13 +155,40 @@ static void st7735r_pipe_enable(struct drm_simple_display_pipe *pipe,
msleep(20);
- mipi_dbi_enable_flush(dbidev, crtc_state, plane_state);
+ backlight_enable(dbidev->backlight);
out_exit:
drm_dev_exit(idx);
}
-static const struct drm_simple_display_pipe_funcs st7735r_pipe_funcs = {
- DRM_MIPI_DBI_SIMPLE_DISPLAY_PIPE_FUNCS(st7735r_pipe_enable),
+static const struct drm_crtc_helper_funcs st7735r_crtc_helper_funcs = {
+ DRM_MIPI_DBI_CRTC_HELPER_FUNCS,
+ .atomic_enable = st7735r_crtc_helper_atomic_enable,
+};
+
+static const struct drm_crtc_funcs st7735r_crtc_funcs = {
+ DRM_MIPI_DBI_CRTC_FUNCS,
+ .destroy = drm_crtc_cleanup,
+};
+
+static const struct drm_encoder_funcs st7735r_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
+static const struct drm_connector_helper_funcs st7735r_connector_helper_funcs = {
+ DRM_MIPI_DBI_CONNECTOR_HELPER_FUNCS,
+};
+
+static const struct drm_connector_funcs st7735r_connector_funcs = {
+ DRM_MIPI_DBI_CONNECTOR_FUNCS,
+ .destroy = drm_connector_cleanup,
+};
+
+static const struct drm_mode_config_helper_funcs st7735r_mode_config_helper_funcs = {
+ DRM_MIPI_DBI_MODE_CONFIG_HELPER_FUNCS,
+};
+
+static const struct drm_mode_config_funcs st7735r_mode_config_funcs = {
+ DRM_MIPI_DBI_MODE_CONFIG_FUNCS,
};
static const struct st7735r_cfg jd_t18003_t01_cfg = {
@@ -184,10 +237,14 @@ static int st7735r_probe(struct spi_device *spi)
struct device *dev = &spi->dev;
const struct st7735r_cfg *cfg;
struct mipi_dbi_dev *dbidev;
- struct st7735r_priv *priv;
+ struct st7735r_device *st7735r;
struct drm_device *drm;
struct mipi_dbi *dbi;
struct gpio_desc *dc;
+ struct drm_plane *plane;
+ struct drm_crtc *crtc;
+ struct drm_encoder *encoder;
+ struct drm_connector *connector;
u32 rotation = 0;
int ret;
@@ -195,13 +252,12 @@ static int st7735r_probe(struct spi_device *spi)
if (!cfg)
cfg = (void *)spi_get_device_id(spi)->driver_data;
- priv = devm_drm_dev_alloc(dev, &st7735r_driver,
- struct st7735r_priv, dbidev.drm);
- if (IS_ERR(priv))
- return PTR_ERR(priv);
+ st7735r = devm_drm_dev_alloc(dev, &st7735r_driver, struct st7735r_device, dbidev.drm);
+ if (IS_ERR(st7735r))
+ return PTR_ERR(st7735r);
- dbidev = &priv->dbidev;
- priv->cfg = cfg;
+ dbidev = &st7735r->dbidev;
+ st7735r->cfg = cfg;
dbi = &dbidev->dbi;
drm = &dbidev->drm;
@@ -230,8 +286,52 @@ static int st7735r_probe(struct spi_device *spi)
dbidev->left_offset = cfg->left_offset;
dbidev->top_offset = cfg->top_offset;
- ret = mipi_dbi_dev_init(dbidev, &st7735r_pipe_funcs, &cfg->mode,
- rotation);
+ ret = drm_mipi_dbi_dev_init(dbidev, &cfg->mode, st7735r_plane_formats[0], rotation, 0);
+ if (ret)
+ return ret;
+
+ ret = drmm_mode_config_init(drm);
+ if (ret)
+ return ret;
+
+ drm->mode_config.min_width = dbidev->mode.hdisplay;
+ drm->mode_config.max_width = dbidev->mode.hdisplay;
+ drm->mode_config.min_height = dbidev->mode.vdisplay;
+ drm->mode_config.max_height = dbidev->mode.vdisplay;
+ drm->mode_config.funcs = &st7735r_mode_config_funcs;
+ drm->mode_config.preferred_depth = 16;
+ drm->mode_config.helper_private = &st7735r_mode_config_helper_funcs;
+
+ plane = &st7735r->plane;
+ ret = drm_universal_plane_init(drm, plane, 0, &st7735r_plane_funcs,
+ st7735r_plane_formats, ARRAY_SIZE(st7735r_plane_formats),
+ st7735r_plane_format_modifiers,
+ DRM_PLANE_TYPE_PRIMARY, NULL);
+ if (ret)
+ return ret;
+ drm_plane_helper_add(plane, &st7735r_plane_helper_funcs);
+ drm_plane_enable_fb_damage_clips(plane);
+
+ crtc = &st7735r->crtc;
+ ret = drm_crtc_init_with_planes(drm, crtc, plane, NULL, &st7735r_crtc_funcs, NULL);
+ if (ret)
+ return ret;
+ drm_crtc_helper_add(crtc, &st7735r_crtc_helper_funcs);
+
+ encoder = &st7735r->encoder;
+ ret = drm_encoder_init(drm, encoder, &st7735r_encoder_funcs, DRM_MODE_ENCODER_NONE, NULL);
+ if (ret)
+ return ret;
+ encoder->possible_crtcs = drm_crtc_mask(crtc);
+
+ connector = &st7735r->connector;
+ ret = drm_connector_init(drm, connector, &st7735r_connector_funcs,
+ DRM_MODE_CONNECTOR_SPI);
+ if (ret)
+ return ret;
+ drm_connector_helper_add(connector, &st7735r_connector_helper_funcs);
+
+ ret = drm_connector_attach_encoder(connector, encoder);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c
index 6391bdc94a5c..bc35dad53b07 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.c
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.c
@@ -798,18 +798,21 @@ static int sun4i_backend_bind(struct device *dev, struct device *master,
dev_set_drvdata(dev, backend);
spin_lock_init(&backend->frontend_lock);
- if (of_property_present(dev->of_node, "interconnects")) {
- /*
- * This assume we have the same DMA constraints for all our the
- * devices in our pipeline (all the backends, but also the
- * frontends). This sounds bad, but it has always been the case
- * for us, and DRM doesn't do per-device allocation either, so
- * we would need to fix DRM first...
- */
- ret = of_dma_configure(drm->dev, dev->of_node, true);
- if (ret)
- return ret;
- }
+ /*
+ * This assume we have the same DMA constraints for all our the
+ * devices in our pipeline (all the backends, but also the
+ * frontends). This sounds bad, but it has always been the case
+ * for us, and DRM doesn't do per-device allocation either, so
+ * we would need to fix DRM first...
+ *
+ * Always use the first bound backend as the DMA device. While
+ * our device trees always have all backends enabled, some in
+ * the wild may actually have the first one disabled. If both
+ * are enabled, the order in which they are bound is guaranteed
+ * since the driver adds components in order.
+ */
+ if (drm_dev_dma_dev(drm) == drm->dev)
+ drm_dev_set_dma_dev(drm, dev);
backend->engine.node = dev->of_node;
backend->engine.ops = &sun4i_backend_engine_ops;
@@ -881,7 +884,8 @@ static int sun4i_backend_bind(struct device *dev, struct device *master,
&sun4i_backend_regmap_config);
if (IS_ERR(backend->engine.regs)) {
dev_err(dev, "Couldn't create the backend regmap\n");
- return PTR_ERR(backend->engine.regs);
+ ret = PTR_ERR(backend->engine.regs);
+ goto err_disable_ram_clk;
}
list_add_tail(&backend->engine.list, &drv->engine_list);
diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
index a50f260c73e4..dd2a78defdb4 100644
--- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
@@ -661,7 +661,7 @@ static int sun4i_hdmi_bind(struct device *dev, struct device *master,
&sun4i_hdmi_hdmi_connector_funcs,
DRM_MODE_CONNECTOR_HDMIA,
hdmi->ddc_i2c,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
8);
if (ret) {
dev_err(dev,
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 02acc7cbdb97..4071ab38b4ae 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -536,18 +536,21 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master,
mixer->engine.ops = &sun8i_engine_ops;
mixer->engine.node = dev->of_node;
- if (of_property_present(dev->of_node, "iommus")) {
- /*
- * This assume we have the same DMA constraints for
- * all our the mixers in our pipeline. This sounds
- * bad, but it has always been the case for us, and
- * DRM doesn't do per-device allocation either, so we
- * would need to fix DRM first...
- */
- ret = of_dma_configure(drm->dev, dev->of_node, true);
- if (ret)
- return ret;
- }
+ /*
+ * This assume we have the same DMA constraints for all our the
+ * devices in our pipeline (all the backends, but also the
+ * frontends). This sounds bad, but it has always been the case
+ * for us, and DRM doesn't do per-device allocation either, so
+ * we would need to fix DRM first...
+ *
+ * Always use the first bound backend as the DMA device. While
+ * our device trees always have all backends enabled, some in
+ * the wild may actually have the first one disabled. If both
+ * are enabled, the order in which they are bound is guaranteed
+ * since the driver adds components in order.
+ */
+ if (drm_dev_dma_dev(drm) == drm->dev)
+ drm_dev_set_dma_dev(drm, dev);
/*
* While this function can fail, we shouldn't do anything
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
index f08f6da55dd0..72c92203ae63 100644
--- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
@@ -124,25 +124,13 @@ static void sun8i_ui_layer_update_buffer(struct sun8i_layer *layer,
{
struct drm_plane_state *state = plane->state;
struct drm_framebuffer *fb = state->fb;
- struct drm_gem_dma_object *gem;
dma_addr_t dma_addr;
u32 ch_base;
- int bpp;
ch_base = sun8i_channel_base(layer);
- /* Get the physical address of the buffer in memory */
- gem = drm_fb_dma_get_gem_obj(fb, 0);
-
- DRM_DEBUG_DRIVER("Using GEM @ %pad\n", &gem->dma_addr);
-
- /* Compute the start of the displayed memory */
- bpp = fb->format->cpp[0];
- dma_addr = gem->dma_addr + fb->offsets[0];
-
- /* Fixup framebuffer address for src coordinates */
- dma_addr += (state->src.x1 >> 16) * bpp;
- dma_addr += (state->src.y1 >> 16) * fb->pitches[0];
+ /* Get the start of the displayed memory */
+ dma_addr = drm_fb_dma_get_gem_addr(fb, state, 0);
/* Set the line width */
DRM_DEBUG_DRIVER("Layer line width: %d bytes\n", fb->pitches[0]);
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
index ca3ab59e108d..cd8d6c2da0c7 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
@@ -197,38 +197,15 @@ static void sun8i_vi_layer_update_buffer(struct sun8i_layer *layer,
struct drm_plane_state *state = plane->state;
struct drm_framebuffer *fb = state->fb;
const struct drm_format_info *format = fb->format;
- struct drm_gem_dma_object *gem;
- u32 dx, dy, src_x, src_y;
dma_addr_t dma_addr;
u32 ch_base;
int i;
ch_base = sun8i_channel_base(layer);
- /* Adjust x and y to be dividable by subsampling factor */
- src_x = (state->src.x1 >> 16) & ~(format->hsub - 1);
- src_y = (state->src.y1 >> 16) & ~(format->vsub - 1);
-
for (i = 0; i < format->num_planes; i++) {
- /* Get the physical address of the buffer in memory */
- gem = drm_fb_dma_get_gem_obj(fb, i);
-
- DRM_DEBUG_DRIVER("Using GEM @ %pad\n", &gem->dma_addr);
-
- /* Compute the start of the displayed memory */
- dma_addr = gem->dma_addr + fb->offsets[i];
-
- dx = src_x;
- dy = src_y;
-
- if (i > 0) {
- dx /= format->hsub;
- dy /= format->vsub;
- }
-
- /* Fixup framebuffer address for src coordinates */
- dma_addr += dx * format->cpp[i];
- dma_addr += dy * fb->pitches[i];
+ /* Get the start of the displayed memory */
+ dma_addr = drm_fb_dma_get_gem_addr(fb, state, i);
/* Set the line width */
DRM_DEBUG_DRIVER("Layer %d. line width: %d bytes\n",
diff --git a/drivers/gpu/drm/sysfb/efidrm.c b/drivers/gpu/drm/sysfb/efidrm.c
index 1114359a1e62..a335c94a7bd7 100644
--- a/drivers/gpu/drm/sysfb/efidrm.c
+++ b/drivers/gpu/drm/sysfb/efidrm.c
@@ -157,7 +157,6 @@ static struct efidrm_device *efidrm_device_create(struct drm_driver *drv,
struct drm_sysfb_device *sysfb;
struct drm_device *dev;
struct resource *mem = NULL;
- void __iomem *screen_base = NULL;
struct drm_plane *primary_plane;
struct drm_crtc *crtc;
struct drm_encoder *encoder;
@@ -244,21 +243,38 @@ static struct efidrm_device *efidrm_device_create(struct drm_driver *drv,
mem_flags = efidrm_get_mem_flags(dev, res->start, vsize);
- if (mem_flags & EFI_MEMORY_WC)
- screen_base = devm_ioremap_wc(&pdev->dev, mem->start, resource_size(mem));
- else if (mem_flags & EFI_MEMORY_UC)
- screen_base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
- else if (mem_flags & EFI_MEMORY_WT)
- screen_base = devm_memremap(&pdev->dev, mem->start, resource_size(mem),
- MEMREMAP_WT);
- else if (mem_flags & EFI_MEMORY_WB)
- screen_base = devm_memremap(&pdev->dev, mem->start, resource_size(mem),
- MEMREMAP_WB);
- else
+ if (mem_flags & EFI_MEMORY_WC) {
+ void __iomem *screen_base = devm_ioremap_wc(&pdev->dev, mem->start,
+ resource_size(mem));
+
+ if (!screen_base)
+ return ERR_PTR(-ENXIO);
+ iosys_map_set_vaddr_iomem(&sysfb->fb_addr, screen_base);
+ } else if (mem_flags & EFI_MEMORY_UC) {
+ void __iomem *screen_base = devm_ioremap(&pdev->dev, mem->start,
+ resource_size(mem));
+
+ if (!screen_base)
+ return ERR_PTR(-ENXIO);
+ iosys_map_set_vaddr_iomem(&sysfb->fb_addr, screen_base);
+ } else if (mem_flags & EFI_MEMORY_WT) {
+ void *screen_base = devm_memremap(&pdev->dev, mem->start,
+ resource_size(mem), MEMREMAP_WT);
+
+ if (IS_ERR(screen_base))
+ return ERR_CAST(screen_base);
+ iosys_map_set_vaddr(&sysfb->fb_addr, screen_base);
+ } else if (mem_flags & EFI_MEMORY_WB) {
+ void *screen_base = devm_memremap(&pdev->dev, mem->start,
+ resource_size(mem), MEMREMAP_WB);
+
+ if (IS_ERR(screen_base))
+ return ERR_CAST(screen_base);
+ iosys_map_set_vaddr(&sysfb->fb_addr, screen_base);
+ } else {
drm_err(dev, "invalid mem_flags: 0x%llx\n", mem_flags);
- if (!screen_base)
- return ERR_PTR(-ENOMEM);
- iosys_map_set_vaddr_iomem(&sysfb->fb_addr, screen_base);
+ return ERR_PTR(-EINVAL);
+ }
/*
* Modesetting
diff --git a/drivers/gpu/drm/tegra/hub.c b/drivers/gpu/drm/tegra/hub.c
index a6fa196c2813..10d993b8d043 100644
--- a/drivers/gpu/drm/tegra/hub.c
+++ b/drivers/gpu/drm/tegra/hub.c
@@ -825,7 +825,22 @@ static void tegra_display_hub_destroy_state(struct drm_private_obj *obj,
kfree(hub_state);
}
+static struct drm_private_state *
+tegra_display_hub_create_state(struct drm_private_obj *obj)
+{
+ struct tegra_display_hub_state *hub_state;
+
+ hub_state = kzalloc_obj(*hub_state);
+ if (!hub_state)
+ return ERR_PTR(-ENOMEM);
+
+ __drm_atomic_helper_private_obj_create_state(obj, &hub_state->base);
+
+ return &hub_state->base;
+}
+
static const struct drm_private_state_funcs tegra_display_hub_state_funcs = {
+ .atomic_create_state = tegra_display_hub_create_state,
.atomic_duplicate_state = tegra_display_hub_duplicate_state,
.atomic_destroy_state = tegra_display_hub_destroy_state,
};
@@ -941,13 +956,8 @@ static int tegra_display_hub_init(struct host1x_client *client)
struct tegra_display_hub *hub = to_tegra_display_hub(client);
struct drm_device *drm = dev_get_drvdata(client->host);
struct tegra_drm *tegra = drm->dev_private;
- struct tegra_display_hub_state *state;
-
- state = kzalloc_obj(*state);
- if (!state)
- return -ENOMEM;
- drm_atomic_private_obj_init(drm, &hub->base, &state->base,
+ drm_atomic_private_obj_init(drm, &hub->base,
&tegra_display_hub_state_funcs);
tegra->hub = hub;
diff --git a/drivers/gpu/drm/tests/drm_connector_test.c b/drivers/gpu/drm/tests/drm_connector_test.c
index 86860ad0861c..beb1d50a6646 100644
--- a/drivers/gpu/drm/tests/drm_connector_test.c
+++ b/drivers/gpu/drm/tests/drm_connector_test.c
@@ -675,7 +675,7 @@ static void drm_test_connector_hdmi_init_valid(struct kunit *test)
&dummy_hdmi_funcs,
DRM_MODE_CONNECTOR_HDMIA,
&priv->ddc,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
8);
KUNIT_EXPECT_EQ(test, ret, 0);
}
@@ -695,7 +695,7 @@ static void drm_test_connector_hdmi_init_null_ddc(struct kunit *test)
&dummy_hdmi_funcs,
DRM_MODE_CONNECTOR_HDMIA,
NULL,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
8);
KUNIT_EXPECT_EQ(test, ret, 0);
}
@@ -715,7 +715,7 @@ static void drm_test_connector_hdmi_init_null_vendor(struct kunit *test)
&dummy_hdmi_funcs,
DRM_MODE_CONNECTOR_HDMIA,
&priv->ddc,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
8);
KUNIT_EXPECT_LT(test, ret, 0);
}
@@ -735,7 +735,7 @@ static void drm_test_connector_hdmi_init_null_product(struct kunit *test)
&dummy_hdmi_funcs,
DRM_MODE_CONNECTOR_HDMIA,
&priv->ddc,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
8);
KUNIT_EXPECT_LT(test, ret, 0);
}
@@ -761,7 +761,7 @@ static void drm_test_connector_hdmi_init_product_valid(struct kunit *test)
&dummy_hdmi_funcs,
DRM_MODE_CONNECTOR_HDMIA,
&priv->ddc,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
8);
KUNIT_EXPECT_EQ(test, ret, 0);
KUNIT_EXPECT_MEMEQ(test,
@@ -794,7 +794,7 @@ static void drm_test_connector_hdmi_init_product_length_exact(struct kunit *test
&dummy_hdmi_funcs,
DRM_MODE_CONNECTOR_HDMIA,
&priv->ddc,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
8);
KUNIT_EXPECT_EQ(test, ret, 0);
KUNIT_EXPECT_MEMEQ(test,
@@ -821,7 +821,7 @@ static void drm_test_connector_hdmi_init_product_length_too_long(struct kunit *t
&dummy_hdmi_funcs,
DRM_MODE_CONNECTOR_HDMIA,
&priv->ddc,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
8);
KUNIT_EXPECT_LT(test, ret, 0);
}
@@ -847,7 +847,7 @@ static void drm_test_connector_hdmi_init_vendor_valid(struct kunit *test)
&dummy_hdmi_funcs,
DRM_MODE_CONNECTOR_HDMIA,
&priv->ddc,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
8);
KUNIT_EXPECT_EQ(test, ret, 0);
KUNIT_EXPECT_MEMEQ(test,
@@ -879,7 +879,7 @@ static void drm_test_connector_hdmi_init_vendor_length_exact(struct kunit *test)
&dummy_hdmi_funcs,
DRM_MODE_CONNECTOR_HDMIA,
&priv->ddc,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
8);
KUNIT_EXPECT_EQ(test, ret, 0);
KUNIT_EXPECT_MEMEQ(test,
@@ -906,7 +906,7 @@ static void drm_test_connector_hdmi_init_vendor_length_too_long(struct kunit *te
&dummy_hdmi_funcs,
DRM_MODE_CONNECTOR_HDMIA,
&priv->ddc,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
8);
KUNIT_EXPECT_LT(test, ret, 0);
}
@@ -926,7 +926,7 @@ static void drm_test_connector_hdmi_init_bpc_invalid(struct kunit *test)
&dummy_hdmi_funcs,
DRM_MODE_CONNECTOR_HDMIA,
&priv->ddc,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
9);
KUNIT_EXPECT_LT(test, ret, 0);
}
@@ -946,7 +946,7 @@ static void drm_test_connector_hdmi_init_bpc_null(struct kunit *test)
&dummy_hdmi_funcs,
DRM_MODE_CONNECTOR_HDMIA,
&priv->ddc,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
0);
KUNIT_EXPECT_LT(test, ret, 0);
}
@@ -971,7 +971,7 @@ static void drm_test_connector_hdmi_init_bpc_8(struct kunit *test)
&dummy_hdmi_funcs,
DRM_MODE_CONNECTOR_HDMIA,
&priv->ddc,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
8);
KUNIT_EXPECT_EQ(test, ret, 0);
@@ -1012,7 +1012,7 @@ static void drm_test_connector_hdmi_init_bpc_10(struct kunit *test)
&dummy_hdmi_funcs,
DRM_MODE_CONNECTOR_HDMIA,
&priv->ddc,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
10);
KUNIT_EXPECT_EQ(test, ret, 0);
@@ -1053,7 +1053,7 @@ static void drm_test_connector_hdmi_init_bpc_12(struct kunit *test)
&dummy_hdmi_funcs,
DRM_MODE_CONNECTOR_HDMIA,
&priv->ddc,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
12);
KUNIT_EXPECT_EQ(test, ret, 0);
@@ -1109,7 +1109,7 @@ static void drm_test_connector_hdmi_init_formats_no_rgb(struct kunit *test)
&dummy_hdmi_funcs,
DRM_MODE_CONNECTOR_HDMIA,
&priv->ddc,
- BIT(HDMI_COLORSPACE_YUV422),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422),
8);
KUNIT_EXPECT_LT(test, ret, 0);
}
@@ -1122,17 +1122,17 @@ struct drm_connector_hdmi_init_formats_yuv420_allowed_test {
#define YUV420_ALLOWED_TEST(_formats, _allowed, _result) \
{ \
- .supported_formats = BIT(HDMI_COLORSPACE_RGB) | (_formats), \
+ .supported_formats = BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444) | (_formats), \
.yuv420_allowed = _allowed, \
.expected_result = _result, \
}
static const struct drm_connector_hdmi_init_formats_yuv420_allowed_test
drm_connector_hdmi_init_formats_yuv420_allowed_tests[] = {
- YUV420_ALLOWED_TEST(BIT(HDMI_COLORSPACE_YUV420), true, 0),
- YUV420_ALLOWED_TEST(BIT(HDMI_COLORSPACE_YUV420), false, -EINVAL),
- YUV420_ALLOWED_TEST(BIT(HDMI_COLORSPACE_YUV422), true, -EINVAL),
- YUV420_ALLOWED_TEST(BIT(HDMI_COLORSPACE_YUV422), false, 0),
+ YUV420_ALLOWED_TEST(BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420), true, 0),
+ YUV420_ALLOWED_TEST(BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420), false, -EINVAL),
+ YUV420_ALLOWED_TEST(BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422), true, -EINVAL),
+ YUV420_ALLOWED_TEST(BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422), false, 0),
};
static void
@@ -1188,7 +1188,7 @@ static void drm_test_connector_hdmi_init_type_valid(struct kunit *test)
&dummy_hdmi_funcs,
connector_type,
&priv->ddc,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
8);
KUNIT_EXPECT_EQ(test, ret, 0);
}
@@ -1223,7 +1223,7 @@ static void drm_test_connector_hdmi_init_type_invalid(struct kunit *test)
&dummy_hdmi_funcs,
connector_type,
&priv->ddc,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
8);
KUNIT_EXPECT_LT(test, ret, 0);
}
@@ -1432,10 +1432,10 @@ static void drm_test_drm_hdmi_connector_get_output_format_name(struct kunit *tes
static const
struct drm_hdmi_connector_get_output_format_name_test
drm_hdmi_connector_get_output_format_name_valid_tests[] = {
- OUTPUT_FORMAT_TEST(HDMI_COLORSPACE_RGB, "RGB"),
- OUTPUT_FORMAT_TEST(HDMI_COLORSPACE_YUV420, "YUV 4:2:0"),
- OUTPUT_FORMAT_TEST(HDMI_COLORSPACE_YUV422, "YUV 4:2:2"),
- OUTPUT_FORMAT_TEST(HDMI_COLORSPACE_YUV444, "YUV 4:4:4"),
+ OUTPUT_FORMAT_TEST(DRM_OUTPUT_COLOR_FORMAT_RGB444, "RGB"),
+ OUTPUT_FORMAT_TEST(DRM_OUTPUT_COLOR_FORMAT_YCBCR420, "YUV 4:2:0"),
+ OUTPUT_FORMAT_TEST(DRM_OUTPUT_COLOR_FORMAT_YCBCR422, "YUV 4:2:2"),
+ OUTPUT_FORMAT_TEST(DRM_OUTPUT_COLOR_FORMAT_YCBCR444, "YUV 4:4:4"),
};
static void
@@ -1500,7 +1500,7 @@ static void drm_test_drm_connector_attach_broadcast_rgb_property_hdmi_connector(
&dummy_hdmi_funcs,
DRM_MODE_CONNECTOR_HDMIA,
&priv->ddc,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
8);
KUNIT_EXPECT_EQ(test, ret, 0);
@@ -1540,7 +1540,7 @@ static void drm_test_drm_hdmi_compute_mode_clock_rgb(struct kunit *test)
KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
- rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_RGB);
+ rate = drm_hdmi_compute_mode_clock(mode, 8, DRM_OUTPUT_COLOR_FORMAT_RGB444);
KUNIT_ASSERT_GT(test, rate, 0);
KUNIT_EXPECT_EQ(test, mode->clock * 1000ULL, rate);
}
@@ -1561,7 +1561,7 @@ static void drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc(struct kunit *test)
KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
- rate = drm_hdmi_compute_mode_clock(mode, 10, HDMI_COLORSPACE_RGB);
+ rate = drm_hdmi_compute_mode_clock(mode, 10, DRM_OUTPUT_COLOR_FORMAT_RGB444);
KUNIT_ASSERT_GT(test, rate, 0);
KUNIT_EXPECT_EQ(test, mode->clock * 1250, rate);
}
@@ -1580,7 +1580,7 @@ static void drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc_vic_1(struct kunit *t
mode = drm_kunit_display_mode_from_cea_vic(test, drm, 1);
KUNIT_ASSERT_NOT_NULL(test, mode);
- rate = drm_hdmi_compute_mode_clock(mode, 10, HDMI_COLORSPACE_RGB);
+ rate = drm_hdmi_compute_mode_clock(mode, 10, DRM_OUTPUT_COLOR_FORMAT_RGB444);
KUNIT_EXPECT_EQ(test, rate, 0);
}
@@ -1600,7 +1600,7 @@ static void drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc(struct kunit *test)
KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
- rate = drm_hdmi_compute_mode_clock(mode, 12, HDMI_COLORSPACE_RGB);
+ rate = drm_hdmi_compute_mode_clock(mode, 12, DRM_OUTPUT_COLOR_FORMAT_RGB444);
KUNIT_ASSERT_GT(test, rate, 0);
KUNIT_EXPECT_EQ(test, mode->clock * 1500, rate);
}
@@ -1619,7 +1619,7 @@ static void drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc_vic_1(struct kunit *t
mode = drm_kunit_display_mode_from_cea_vic(test, drm, 1);
KUNIT_ASSERT_NOT_NULL(test, mode);
- rate = drm_hdmi_compute_mode_clock(mode, 12, HDMI_COLORSPACE_RGB);
+ rate = drm_hdmi_compute_mode_clock(mode, 12, DRM_OUTPUT_COLOR_FORMAT_RGB444);
KUNIT_EXPECT_EQ(test, rate, 0);
}
@@ -1639,7 +1639,7 @@ static void drm_test_drm_hdmi_compute_mode_clock_rgb_double(struct kunit *test)
KUNIT_ASSERT_TRUE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
- rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_RGB);
+ rate = drm_hdmi_compute_mode_clock(mode, 8, DRM_OUTPUT_COLOR_FORMAT_RGB444);
KUNIT_ASSERT_GT(test, rate, 0);
KUNIT_EXPECT_EQ(test, (mode->clock * 1000ULL) * 2, rate);
}
@@ -1662,7 +1662,7 @@ static void drm_test_connector_hdmi_compute_mode_clock_yuv420_valid(struct kunit
KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
- rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_YUV420);
+ rate = drm_hdmi_compute_mode_clock(mode, 8, DRM_OUTPUT_COLOR_FORMAT_YCBCR420);
KUNIT_ASSERT_GT(test, rate, 0);
KUNIT_EXPECT_EQ(test, (mode->clock * 1000ULL) / 2, rate);
}
@@ -1699,7 +1699,7 @@ static void drm_test_connector_hdmi_compute_mode_clock_yuv420_10_bpc(struct kuni
KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
- rate = drm_hdmi_compute_mode_clock(mode, 10, HDMI_COLORSPACE_YUV420);
+ rate = drm_hdmi_compute_mode_clock(mode, 10, DRM_OUTPUT_COLOR_FORMAT_YCBCR420);
KUNIT_ASSERT_GT(test, rate, 0);
KUNIT_EXPECT_EQ(test, mode->clock * 625, rate);
@@ -1724,7 +1724,7 @@ static void drm_test_connector_hdmi_compute_mode_clock_yuv420_12_bpc(struct kuni
KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
- rate = drm_hdmi_compute_mode_clock(mode, 12, HDMI_COLORSPACE_YUV420);
+ rate = drm_hdmi_compute_mode_clock(mode, 12, DRM_OUTPUT_COLOR_FORMAT_YCBCR420);
KUNIT_ASSERT_GT(test, rate, 0);
KUNIT_EXPECT_EQ(test, mode->clock * 750, rate);
@@ -1747,7 +1747,7 @@ static void drm_test_connector_hdmi_compute_mode_clock_yuv422_8_bpc(struct kunit
KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
- rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_YUV422);
+ rate = drm_hdmi_compute_mode_clock(mode, 8, DRM_OUTPUT_COLOR_FORMAT_YCBCR422);
KUNIT_ASSERT_GT(test, rate, 0);
KUNIT_EXPECT_EQ(test, mode->clock * 1000, rate);
}
@@ -1769,7 +1769,7 @@ static void drm_test_connector_hdmi_compute_mode_clock_yuv422_10_bpc(struct kuni
KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
- rate = drm_hdmi_compute_mode_clock(mode, 10, HDMI_COLORSPACE_YUV422);
+ rate = drm_hdmi_compute_mode_clock(mode, 10, DRM_OUTPUT_COLOR_FORMAT_YCBCR422);
KUNIT_ASSERT_GT(test, rate, 0);
KUNIT_EXPECT_EQ(test, mode->clock * 1000, rate);
}
@@ -1791,7 +1791,7 @@ static void drm_test_connector_hdmi_compute_mode_clock_yuv422_12_bpc(struct kuni
KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
- rate = drm_hdmi_compute_mode_clock(mode, 12, HDMI_COLORSPACE_YUV422);
+ rate = drm_hdmi_compute_mode_clock(mode, 12, DRM_OUTPUT_COLOR_FORMAT_YCBCR422);
KUNIT_ASSERT_GT(test, rate, 0);
KUNIT_EXPECT_EQ(test, mode->clock * 1000, rate);
}
diff --git a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c
index 4bdcea3c7435..a4357efaa983 100644
--- a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c
+++ b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c
@@ -239,7 +239,7 @@ __connector_hdmi_init(struct kunit *test,
enc->possible_crtcs = drm_crtc_mask(priv->crtc);
conn = &priv->connector;
- conn->ycbcr_420_allowed = !!(formats & BIT(HDMI_COLORSPACE_YUV420));
+ conn->ycbcr_420_allowed = !!(formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420));
ret = drmm_connector_hdmi_init(drm, conn,
"Vendor", "Product",
@@ -300,7 +300,7 @@ static void drm_test_check_broadcast_rgb_crtc_mode_changed(struct kunit *test)
int ret;
priv = drm_kunit_helper_connector_hdmi_init(test,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
8);
KUNIT_ASSERT_NOT_NULL(test, priv);
@@ -375,7 +375,7 @@ static void drm_test_check_broadcast_rgb_crtc_mode_not_changed(struct kunit *tes
int ret;
priv = drm_kunit_helper_connector_hdmi_init(test,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
8);
KUNIT_ASSERT_NOT_NULL(test, priv);
@@ -450,7 +450,7 @@ static void drm_test_check_broadcast_rgb_auto_cea_mode(struct kunit *test)
int ret;
priv = drm_kunit_helper_connector_hdmi_init(test,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
8);
KUNIT_ASSERT_NOT_NULL(test, priv);
@@ -517,7 +517,7 @@ static void drm_test_check_broadcast_rgb_auto_cea_mode_vic_1(struct kunit *test)
int ret;
priv = drm_kunit_helper_connector_hdmi_init(test,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
8);
KUNIT_ASSERT_NOT_NULL(test, priv);
@@ -584,7 +584,7 @@ static void drm_test_check_broadcast_rgb_full_cea_mode(struct kunit *test)
int ret;
priv = drm_kunit_helper_connector_hdmi_init(test,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
8);
KUNIT_ASSERT_NOT_NULL(test, priv);
@@ -653,7 +653,7 @@ static void drm_test_check_broadcast_rgb_full_cea_mode_vic_1(struct kunit *test)
int ret;
priv = drm_kunit_helper_connector_hdmi_init(test,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
8);
KUNIT_ASSERT_NOT_NULL(test, priv);
@@ -722,7 +722,7 @@ static void drm_test_check_broadcast_rgb_limited_cea_mode(struct kunit *test)
int ret;
priv = drm_kunit_helper_connector_hdmi_init(test,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
8);
KUNIT_ASSERT_NOT_NULL(test, priv);
@@ -791,7 +791,7 @@ static void drm_test_check_broadcast_rgb_limited_cea_mode_vic_1(struct kunit *te
int ret;
priv = drm_kunit_helper_connector_hdmi_init(test,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
8);
KUNIT_ASSERT_NOT_NULL(test, priv);
@@ -863,8 +863,8 @@ static void drm_test_check_broadcast_rgb_cea_mode_yuv420(struct kunit *test)
broadcast_rgb = *(enum drm_hdmi_broadcast_rgb *)test->param_value;
priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
- BIT(HDMI_COLORSPACE_RGB) |
- BIT(HDMI_COLORSPACE_YUV420),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444) |
+ BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420),
8,
&dummy_connector_hdmi_funcs,
test_edid_hdmi_1080p_rgb_yuv_4k_yuv420_dc_max_200mhz);
@@ -918,7 +918,7 @@ retry_conn_state:
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
KUNIT_ASSERT_EQ(test, conn_state->hdmi.broadcast_rgb, broadcast_rgb);
- KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_YUV420);
+ KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_format, DRM_OUTPUT_COLOR_FORMAT_YCBCR420);
KUNIT_EXPECT_TRUE(test, conn_state->hdmi.is_limited_range);
@@ -963,7 +963,7 @@ static void drm_test_check_output_bpc_crtc_mode_changed(struct kunit *test)
int ret;
priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
10,
&dummy_connector_hdmi_funcs,
test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz);
@@ -1045,7 +1045,7 @@ static void drm_test_check_output_bpc_crtc_mode_not_changed(struct kunit *test)
int ret;
priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
10,
&dummy_connector_hdmi_funcs,
test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz);
@@ -1122,9 +1122,9 @@ static void drm_test_check_output_bpc_dvi(struct kunit *test)
int ret;
priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
- BIT(HDMI_COLORSPACE_RGB) |
- BIT(HDMI_COLORSPACE_YUV422) |
- BIT(HDMI_COLORSPACE_YUV444),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444) |
+ BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422) |
+ BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444),
12,
&dummy_connector_hdmi_funcs,
test_edid_dvi_1080p);
@@ -1157,7 +1157,7 @@ retry_conn_enable:
KUNIT_ASSERT_NOT_NULL(test, conn_state);
KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 8);
- KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
+ KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, DRM_OUTPUT_COLOR_FORMAT_RGB444);
drm_modeset_drop_locks(&ctx);
drm_modeset_acquire_fini(&ctx);
@@ -1179,7 +1179,7 @@ static void drm_test_check_tmds_char_rate_rgb_8bpc(struct kunit *test)
int ret;
priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
8,
&dummy_connector_hdmi_funcs,
test_edid_hdmi_1080p_rgb_max_200mhz);
@@ -1210,7 +1210,7 @@ retry_conn_enable:
KUNIT_ASSERT_NOT_NULL(test, conn_state);
KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_bpc, 8);
- KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
+ KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_format, DRM_OUTPUT_COLOR_FORMAT_RGB444);
KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, preferred->clock * 1000);
drm_modeset_drop_locks(&ctx);
@@ -1234,7 +1234,7 @@ static void drm_test_check_tmds_char_rate_rgb_10bpc(struct kunit *test)
int ret;
priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
10,
&dummy_connector_hdmi_funcs,
test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz);
@@ -1265,7 +1265,7 @@ retry_conn_enable:
KUNIT_ASSERT_NOT_NULL(test, conn_state);
KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_bpc, 10);
- KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
+ KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_format, DRM_OUTPUT_COLOR_FORMAT_RGB444);
KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, preferred->clock * 1250);
drm_modeset_drop_locks(&ctx);
@@ -1289,7 +1289,7 @@ static void drm_test_check_tmds_char_rate_rgb_12bpc(struct kunit *test)
int ret;
priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
12,
&dummy_connector_hdmi_funcs,
test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz);
@@ -1320,7 +1320,7 @@ retry_conn_enable:
KUNIT_ASSERT_NOT_NULL(test, conn_state);
KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_bpc, 12);
- KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
+ KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_format, DRM_OUTPUT_COLOR_FORMAT_RGB444);
KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, preferred->clock * 1500);
drm_modeset_drop_locks(&ctx);
@@ -1348,7 +1348,7 @@ static void drm_test_check_hdmi_funcs_reject_rate(struct kunit *test)
int ret;
priv = drm_kunit_helper_connector_hdmi_init(test,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
8);
KUNIT_ASSERT_NOT_NULL(test, priv);
@@ -1416,7 +1416,7 @@ static void drm_test_check_max_tmds_rate_bpc_fallback_rgb(struct kunit *test)
int ret;
priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
12,
&dummy_connector_hdmi_funcs,
test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz);
@@ -1433,10 +1433,10 @@ static void drm_test_check_max_tmds_rate_bpc_fallback_rgb(struct kunit *test)
KUNIT_ASSERT_NOT_NULL(test, preferred);
KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK);
- rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB);
+ rate = drm_hdmi_compute_mode_clock(preferred, 12, DRM_OUTPUT_COLOR_FORMAT_RGB444);
KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000);
- rate = drm_hdmi_compute_mode_clock(preferred, 10, HDMI_COLORSPACE_RGB);
+ rate = drm_hdmi_compute_mode_clock(preferred, 10, DRM_OUTPUT_COLOR_FORMAT_RGB444);
KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
drm_modeset_acquire_init(&ctx, 0);
@@ -1457,7 +1457,7 @@ retry_conn_enable:
KUNIT_ASSERT_NOT_NULL(test, conn_state);
KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 10);
- KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
+ KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, DRM_OUTPUT_COLOR_FORMAT_RGB444);
KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, preferred->clock * 1250);
drm_modeset_drop_locks(&ctx);
@@ -1490,8 +1490,8 @@ static void drm_test_check_max_tmds_rate_bpc_fallback_yuv420(struct kunit *test)
int ret;
priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
- BIT(HDMI_COLORSPACE_RGB) |
- BIT(HDMI_COLORSPACE_YUV420),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444) |
+ BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420),
12,
&dummy_connector_hdmi_funcs,
test_edid_hdmi_1080p_rgb_yuv_4k_yuv420_dc_max_200mhz);
@@ -1509,10 +1509,10 @@ static void drm_test_check_max_tmds_rate_bpc_fallback_yuv420(struct kunit *test)
KUNIT_ASSERT_NOT_NULL(test, yuv420_only_mode);
KUNIT_ASSERT_TRUE(test, drm_mode_is_420_only(info, yuv420_only_mode));
- rate = drm_hdmi_compute_mode_clock(yuv420_only_mode, 12, HDMI_COLORSPACE_YUV420);
+ rate = drm_hdmi_compute_mode_clock(yuv420_only_mode, 12, DRM_OUTPUT_COLOR_FORMAT_YCBCR420);
KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000);
- rate = drm_hdmi_compute_mode_clock(yuv420_only_mode, 10, HDMI_COLORSPACE_YUV420);
+ rate = drm_hdmi_compute_mode_clock(yuv420_only_mode, 10, DRM_OUTPUT_COLOR_FORMAT_YCBCR420);
KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
drm_modeset_acquire_init(&ctx, 0);
@@ -1531,7 +1531,7 @@ retry_conn_enable:
KUNIT_ASSERT_NOT_NULL(test, conn_state);
KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 10);
- KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_YUV420);
+ KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, DRM_OUTPUT_COLOR_FORMAT_YCBCR420);
KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, yuv420_only_mode->clock * 625);
drm_modeset_drop_locks(&ctx);
@@ -1565,9 +1565,9 @@ static void drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv422(struct kunit
int ret;
priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
- BIT(HDMI_COLORSPACE_RGB) |
- BIT(HDMI_COLORSPACE_YUV422) |
- BIT(HDMI_COLORSPACE_YUV444),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444) |
+ BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422) |
+ BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444),
12,
&dummy_connector_hdmi_funcs,
test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz);
@@ -1584,13 +1584,13 @@ static void drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv422(struct kunit
KUNIT_ASSERT_NOT_NULL(test, preferred);
KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK);
- rate = drm_hdmi_compute_mode_clock(preferred, 10, HDMI_COLORSPACE_RGB);
+ rate = drm_hdmi_compute_mode_clock(preferred, 10, DRM_OUTPUT_COLOR_FORMAT_RGB444);
KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
- rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB);
+ rate = drm_hdmi_compute_mode_clock(preferred, 12, DRM_OUTPUT_COLOR_FORMAT_RGB444);
KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000);
- rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_YUV422);
+ rate = drm_hdmi_compute_mode_clock(preferred, 12, DRM_OUTPUT_COLOR_FORMAT_YCBCR422);
KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
drm_modeset_acquire_init(&ctx, 0);
@@ -1611,7 +1611,7 @@ retry_conn_enable:
KUNIT_ASSERT_NOT_NULL(test, conn_state);
KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 10);
- KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
+ KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, DRM_OUTPUT_COLOR_FORMAT_RGB444);
drm_modeset_drop_locks(&ctx);
drm_modeset_acquire_fini(&ctx);
@@ -1644,8 +1644,8 @@ static void drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv420(struct kunit
int ret;
priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
- BIT(HDMI_COLORSPACE_RGB) |
- BIT(HDMI_COLORSPACE_YUV420),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444) |
+ BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420),
12,
&dummy_connector_hdmi_funcs,
test_edid_hdmi_4k_rgb_yuv420_dc_max_340mhz);
@@ -1664,13 +1664,13 @@ static void drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv420(struct kunit
KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK);
KUNIT_ASSERT_TRUE(test, drm_mode_is_420_also(info, preferred));
- rate = drm_hdmi_compute_mode_clock(preferred, 8, HDMI_COLORSPACE_RGB);
+ rate = drm_hdmi_compute_mode_clock(preferred, 8, DRM_OUTPUT_COLOR_FORMAT_RGB444);
KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
- rate = drm_hdmi_compute_mode_clock(preferred, 10, HDMI_COLORSPACE_RGB);
+ rate = drm_hdmi_compute_mode_clock(preferred, 10, DRM_OUTPUT_COLOR_FORMAT_RGB444);
KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000);
- rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_YUV420);
+ rate = drm_hdmi_compute_mode_clock(preferred, 12, DRM_OUTPUT_COLOR_FORMAT_YCBCR420);
KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
drm_modeset_acquire_init(&ctx, 0);
@@ -1689,7 +1689,7 @@ retry_conn_enable:
KUNIT_ASSERT_NOT_NULL(test, conn_state);
KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 8);
- KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
+ KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, DRM_OUTPUT_COLOR_FORMAT_RGB444);
drm_modeset_drop_locks(&ctx);
drm_modeset_acquire_fini(&ctx);
@@ -1715,7 +1715,7 @@ static void drm_test_check_driver_unsupported_fallback_yuv420(struct kunit *test
int ret;
priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
12,
&dummy_connector_hdmi_funcs,
test_edid_hdmi_1080p_rgb_yuv_4k_yuv420_dc_max_200mhz);
@@ -1750,7 +1750,7 @@ retry_conn_enable:
conn_state = conn->state;
KUNIT_ASSERT_NOT_NULL(test, conn_state);
- KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
+ KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, DRM_OUTPUT_COLOR_FORMAT_RGB444);
state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
@@ -1800,9 +1800,9 @@ static void drm_test_check_output_bpc_format_vic_1(struct kunit *test)
int ret;
priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
- BIT(HDMI_COLORSPACE_RGB) |
- BIT(HDMI_COLORSPACE_YUV422) |
- BIT(HDMI_COLORSPACE_YUV444),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444) |
+ BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422) |
+ BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444),
12,
&dummy_connector_hdmi_funcs,
test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz);
@@ -1847,7 +1847,7 @@ retry_conn_enable:
KUNIT_ASSERT_NOT_NULL(test, conn_state);
KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 8);
- KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
+ KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, DRM_OUTPUT_COLOR_FORMAT_RGB444);
drm_modeset_drop_locks(&ctx);
drm_modeset_acquire_fini(&ctx);
@@ -1871,7 +1871,7 @@ static void drm_test_check_output_bpc_format_driver_rgb_only(struct kunit *test)
int ret;
priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
12,
&dummy_connector_hdmi_funcs,
test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz);
@@ -1896,10 +1896,10 @@ static void drm_test_check_output_bpc_format_driver_rgb_only(struct kunit *test)
* But since the driver only supports RGB, we should fallback to
* a lower bpc with RGB.
*/
- rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB);
+ rate = drm_hdmi_compute_mode_clock(preferred, 12, DRM_OUTPUT_COLOR_FORMAT_RGB444);
KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000);
- rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_YUV422);
+ rate = drm_hdmi_compute_mode_clock(preferred, 12, DRM_OUTPUT_COLOR_FORMAT_YCBCR422);
KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
drm_modeset_acquire_init(&ctx, 0);
@@ -1920,7 +1920,7 @@ retry_conn_enable:
KUNIT_ASSERT_NOT_NULL(test, conn_state);
KUNIT_EXPECT_LT(test, conn_state->hdmi.output_bpc, 12);
- KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
+ KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, DRM_OUTPUT_COLOR_FORMAT_RGB444);
drm_modeset_drop_locks(&ctx);
drm_modeset_acquire_fini(&ctx);
@@ -1944,9 +1944,9 @@ static void drm_test_check_output_bpc_format_display_rgb_only(struct kunit *test
int ret;
priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
- BIT(HDMI_COLORSPACE_RGB) |
- BIT(HDMI_COLORSPACE_YUV422) |
- BIT(HDMI_COLORSPACE_YUV444),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444) |
+ BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422) |
+ BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444),
12,
&dummy_connector_hdmi_funcs,
test_edid_hdmi_1080p_rgb_max_200mhz);
@@ -1971,10 +1971,10 @@ static void drm_test_check_output_bpc_format_display_rgb_only(struct kunit *test
* But since the display only supports RGB, we should fallback to
* a lower bpc with RGB.
*/
- rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB);
+ rate = drm_hdmi_compute_mode_clock(preferred, 12, DRM_OUTPUT_COLOR_FORMAT_RGB444);
KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000);
- rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_YUV422);
+ rate = drm_hdmi_compute_mode_clock(preferred, 12, DRM_OUTPUT_COLOR_FORMAT_YCBCR422);
KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
drm_modeset_acquire_init(&ctx, 0);
@@ -1995,7 +1995,7 @@ retry_conn_enable:
KUNIT_ASSERT_NOT_NULL(test, conn_state);
KUNIT_EXPECT_LT(test, conn_state->hdmi.output_bpc, 12);
- KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
+ KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, DRM_OUTPUT_COLOR_FORMAT_RGB444);
drm_modeset_drop_locks(&ctx);
drm_modeset_acquire_fini(&ctx);
@@ -2020,7 +2020,7 @@ static void drm_test_check_output_bpc_format_driver_8bpc_only(struct kunit *test
int ret;
priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
8,
&dummy_connector_hdmi_funcs,
test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz);
@@ -2040,7 +2040,7 @@ static void drm_test_check_output_bpc_format_driver_8bpc_only(struct kunit *test
* We're making sure that we have headroom on the TMDS character
* clock to actually use 12bpc.
*/
- rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB);
+ rate = drm_hdmi_compute_mode_clock(preferred, 12, DRM_OUTPUT_COLOR_FORMAT_RGB444);
KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
drm_modeset_acquire_init(&ctx, 0);
@@ -2061,7 +2061,7 @@ retry_conn_enable:
KUNIT_ASSERT_NOT_NULL(test, conn_state);
KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 8);
- KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
+ KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, DRM_OUTPUT_COLOR_FORMAT_RGB444);
drm_modeset_drop_locks(&ctx);
drm_modeset_acquire_fini(&ctx);
@@ -2086,9 +2086,9 @@ static void drm_test_check_output_bpc_format_display_8bpc_only(struct kunit *tes
int ret;
priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
- BIT(HDMI_COLORSPACE_RGB) |
- BIT(HDMI_COLORSPACE_YUV422) |
- BIT(HDMI_COLORSPACE_YUV444),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444) |
+ BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422) |
+ BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444),
12,
&dummy_connector_hdmi_funcs,
test_edid_hdmi_1080p_rgb_max_340mhz);
@@ -2108,7 +2108,7 @@ static void drm_test_check_output_bpc_format_display_8bpc_only(struct kunit *tes
* We're making sure that we have headroom on the TMDS character
* clock to actually use 12bpc.
*/
- rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB);
+ rate = drm_hdmi_compute_mode_clock(preferred, 12, DRM_OUTPUT_COLOR_FORMAT_RGB444);
KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
drm_modeset_acquire_init(&ctx, 0);
@@ -2129,7 +2129,7 @@ retry_conn_enable:
KUNIT_ASSERT_NOT_NULL(test, conn_state);
KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 8);
- KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
+ KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, DRM_OUTPUT_COLOR_FORMAT_RGB444);
drm_modeset_drop_locks(&ctx);
drm_modeset_acquire_fini(&ctx);
@@ -2150,7 +2150,7 @@ static void drm_test_check_disable_connector(struct kunit *test)
int ret;
priv = drm_kunit_helper_connector_hdmi_init(test,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
8);
KUNIT_ASSERT_NOT_NULL(test, priv);
@@ -2255,7 +2255,7 @@ static void drm_test_check_broadcast_rgb_value(struct kunit *test)
struct drm_connector *conn;
priv = drm_kunit_helper_connector_hdmi_init(test,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
8);
KUNIT_ASSERT_NOT_NULL(test, priv);
@@ -2277,7 +2277,7 @@ static void drm_test_check_bpc_8_value(struct kunit *test)
struct drm_connector *conn;
priv = drm_kunit_helper_connector_hdmi_init(test,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
8);
KUNIT_ASSERT_NOT_NULL(test, priv);
@@ -2301,7 +2301,7 @@ static void drm_test_check_bpc_10_value(struct kunit *test)
struct drm_connector *conn;
priv = drm_kunit_helper_connector_hdmi_init(test,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
10);
KUNIT_ASSERT_NOT_NULL(test, priv);
@@ -2325,7 +2325,7 @@ static void drm_test_check_bpc_12_value(struct kunit *test)
struct drm_connector *conn;
priv = drm_kunit_helper_connector_hdmi_init(test,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
12);
KUNIT_ASSERT_NOT_NULL(test, priv);
@@ -2347,9 +2347,9 @@ static void drm_test_check_format_value(struct kunit *test)
struct drm_connector *conn;
priv = drm_kunit_helper_connector_hdmi_init(test,
- BIT(HDMI_COLORSPACE_RGB) |
- BIT(HDMI_COLORSPACE_YUV422) |
- BIT(HDMI_COLORSPACE_YUV444),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444) |
+ BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422) |
+ BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444),
8);
KUNIT_ASSERT_NOT_NULL(test, priv);
@@ -2369,9 +2369,9 @@ static void drm_test_check_tmds_char_value(struct kunit *test)
struct drm_connector *conn;
priv = drm_kunit_helper_connector_hdmi_init(test,
- BIT(HDMI_COLORSPACE_RGB) |
- BIT(HDMI_COLORSPACE_YUV422) |
- BIT(HDMI_COLORSPACE_YUV444),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444) |
+ BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422) |
+ BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444),
12);
KUNIT_ASSERT_NOT_NULL(test, priv);
@@ -2407,7 +2407,7 @@ static void drm_test_check_mode_valid(struct kunit *test)
struct drm_display_mode *preferred;
priv = drm_kunit_helper_connector_hdmi_init(test,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
8);
KUNIT_ASSERT_NOT_NULL(test, priv);
@@ -2431,7 +2431,7 @@ static void drm_test_check_mode_valid_reject_rate(struct kunit *test)
struct drm_display_mode *preferred;
priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
8,
&reject_100mhz_connector_hdmi_funcs,
test_edid_hdmi_1080p_rgb_max_200mhz);
@@ -2463,7 +2463,7 @@ static void drm_test_check_mode_valid_reject(struct kunit *test)
int ret;
priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
8,
&reject_connector_hdmi_funcs,
no_edid);
@@ -2493,7 +2493,7 @@ static void drm_test_check_mode_valid_reject_max_clock(struct kunit *test)
struct drm_display_mode *preferred;
priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
8,
&dummy_connector_hdmi_funcs,
test_edid_hdmi_1080p_rgb_max_100mhz);
@@ -2540,7 +2540,7 @@ static void drm_test_check_infoframes(struct kunit *test)
int ret;
priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
8,
&dummy_connector_hdmi_funcs,
test_edid_hdmi_1080p_rgb_max_200mhz);
@@ -2643,7 +2643,7 @@ static void drm_test_check_reject_avi_infoframe(struct kunit *test)
int ret;
priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
8,
&reject_avi_infoframe_hdmi_funcs,
test_edid_hdmi_1080p_rgb_max_200mhz);
@@ -2747,7 +2747,7 @@ static void drm_test_check_reject_hdr_infoframe_bpc_8(struct kunit *test)
int ret;
priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
8,
&reject_hdr_infoframe_hdmi_funcs,
test_edid_hdmi_1080p_rgb_max_200mhz_hdr);
@@ -2861,7 +2861,7 @@ static void drm_test_check_reject_hdr_infoframe_bpc_10(struct kunit *test)
int ret;
priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
10,
&reject_hdr_infoframe_hdmi_funcs,
test_edid_hdmi_1080p_rgb_max_200mhz_hdr);
@@ -2996,7 +2996,7 @@ static void drm_test_check_reject_audio_infoframe(struct kunit *test)
int ret;
priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
- BIT(HDMI_COLORSPACE_RGB),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444),
8,
&reject_audio_infoframe_hdmi_funcs,
test_edid_hdmi_1080p_rgb_max_200mhz);
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.c b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
deleted file mode 100644
index 1de3996501f7..000000000000
--- a/drivers/gpu/drm/tilcdc/tilcdc_panel.c
+++ /dev/null
@@ -1,408 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2012 Texas Instruments
- * Author: Rob Clark <robdclark@gmail.com>
- */
-
-#include <linux/backlight.h>
-#include <linux/gpio/consumer.h>
-#include <linux/platform_device.h>
-
-#include <video/display_timing.h>
-#include <video/of_display_timing.h>
-#include <video/videomode.h>
-
-#include <drm/drm_atomic_state_helper.h>
-#include <drm/drm_connector.h>
-#include <drm/drm_modeset_helper_vtables.h>
-#include <drm/drm_probe_helper.h>
-#include <drm/drm_simple_kms_helper.h>
-
-#include "tilcdc_drv.h"
-#include "tilcdc_panel.h"
-
-struct panel_module {
- struct tilcdc_module base;
- struct tilcdc_panel_info *info;
- struct display_timings *timings;
- struct backlight_device *backlight;
- struct gpio_desc *enable_gpio;
-};
-#define to_panel_module(x) container_of(x, struct panel_module, base)
-
-
-/*
- * Encoder:
- */
-
-struct panel_encoder {
- struct drm_encoder base;
- struct panel_module *mod;
-};
-#define to_panel_encoder(x) container_of(x, struct panel_encoder, base)
-
-static void panel_encoder_dpms(struct drm_encoder *encoder, int mode)
-{
- struct panel_encoder *panel_encoder = to_panel_encoder(encoder);
- struct backlight_device *backlight = panel_encoder->mod->backlight;
- struct gpio_desc *gpio = panel_encoder->mod->enable_gpio;
-
- if (backlight) {
- backlight->props.power = mode == DRM_MODE_DPMS_ON ?
- BACKLIGHT_POWER_ON : BACKLIGHT_POWER_OFF;
- backlight_update_status(backlight);
- }
-
- if (gpio)
- gpiod_set_value_cansleep(gpio,
- mode == DRM_MODE_DPMS_ON ? 1 : 0);
-}
-
-static void panel_encoder_prepare(struct drm_encoder *encoder)
-{
- panel_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
-}
-
-static void panel_encoder_commit(struct drm_encoder *encoder)
-{
- panel_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
-}
-
-static void panel_encoder_mode_set(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- /* nothing needed */
-}
-
-static const struct drm_encoder_helper_funcs panel_encoder_helper_funcs = {
- .dpms = panel_encoder_dpms,
- .prepare = panel_encoder_prepare,
- .commit = panel_encoder_commit,
- .mode_set = panel_encoder_mode_set,
-};
-
-static struct drm_encoder *panel_encoder_create(struct drm_device *dev,
- struct panel_module *mod)
-{
- struct panel_encoder *panel_encoder;
- struct drm_encoder *encoder;
- int ret;
-
- panel_encoder = devm_kzalloc(dev->dev, sizeof(*panel_encoder),
- GFP_KERNEL);
- if (!panel_encoder)
- return NULL;
-
- panel_encoder->mod = mod;
-
- encoder = &panel_encoder->base;
- encoder->possible_crtcs = 1;
-
- ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_LVDS);
- if (ret < 0)
- goto fail;
-
- drm_encoder_helper_add(encoder, &panel_encoder_helper_funcs);
-
- return encoder;
-
-fail:
- drm_encoder_cleanup(encoder);
- return NULL;
-}
-
-/*
- * Connector:
- */
-
-struct panel_connector {
- struct drm_connector base;
-
- struct drm_encoder *encoder; /* our connected encoder */
- struct panel_module *mod;
-};
-#define to_panel_connector(x) container_of(x, struct panel_connector, base)
-
-
-static void panel_connector_destroy(struct drm_connector *connector)
-{
- drm_connector_unregister(connector);
- drm_connector_cleanup(connector);
-}
-
-static int panel_connector_get_modes(struct drm_connector *connector)
-{
- struct drm_device *dev = connector->dev;
- struct panel_connector *panel_connector = to_panel_connector(connector);
- struct display_timings *timings = panel_connector->mod->timings;
- int i;
-
- for (i = 0; i < timings->num_timings; i++) {
- struct drm_display_mode *mode;
- struct videomode vm;
-
- if (videomode_from_timings(timings, &vm, i))
- break;
-
- mode = drm_mode_create(dev);
- if (!mode)
- break;
-
- drm_display_mode_from_videomode(&vm, mode);
-
- mode->type = DRM_MODE_TYPE_DRIVER;
-
- if (timings->native_mode == i)
- mode->type |= DRM_MODE_TYPE_PREFERRED;
-
- drm_mode_set_name(mode);
- drm_mode_probed_add(connector, mode);
- }
-
- return i;
-}
-
-static struct drm_encoder *panel_connector_best_encoder(
- struct drm_connector *connector)
-{
- struct panel_connector *panel_connector = to_panel_connector(connector);
- return panel_connector->encoder;
-}
-
-static const struct drm_connector_funcs panel_connector_funcs = {
- .destroy = panel_connector_destroy,
- .fill_modes = drm_helper_probe_single_connector_modes,
- .reset = drm_atomic_helper_connector_reset,
- .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
- .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
-};
-
-static const struct drm_connector_helper_funcs panel_connector_helper_funcs = {
- .get_modes = panel_connector_get_modes,
- .best_encoder = panel_connector_best_encoder,
-};
-
-static struct drm_connector *panel_connector_create(struct drm_device *dev,
- struct panel_module *mod, struct drm_encoder *encoder)
-{
- struct panel_connector *panel_connector;
- struct drm_connector *connector;
- int ret;
-
- panel_connector = devm_kzalloc(dev->dev, sizeof(*panel_connector),
- GFP_KERNEL);
- if (!panel_connector)
- return NULL;
-
- panel_connector->encoder = encoder;
- panel_connector->mod = mod;
-
- connector = &panel_connector->base;
-
- drm_connector_init(dev, connector, &panel_connector_funcs,
- DRM_MODE_CONNECTOR_LVDS);
- drm_connector_helper_add(connector, &panel_connector_helper_funcs);
-
- connector->interlace_allowed = 0;
- connector->doublescan_allowed = 0;
-
- ret = drm_connector_attach_encoder(connector, encoder);
- if (ret)
- goto fail;
-
- return connector;
-
-fail:
- panel_connector_destroy(connector);
- return NULL;
-}
-
-/*
- * Module:
- */
-
-static int panel_modeset_init(struct tilcdc_module *mod, struct drm_device *dev)
-{
- struct panel_module *panel_mod = to_panel_module(mod);
- struct tilcdc_drm_private *priv = dev->dev_private;
- struct drm_encoder *encoder;
- struct drm_connector *connector;
-
- encoder = panel_encoder_create(dev, panel_mod);
- if (!encoder)
- return -ENOMEM;
-
- connector = panel_connector_create(dev, panel_mod, encoder);
- if (!connector)
- return -ENOMEM;
-
- priv->encoders[priv->num_encoders++] = encoder;
- priv->connectors[priv->num_connectors++] = connector;
-
- tilcdc_crtc_set_panel_info(priv->crtc,
- to_panel_encoder(encoder)->mod->info);
-
- return 0;
-}
-
-static const struct tilcdc_module_ops panel_module_ops = {
- .modeset_init = panel_modeset_init,
-};
-
-/*
- * Device:
- */
-
-/* maybe move this somewhere common if it is needed by other outputs? */
-static struct tilcdc_panel_info *of_get_panel_info(struct device_node *np)
-{
- struct device_node *info_np;
- struct tilcdc_panel_info *info;
- int ret = 0;
-
- if (!np) {
- pr_err("%s: no devicenode given\n", __func__);
- return NULL;
- }
-
- info_np = of_get_child_by_name(np, "panel-info");
- if (!info_np) {
- pr_err("%s: could not find panel-info node\n", __func__);
- return NULL;
- }
-
- info = kzalloc_obj(*info);
- if (!info)
- goto put_node;
-
- ret |= of_property_read_u32(info_np, "ac-bias", &info->ac_bias);
- ret |= of_property_read_u32(info_np, "ac-bias-intrpt", &info->ac_bias_intrpt);
- ret |= of_property_read_u32(info_np, "dma-burst-sz", &info->dma_burst_sz);
- ret |= of_property_read_u32(info_np, "bpp", &info->bpp);
- ret |= of_property_read_u32(info_np, "fdd", &info->fdd);
- ret |= of_property_read_u32(info_np, "sync-edge", &info->sync_edge);
- ret |= of_property_read_u32(info_np, "sync-ctrl", &info->sync_ctrl);
- ret |= of_property_read_u32(info_np, "raster-order", &info->raster_order);
- ret |= of_property_read_u32(info_np, "fifo-th", &info->fifo_th);
-
- /* optional: */
- info->tft_alt_mode = of_property_read_bool(info_np, "tft-alt-mode");
- info->invert_pxl_clk = of_property_read_bool(info_np, "invert-pxl-clk");
-
- if (ret) {
- pr_err("%s: error reading panel-info properties\n", __func__);
- kfree(info);
- info = NULL;
- }
-
-put_node:
- of_node_put(info_np);
- return info;
-}
-
-static int panel_probe(struct platform_device *pdev)
-{
- struct device_node *node = pdev->dev.of_node;
- struct backlight_device *backlight;
- struct panel_module *panel_mod;
- struct tilcdc_module *mod;
- int ret;
-
- /* bail out early if no DT data: */
- if (!node) {
- dev_err(&pdev->dev, "device-tree data is missing\n");
- return -ENXIO;
- }
-
- panel_mod = devm_kzalloc(&pdev->dev, sizeof(*panel_mod), GFP_KERNEL);
- if (!panel_mod)
- return -ENOMEM;
-
- backlight = devm_of_find_backlight(&pdev->dev);
- if (IS_ERR(backlight))
- return PTR_ERR(backlight);
- panel_mod->backlight = backlight;
-
- panel_mod->enable_gpio = devm_gpiod_get_optional(&pdev->dev, "enable",
- GPIOD_OUT_LOW);
- if (IS_ERR(panel_mod->enable_gpio)) {
- ret = PTR_ERR(panel_mod->enable_gpio);
- dev_err(&pdev->dev, "failed to request enable GPIO\n");
- goto fail_backlight;
- }
-
- if (panel_mod->enable_gpio)
- dev_info(&pdev->dev, "found enable GPIO\n");
-
- mod = &panel_mod->base;
- pdev->dev.platform_data = mod;
-
- tilcdc_module_init(mod, "panel", &panel_module_ops);
-
- panel_mod->timings = of_get_display_timings(node);
- if (!panel_mod->timings) {
- dev_err(&pdev->dev, "could not get panel timings\n");
- ret = -EINVAL;
- goto fail_free;
- }
-
- panel_mod->info = of_get_panel_info(node);
- if (!panel_mod->info) {
- dev_err(&pdev->dev, "could not get panel info\n");
- ret = -EINVAL;
- goto fail_timings;
- }
-
- return 0;
-
-fail_timings:
- display_timings_release(panel_mod->timings);
-
-fail_free:
- tilcdc_module_cleanup(mod);
-
-fail_backlight:
- if (panel_mod->backlight)
- put_device(&panel_mod->backlight->dev);
- return ret;
-}
-
-static void panel_remove(struct platform_device *pdev)
-{
- struct tilcdc_module *mod = dev_get_platdata(&pdev->dev);
- struct panel_module *panel_mod = to_panel_module(mod);
- struct backlight_device *backlight = panel_mod->backlight;
-
- if (backlight)
- put_device(&backlight->dev);
-
- display_timings_release(panel_mod->timings);
-
- tilcdc_module_cleanup(mod);
- kfree(panel_mod->info);
-}
-
-static const struct of_device_id panel_of_match[] = {
- { .compatible = "ti,tilcdc,panel", },
- { },
-};
-
-static struct platform_driver panel_driver = {
- .probe = panel_probe,
- .remove = panel_remove,
- .driver = {
- .name = "tilcdc-panel",
- .of_match_table = panel_of_match,
- },
-};
-
-int __init tilcdc_panel_init(void)
-{
- return platform_driver_register(&panel_driver);
-}
-
-void __exit tilcdc_panel_fini(void)
-{
- platform_driver_unregister(&panel_driver);
-}
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel_legacy.c b/drivers/gpu/drm/tilcdc/tilcdc_panel_legacy.c
index 37a69b3cf04b..2e7b3e87fea1 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_panel_legacy.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_panel_legacy.c
@@ -105,14 +105,14 @@ static int __init tilcdc_panel_copy_props(struct device_node *old_panel,
if (!invert_pxl_clk) {
ret = tilcdc_panel_update_prop(&ocs, new_timing, "pixelclk-active",
- &(u32){cpu_to_be32(1)}, sizeof(u32));
+ &(__be32){cpu_to_be32(1)}, sizeof(__be32));
if (ret)
goto destroy_ocs;
}
if (!sync_edge) {
ret = tilcdc_panel_update_prop(&ocs, new_timing, "syncclk-active",
- &(u32){cpu_to_be32(1)}, sizeof(u32));
+ &(__be32){cpu_to_be32(1)}, sizeof(__be32));
if (ret)
goto destroy_ocs;
}
diff --git a/drivers/gpu/drm/tiny/hx8357d.c b/drivers/gpu/drm/tiny/hx8357d.c
index 9f26aaca0bfa..53b152fc6b04 100644
--- a/drivers/gpu/drm/tiny/hx8357d.c
+++ b/drivers/gpu/drm/tiny/hx8357d.c
@@ -46,16 +46,48 @@
#define HX8357D_MADCTL_BGR 0x08
#define HX8357D_MADCTL_MH 0x04
-static void yx240qv29_enable(struct drm_simple_display_pipe *pipe,
- struct drm_crtc_state *crtc_state,
- struct drm_plane_state *plane_state)
+struct hx8357d_device {
+ struct mipi_dbi_dev dbidev;
+
+ struct drm_plane plane;
+ struct drm_crtc crtc;
+ struct drm_encoder encoder;
+ struct drm_connector connector;
+};
+
+static struct hx8357d_device *to_hx8357d_device(struct drm_device *dev)
{
- struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev);
+ return container_of(drm_to_mipi_dbi_dev(dev), struct hx8357d_device, dbidev);
+}
+
+static const u32 hx8357d_plane_formats[] = {
+ DRM_MIPI_DBI_PLANE_FORMATS,
+};
+
+static const u64 hx8357d_plane_format_modifiers[] = {
+ DRM_MIPI_DBI_PLANE_FORMAT_MODIFIERS,
+};
+
+static const struct drm_plane_helper_funcs hx8357d_plane_helper_funcs = {
+ DRM_MIPI_DBI_PLANE_HELPER_FUNCS,
+};
+
+static const struct drm_plane_funcs hx8357d_plane_funcs = {
+ DRM_MIPI_DBI_PLANE_FUNCS,
+ .destroy = drm_plane_cleanup,
+};
+
+static void hx8357d_crtc_helper_atomic_enable(struct drm_crtc *crtc,
+ struct drm_atomic_state *state)
+{
+ struct drm_device *drm = crtc->dev;
+ struct hx8357d_device *hx8357d = to_hx8357d_device(drm);
+ struct mipi_dbi_dev *dbidev = &hx8357d->dbidev;
struct mipi_dbi *dbi = &dbidev->dbi;
u8 addr_mode;
int ret, idx;
- if (!drm_dev_enter(pipe->crtc.dev, &idx))
+ if (!drm_dev_enter(drm, &idx))
return;
DRM_DEBUG_KMS("\n");
@@ -177,13 +209,41 @@ out_enable:
break;
}
mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode);
- mipi_dbi_enable_flush(dbidev, crtc_state, plane_state);
+
+ backlight_enable(dbidev->backlight);
out_exit:
drm_dev_exit(idx);
}
-static const struct drm_simple_display_pipe_funcs hx8357d_pipe_funcs = {
- DRM_MIPI_DBI_SIMPLE_DISPLAY_PIPE_FUNCS(yx240qv29_enable),
+static const struct drm_crtc_helper_funcs hx8357d_crtc_helper_funcs = {
+ DRM_MIPI_DBI_CRTC_HELPER_FUNCS,
+ .atomic_enable = hx8357d_crtc_helper_atomic_enable,
+};
+
+static const struct drm_crtc_funcs hx8357d_crtc_funcs = {
+ DRM_MIPI_DBI_CRTC_FUNCS,
+ .destroy = drm_crtc_cleanup,
+};
+
+static const struct drm_encoder_funcs hx8357d_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
+static const struct drm_connector_helper_funcs hx8357d_connector_helper_funcs = {
+ DRM_MIPI_DBI_CONNECTOR_HELPER_FUNCS,
+};
+
+static const struct drm_connector_funcs hx8357d_connector_funcs = {
+ DRM_MIPI_DBI_CONNECTOR_FUNCS,
+ .destroy = drm_connector_cleanup,
+};
+
+static const struct drm_mode_config_helper_funcs hx8357d_mode_config_helper_funcs = {
+ DRM_MIPI_DBI_MODE_CONFIG_HELPER_FUNCS,
+};
+
+static const struct drm_mode_config_funcs hx8357d_mode_config_funcs = {
+ DRM_MIPI_DBI_MODE_CONFIG_FUNCS,
};
static const struct drm_display_mode yx350hv15_mode = {
@@ -219,17 +279,21 @@ MODULE_DEVICE_TABLE(spi, hx8357d_id);
static int hx8357d_probe(struct spi_device *spi)
{
struct device *dev = &spi->dev;
+ struct hx8357d_device *hx8357d;
struct mipi_dbi_dev *dbidev;
struct drm_device *drm;
struct gpio_desc *dc;
+ struct drm_plane *plane;
+ struct drm_crtc *crtc;
+ struct drm_encoder *encoder;
+ struct drm_connector *connector;
u32 rotation = 0;
int ret;
- dbidev = devm_drm_dev_alloc(dev, &hx8357d_driver,
- struct mipi_dbi_dev, drm);
- if (IS_ERR(dbidev))
- return PTR_ERR(dbidev);
-
+ hx8357d = devm_drm_dev_alloc(dev, &hx8357d_driver, struct hx8357d_device, dbidev.drm);
+ if (IS_ERR(hx8357d))
+ return PTR_ERR(hx8357d);
+ dbidev = &hx8357d->dbidev;
drm = &dbidev->drm;
dc = devm_gpiod_get(dev, "dc", GPIOD_OUT_LOW);
@@ -246,7 +310,53 @@ static int hx8357d_probe(struct spi_device *spi)
if (ret)
return ret;
- ret = mipi_dbi_dev_init(dbidev, &hx8357d_pipe_funcs, &yx350hv15_mode, rotation);
+ ret = drm_mipi_dbi_dev_init(dbidev, &yx350hv15_mode, hx8357d_plane_formats[0],
+ rotation, 0);
+ if (ret)
+ return ret;
+
+ ret = drmm_mode_config_init(drm);
+ if (ret)
+ return ret;
+
+ drm->mode_config.min_width = dbidev->mode.hdisplay;
+ drm->mode_config.max_width = dbidev->mode.hdisplay;
+ drm->mode_config.min_height = dbidev->mode.vdisplay;
+ drm->mode_config.max_height = dbidev->mode.vdisplay;
+ drm->mode_config.funcs = &hx8357d_mode_config_funcs;
+ drm->mode_config.preferred_depth = 16;
+ drm->mode_config.helper_private = &hx8357d_mode_config_helper_funcs;
+
+ plane = &hx8357d->plane;
+ ret = drm_universal_plane_init(drm, plane, 0, &hx8357d_plane_funcs,
+ hx8357d_plane_formats, ARRAY_SIZE(hx8357d_plane_formats),
+ hx8357d_plane_format_modifiers,
+ DRM_PLANE_TYPE_PRIMARY, NULL);
+ if (ret)
+ return ret;
+ drm_plane_helper_add(plane, &hx8357d_plane_helper_funcs);
+ drm_plane_enable_fb_damage_clips(plane);
+
+ crtc = &hx8357d->crtc;
+ ret = drm_crtc_init_with_planes(drm, crtc, plane, NULL, &hx8357d_crtc_funcs, NULL);
+ if (ret)
+ return ret;
+ drm_crtc_helper_add(crtc, &hx8357d_crtc_helper_funcs);
+
+ encoder = &hx8357d->encoder;
+ ret = drm_encoder_init(drm, encoder, &hx8357d_encoder_funcs, DRM_MODE_ENCODER_NONE, NULL);
+ if (ret)
+ return ret;
+ encoder->possible_crtcs = drm_crtc_mask(crtc);
+
+ connector = &hx8357d->connector;
+ ret = drm_connector_init(drm, connector, &hx8357d_connector_funcs,
+ DRM_MODE_CONNECTOR_SPI);
+ if (ret)
+ return ret;
+ drm_connector_helper_add(connector, &hx8357d_connector_helper_funcs);
+
+ ret = drm_connector_attach_encoder(connector, encoder);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/tiny/ili9163.c b/drivers/gpu/drm/tiny/ili9163.c
index 7c154c008344..1e581576fc7e 100644
--- a/drivers/gpu/drm/tiny/ili9163.c
+++ b/drivers/gpu/drm/tiny/ili9163.c
@@ -35,16 +35,48 @@
#define ILI9163_MADCTL_MX BIT(6)
#define ILI9163_MADCTL_MY BIT(7)
-static void yx240qv29_enable(struct drm_simple_display_pipe *pipe,
- struct drm_crtc_state *crtc_state,
- struct drm_plane_state *plane_state)
+struct ili9163_device {
+ struct mipi_dbi_dev dbidev;
+
+ struct drm_plane plane;
+ struct drm_crtc crtc;
+ struct drm_encoder encoder;
+ struct drm_connector connector;
+};
+
+static struct ili9163_device *to_ili9163_device(struct drm_device *dev)
{
- struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev);
+ return container_of(drm_to_mipi_dbi_dev(dev), struct ili9163_device, dbidev);
+}
+
+static const u32 ili9163_plane_formats[] = {
+ DRM_MIPI_DBI_PLANE_FORMATS,
+};
+
+static const u64 ili9163_plane_format_modifiers[] = {
+ DRM_MIPI_DBI_PLANE_FORMAT_MODIFIERS,
+};
+
+static const struct drm_plane_helper_funcs ili9163_plane_helper_funcs = {
+ DRM_MIPI_DBI_PLANE_HELPER_FUNCS,
+};
+
+static const struct drm_plane_funcs ili9163_plane_funcs = {
+ DRM_MIPI_DBI_PLANE_FUNCS,
+ .destroy = drm_plane_cleanup,
+};
+
+static void ili9163_crtc_helper_atomic_enable(struct drm_crtc *crtc,
+ struct drm_atomic_state *state)
+{
+ struct drm_device *drm = crtc->dev;
+ struct ili9163_device *ili9163 = to_ili9163_device(drm);
+ struct mipi_dbi_dev *dbidev = &ili9163->dbidev;
struct mipi_dbi *dbi = &dbidev->dbi;
u8 addr_mode;
int ret, idx;
- if (!drm_dev_enter(pipe->crtc.dev, &idx))
+ if (!drm_dev_enter(drm, &idx))
return;
DRM_DEBUG_KMS("\n");
@@ -96,13 +128,41 @@ out_enable:
}
addr_mode |= ILI9163_MADCTL_BGR;
mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode);
- mipi_dbi_enable_flush(dbidev, crtc_state, plane_state);
+
+ backlight_enable(dbidev->backlight);
out_exit:
drm_dev_exit(idx);
}
-static const struct drm_simple_display_pipe_funcs ili9163_pipe_funcs = {
- DRM_MIPI_DBI_SIMPLE_DISPLAY_PIPE_FUNCS(yx240qv29_enable),
+static const struct drm_crtc_helper_funcs ili9163_crtc_helper_funcs = {
+ DRM_MIPI_DBI_CRTC_HELPER_FUNCS,
+ .atomic_enable = ili9163_crtc_helper_atomic_enable,
+};
+
+static const struct drm_crtc_funcs ili9163_crtc_funcs = {
+ DRM_MIPI_DBI_CRTC_FUNCS,
+ .destroy = drm_crtc_cleanup,
+};
+
+static const struct drm_encoder_funcs ili9163_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
+static const struct drm_connector_helper_funcs ili9163_connector_helper_funcs = {
+ DRM_MIPI_DBI_CONNECTOR_HELPER_FUNCS,
+};
+
+static const struct drm_connector_funcs ili9163_connector_funcs = {
+ DRM_MIPI_DBI_CONNECTOR_FUNCS,
+ .destroy = drm_connector_cleanup,
+};
+
+static const struct drm_mode_config_helper_funcs ili9163_mode_config_helper_funcs = {
+ DRM_MIPI_DBI_MODE_CONFIG_HELPER_FUNCS,
+};
+
+static const struct drm_mode_config_funcs ili9163_mode_config_funcs = {
+ DRM_MIPI_DBI_MODE_CONFIG_FUNCS,
};
static const struct drm_display_mode yx240qv29_mode = {
@@ -138,18 +198,22 @@ MODULE_DEVICE_TABLE(spi, ili9163_id);
static int ili9163_probe(struct spi_device *spi)
{
struct device *dev = &spi->dev;
+ struct ili9163_device *ili9163;
struct mipi_dbi_dev *dbidev;
struct drm_device *drm;
struct mipi_dbi *dbi;
struct gpio_desc *dc;
+ struct drm_plane *plane;
+ struct drm_crtc *crtc;
+ struct drm_encoder *encoder;
+ struct drm_connector *connector;
u32 rotation = 0;
int ret;
- dbidev = devm_drm_dev_alloc(dev, &ili9163_driver,
- struct mipi_dbi_dev, drm);
- if (IS_ERR(dbidev))
- return PTR_ERR(dbidev);
-
+ ili9163 = devm_drm_dev_alloc(dev, &ili9163_driver, struct ili9163_device, dbidev.drm);
+ if (IS_ERR(ili9163))
+ return PTR_ERR(ili9163);
+ dbidev = &ili9163->dbidev;
dbi = &dbidev->dbi;
drm = &dbidev->drm;
@@ -177,7 +241,53 @@ static int ili9163_probe(struct spi_device *spi)
if (ret)
return ret;
- ret = mipi_dbi_dev_init(dbidev, &ili9163_pipe_funcs, &yx240qv29_mode, rotation);
+ ret = drm_mipi_dbi_dev_init(dbidev, &yx240qv29_mode, ili9163_plane_formats[0],
+ rotation, 0);
+ if (ret)
+ return ret;
+
+ ret = drmm_mode_config_init(drm);
+ if (ret)
+ return ret;
+
+ drm->mode_config.min_width = dbidev->mode.hdisplay;
+ drm->mode_config.max_width = dbidev->mode.hdisplay;
+ drm->mode_config.min_height = dbidev->mode.vdisplay;
+ drm->mode_config.max_height = dbidev->mode.vdisplay;
+ drm->mode_config.funcs = &ili9163_mode_config_funcs;
+ drm->mode_config.preferred_depth = 16;
+ drm->mode_config.helper_private = &ili9163_mode_config_helper_funcs;
+
+ plane = &ili9163->plane;
+ ret = drm_universal_plane_init(drm, plane, 0, &ili9163_plane_funcs,
+ ili9163_plane_formats, ARRAY_SIZE(ili9163_plane_formats),
+ ili9163_plane_format_modifiers,
+ DRM_PLANE_TYPE_PRIMARY, NULL);
+ if (ret)
+ return ret;
+ drm_plane_helper_add(plane, &ili9163_plane_helper_funcs);
+ drm_plane_enable_fb_damage_clips(plane);
+
+ crtc = &ili9163->crtc;
+ ret = drm_crtc_init_with_planes(drm, crtc, plane, NULL, &ili9163_crtc_funcs, NULL);
+ if (ret)
+ return ret;
+ drm_crtc_helper_add(crtc, &ili9163_crtc_helper_funcs);
+
+ encoder = &ili9163->encoder;
+ ret = drm_encoder_init(drm, encoder, &ili9163_encoder_funcs, DRM_MODE_ENCODER_NONE, NULL);
+ if (ret)
+ return ret;
+ encoder->possible_crtcs = drm_crtc_mask(crtc);
+
+ connector = &ili9163->connector;
+ ret = drm_connector_init(drm, connector, &ili9163_connector_funcs,
+ DRM_MODE_CONNECTOR_SPI);
+ if (ret)
+ return ret;
+ drm_connector_helper_add(connector, &ili9163_connector_helper_funcs);
+
+ ret = drm_connector_attach_encoder(connector, encoder);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/tiny/ili9225.c b/drivers/gpu/drm/tiny/ili9225.c
index d32538b1eb09..0371527002f9 100644
--- a/drivers/gpu/drm/tiny/ili9225.c
+++ b/drivers/gpu/drm/tiny/ili9225.c
@@ -17,6 +17,7 @@
#include <video/mipi_display.h>
#include <drm/clients/drm_client_setup.h>
+#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_damage_helper.h>
#include <drm/drm_drv.h>
@@ -24,9 +25,7 @@
#include <drm/drm_fbdev_dma.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
-#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_dma_helper.h>
-#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_managed.h>
#include <drm/drm_mipi_dbi.h>
#include <drm/drm_print.h>
@@ -72,6 +71,20 @@
#define ILI9225_GAMMA_CONTROL_9 0x58
#define ILI9225_GAMMA_CONTROL_10 0x59
+struct ili9225_device {
+ struct mipi_dbi_dev dbidev;
+
+ struct drm_plane plane;
+ struct drm_crtc crtc;
+ struct drm_encoder encoder;
+ struct drm_connector connector;
+};
+
+static struct ili9225_device *to_ili9225_device(struct drm_device *dev)
+{
+ return container_of(drm_to_mipi_dbi_dev(dev), struct ili9225_device, dbidev);
+}
+
static inline int ili9225_command(struct mipi_dbi *dbi, u8 cmd, u16 data)
{
u8 par[2] = { data >> 8, data & 0xff };
@@ -157,47 +170,61 @@ err_msg:
dev_err_once(fb->dev->dev, "Failed to update display %d\n", ret);
}
-static void ili9225_pipe_update(struct drm_simple_display_pipe *pipe,
- struct drm_plane_state *old_state)
+static const u32 ili9225_plane_formats[] = {
+ DRM_MIPI_DBI_PLANE_FORMATS,
+};
+
+static const u64 ili9225_plane_format_modifiers[] = {
+ DRM_MIPI_DBI_PLANE_FORMAT_MODIFIERS,
+};
+
+static void ili9225_plane_helper_atomic_update(struct drm_plane *plane,
+ struct drm_atomic_state *state)
{
- struct drm_plane_state *state = pipe->plane.state;
- struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(state);
- struct drm_framebuffer *fb = state->fb;
+ struct drm_device *drm = plane->dev;
+ struct drm_plane_state *plane_state = plane->state;
+ struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
+ struct drm_framebuffer *fb = plane_state->fb;
+ struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
struct drm_rect rect;
int idx;
- if (!pipe->crtc.state->active)
+ if (!plane_state->fb)
return;
- if (!drm_dev_enter(fb->dev, &idx))
+ if (!drm_dev_enter(drm, &idx))
return;
- if (drm_atomic_helper_damage_merged(old_state, state, &rect))
+ if (drm_atomic_helper_damage_merged(old_plane_state, plane_state, &rect))
ili9225_fb_dirty(&shadow_plane_state->data[0], fb, &rect,
&shadow_plane_state->fmtcnv_state);
drm_dev_exit(idx);
}
-static void ili9225_pipe_enable(struct drm_simple_display_pipe *pipe,
- struct drm_crtc_state *crtc_state,
- struct drm_plane_state *plane_state)
+static const struct drm_plane_helper_funcs ili9225_plane_helper_funcs = {
+ DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
+ .atomic_check = drm_mipi_dbi_plane_helper_atomic_check,
+ .atomic_update = ili9225_plane_helper_atomic_update,
+};
+
+static const struct drm_plane_funcs ili9225_plane_funcs = {
+ DRM_MIPI_DBI_PLANE_FUNCS,
+ .destroy = drm_plane_cleanup,
+};
+
+static void ili9225_crtc_helper_atomic_enable(struct drm_crtc *crtc,
+ struct drm_atomic_state *state)
{
- struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev);
- struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
- struct drm_framebuffer *fb = plane_state->fb;
- struct device *dev = pipe->crtc.dev->dev;
+ struct drm_device *drm = crtc->dev;
+ struct ili9225_device *ili9225 = to_ili9225_device(drm);
+ struct mipi_dbi_dev *dbidev = &ili9225->dbidev;
+ struct device *dev = drm->dev;
struct mipi_dbi *dbi = &dbidev->dbi;
- struct drm_rect rect = {
- .x1 = 0,
- .x2 = fb->width,
- .y1 = 0,
- .y2 = fb->height,
- };
int ret, idx;
u8 am_id;
- if (!drm_dev_enter(pipe->crtc.dev, &idx))
+ if (!drm_dev_enter(drm, &idx))
return;
DRM_DEBUG_KMS("\n");
@@ -284,16 +311,16 @@ static void ili9225_pipe_enable(struct drm_simple_display_pipe *pipe,
ili9225_command(dbi, ILI9225_DISPLAY_CONTROL_1, 0x1017);
- ili9225_fb_dirty(&shadow_plane_state->data[0], fb, &rect,
- &shadow_plane_state->fmtcnv_state);
-
out_exit:
drm_dev_exit(idx);
}
-static void ili9225_pipe_disable(struct drm_simple_display_pipe *pipe)
+static void ili9225_crtc_helper_atomic_disable(struct drm_crtc *crtc,
+ struct drm_atomic_state *state)
{
- struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev);
+ struct drm_device *drm = crtc->dev;
+ struct ili9225_device *ili9225 = to_ili9225_device(drm);
+ struct mipi_dbi_dev *dbidev = &ili9225->dbidev;
struct mipi_dbi *dbi = &dbidev->dbi;
DRM_DEBUG_KMS("\n");
@@ -312,6 +339,39 @@ static void ili9225_pipe_disable(struct drm_simple_display_pipe *pipe)
ili9225_command(dbi, ILI9225_POWER_CONTROL_1, 0x0a02);
}
+static const struct drm_crtc_helper_funcs ili9225_crtc_helper_funcs = {
+ .mode_valid = drm_mipi_dbi_crtc_helper_mode_valid,
+ .atomic_check = drm_mipi_dbi_crtc_helper_atomic_check,
+ .atomic_enable = ili9225_crtc_helper_atomic_enable,
+ .atomic_disable = ili9225_crtc_helper_atomic_disable,
+};
+
+static const struct drm_crtc_funcs ili9225_crtc_funcs = {
+ DRM_MIPI_DBI_CRTC_FUNCS,
+ .destroy = drm_crtc_cleanup,
+};
+
+static const struct drm_encoder_funcs ili9225_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
+static const struct drm_connector_helper_funcs ili9225_connector_helper_funcs = {
+ DRM_MIPI_DBI_CONNECTOR_HELPER_FUNCS,
+};
+
+static const struct drm_connector_funcs ili9225_connector_funcs = {
+ DRM_MIPI_DBI_CONNECTOR_FUNCS,
+ .destroy = drm_connector_cleanup,
+};
+
+static const struct drm_mode_config_helper_funcs ili9225_mode_config_helper_funcs = {
+ DRM_MIPI_DBI_MODE_CONFIG_HELPER_FUNCS,
+};
+
+static const struct drm_mode_config_funcs ili9225_mode_config_funcs = {
+ DRM_MIPI_DBI_MODE_CONFIG_FUNCS,
+};
+
static int ili9225_dbi_command(struct mipi_dbi *dbi, u8 *cmd, u8 *par,
size_t num)
{
@@ -340,18 +400,6 @@ static int ili9225_dbi_command(struct mipi_dbi *dbi, u8 *cmd, u8 *par,
return ret;
}
-static const struct drm_simple_display_pipe_funcs ili9225_pipe_funcs = {
- .mode_valid = mipi_dbi_pipe_mode_valid,
- .enable = ili9225_pipe_enable,
- .disable = ili9225_pipe_disable,
- .update = ili9225_pipe_update,
- .begin_fb_access = mipi_dbi_pipe_begin_fb_access,
- .end_fb_access = mipi_dbi_pipe_end_fb_access,
- .reset_plane = mipi_dbi_pipe_reset_plane,
- .duplicate_plane_state = mipi_dbi_pipe_duplicate_plane_state,
- .destroy_plane_state = mipi_dbi_pipe_destroy_plane_state,
-};
-
static const struct drm_display_mode ili9225_mode = {
DRM_SIMPLE_MODE(176, 220, 35, 44),
};
@@ -384,18 +432,22 @@ MODULE_DEVICE_TABLE(spi, ili9225_id);
static int ili9225_probe(struct spi_device *spi)
{
struct device *dev = &spi->dev;
+ struct ili9225_device *ili9225;
struct mipi_dbi_dev *dbidev;
struct drm_device *drm;
struct mipi_dbi *dbi;
struct gpio_desc *rs;
+ struct drm_plane *plane;
+ struct drm_crtc *crtc;
+ struct drm_encoder *encoder;
+ struct drm_connector *connector;
u32 rotation = 0;
int ret;
- dbidev = devm_drm_dev_alloc(dev, &ili9225_driver,
- struct mipi_dbi_dev, drm);
- if (IS_ERR(dbidev))
- return PTR_ERR(dbidev);
-
+ ili9225 = devm_drm_dev_alloc(dev, &ili9225_driver, struct ili9225_device, dbidev.drm);
+ if (IS_ERR(ili9225))
+ return PTR_ERR(ili9225);
+ dbidev = &ili9225->dbidev;
dbi = &dbidev->dbi;
drm = &dbidev->drm;
@@ -416,7 +468,53 @@ static int ili9225_probe(struct spi_device *spi)
/* override the command function set in mipi_dbi_spi_init() */
dbi->command = ili9225_dbi_command;
- ret = mipi_dbi_dev_init(dbidev, &ili9225_pipe_funcs, &ili9225_mode, rotation);
+ ret = drm_mipi_dbi_dev_init(dbidev, &ili9225_mode, ili9225_plane_formats[0],
+ rotation, 0);
+ if (ret)
+ return ret;
+
+ ret = drmm_mode_config_init(drm);
+ if (ret)
+ return ret;
+
+ drm->mode_config.min_width = dbidev->mode.hdisplay;
+ drm->mode_config.max_width = dbidev->mode.hdisplay;
+ drm->mode_config.min_height = dbidev->mode.vdisplay;
+ drm->mode_config.max_height = dbidev->mode.vdisplay;
+ drm->mode_config.funcs = &ili9225_mode_config_funcs;
+ drm->mode_config.preferred_depth = 16;
+ drm->mode_config.helper_private = &ili9225_mode_config_helper_funcs;
+
+ plane = &ili9225->plane;
+ ret = drm_universal_plane_init(drm, plane, 0, &ili9225_plane_funcs,
+ ili9225_plane_formats, ARRAY_SIZE(ili9225_plane_formats),
+ ili9225_plane_format_modifiers,
+ DRM_PLANE_TYPE_PRIMARY, NULL);
+ if (ret)
+ return ret;
+ drm_plane_helper_add(plane, &ili9225_plane_helper_funcs);
+ drm_plane_enable_fb_damage_clips(plane);
+
+ crtc = &ili9225->crtc;
+ ret = drm_crtc_init_with_planes(drm, crtc, plane, NULL, &ili9225_crtc_funcs, NULL);
+ if (ret)
+ return ret;
+ drm_crtc_helper_add(crtc, &ili9225_crtc_helper_funcs);
+
+ encoder = &ili9225->encoder;
+ ret = drm_encoder_init(drm, encoder, &ili9225_encoder_funcs, DRM_MODE_ENCODER_NONE, NULL);
+ if (ret)
+ return ret;
+ encoder->possible_crtcs = drm_crtc_mask(crtc);
+
+ connector = &ili9225->connector;
+ ret = drm_connector_init(drm, connector, &ili9225_connector_funcs,
+ DRM_MODE_CONNECTOR_SPI);
+ if (ret)
+ return ret;
+ drm_connector_helper_add(connector, &ili9225_connector_helper_funcs);
+
+ ret = drm_connector_attach_encoder(connector, encoder);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/tiny/ili9341.c b/drivers/gpu/drm/tiny/ili9341.c
index 2ab750cba505..e623bd8a1827 100644
--- a/drivers/gpu/drm/tiny/ili9341.c
+++ b/drivers/gpu/drm/tiny/ili9341.c
@@ -52,16 +52,48 @@
#define ILI9341_MADCTL_MX BIT(6)
#define ILI9341_MADCTL_MY BIT(7)
-static void yx240qv29_enable(struct drm_simple_display_pipe *pipe,
- struct drm_crtc_state *crtc_state,
- struct drm_plane_state *plane_state)
+struct ili9341_device {
+ struct mipi_dbi_dev dbidev;
+
+ struct drm_plane plane;
+ struct drm_crtc crtc;
+ struct drm_encoder encoder;
+ struct drm_connector connector;
+};
+
+static struct ili9341_device *to_ili9341_device(struct drm_device *dev)
{
- struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev);
+ return container_of(drm_to_mipi_dbi_dev(dev), struct ili9341_device, dbidev);
+}
+
+static const u32 ili9341_plane_formats[] = {
+ DRM_MIPI_DBI_PLANE_FORMATS,
+};
+
+static const u64 ili9341_plane_format_modifiers[] = {
+ DRM_MIPI_DBI_PLANE_FORMAT_MODIFIERS,
+};
+
+static const struct drm_plane_helper_funcs ili9341_plane_helper_funcs = {
+ DRM_MIPI_DBI_PLANE_HELPER_FUNCS,
+};
+
+static const struct drm_plane_funcs ili9341_plane_funcs = {
+ DRM_MIPI_DBI_PLANE_FUNCS,
+ .destroy = drm_plane_cleanup,
+};
+
+static void ili9341_crtc_helper_atomic_enable(struct drm_crtc *crtc,
+ struct drm_atomic_state *state)
+{
+ struct drm_device *drm = crtc->dev;
+ struct ili9341_device *ili9341 = to_ili9341_device(drm);
+ struct mipi_dbi_dev *dbidev = &ili9341->dbidev;
struct mipi_dbi *dbi = &dbidev->dbi;
u8 addr_mode;
int ret, idx;
- if (!drm_dev_enter(pipe->crtc.dev, &idx))
+ if (!drm_dev_enter(drm, &idx))
return;
DRM_DEBUG_KMS("\n");
@@ -133,13 +165,41 @@ out_enable:
}
addr_mode |= ILI9341_MADCTL_BGR;
mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode);
- mipi_dbi_enable_flush(dbidev, crtc_state, plane_state);
+
+ backlight_enable(dbidev->backlight);
out_exit:
drm_dev_exit(idx);
}
-static const struct drm_simple_display_pipe_funcs ili9341_pipe_funcs = {
- DRM_MIPI_DBI_SIMPLE_DISPLAY_PIPE_FUNCS(yx240qv29_enable),
+static const struct drm_crtc_helper_funcs ili9341_crtc_helper_funcs = {
+ DRM_MIPI_DBI_CRTC_HELPER_FUNCS,
+ .atomic_enable = ili9341_crtc_helper_atomic_enable,
+};
+
+static const struct drm_crtc_funcs ili9341_crtc_funcs = {
+ DRM_MIPI_DBI_CRTC_FUNCS,
+ .destroy = drm_crtc_cleanup,
+};
+
+static const struct drm_encoder_funcs ili9341_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
+static const struct drm_connector_helper_funcs ili9341_connector_helper_funcs = {
+ DRM_MIPI_DBI_CONNECTOR_HELPER_FUNCS,
+};
+
+static const struct drm_connector_funcs ili9341_connector_funcs = {
+ DRM_MIPI_DBI_CONNECTOR_FUNCS,
+ .destroy = drm_connector_cleanup,
+};
+
+static const struct drm_mode_config_helper_funcs ili9341_mode_config_helper_funcs = {
+ DRM_MIPI_DBI_MODE_CONFIG_HELPER_FUNCS,
+};
+
+static const struct drm_mode_config_funcs ili9341_mode_config_funcs = {
+ DRM_MIPI_DBI_MODE_CONFIG_FUNCS,
};
static const struct drm_display_mode yx240qv29_mode = {
@@ -175,18 +235,22 @@ MODULE_DEVICE_TABLE(spi, ili9341_id);
static int ili9341_probe(struct spi_device *spi)
{
struct device *dev = &spi->dev;
+ struct ili9341_device *ili9341;
struct mipi_dbi_dev *dbidev;
struct drm_device *drm;
struct mipi_dbi *dbi;
struct gpio_desc *dc;
+ struct drm_plane *plane;
+ struct drm_crtc *crtc;
+ struct drm_encoder *encoder;
+ struct drm_connector *connector;
u32 rotation = 0;
int ret;
- dbidev = devm_drm_dev_alloc(dev, &ili9341_driver,
- struct mipi_dbi_dev, drm);
- if (IS_ERR(dbidev))
- return PTR_ERR(dbidev);
-
+ ili9341 = devm_drm_dev_alloc(dev, &ili9341_driver, struct ili9341_device, dbidev.drm);
+ if (IS_ERR(ili9341))
+ return PTR_ERR(ili9341);
+ dbidev = &ili9341->dbidev;
dbi = &dbidev->dbi;
drm = &dbidev->drm;
@@ -208,7 +272,53 @@ static int ili9341_probe(struct spi_device *spi)
if (ret)
return ret;
- ret = mipi_dbi_dev_init(dbidev, &ili9341_pipe_funcs, &yx240qv29_mode, rotation);
+ ret = drm_mipi_dbi_dev_init(dbidev, &yx240qv29_mode, ili9341_plane_formats[0],
+ rotation, 0);
+ if (ret)
+ return ret;
+
+ ret = drmm_mode_config_init(drm);
+ if (ret)
+ return ret;
+
+ drm->mode_config.min_width = dbidev->mode.hdisplay;
+ drm->mode_config.max_width = dbidev->mode.hdisplay;
+ drm->mode_config.min_height = dbidev->mode.vdisplay;
+ drm->mode_config.max_height = dbidev->mode.vdisplay;
+ drm->mode_config.funcs = &ili9341_mode_config_funcs;
+ drm->mode_config.preferred_depth = 16;
+ drm->mode_config.helper_private = &ili9341_mode_config_helper_funcs;
+
+ plane = &ili9341->plane;
+ ret = drm_universal_plane_init(drm, plane, 0, &ili9341_plane_funcs,
+ ili9341_plane_formats, ARRAY_SIZE(ili9341_plane_formats),
+ ili9341_plane_format_modifiers,
+ DRM_PLANE_TYPE_PRIMARY, NULL);
+ if (ret)
+ return ret;
+ drm_plane_helper_add(plane, &ili9341_plane_helper_funcs);
+ drm_plane_enable_fb_damage_clips(plane);
+
+ crtc = &ili9341->crtc;
+ ret = drm_crtc_init_with_planes(drm, crtc, plane, NULL, &ili9341_crtc_funcs, NULL);
+ if (ret)
+ return ret;
+ drm_crtc_helper_add(crtc, &ili9341_crtc_helper_funcs);
+
+ encoder = &ili9341->encoder;
+ ret = drm_encoder_init(drm, encoder, &ili9341_encoder_funcs, DRM_MODE_ENCODER_NONE, NULL);
+ if (ret)
+ return ret;
+ encoder->possible_crtcs = drm_crtc_mask(crtc);
+
+ connector = &ili9341->connector;
+ ret = drm_connector_init(drm, connector, &ili9341_connector_funcs,
+ DRM_MODE_CONNECTOR_SPI);
+ if (ret)
+ return ret;
+ drm_connector_helper_add(connector, &ili9341_connector_helper_funcs);
+
+ ret = drm_connector_attach_encoder(connector, encoder);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/tiny/ili9486.c b/drivers/gpu/drm/tiny/ili9486.c
index 1e411a0f4567..030e87a8a3f0 100644
--- a/drivers/gpu/drm/tiny/ili9486.c
+++ b/drivers/gpu/drm/tiny/ili9486.c
@@ -36,6 +36,20 @@
#define ILI9486_MADCTL_MX BIT(6)
#define ILI9486_MADCTL_MY BIT(7)
+struct ili9486_device {
+ struct mipi_dbi_dev dbidev;
+
+ struct drm_plane plane;
+ struct drm_crtc crtc;
+ struct drm_encoder encoder;
+ struct drm_connector connector;
+};
+
+static struct ili9486_device *to_ili9486_device(struct drm_device *dev)
+{
+ return container_of(drm_to_mipi_dbi_dev(dev), struct ili9486_device, dbidev);
+}
+
/*
* The PiScreen/waveshare rpi-lcd-35 has a SPI to 16-bit parallel bus converter
* in front of the display controller. This means that 8-bit values have to be
@@ -94,16 +108,34 @@ static int waveshare_command(struct mipi_dbi *mipi, u8 *cmd, u8 *par,
return ret;
}
-static void waveshare_enable(struct drm_simple_display_pipe *pipe,
- struct drm_crtc_state *crtc_state,
- struct drm_plane_state *plane_state)
+static const u32 ili9486_plane_formats[] = {
+ DRM_MIPI_DBI_PLANE_FORMATS,
+};
+
+static const u64 ili9486_plane_format_modifiers[] = {
+ DRM_MIPI_DBI_PLANE_FORMAT_MODIFIERS,
+};
+
+static const struct drm_plane_helper_funcs ili9486_plane_helper_funcs = {
+ DRM_MIPI_DBI_PLANE_HELPER_FUNCS,
+};
+
+static const struct drm_plane_funcs ili9486_plane_funcs = {
+ DRM_MIPI_DBI_PLANE_FUNCS,
+ .destroy = drm_plane_cleanup,
+};
+
+static void ili9486_crtc_helper_atomic_enable(struct drm_crtc *crtc,
+ struct drm_atomic_state *state)
{
- struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev);
+ struct drm_device *drm = crtc->dev;
+ struct ili9486_device *ili9486 = to_ili9486_device(drm);
+ struct mipi_dbi_dev *dbidev = &ili9486->dbidev;
struct mipi_dbi *dbi = &dbidev->dbi;
u8 addr_mode;
int ret, idx;
- if (!drm_dev_enter(pipe->crtc.dev, &idx))
+ if (!drm_dev_enter(drm, &idx))
return;
DRM_DEBUG_KMS("\n");
@@ -155,13 +187,41 @@ static void waveshare_enable(struct drm_simple_display_pipe *pipe,
}
addr_mode |= ILI9486_MADCTL_BGR;
mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode);
- mipi_dbi_enable_flush(dbidev, crtc_state, plane_state);
+
+ backlight_enable(dbidev->backlight);
out_exit:
drm_dev_exit(idx);
}
-static const struct drm_simple_display_pipe_funcs waveshare_pipe_funcs = {
- DRM_MIPI_DBI_SIMPLE_DISPLAY_PIPE_FUNCS(waveshare_enable),
+static const struct drm_crtc_helper_funcs ili9486_crtc_helper_funcs = {
+ DRM_MIPI_DBI_CRTC_HELPER_FUNCS,
+ .atomic_enable = ili9486_crtc_helper_atomic_enable,
+};
+
+static const struct drm_crtc_funcs ili9486_crtc_funcs = {
+ DRM_MIPI_DBI_CRTC_FUNCS,
+ .destroy = drm_crtc_cleanup,
+};
+
+static const struct drm_encoder_funcs ili9486_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
+static const struct drm_connector_helper_funcs ili9486_connector_helper_funcs = {
+ DRM_MIPI_DBI_CONNECTOR_HELPER_FUNCS,
+};
+
+static const struct drm_connector_funcs ili9486_connector_funcs = {
+ DRM_MIPI_DBI_CONNECTOR_FUNCS,
+ .destroy = drm_connector_cleanup,
+};
+
+static const struct drm_mode_config_helper_funcs ili9486_mode_config_helper_funcs = {
+ DRM_MIPI_DBI_MODE_CONFIG_HELPER_FUNCS,
+};
+
+static const struct drm_mode_config_funcs ili9486_mode_config_funcs = {
+ DRM_MIPI_DBI_MODE_CONFIG_FUNCS,
};
static const struct drm_display_mode waveshare_mode = {
@@ -200,18 +260,22 @@ MODULE_DEVICE_TABLE(spi, ili9486_id);
static int ili9486_probe(struct spi_device *spi)
{
struct device *dev = &spi->dev;
+ struct ili9486_device *ili9486;
struct mipi_dbi_dev *dbidev;
struct drm_device *drm;
struct mipi_dbi *dbi;
struct gpio_desc *dc;
+ struct drm_plane *plane;
+ struct drm_crtc *crtc;
+ struct drm_encoder *encoder;
+ struct drm_connector *connector;
u32 rotation = 0;
int ret;
- dbidev = devm_drm_dev_alloc(dev, &ili9486_driver,
- struct mipi_dbi_dev, drm);
- if (IS_ERR(dbidev))
- return PTR_ERR(dbidev);
-
+ ili9486 = devm_drm_dev_alloc(dev, &ili9486_driver, struct ili9486_device, dbidev.drm);
+ if (IS_ERR(ili9486))
+ return PTR_ERR(ili9486);
+ dbidev = &ili9486->dbidev;
dbi = &dbidev->dbi;
drm = &dbidev->drm;
@@ -236,8 +300,53 @@ static int ili9486_probe(struct spi_device *spi)
dbi->command = waveshare_command;
dbi->read_commands = NULL;
- ret = mipi_dbi_dev_init(dbidev, &waveshare_pipe_funcs,
- &waveshare_mode, rotation);
+ ret = drm_mipi_dbi_dev_init(dbidev, &waveshare_mode, ili9486_plane_formats[0],
+ rotation, 0);
+ if (ret)
+ return ret;
+
+ ret = drmm_mode_config_init(drm);
+ if (ret)
+ return ret;
+
+ drm->mode_config.min_width = dbidev->mode.hdisplay;
+ drm->mode_config.max_width = dbidev->mode.hdisplay;
+ drm->mode_config.min_height = dbidev->mode.vdisplay;
+ drm->mode_config.max_height = dbidev->mode.vdisplay;
+ drm->mode_config.funcs = &ili9486_mode_config_funcs;
+ drm->mode_config.preferred_depth = 16;
+ drm->mode_config.helper_private = &ili9486_mode_config_helper_funcs;
+
+ plane = &ili9486->plane;
+ ret = drm_universal_plane_init(drm, plane, 0, &ili9486_plane_funcs,
+ ili9486_plane_formats, ARRAY_SIZE(ili9486_plane_formats),
+ ili9486_plane_format_modifiers,
+ DRM_PLANE_TYPE_PRIMARY, NULL);
+ if (ret)
+ return ret;
+ drm_plane_helper_add(plane, &ili9486_plane_helper_funcs);
+ drm_plane_enable_fb_damage_clips(plane);
+
+ crtc = &ili9486->crtc;
+ ret = drm_crtc_init_with_planes(drm, crtc, plane, NULL, &ili9486_crtc_funcs, NULL);
+ if (ret)
+ return ret;
+ drm_crtc_helper_add(crtc, &ili9486_crtc_helper_funcs);
+
+ encoder = &ili9486->encoder;
+ ret = drm_encoder_init(drm, encoder, &ili9486_encoder_funcs, DRM_MODE_ENCODER_NONE, NULL);
+ if (ret)
+ return ret;
+ encoder->possible_crtcs = drm_crtc_mask(crtc);
+
+ connector = &ili9486->connector;
+ ret = drm_connector_init(drm, connector, &ili9486_connector_funcs,
+ DRM_MODE_CONNECTOR_SPI);
+ if (ret)
+ return ret;
+ drm_connector_helper_add(connector, &ili9486_connector_helper_funcs);
+
+ ret = drm_connector_attach_encoder(connector, encoder);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/tiny/mi0283qt.c b/drivers/gpu/drm/tiny/mi0283qt.c
index a063eff77624..ee597d023390 100644
--- a/drivers/gpu/drm/tiny/mi0283qt.c
+++ b/drivers/gpu/drm/tiny/mi0283qt.c
@@ -50,16 +50,48 @@
#define ILI9341_MADCTL_MX BIT(6)
#define ILI9341_MADCTL_MY BIT(7)
-static void mi0283qt_enable(struct drm_simple_display_pipe *pipe,
- struct drm_crtc_state *crtc_state,
- struct drm_plane_state *plane_state)
+struct mi0283qt_device {
+ struct mipi_dbi_dev dbidev;
+
+ struct drm_plane plane;
+ struct drm_crtc crtc;
+ struct drm_encoder encoder;
+ struct drm_connector connector;
+};
+
+static struct mi0283qt_device *to_mi0283qt_device(struct drm_device *dev)
{
- struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev);
+ return container_of(drm_to_mipi_dbi_dev(dev), struct mi0283qt_device, dbidev);
+}
+
+static const u32 mi0283qt_plane_formats[] = {
+ DRM_MIPI_DBI_PLANE_FORMATS,
+};
+
+static const u64 mi0283qt_plane_format_modifiers[] = {
+ DRM_MIPI_DBI_PLANE_FORMAT_MODIFIERS,
+};
+
+static const struct drm_plane_helper_funcs mi0283qt_plane_helper_funcs = {
+ DRM_MIPI_DBI_PLANE_HELPER_FUNCS,
+};
+
+static const struct drm_plane_funcs mi0283qt_plane_funcs = {
+ DRM_MIPI_DBI_PLANE_FUNCS,
+ .destroy = drm_plane_cleanup,
+};
+
+static void mi0283qt_crtc_helper_atomic_enable(struct drm_crtc *crtc,
+ struct drm_atomic_state *state)
+{
+ struct drm_device *drm = crtc->dev;
+ struct mi0283qt_device *mi0283qt = to_mi0283qt_device(drm);
+ struct mipi_dbi_dev *dbidev = &mi0283qt->dbidev;
struct mipi_dbi *dbi = &dbidev->dbi;
u8 addr_mode;
int ret, idx;
- if (!drm_dev_enter(pipe->crtc.dev, &idx))
+ if (!drm_dev_enter(drm, &idx))
return;
DRM_DEBUG_KMS("\n");
@@ -137,13 +169,41 @@ out_enable:
}
addr_mode |= ILI9341_MADCTL_BGR;
mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode);
- mipi_dbi_enable_flush(dbidev, crtc_state, plane_state);
+
+ backlight_enable(dbidev->backlight);
out_exit:
drm_dev_exit(idx);
}
-static const struct drm_simple_display_pipe_funcs mi0283qt_pipe_funcs = {
- DRM_MIPI_DBI_SIMPLE_DISPLAY_PIPE_FUNCS(mi0283qt_enable),
+static const struct drm_crtc_helper_funcs mi0283qt_crtc_helper_funcs = {
+ DRM_MIPI_DBI_CRTC_HELPER_FUNCS,
+ .atomic_enable = mi0283qt_crtc_helper_atomic_enable,
+};
+
+static const struct drm_crtc_funcs mi0283qt_crtc_funcs = {
+ DRM_MIPI_DBI_CRTC_FUNCS,
+ .destroy = drm_crtc_cleanup,
+};
+
+static const struct drm_encoder_funcs mi0283qt_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
+static const struct drm_connector_helper_funcs mi0283qt_connector_helper_funcs = {
+ DRM_MIPI_DBI_CONNECTOR_HELPER_FUNCS,
+};
+
+static const struct drm_connector_funcs mi0283qt_connector_funcs = {
+ DRM_MIPI_DBI_CONNECTOR_FUNCS,
+ .destroy = drm_connector_cleanup,
+};
+
+static const struct drm_mode_config_helper_funcs mi0283qt_mode_config_helper_funcs = {
+ DRM_MIPI_DBI_MODE_CONFIG_HELPER_FUNCS,
+};
+
+static const struct drm_mode_config_funcs mi0283qt_mode_config_funcs = {
+ DRM_MIPI_DBI_MODE_CONFIG_FUNCS,
};
static const struct drm_display_mode mi0283qt_mode = {
@@ -179,18 +239,22 @@ MODULE_DEVICE_TABLE(spi, mi0283qt_id);
static int mi0283qt_probe(struct spi_device *spi)
{
struct device *dev = &spi->dev;
+ struct mi0283qt_device *mi0283qt;
struct mipi_dbi_dev *dbidev;
struct drm_device *drm;
struct mipi_dbi *dbi;
struct gpio_desc *dc;
+ struct drm_plane *plane;
+ struct drm_crtc *crtc;
+ struct drm_encoder *encoder;
+ struct drm_connector *connector;
u32 rotation = 0;
int ret;
- dbidev = devm_drm_dev_alloc(dev, &mi0283qt_driver,
- struct mipi_dbi_dev, drm);
- if (IS_ERR(dbidev))
- return PTR_ERR(dbidev);
-
+ mi0283qt = devm_drm_dev_alloc(dev, &mi0283qt_driver, struct mi0283qt_device, dbidev.drm);
+ if (IS_ERR(mi0283qt))
+ return PTR_ERR(mi0283qt);
+ dbidev = &mi0283qt->dbidev;
dbi = &dbidev->dbi;
drm = &dbidev->drm;
@@ -216,7 +280,53 @@ static int mi0283qt_probe(struct spi_device *spi)
if (ret)
return ret;
- ret = mipi_dbi_dev_init(dbidev, &mi0283qt_pipe_funcs, &mi0283qt_mode, rotation);
+ ret = drm_mipi_dbi_dev_init(dbidev, &mi0283qt_mode, mi0283qt_plane_formats[0],
+ rotation, 0);
+ if (ret)
+ return ret;
+
+ ret = drmm_mode_config_init(drm);
+ if (ret)
+ return ret;
+
+ drm->mode_config.min_width = dbidev->mode.hdisplay;
+ drm->mode_config.max_width = dbidev->mode.hdisplay;
+ drm->mode_config.min_height = dbidev->mode.vdisplay;
+ drm->mode_config.max_height = dbidev->mode.vdisplay;
+ drm->mode_config.funcs = &mi0283qt_mode_config_funcs;
+ drm->mode_config.preferred_depth = 16;
+ drm->mode_config.helper_private = &mi0283qt_mode_config_helper_funcs;
+
+ plane = &mi0283qt->plane;
+ ret = drm_universal_plane_init(drm, plane, 0, &mi0283qt_plane_funcs,
+ mi0283qt_plane_formats, ARRAY_SIZE(mi0283qt_plane_formats),
+ mi0283qt_plane_format_modifiers,
+ DRM_PLANE_TYPE_PRIMARY, NULL);
+ if (ret)
+ return ret;
+ drm_plane_helper_add(plane, &mi0283qt_plane_helper_funcs);
+ drm_plane_enable_fb_damage_clips(plane);
+
+ crtc = &mi0283qt->crtc;
+ ret = drm_crtc_init_with_planes(drm, crtc, plane, NULL, &mi0283qt_crtc_funcs, NULL);
+ if (ret)
+ return ret;
+ drm_crtc_helper_add(crtc, &mi0283qt_crtc_helper_funcs);
+
+ encoder = &mi0283qt->encoder;
+ ret = drm_encoder_init(drm, encoder, &mi0283qt_encoder_funcs, DRM_MODE_ENCODER_NONE, NULL);
+ if (ret)
+ return ret;
+ encoder->possible_crtcs = drm_crtc_mask(crtc);
+
+ connector = &mi0283qt->connector;
+ ret = drm_connector_init(drm, connector, &mi0283qt_connector_funcs,
+ DRM_MODE_CONNECTOR_SPI);
+ if (ret)
+ return ret;
+ drm_connector_helper_add(connector, &mi0283qt_connector_helper_funcs);
+
+ ret = drm_connector_attach_encoder(connector, encoder);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/tiny/panel-mipi-dbi.c b/drivers/gpu/drm/tiny/panel-mipi-dbi.c
index 82dfa169f762..581e14528608 100644
--- a/drivers/gpu/drm/tiny/panel-mipi-dbi.c
+++ b/drivers/gpu/drm/tiny/panel-mipi-dbi.c
@@ -233,18 +233,46 @@ static void panel_mipi_dbi_commands_execute(struct mipi_dbi *dbi,
}
}
-static void panel_mipi_dbi_enable(struct drm_simple_display_pipe *pipe,
- struct drm_crtc_state *crtc_state,
- struct drm_plane_state *plane_state)
+struct panel_mipi_dbi_device {
+ struct mipi_dbi_dev dbidev;
+
+ struct drm_plane plane;
+ struct drm_crtc crtc;
+ struct drm_encoder encoder;
+ struct drm_connector connector;
+};
+
+static struct panel_mipi_dbi_device *to_panel_mipi_dbi_device(struct drm_device *dev)
+{
+ return container_of(drm_to_mipi_dbi_dev(dev), struct panel_mipi_dbi_device, dbidev);
+}
+
+static const u64 panel_mipi_dbi_plane_format_modifiers[] = {
+ DRM_MIPI_DBI_PLANE_FORMAT_MODIFIERS,
+};
+
+static const struct drm_plane_helper_funcs panel_mipi_dbi_plane_helper_funcs = {
+ DRM_MIPI_DBI_PLANE_HELPER_FUNCS,
+};
+
+static const struct drm_plane_funcs panel_mipi_dbi_plane_funcs = {
+ DRM_MIPI_DBI_PLANE_FUNCS,
+ .destroy = drm_plane_cleanup,
+};
+
+static void panel_mipi_dbi_crtc_helper_atomic_enable(struct drm_crtc *crtc,
+ struct drm_atomic_state *state)
{
- struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev);
+ struct drm_device *drm = crtc->dev;
+ struct panel_mipi_dbi_device *panel_mipi_dbi = to_panel_mipi_dbi_device(drm);
+ struct mipi_dbi_dev *dbidev = &panel_mipi_dbi->dbidev;
struct mipi_dbi *dbi = &dbidev->dbi;
int ret, idx;
- if (!drm_dev_enter(pipe->crtc.dev, &idx))
+ if (!drm_dev_enter(drm, &idx))
return;
- drm_dbg(pipe->crtc.dev, "\n");
+ drm_dbg(drm, "\n");
ret = mipi_dbi_poweron_conditional_reset(dbidev);
if (ret < 0)
@@ -252,13 +280,40 @@ static void panel_mipi_dbi_enable(struct drm_simple_display_pipe *pipe,
if (!ret)
panel_mipi_dbi_commands_execute(dbi, dbidev->driver_private);
- mipi_dbi_enable_flush(dbidev, crtc_state, plane_state);
+ backlight_enable(dbidev->backlight);
out_exit:
drm_dev_exit(idx);
}
-static const struct drm_simple_display_pipe_funcs panel_mipi_dbi_pipe_funcs = {
- DRM_MIPI_DBI_SIMPLE_DISPLAY_PIPE_FUNCS(panel_mipi_dbi_enable),
+static const struct drm_crtc_helper_funcs panel_mipi_dbi_crtc_helper_funcs = {
+ DRM_MIPI_DBI_CRTC_HELPER_FUNCS,
+ .atomic_enable = panel_mipi_dbi_crtc_helper_atomic_enable,
+};
+
+static const struct drm_crtc_funcs panel_mipi_dbi_crtc_funcs = {
+ DRM_MIPI_DBI_CRTC_FUNCS,
+ .destroy = drm_crtc_cleanup,
+};
+
+static const struct drm_encoder_funcs panel_mipi_dbi_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
+static const struct drm_connector_helper_funcs panel_mipi_dbi_connector_helper_funcs = {
+ DRM_MIPI_DBI_CONNECTOR_HELPER_FUNCS,
+};
+
+static const struct drm_connector_funcs panel_mipi_dbi_connector_funcs = {
+ DRM_MIPI_DBI_CONNECTOR_FUNCS,
+ .destroy = drm_connector_cleanup,
+};
+
+static const struct drm_mode_config_helper_funcs panel_mipi_dbi_mode_config_helper_funcs = {
+ DRM_MIPI_DBI_MODE_CONFIG_HELPER_FUNCS,
+};
+
+static const struct drm_mode_config_funcs panel_mipi_dbi_mode_config_funcs = {
+ DRM_MIPI_DBI_MODE_CONFIG_FUNCS,
};
DEFINE_DRM_GEM_DMA_FOPS(panel_mipi_dbi_fops);
@@ -317,20 +372,27 @@ static int panel_mipi_dbi_get_mode(struct mipi_dbi_dev *dbidev, struct drm_displ
static int panel_mipi_dbi_spi_probe(struct spi_device *spi)
{
struct device *dev = &spi->dev;
- struct drm_display_mode mode;
+ struct panel_mipi_dbi_device *panel_mipi_dbi;
struct mipi_dbi_dev *dbidev;
struct drm_device *drm;
+ struct drm_display_mode mode;
struct mipi_dbi *dbi;
struct gpio_desc *dc;
unsigned int bpp;
size_t buf_size;
u32 formats[2];
+ struct drm_plane *plane;
+ struct drm_crtc *crtc;
+ struct drm_encoder *encoder;
+ struct drm_connector *connector;
int ret;
- dbidev = devm_drm_dev_alloc(dev, &panel_mipi_dbi_driver, struct mipi_dbi_dev, drm);
- if (IS_ERR(dbidev))
- return PTR_ERR(dbidev);
-
+ panel_mipi_dbi = devm_drm_dev_alloc(dev, &panel_mipi_dbi_driver,
+ struct panel_mipi_dbi_device,
+ dbidev.drm);
+ if (IS_ERR(panel_mipi_dbi))
+ return PTR_ERR(panel_mipi_dbi);
+ dbidev = &panel_mipi_dbi->dbidev;
dbi = &dbidev->dbi;
drm = &dbidev->drm;
@@ -377,9 +439,54 @@ static int panel_mipi_dbi_spi_probe(struct spi_device *spi)
return ret;
buf_size = DIV_ROUND_UP(mode.hdisplay * mode.vdisplay * bpp, 8);
- ret = mipi_dbi_dev_init_with_formats(dbidev, &panel_mipi_dbi_pipe_funcs,
- formats, ARRAY_SIZE(formats),
- &mode, 0, buf_size);
+ ret = drm_mipi_dbi_dev_init(dbidev, &mode, formats[0], 0, buf_size);
+ if (ret)
+ return ret;
+
+ ret = drmm_mode_config_init(drm);
+ if (ret)
+ return ret;
+
+ drm->mode_config.min_width = dbidev->mode.hdisplay;
+ drm->mode_config.max_width = dbidev->mode.hdisplay;
+ drm->mode_config.min_height = dbidev->mode.vdisplay;
+ drm->mode_config.max_height = dbidev->mode.vdisplay;
+ drm->mode_config.funcs = &panel_mipi_dbi_mode_config_funcs;
+ drm->mode_config.preferred_depth = bpp;
+ drm->mode_config.helper_private = &panel_mipi_dbi_mode_config_helper_funcs;
+
+ plane = &panel_mipi_dbi->plane;
+ ret = drm_universal_plane_init(drm, plane, 0, &panel_mipi_dbi_plane_funcs,
+ formats, ARRAY_SIZE(formats),
+ panel_mipi_dbi_plane_format_modifiers,
+ DRM_PLANE_TYPE_PRIMARY, NULL);
+ if (ret)
+ return ret;
+ drm_plane_helper_add(plane, &panel_mipi_dbi_plane_helper_funcs);
+ drm_plane_enable_fb_damage_clips(plane);
+
+ crtc = &panel_mipi_dbi->crtc;
+ ret = drm_crtc_init_with_planes(drm, crtc, plane, NULL, &panel_mipi_dbi_crtc_funcs,
+ NULL);
+ if (ret)
+ return ret;
+ drm_crtc_helper_add(crtc, &panel_mipi_dbi_crtc_helper_funcs);
+
+ encoder = &panel_mipi_dbi->encoder;
+ ret = drm_encoder_init(drm, encoder, &panel_mipi_dbi_encoder_funcs,
+ DRM_MODE_ENCODER_NONE, NULL);
+ if (ret)
+ return ret;
+ encoder->possible_crtcs = drm_crtc_mask(crtc);
+
+ connector = &panel_mipi_dbi->connector;
+ ret = drm_connector_init(drm, connector, &panel_mipi_dbi_connector_funcs,
+ DRM_MODE_CONNECTOR_SPI);
+ if (ret)
+ return ret;
+ drm_connector_helper_add(connector, &panel_mipi_dbi_connector_helper_funcs);
+
+ ret = drm_connector_attach_encoder(connector, encoder);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c b/drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c
index e32f3c8d7b84..2db221f6fc3a 100644
--- a/drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c
+++ b/drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c
@@ -759,6 +759,46 @@ static void ttm_bo_validate_move_fence_not_signaled(struct kunit *test)
ttm_mock_manager_fini(priv->ttm_dev, snd_mem);
}
+static void ttm_bo_validate_swapout(struct kunit *test)
+{
+ u32 mem_type = TTM_PL_TT;
+ struct ttm_test_devices *priv = test->priv;
+ struct ttm_operation_ctx ctx_init = { };
+ enum ttm_bo_type bo_type = ttm_bo_type_device;
+ struct ttm_resource_manager *man;
+ struct ttm_placement *placement;
+ struct ttm_buffer_object *bo;
+ struct ttm_place *place;
+ int err;
+ s64 swapped;
+
+ ttm_mock_manager_init(priv->ttm_dev, mem_type, MANAGER_SIZE);
+ man = ttm_manager_type(priv->ttm_dev, mem_type);
+ KUNIT_ASSERT_NOT_NULL(test, man);
+
+ place = ttm_place_kunit_init(test, mem_type, 0);
+ placement = ttm_placement_kunit_init(test, place, 1);
+
+ bo = kunit_kzalloc(test, sizeof(*bo), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, bo);
+
+ drm_gem_private_object_init(priv->drm, &bo->base, MANAGER_SIZE);
+ err = ttm_bo_init_reserved(priv->ttm_dev, bo, bo_type, placement,
+ PAGE_SIZE, &ctx_init, NULL, NULL,
+ &dummy_ttm_bo_destroy);
+ KUNIT_EXPECT_EQ(test, err, 0);
+ dma_resv_unlock(bo->base.resv);
+
+ swapped = ttm_bo_swapout(priv->ttm_dev, &ctx_init, man, GFP_KERNEL,
+ MANAGER_SIZE / PAGE_SIZE);
+ KUNIT_EXPECT_EQ(test, swapped, MANAGER_SIZE / PAGE_SIZE);
+ KUNIT_EXPECT_EQ(test, bo->resource->mem_type, TTM_PL_SYSTEM);
+ KUNIT_EXPECT_TRUE(test, bo->ttm->page_flags & TTM_TT_FLAG_SWAPPED);
+
+ ttm_bo_fini(bo);
+ ttm_mock_manager_fini(priv->ttm_dev, mem_type);
+}
+
static void ttm_bo_validate_happy_evict(struct kunit *test)
{
u32 mem_type = TTM_PL_VRAM, mem_multihop = TTM_PL_TT,
@@ -1153,6 +1193,7 @@ static struct kunit_case ttm_bo_validate_test_cases[] = {
KUNIT_CASE(ttm_bo_validate_move_fence_signaled),
KUNIT_CASE_PARAM(ttm_bo_validate_move_fence_not_signaled,
ttm_bo_validate_wait_gen_params),
+ KUNIT_CASE(ttm_bo_validate_swapout),
KUNIT_CASE(ttm_bo_validate_happy_evict),
KUNIT_CASE(ttm_bo_validate_all_pinned_evict),
KUNIT_CASE(ttm_bo_validate_allowed_only_evict),
diff --git a/drivers/gpu/drm/ttm/tests/ttm_device_test.c b/drivers/gpu/drm/ttm/tests/ttm_device_test.c
index 2d55ad34fe48..db4b4a09a73f 100644
--- a/drivers/gpu/drm/ttm/tests/ttm_device_test.c
+++ b/drivers/gpu/drm/ttm/tests/ttm_device_test.c
@@ -176,7 +176,7 @@ static void ttm_device_init_pools(struct kunit *test)
if (ttm_pool_uses_dma_alloc(pool))
KUNIT_ASSERT_FALSE(test,
- list_empty(&pt.pages));
+ !list_lru_count(&pt.pages));
}
}
}
diff --git a/drivers/gpu/drm/ttm/tests/ttm_pool_test.c b/drivers/gpu/drm/ttm/tests/ttm_pool_test.c
index 11c92bd75779..01197014b83f 100644
--- a/drivers/gpu/drm/ttm/tests/ttm_pool_test.c
+++ b/drivers/gpu/drm/ttm/tests/ttm_pool_test.c
@@ -248,7 +248,7 @@ static void ttm_pool_alloc_order_caching_match(struct kunit *test)
pool = ttm_pool_pre_populated(test, size, caching);
pt = &pool->caching[caching].orders[order];
- KUNIT_ASSERT_FALSE(test, list_empty(&pt->pages));
+ KUNIT_ASSERT_FALSE(test, !list_lru_count(&pt->pages));
tt = ttm_tt_kunit_init(test, 0, caching, size);
KUNIT_ASSERT_NOT_NULL(test, tt);
@@ -256,7 +256,7 @@ static void ttm_pool_alloc_order_caching_match(struct kunit *test)
err = ttm_pool_alloc(pool, tt, &simple_ctx);
KUNIT_ASSERT_EQ(test, err, 0);
- KUNIT_ASSERT_TRUE(test, list_empty(&pt->pages));
+ KUNIT_ASSERT_TRUE(test, !list_lru_count(&pt->pages));
ttm_pool_free(pool, tt);
ttm_tt_fini(tt);
@@ -282,8 +282,8 @@ static void ttm_pool_alloc_caching_mismatch(struct kunit *test)
tt = ttm_tt_kunit_init(test, 0, tt_caching, size);
KUNIT_ASSERT_NOT_NULL(test, tt);
- KUNIT_ASSERT_FALSE(test, list_empty(&pt_pool->pages));
- KUNIT_ASSERT_TRUE(test, list_empty(&pt_tt->pages));
+ KUNIT_ASSERT_FALSE(test, !list_lru_count(&pt_pool->pages));
+ KUNIT_ASSERT_TRUE(test, !list_lru_count(&pt_tt->pages));
err = ttm_pool_alloc(pool, tt, &simple_ctx);
KUNIT_ASSERT_EQ(test, err, 0);
@@ -291,8 +291,8 @@ static void ttm_pool_alloc_caching_mismatch(struct kunit *test)
ttm_pool_free(pool, tt);
ttm_tt_fini(tt);
- KUNIT_ASSERT_FALSE(test, list_empty(&pt_pool->pages));
- KUNIT_ASSERT_FALSE(test, list_empty(&pt_tt->pages));
+ KUNIT_ASSERT_FALSE(test, !list_lru_count(&pt_pool->pages));
+ KUNIT_ASSERT_FALSE(test, !list_lru_count(&pt_tt->pages));
ttm_pool_fini(pool);
}
@@ -316,8 +316,8 @@ static void ttm_pool_alloc_order_mismatch(struct kunit *test)
tt = ttm_tt_kunit_init(test, 0, caching, snd_size);
KUNIT_ASSERT_NOT_NULL(test, tt);
- KUNIT_ASSERT_FALSE(test, list_empty(&pt_pool->pages));
- KUNIT_ASSERT_TRUE(test, list_empty(&pt_tt->pages));
+ KUNIT_ASSERT_FALSE(test, !list_lru_count(&pt_pool->pages));
+ KUNIT_ASSERT_TRUE(test, !list_lru_count(&pt_tt->pages));
err = ttm_pool_alloc(pool, tt, &simple_ctx);
KUNIT_ASSERT_EQ(test, err, 0);
@@ -325,8 +325,8 @@ static void ttm_pool_alloc_order_mismatch(struct kunit *test)
ttm_pool_free(pool, tt);
ttm_tt_fini(tt);
- KUNIT_ASSERT_FALSE(test, list_empty(&pt_pool->pages));
- KUNIT_ASSERT_FALSE(test, list_empty(&pt_tt->pages));
+ KUNIT_ASSERT_FALSE(test, !list_lru_count(&pt_pool->pages));
+ KUNIT_ASSERT_FALSE(test, !list_lru_count(&pt_tt->pages));
ttm_pool_fini(pool);
}
@@ -352,12 +352,12 @@ static void ttm_pool_free_dma_alloc(struct kunit *test)
ttm_pool_alloc(pool, tt, &simple_ctx);
pt = &pool->caching[caching].orders[order];
- KUNIT_ASSERT_TRUE(test, list_empty(&pt->pages));
+ KUNIT_ASSERT_TRUE(test, !list_lru_count(&pt->pages));
ttm_pool_free(pool, tt);
ttm_tt_fini(tt);
- KUNIT_ASSERT_FALSE(test, list_empty(&pt->pages));
+ KUNIT_ASSERT_FALSE(test, !list_lru_count(&pt->pages));
ttm_pool_fini(pool);
}
@@ -383,12 +383,12 @@ static void ttm_pool_free_no_dma_alloc(struct kunit *test)
ttm_pool_alloc(pool, tt, &simple_ctx);
pt = &pool->caching[caching].orders[order];
- KUNIT_ASSERT_TRUE(test, list_is_singular(&pt->pages));
+ KUNIT_ASSERT_TRUE(test, list_lru_count(&pt->pages) == 1);
ttm_pool_free(pool, tt);
ttm_tt_fini(tt);
- KUNIT_ASSERT_TRUE(test, list_is_singular(&pt->pages));
+ KUNIT_ASSERT_TRUE(test, list_lru_count(&pt->pages) == 1);
ttm_pool_fini(pool);
}
@@ -404,11 +404,11 @@ static void ttm_pool_fini_basic(struct kunit *test)
pool = ttm_pool_pre_populated(test, size, caching);
pt = &pool->caching[caching].orders[order];
- KUNIT_ASSERT_FALSE(test, list_empty(&pt->pages));
+ KUNIT_ASSERT_FALSE(test, !list_lru_count(&pt->pages));
ttm_pool_fini(pool);
- KUNIT_ASSERT_TRUE(test, list_empty(&pt->pages));
+ KUNIT_ASSERT_TRUE(test, !list_lru_count(&pt->pages));
}
static struct kunit_case ttm_pool_test_cases[] = {
diff --git a/drivers/gpu/drm/ttm/ttm_backup.c b/drivers/gpu/drm/ttm/ttm_backup.c
index 6bd4c123d94c..81df4cb5606b 100644
--- a/drivers/gpu/drm/ttm/ttm_backup.c
+++ b/drivers/gpu/drm/ttm/ttm_backup.c
@@ -44,18 +44,20 @@ void ttm_backup_drop(struct file *backup, pgoff_t handle)
* @dst: The struct page to copy into.
* @handle: The handle returned when the page was backed up.
* @intr: Try to perform waits interruptible or at least killable.
+ * @additional_gfp: GFP mask to add to the default GFP mask if any.
*
* Return: 0 on success, Negative error code on failure, notably
* -EINTR if @intr was set to true and a signal is pending.
*/
int ttm_backup_copy_page(struct file *backup, struct page *dst,
- pgoff_t handle, bool intr)
+ pgoff_t handle, bool intr, gfp_t additional_gfp)
{
struct address_space *mapping = backup->f_mapping;
struct folio *from_folio;
pgoff_t idx = ttm_backup_handle_to_shmem_idx(handle);
- from_folio = shmem_read_folio(mapping, idx);
+ from_folio = shmem_read_folio_gfp(mapping, idx, mapping_gfp_mask(mapping)
+ | additional_gfp);
if (IS_ERR(from_folio))
return PTR_ERR(from_folio);
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index 34ce53b4bdb9..d85f0a37ac35 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -32,6 +32,7 @@
#define pr_fmt(fmt) "[TTM] " fmt
#include <drm/drm_print.h>
+#include <drm/drm_util.h>
#include <drm/ttm/ttm_allocation.h>
#include <drm/ttm/ttm_bo.h>
#include <drm/ttm/ttm_placement.h>
@@ -1208,9 +1209,9 @@ const struct ttm_lru_walk_ops ttm_swap_ops = {
* @man: The resource manager whose resources / buffer objects are
* goint to be swapped out.
* @gfp_flags: The gfp flags used for shmem page allocations.
- * @target: The desired number of bytes to swap out.
+ * @target: The desired number of pages to swap out.
*
- * Return: The number of bytes actually swapped out, or negative error code
+ * Return: The number of pages actually swapped out, or negative error code
* on error.
*/
s64 ttm_bo_swapout(struct ttm_device *bdev, struct ttm_operation_ctx *ctx,
@@ -1230,6 +1231,7 @@ s64 ttm_bo_swapout(struct ttm_device *bdev, struct ttm_operation_ctx *ctx,
return ttm_lru_walk_for_evict(&swapout_walk.walk, bdev, man, target);
}
+EXPORT_SYMBOL_FOR_TESTS_ONLY(ttm_bo_swapout);
void ttm_bo_tt_destroy(struct ttm_buffer_object *bo)
{
diff --git a/drivers/gpu/drm/ttm/ttm_pool.c b/drivers/gpu/drm/ttm/ttm_pool.c
index c0d95559197c..26a3689e5fd9 100644
--- a/drivers/gpu/drm/ttm/ttm_pool.c
+++ b/drivers/gpu/drm/ttm/ttm_pool.c
@@ -116,10 +116,11 @@ struct ttm_pool_tt_restore {
static unsigned long page_pool_size;
-MODULE_PARM_DESC(page_pool_size, "Number of pages in the WC/UC/DMA pool");
+MODULE_PARM_DESC(page_pool_size, "Number of pages in the WC/UC/DMA pool per NUMA node");
module_param(page_pool_size, ulong, 0644);
-static atomic_long_t allocated_pages;
+static unsigned long pool_node_limit[MAX_NUMNODES];
+static atomic_long_t allocated_pages[MAX_NUMNODES];
static struct ttm_pool_type global_write_combined[NR_PAGE_ORDERS];
static struct ttm_pool_type global_uncached[NR_PAGE_ORDERS];
@@ -132,6 +133,16 @@ static struct list_head shrinker_list;
static struct shrinker *mm_shrinker;
static DECLARE_RWSEM(pool_shrink_rwsem);
+static int ttm_pool_nid(struct ttm_pool *pool)
+{
+ int nid = NUMA_NO_NODE;
+ if (pool)
+ nid = pool->nid;
+ if (nid == NUMA_NO_NODE)
+ nid = numa_node_id();
+ return nid;
+}
+
/* Allocate pages of size 1 << order with the given gfp_flags */
static struct page *ttm_pool_alloc_page(struct ttm_pool *pool, gfp_t gfp_flags,
unsigned int order)
@@ -159,8 +170,10 @@ static struct page *ttm_pool_alloc_page(struct ttm_pool *pool, gfp_t gfp_flags,
if (!ttm_pool_uses_dma_alloc(pool)) {
p = alloc_pages_node(pool->nid, gfp_flags, order);
- if (p)
+ if (p) {
p->private = order;
+ mod_lruvec_page_state(p, NR_GPU_ACTIVE, 1 << order);
+ }
return p;
}
@@ -195,7 +208,7 @@ error_free:
/* Reset the caching and pages of size 1 << order */
static void ttm_pool_free_page(struct ttm_pool *pool, enum ttm_caching caching,
- unsigned int order, struct page *p)
+ unsigned int order, struct page *p, bool reclaim)
{
unsigned long attr = DMA_ATTR_FORCE_CONTIGUOUS;
struct ttm_pool_dma *dma;
@@ -210,6 +223,8 @@ static void ttm_pool_free_page(struct ttm_pool *pool, enum ttm_caching caching,
#endif
if (!pool || !ttm_pool_uses_dma_alloc(pool)) {
+ mod_lruvec_page_state(p, reclaim ? NR_GPU_RECLAIM : NR_GPU_ACTIVE,
+ -(1 << order));
__free_pages(p, order);
return;
}
@@ -285,6 +300,7 @@ static void ttm_pool_unmap(struct ttm_pool *pool, dma_addr_t dma_addr,
static void ttm_pool_type_give(struct ttm_pool_type *pt, struct page *p)
{
unsigned int i, num_pages = 1 << pt->order;
+ int nid = page_to_nid(p);
for (i = 0; i < num_pages; ++i) {
if (PageHighMem(p))
@@ -293,25 +309,41 @@ static void ttm_pool_type_give(struct ttm_pool_type *pt, struct page *p)
clear_page(page_address(p + i));
}
- spin_lock(&pt->lock);
- list_add(&p->lru, &pt->pages);
- spin_unlock(&pt->lock);
- atomic_long_add(1 << pt->order, &allocated_pages);
+ INIT_LIST_HEAD(&p->lru);
+ rcu_read_lock();
+ list_lru_add(&pt->pages, &p->lru, nid, NULL);
+ rcu_read_unlock();
+
+ atomic_long_add(num_pages, &allocated_pages[nid]);
+ mod_lruvec_page_state(p, NR_GPU_ACTIVE, -num_pages);
+ mod_lruvec_page_state(p, NR_GPU_RECLAIM, num_pages);
}
-/* Take pages from a specific pool_type, return NULL when nothing available */
-static struct page *ttm_pool_type_take(struct ttm_pool_type *pt)
+static enum lru_status take_one_from_lru(struct list_head *item,
+ struct list_lru_one *list,
+ void *cb_arg)
{
- struct page *p;
+ struct page **out_page = cb_arg;
+ struct page *p = container_of(item, struct page, lru);
+ list_lru_isolate(list, item);
- spin_lock(&pt->lock);
- p = list_first_entry_or_null(&pt->pages, typeof(*p), lru);
- if (p) {
- atomic_long_sub(1 << pt->order, &allocated_pages);
- list_del(&p->lru);
- }
- spin_unlock(&pt->lock);
+ *out_page = p;
+ return LRU_REMOVED;
+}
+/* Take pages from a specific pool_type, return NULL when nothing available */
+static struct page *ttm_pool_type_take(struct ttm_pool_type *pt, int nid)
+{
+ int ret;
+ struct page *p = NULL;
+ unsigned long nr_to_walk = 1;
+
+ ret = list_lru_walk_node(&pt->pages, nid, take_one_from_lru, (void *)&p, &nr_to_walk);
+ if (ret == 1 && p) {
+ atomic_long_sub(1 << pt->order, &allocated_pages[nid]);
+ mod_lruvec_page_state(p, NR_GPU_ACTIVE, (1 << pt->order));
+ mod_lruvec_page_state(p, NR_GPU_RECLAIM, -(1 << pt->order));
+ }
return p;
}
@@ -322,25 +354,47 @@ static void ttm_pool_type_init(struct ttm_pool_type *pt, struct ttm_pool *pool,
pt->pool = pool;
pt->caching = caching;
pt->order = order;
- spin_lock_init(&pt->lock);
- INIT_LIST_HEAD(&pt->pages);
+ list_lru_init(&pt->pages);
spin_lock(&shrinker_lock);
list_add_tail(&pt->shrinker_list, &shrinker_list);
spin_unlock(&shrinker_lock);
}
+static enum lru_status pool_move_to_dispose_list(struct list_head *item,
+ struct list_lru_one *list,
+ void *cb_arg)
+{
+ struct list_head *dispose = cb_arg;
+
+ list_lru_isolate_move(list, item, dispose);
+
+ return LRU_REMOVED;
+}
+
+static void ttm_pool_dispose_list(struct ttm_pool_type *pt,
+ struct list_head *dispose)
+{
+ while (!list_empty(dispose)) {
+ struct page *p;
+ p = list_first_entry(dispose, struct page, lru);
+ list_del_init(&p->lru);
+ atomic_long_sub(1 << pt->order, &allocated_pages[page_to_nid(p)]);
+ ttm_pool_free_page(pt->pool, pt->caching, pt->order, p, true);
+ }
+}
+
/* Remove a pool_type from the global shrinker list and free all pages */
static void ttm_pool_type_fini(struct ttm_pool_type *pt)
{
- struct page *p;
+ LIST_HEAD(dispose);
spin_lock(&shrinker_lock);
list_del(&pt->shrinker_list);
spin_unlock(&shrinker_lock);
- while ((p = ttm_pool_type_take(pt)))
- ttm_pool_free_page(pt->pool, pt->caching, pt->order, p);
+ list_lru_walk(&pt->pages, pool_move_to_dispose_list, &dispose, LONG_MAX);
+ ttm_pool_dispose_list(pt, &dispose);
}
/* Return the pool_type to use for the given caching and order */
@@ -354,17 +408,11 @@ static struct ttm_pool_type *ttm_pool_select_type(struct ttm_pool *pool,
#ifdef CONFIG_X86
switch (caching) {
case ttm_write_combined:
- if (pool->nid != NUMA_NO_NODE)
- return &pool->caching[caching].orders[order];
-
if (ttm_pool_uses_dma32(pool))
return &global_dma32_write_combined[order];
return &global_write_combined[order];
case ttm_uncached:
- if (pool->nid != NUMA_NO_NODE)
- return &pool->caching[caching].orders[order];
-
if (ttm_pool_uses_dma32(pool))
return &global_dma32_uncached[order];
@@ -377,12 +425,12 @@ static struct ttm_pool_type *ttm_pool_select_type(struct ttm_pool *pool,
return NULL;
}
-/* Free pages using the global shrinker list */
-static unsigned int ttm_pool_shrink(void)
+/* Free pages using the per-node shrinker list */
+static unsigned int ttm_pool_shrink(int nid, unsigned long num_to_free)
{
+ LIST_HEAD(dispose);
struct ttm_pool_type *pt;
unsigned int num_pages;
- struct page *p;
down_read(&pool_shrink_rwsem);
spin_lock(&shrinker_lock);
@@ -390,13 +438,10 @@ static unsigned int ttm_pool_shrink(void)
list_move_tail(&pt->shrinker_list, &shrinker_list);
spin_unlock(&shrinker_lock);
- p = ttm_pool_type_take(pt);
- if (p) {
- ttm_pool_free_page(pt->pool, pt->caching, pt->order, p);
- num_pages = 1 << pt->order;
- } else {
- num_pages = 0;
- }
+ num_pages = list_lru_walk_node(&pt->pages, nid, pool_move_to_dispose_list, &dispose, &num_to_free);
+ num_pages *= 1 << pt->order;
+
+ ttm_pool_dispose_list(pt, &dispose);
up_read(&pool_shrink_rwsem);
return num_pages;
@@ -484,7 +529,7 @@ static pgoff_t ttm_pool_unmap_and_free(struct ttm_pool *pool, struct page *page,
if (pt)
ttm_pool_type_give(pt, page);
else
- ttm_pool_free_page(pool, caching, order, page);
+ ttm_pool_free_page(pool, caching, order, page, false);
return nr;
}
@@ -530,6 +575,8 @@ static int ttm_pool_restore_commit(struct ttm_pool_tt_restore *restore,
p = first_page[i];
if (ttm_backup_page_ptr_is_handle(p)) {
unsigned long handle = ttm_backup_page_ptr_to_handle(p);
+ gfp_t additional_gfp = ctx->gfp_retry_mayfail ?
+ __GFP_RETRY_MAYFAIL | __GFP_NOWARN : 0;
if (IS_ENABLED(CONFIG_FAULT_INJECTION) && ctx->interruptible &&
should_fail(&backup_fault_inject, 1)) {
@@ -543,7 +590,8 @@ static int ttm_pool_restore_commit(struct ttm_pool_tt_restore *restore,
}
ret = ttm_backup_copy_page(backup, restore->alloced_page + i,
- handle, ctx->interruptible);
+ handle, ctx->interruptible,
+ additional_gfp);
if (ret)
break;
@@ -726,7 +774,7 @@ static int __ttm_pool_alloc(struct ttm_pool *pool, struct ttm_tt *tt,
gfp_flags |= __GFP_ZERO;
if (ctx->gfp_retry_mayfail)
- gfp_flags |= __GFP_RETRY_MAYFAIL;
+ gfp_flags |= __GFP_RETRY_MAYFAIL | __GFP_NOWARN;
if (ttm_pool_uses_dma32(pool))
gfp_flags |= GFP_DMA32;
@@ -744,7 +792,8 @@ static int __ttm_pool_alloc(struct ttm_pool *pool, struct ttm_tt *tt,
p = NULL;
pt = ttm_pool_select_type(pool, page_caching, order);
if (pt && allow_pools)
- p = ttm_pool_type_take(pt);
+ p = ttm_pool_type_take(pt, ttm_pool_nid(pool));
+
/*
* If that fails or previously failed, allocate from system.
* Note that this also disallows additional pool allocations using
@@ -789,7 +838,7 @@ static int __ttm_pool_alloc(struct ttm_pool *pool, struct ttm_tt *tt,
return 0;
error_free_page:
- ttm_pool_free_page(pool, page_caching, order, p);
+ ttm_pool_free_page(pool, page_caching, order, p, false);
error_free_all:
if (tt->restore)
@@ -893,10 +942,14 @@ int ttm_pool_restore_and_alloc(struct ttm_pool *pool, struct ttm_tt *tt,
*/
void ttm_pool_free(struct ttm_pool *pool, struct ttm_tt *tt)
{
+ int nid = ttm_pool_nid(pool);
+
ttm_pool_free_range(pool, tt, tt->caching, 0, tt->num_pages);
- while (atomic_long_read(&allocated_pages) > page_pool_size)
- ttm_pool_shrink();
+ while (atomic_long_read(&allocated_pages[nid]) > pool_node_limit[nid]) {
+ unsigned long diff = atomic_long_read(&allocated_pages[nid]) - pool_node_limit[nid];
+ ttm_pool_shrink(nid, diff);
+ }
}
EXPORT_SYMBOL(ttm_pool_free);
@@ -1151,9 +1204,9 @@ static unsigned long ttm_pool_shrinker_scan(struct shrinker *shrink,
unsigned long num_freed = 0;
do
- num_freed += ttm_pool_shrink();
+ num_freed += ttm_pool_shrink(sc->nid, sc->nr_to_scan);
while (num_freed < sc->nr_to_scan &&
- atomic_long_read(&allocated_pages));
+ atomic_long_read(&allocated_pages[sc->nid]));
sc->nr_scanned = num_freed;
@@ -1164,7 +1217,7 @@ static unsigned long ttm_pool_shrinker_scan(struct shrinker *shrink,
static unsigned long ttm_pool_shrinker_count(struct shrinker *shrink,
struct shrink_control *sc)
{
- unsigned long num_pages = atomic_long_read(&allocated_pages);
+ unsigned long num_pages = atomic_long_read(&allocated_pages[sc->nid]);
return num_pages ? num_pages : SHRINK_EMPTY;
}
@@ -1173,16 +1226,7 @@ static unsigned long ttm_pool_shrinker_count(struct shrinker *shrink,
/* Count the number of pages available in a pool_type */
static unsigned int ttm_pool_type_count(struct ttm_pool_type *pt)
{
- unsigned int count = 0;
- struct page *p;
-
- spin_lock(&pt->lock);
- /* Only used for debugfs, the overhead doesn't matter */
- list_for_each_entry(p, &pt->pages, lru)
- ++count;
- spin_unlock(&pt->lock);
-
- return count;
+ return list_lru_count(&pt->pages);
}
/* Print a nice header for the order */
@@ -1210,8 +1254,12 @@ static void ttm_pool_debugfs_orders(struct ttm_pool_type *pt,
/* Dump the total amount of allocated pages */
static void ttm_pool_debugfs_footer(struct seq_file *m)
{
- seq_printf(m, "\ntotal\t: %8lu of %8lu\n",
- atomic_long_read(&allocated_pages), page_pool_size);
+ int nid;
+
+ for_each_node(nid) {
+ seq_printf(m, "\ntotal node%d\t: %8lu of %8lu\n", nid,
+ atomic_long_read(&allocated_pages[nid]), pool_node_limit[nid]);
+ }
}
/* Dump the information for the global pools */
@@ -1248,7 +1296,7 @@ int ttm_pool_debugfs(struct ttm_pool *pool, struct seq_file *m)
{
unsigned int i;
- if (!ttm_pool_uses_dma_alloc(pool) && pool->nid == NUMA_NO_NODE) {
+ if (!ttm_pool_uses_dma_alloc(pool)) {
seq_puts(m, "unused\n");
return 0;
}
@@ -1259,10 +1307,7 @@ int ttm_pool_debugfs(struct ttm_pool *pool, struct seq_file *m)
for (i = 0; i < TTM_NUM_CACHING_TYPES; ++i) {
if (!ttm_pool_select_type(pool, i, 0))
continue;
- if (ttm_pool_uses_dma_alloc(pool))
- seq_puts(m, "DMA ");
- else
- seq_printf(m, "N%d ", pool->nid);
+ seq_puts(m, "DMA ");
switch (i) {
case ttm_cached:
seq_puts(m, "\t:");
@@ -1291,11 +1336,15 @@ static int ttm_pool_debugfs_shrink_show(struct seq_file *m, void *data)
.nr_to_scan = TTM_SHRINKER_BATCH,
};
unsigned long count;
+ int nid;
fs_reclaim_acquire(GFP_KERNEL);
- count = ttm_pool_shrinker_count(mm_shrinker, &sc);
- seq_printf(m, "%lu/%lu\n", count,
- ttm_pool_shrinker_scan(mm_shrinker, &sc));
+ for_each_node(nid) {
+ sc.nid = nid;
+ count = ttm_pool_shrinker_count(mm_shrinker, &sc);
+ seq_printf(m, "%d: %lu/%lu\n", nid, count,
+ ttm_pool_shrinker_scan(mm_shrinker, &sc));
+ }
fs_reclaim_release(GFP_KERNEL);
return 0;
@@ -1304,6 +1353,23 @@ DEFINE_SHOW_ATTRIBUTE(ttm_pool_debugfs_shrink);
#endif
+static inline u64 ttm_get_node_memory_size(int nid)
+{
+ /*
+ * This is directly using si_meminfo_node implementation as the
+ * function is not exported.
+ */
+ int zone_type;
+ u64 managed_pages = 0;
+
+ pg_data_t *pgdat = NODE_DATA(nid);
+
+ for (zone_type = 0; zone_type < MAX_NR_ZONES; zone_type++)
+ managed_pages +=
+ zone_managed_pages(&pgdat->node_zones[zone_type]);
+ return managed_pages * PAGE_SIZE;
+}
+
/**
* ttm_pool_mgr_init - Initialize globals
*
@@ -1315,8 +1381,15 @@ int ttm_pool_mgr_init(unsigned long num_pages)
{
unsigned int i;
- if (!page_pool_size)
- page_pool_size = num_pages;
+ int nid;
+ for_each_node(nid) {
+ if (!page_pool_size) {
+ u64 node_size = ttm_get_node_memory_size(nid);
+ pool_node_limit[nid] = (node_size >> PAGE_SHIFT) / 2;
+ } else {
+ pool_node_limit[nid] = page_pool_size;
+ }
+ }
spin_lock_init(&shrinker_lock);
INIT_LIST_HEAD(&shrinker_list);
@@ -1343,7 +1416,7 @@ int ttm_pool_mgr_init(unsigned long num_pages)
#endif
#endif
- mm_shrinker = shrinker_alloc(0, "drm-ttm_pool");
+ mm_shrinker = shrinker_alloc(SHRINKER_NUMA_AWARE, "drm-ttm_pool");
if (!mm_shrinker)
return -ENOMEM;
diff --git a/drivers/gpu/drm/tyr/driver.rs b/drivers/gpu/drm/tyr/driver.rs
index beeffe36b6cb..611434641580 100644
--- a/drivers/gpu/drm/tyr/driver.rs
+++ b/drivers/gpu/drm/tyr/driver.rs
@@ -1,44 +1,56 @@
// SPDX-License-Identifier: GPL-2.0 or MIT
-use kernel::clk::Clk;
-use kernel::clk::OptionalClk;
-use kernel::device::Bound;
-use kernel::device::Core;
-use kernel::device::Device;
-use kernel::devres::Devres;
-use kernel::drm;
-use kernel::drm::ioctl;
-use kernel::io::poll;
-use kernel::new_mutex;
-use kernel::of;
-use kernel::platform;
-use kernel::prelude::*;
-use kernel::regulator;
-use kernel::regulator::Regulator;
-use kernel::sizes::SZ_2M;
-use kernel::sync::aref::ARef;
-use kernel::sync::Arc;
-use kernel::sync::Mutex;
-use kernel::time;
-
-use crate::file::File;
-use crate::gem::TyrObject;
-use crate::gpu;
-use crate::gpu::GpuInfo;
-use crate::regs;
+use kernel::{
+ clk::{
+ Clk,
+ OptionalClk, //
+ },
+ device::{
+ Bound,
+ Core,
+ Device, //
+ },
+ devres::Devres,
+ drm,
+ drm::ioctl,
+ io::poll,
+ new_mutex,
+ of,
+ platform,
+ prelude::*,
+ regulator,
+ regulator::Regulator,
+ sizes::SZ_2M,
+ sync::{
+ aref::ARef,
+ Arc,
+ Mutex, //
+ },
+ time, //
+};
+
+use crate::{
+ file::TyrDrmFileData,
+ gem::TyrObject,
+ gpu,
+ gpu::GpuInfo,
+ regs, //
+};
pub(crate) type IoMem = kernel::io::mem::IoMem<SZ_2M>;
+pub(crate) struct TyrDrmDriver;
+
/// Convenience type alias for the DRM device type for this driver.
-pub(crate) type TyrDevice = drm::Device<TyrDriver>;
+pub(crate) type TyrDrmDevice = drm::Device<TyrDrmDriver>;
#[pin_data(PinnedDrop)]
-pub(crate) struct TyrDriver {
- _device: ARef<TyrDevice>,
+pub(crate) struct TyrPlatformDriverData {
+ _device: ARef<TyrDrmDevice>,
}
#[pin_data(PinnedDrop)]
-pub(crate) struct TyrData {
+pub(crate) struct TyrDrmDeviceData {
pub(crate) pdev: ARef<platform::Device>,
#[pin]
@@ -61,9 +73,9 @@ pub(crate) struct TyrData {
// that it will be removed in a future patch.
//
// SAFETY: This will be removed in a future patch.
-unsafe impl Send for TyrData {}
+unsafe impl Send for TyrDrmDeviceData {}
// SAFETY: This will be removed in a future patch.
-unsafe impl Sync for TyrData {}
+unsafe impl Sync for TyrDrmDeviceData {}
fn issue_soft_reset(dev: &Device<Bound>, iomem: &Devres<IoMem>) -> Result {
regs::GPU_CMD.write(dev, iomem, regs::GPU_CMD_SOFT_RESET)?;
@@ -82,14 +94,14 @@ fn issue_soft_reset(dev: &Device<Bound>, iomem: &Devres<IoMem>) -> Result {
kernel::of_device_table!(
OF_TABLE,
MODULE_OF_TABLE,
- <TyrDriver as platform::Driver>::IdInfo,
+ <TyrPlatformDriverData as platform::Driver>::IdInfo,
[
(of::DeviceId::new(c"rockchip,rk3588-mali"), ()),
(of::DeviceId::new(c"arm,mali-valhall-csf"), ())
]
);
-impl platform::Driver for TyrDriver {
+impl platform::Driver for TyrPlatformDriverData {
type IdInfo = ();
const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE);
@@ -119,7 +131,7 @@ impl platform::Driver for TyrDriver {
let platform: ARef<platform::Device> = pdev.into();
- let data = try_pin_init!(TyrData {
+ let data = try_pin_init!(TyrDrmDeviceData {
pdev: platform.clone(),
clks <- new_mutex!(Clocks {
core: core_clk,
@@ -133,10 +145,10 @@ impl platform::Driver for TyrDriver {
gpu_info,
});
- let tdev: ARef<TyrDevice> = drm::Device::new(pdev.as_ref(), data)?;
- drm::driver::Registration::new_foreign_owned(&tdev, pdev.as_ref(), 0)?;
+ let ddev: ARef<TyrDrmDevice> = drm::Device::new(pdev.as_ref(), data)?;
+ drm::driver::Registration::new_foreign_owned(&ddev, pdev.as_ref(), 0)?;
- let driver = TyrDriver { _device: tdev };
+ let driver = TyrPlatformDriverData { _device: ddev };
// We need this to be dev_info!() because dev_dbg!() does not work at
// all in Rust for now, and we need to see whether probe succeeded.
@@ -146,12 +158,12 @@ impl platform::Driver for TyrDriver {
}
#[pinned_drop]
-impl PinnedDrop for TyrDriver {
+impl PinnedDrop for TyrPlatformDriverData {
fn drop(self: Pin<&mut Self>) {}
}
#[pinned_drop]
-impl PinnedDrop for TyrData {
+impl PinnedDrop for TyrDrmDeviceData {
fn drop(self: Pin<&mut Self>) {
// TODO: the type-state pattern for Clks will fix this.
let clks = self.clks.lock();
@@ -172,15 +184,15 @@ const INFO: drm::DriverInfo = drm::DriverInfo {
};
#[vtable]
-impl drm::Driver for TyrDriver {
- type Data = TyrData;
- type File = File;
+impl drm::Driver for TyrDrmDriver {
+ type Data = TyrDrmDeviceData;
+ type File = TyrDrmFileData;
type Object = drm::gem::Object<TyrObject>;
const INFO: drm::DriverInfo = INFO;
kernel::declare_drm_ioctls! {
- (PANTHOR_DEV_QUERY, drm_panthor_dev_query, ioctl::RENDER_ALLOW, File::dev_query),
+ (PANTHOR_DEV_QUERY, drm_panthor_dev_query, ioctl::RENDER_ALLOW, TyrDrmFileData::dev_query),
}
}
diff --git a/drivers/gpu/drm/tyr/file.rs b/drivers/gpu/drm/tyr/file.rs
index 0ef432947b73..31411da203c5 100644
--- a/drivers/gpu/drm/tyr/file.rs
+++ b/drivers/gpu/drm/tyr/file.rs
@@ -1,37 +1,41 @@
// SPDX-License-Identifier: GPL-2.0 or MIT
-use kernel::drm;
-use kernel::prelude::*;
-use kernel::uaccess::UserSlice;
-use kernel::uapi;
-
-use crate::driver::TyrDevice;
-use crate::TyrDriver;
+use kernel::{
+ drm,
+ prelude::*,
+ uaccess::UserSlice,
+ uapi, //
+};
+
+use crate::driver::{
+ TyrDrmDevice,
+ TyrDrmDriver, //
+};
#[pin_data]
-pub(crate) struct File {}
+pub(crate) struct TyrDrmFileData {}
/// Convenience type alias for our DRM `File` type
-pub(crate) type DrmFile = drm::file::File<File>;
+pub(crate) type TyrDrmFile = drm::file::File<TyrDrmFileData>;
-impl drm::file::DriverFile for File {
- type Driver = TyrDriver;
+impl drm::file::DriverFile for TyrDrmFileData {
+ type Driver = TyrDrmDriver;
fn open(_dev: &drm::Device<Self::Driver>) -> Result<Pin<KBox<Self>>> {
KBox::try_pin_init(try_pin_init!(Self {}), GFP_KERNEL)
}
}
-impl File {
+impl TyrDrmFileData {
pub(crate) fn dev_query(
- tdev: &TyrDevice,
+ ddev: &TyrDrmDevice,
devquery: &mut uapi::drm_panthor_dev_query,
- _file: &DrmFile,
+ _file: &TyrDrmFile,
) -> Result<u32> {
if devquery.pointer == 0 {
match devquery.type_ {
uapi::drm_panthor_dev_query_type_DRM_PANTHOR_DEV_QUERY_GPU_INFO => {
- devquery.size = core::mem::size_of_val(&tdev.gpu_info) as u32;
+ devquery.size = core::mem::size_of_val(&ddev.gpu_info) as u32;
Ok(0)
}
_ => Err(EINVAL),
@@ -45,7 +49,7 @@ impl File {
)
.writer();
- writer.write(&tdev.gpu_info)?;
+ writer.write(&ddev.gpu_info)?;
Ok(0)
}
diff --git a/drivers/gpu/drm/tyr/gem.rs b/drivers/gpu/drm/tyr/gem.rs
index 1273bf89dbd5..5cc6eb0b5d3f 100644
--- a/drivers/gpu/drm/tyr/gem.rs
+++ b/drivers/gpu/drm/tyr/gem.rs
@@ -1,18 +1,24 @@
// SPDX-License-Identifier: GPL-2.0 or MIT
-use crate::driver::TyrDevice;
-use crate::driver::TyrDriver;
-use kernel::drm::gem;
-use kernel::prelude::*;
+use kernel::{
+ drm::gem,
+ prelude::*, //
+};
+
+use crate::driver::{
+ TyrDrmDevice,
+ TyrDrmDriver, //
+};
/// GEM Object inner driver data
#[pin_data]
pub(crate) struct TyrObject {}
impl gem::DriverObject for TyrObject {
- type Driver = TyrDriver;
+ type Driver = TyrDrmDriver;
+ type Args = ();
- fn new(_dev: &TyrDevice, _size: usize) -> impl PinInit<Self, Error> {
+ fn new(_dev: &TyrDrmDevice, _size: usize, _args: ()) -> impl PinInit<Self, Error> {
try_pin_init!(TyrObject {})
}
}
diff --git a/drivers/gpu/drm/tyr/gpu.rs b/drivers/gpu/drm/tyr/gpu.rs
index 64ca8311d4e8..a88775160f98 100644
--- a/drivers/gpu/drm/tyr/gpu.rs
+++ b/drivers/gpu/drm/tyr/gpu.rs
@@ -1,20 +1,28 @@
// SPDX-License-Identifier: GPL-2.0 or MIT
-use core::ops::Deref;
-use core::ops::DerefMut;
-use kernel::bits::genmask_u32;
-use kernel::device::Bound;
-use kernel::device::Device;
-use kernel::devres::Devres;
-use kernel::io::poll;
-use kernel::platform;
-use kernel::prelude::*;
-use kernel::time::Delta;
-use kernel::transmute::AsBytes;
-use kernel::uapi;
-
-use crate::driver::IoMem;
-use crate::regs;
+use core::ops::{
+ Deref,
+ DerefMut, //
+};
+use kernel::{
+ bits::genmask_u32,
+ device::{
+ Bound,
+ Device, //
+ },
+ devres::Devres,
+ io::poll,
+ platform,
+ prelude::*,
+ time::Delta,
+ transmute::AsBytes,
+ uapi, //
+};
+
+use crate::{
+ driver::IoMem,
+ regs, //
+};
/// Struct containing information that can be queried by userspace. This is read from
/// the GPU's registers.
@@ -84,13 +92,11 @@ impl GpuInfo {
}
pub(crate) fn log(&self, pdev: &platform::Device) {
- let major = (self.gpu_id >> 16) & 0xff;
- let minor = (self.gpu_id >> 8) & 0xff;
- let status = self.gpu_id & 0xff;
+ let gpu_id = GpuId::from(self.gpu_id);
let model_name = if let Some(model) = GPU_MODELS
.iter()
- .find(|&f| f.major == major && f.minor == minor)
+ .find(|&f| f.arch_major == gpu_id.arch_major && f.prod_major == gpu_id.prod_major)
{
model.name
} else {
@@ -102,9 +108,9 @@ impl GpuInfo {
"mali-{} id 0x{:x} major 0x{:x} minor 0x{:x} status 0x{:x}",
model_name,
self.gpu_id >> 16,
- major,
- minor,
- status
+ gpu_id.ver_major,
+ gpu_id.ver_minor,
+ gpu_id.ver_status
);
dev_info!(
@@ -166,14 +172,14 @@ unsafe impl AsBytes for GpuInfo {}
struct GpuModels {
name: &'static str,
- major: u32,
- minor: u32,
+ arch_major: u32,
+ prod_major: u32,
}
const GPU_MODELS: [GpuModels; 1] = [GpuModels {
name: "g610",
- major: 10,
- minor: 7,
+ arch_major: 10,
+ prod_major: 7,
}];
#[allow(dead_code)]
diff --git a/drivers/gpu/drm/tyr/regs.rs b/drivers/gpu/drm/tyr/regs.rs
index d3a541cb37c6..611870c2e6af 100644
--- a/drivers/gpu/drm/tyr/regs.rs
+++ b/drivers/gpu/drm/tyr/regs.rs
@@ -7,12 +7,16 @@
// does.
#![allow(dead_code)]
-use kernel::bits::bit_u32;
-use kernel::device::Bound;
-use kernel::device::Device;
-use kernel::devres::Devres;
-use kernel::io::Io;
-use kernel::prelude::*;
+use kernel::{
+ bits::bit_u32,
+ device::{
+ Bound,
+ Device, //
+ },
+ devres::Devres,
+ io::Io,
+ prelude::*, //
+};
use crate::driver::IoMem;
diff --git a/drivers/gpu/drm/tyr/tyr.rs b/drivers/gpu/drm/tyr/tyr.rs
index 861d1db43072..9432ddd6b5b8 100644
--- a/drivers/gpu/drm/tyr/tyr.rs
+++ b/drivers/gpu/drm/tyr/tyr.rs
@@ -5,7 +5,7 @@
//! The name "Tyr" is inspired by Norse mythology, reflecting Arm's tradition of
//! naming their GPUs after Nordic mythological figures and places.
-use crate::driver::TyrDriver;
+use crate::driver::TyrPlatformDriverData;
mod driver;
mod file;
@@ -14,7 +14,7 @@ mod gpu;
mod regs;
kernel::module_platform_driver! {
- type: TyrDriver,
+ type: TyrPlatformDriverData,
name: "tyr",
authors: ["The Tyr driver authors"],
description: "Arm Mali Tyr DRM driver",
diff --git a/drivers/gpu/drm/v3d/v3d_drv.c b/drivers/gpu/drm/v3d/v3d_drv.c
index dd60acdf52c2..4b441afcb602 100644
--- a/drivers/gpu/drm/v3d/v3d_drv.c
+++ b/drivers/gpu/drm/v3d/v3d_drv.c
@@ -110,14 +110,12 @@ static int v3d_get_param_ioctl(struct drm_device *dev, void *data,
args->value = !!drm_gem_get_huge_mnt(dev);
return 0;
case DRM_V3D_PARAM_GLOBAL_RESET_COUNTER:
- mutex_lock(&v3d->reset_lock);
- args->value = v3d->reset_counter;
- mutex_unlock(&v3d->reset_lock);
+ args->value = atomic_read(&v3d->reset_counter);
return 0;
case DRM_V3D_PARAM_CONTEXT_RESET_COUNTER:
- mutex_lock(&v3d->reset_lock);
- args->value = v3d_priv->reset_counter;
- mutex_unlock(&v3d->reset_lock);
+ args->value = 0;
+ for (enum v3d_queue q = 0; q < V3D_MAX_QUEUES; q++)
+ args->value += atomic_read(&v3d_priv->stats[q]->reset_counter);
return 0;
default:
drm_dbg(dev, "Unknown parameter %d\n", args->param);
@@ -131,7 +129,7 @@ v3d_open(struct drm_device *dev, struct drm_file *file)
struct v3d_dev *v3d = to_v3d_dev(dev);
struct v3d_file_priv *v3d_priv;
struct drm_gpu_scheduler *sched;
- int i;
+ int i, ret;
v3d_priv = kzalloc_obj(*v3d_priv);
if (!v3d_priv)
@@ -140,40 +138,45 @@ v3d_open(struct drm_device *dev, struct drm_file *file)
v3d_priv->v3d = v3d;
for (i = 0; i < V3D_MAX_QUEUES; i++) {
- sched = &v3d->queue[i].sched;
- drm_sched_entity_init(&v3d_priv->sched_entity[i],
- DRM_SCHED_PRIORITY_NORMAL, &sched,
- 1, NULL);
+ v3d_priv->stats[i] = v3d_stats_alloc();
+ if (!v3d_priv->stats[i]) {
+ ret = -ENOMEM;
+ goto err_stats;
+ }
- memset(&v3d_priv->stats[i], 0, sizeof(v3d_priv->stats[i]));
- seqcount_init(&v3d_priv->stats[i].lock);
+ sched = &v3d->queue[i].sched;
+ ret = drm_sched_entity_init(&v3d_priv->sched_entity[i],
+ DRM_SCHED_PRIORITY_NORMAL, &sched,
+ 1, NULL);
+ if (ret)
+ goto err_sched;
}
v3d_perfmon_open_file(v3d_priv);
file->driver_priv = v3d_priv;
return 0;
+
+err_sched:
+ v3d_stats_put(v3d_priv->stats[i]);
+err_stats:
+ for (i--; i >= 0; i--) {
+ drm_sched_entity_destroy(&v3d_priv->sched_entity[i]);
+ v3d_stats_put(v3d_priv->stats[i]);
+ }
+ kfree(v3d_priv);
+ return ret;
}
static void
v3d_postclose(struct drm_device *dev, struct drm_file *file)
{
- struct v3d_dev *v3d = to_v3d_dev(dev);
struct v3d_file_priv *v3d_priv = file->driver_priv;
- unsigned long irqflags;
enum v3d_queue q;
for (q = 0; q < V3D_MAX_QUEUES; q++) {
- struct v3d_queue_state *queue = &v3d->queue[q];
- struct v3d_job *job = queue->active_job;
-
drm_sched_entity_destroy(&v3d_priv->sched_entity[q]);
-
- if (job && job->base.entity == &v3d_priv->sched_entity[q]) {
- spin_lock_irqsave(&queue->queue_lock, irqflags);
- job->file_priv = NULL;
- spin_unlock_irqrestore(&queue->queue_lock, irqflags);
- }
+ v3d_stats_put(v3d_priv->stats[q]);
}
v3d_perfmon_close_file(v3d_priv);
@@ -186,7 +189,7 @@ void v3d_get_stats(const struct v3d_stats *stats, u64 timestamp,
unsigned int seq;
do {
- seq = read_seqcount_begin(&stats->lock);
+ seq = raw_read_seqcount_begin(&stats->lock);
*active_runtime = stats->enabled_ns;
if (stats->start_ns)
*active_runtime += timestamp - stats->start_ns;
@@ -201,7 +204,7 @@ static void v3d_show_fdinfo(struct drm_printer *p, struct drm_file *file)
enum v3d_queue queue;
for (queue = 0; queue < V3D_MAX_QUEUES; queue++) {
- struct v3d_stats *stats = &file_priv->stats[queue];
+ struct v3d_stats *stats = file_priv->stats[queue];
u64 active_runtime, jobs_completed;
v3d_get_stats(stats, timestamp, &active_runtime, &jobs_completed);
diff --git a/drivers/gpu/drm/v3d/v3d_drv.h b/drivers/gpu/drm/v3d/v3d_drv.h
index 314213c26710..6a3cad933439 100644
--- a/drivers/gpu/drm/v3d/v3d_drv.h
+++ b/drivers/gpu/drm/v3d/v3d_drv.h
@@ -38,6 +38,8 @@ static inline char *v3d_queue_to_string(enum v3d_queue queue)
}
struct v3d_stats {
+ struct kref refcount;
+
u64 start_ns;
u64 enabled_ns;
u64 jobs_completed;
@@ -46,8 +48,15 @@ struct v3d_stats {
* This seqcount is used to protect the access to the GPU stats
* variables. It must be used as, while we are reading the stats,
* IRQs can happen and the stats can be updated.
+ *
+ * However, we use the raw seqcount helpers to interact with this lock
+ * to avoid false positives from lockdep, which is unable to detect that
+ * our readers are never from irq or softirq context, and that, for CPU
+ * job queues, even the write side never is.
*/
seqcount_t lock;
+
+ atomic_t reset_counter;
};
struct v3d_queue_state {
@@ -57,13 +66,11 @@ struct v3d_queue_state {
u64 emit_seqno;
/* Stores the GPU stats for this queue in the global context. */
- struct v3d_stats stats;
+ struct v3d_stats *stats;
/* Currently active job for this queue */
struct v3d_job *active_job;
spinlock_t queue_lock;
- /* Protect dma fence for signalling job completion */
- spinlock_t fence_lock;
};
/* Performance monitor object. The perform lifetime is controlled by userspace
@@ -196,10 +203,8 @@ struct v3d_dev {
*/
struct v3d_perfmon *global_perfmon;
- /* Global reset counter. The counter must be incremented when
- * a GPU reset happens. It must be protected by @reset_lock.
- */
- unsigned int reset_counter;
+ /* Global reset counter incremented on each GPU reset. */
+ atomic_t reset_counter;
};
static inline struct v3d_dev *
@@ -225,13 +230,7 @@ struct v3d_file_priv {
struct drm_sched_entity sched_entity[V3D_MAX_QUEUES];
/* Stores the GPU stats for a specific queue for this fd. */
- struct v3d_stats stats[V3D_MAX_QUEUES];
-
- /* Per-fd reset counter, must be incremented when a job submitted
- * by this fd causes a GPU reset. It must be protected by
- * &struct v3d_dev->reset_lock.
- */
- unsigned int reset_counter;
+ struct v3d_stats *stats[V3D_MAX_QUEUES];
};
struct v3d_bo {
@@ -319,6 +318,10 @@ struct v3d_job {
*/
struct v3d_file_priv *file_priv;
+ /* Pointers to this job's per-fd and global queue stats. */
+ struct v3d_stats *client_stats;
+ struct v3d_stats *global_stats;
+
/* Callback for the freeing of the job on refcount going to 0. */
void (*free)(struct kref *ref);
};
@@ -598,10 +601,23 @@ void v3d_timestamp_query_info_free(struct v3d_timestamp_query_info *query_info,
unsigned int count);
void v3d_performance_query_info_free(struct v3d_performance_query_info *query_info,
unsigned int count);
-void v3d_job_update_stats(struct v3d_job *job, enum v3d_queue q);
+struct v3d_stats *v3d_stats_alloc(void);
+void v3d_stats_release(struct kref *refcount);
+void v3d_job_update_stats(struct v3d_job *job);
int v3d_sched_init(struct v3d_dev *v3d);
void v3d_sched_fini(struct v3d_dev *v3d);
+static inline struct v3d_stats *v3d_stats_get(struct v3d_stats *stats)
+{
+ kref_get(&stats->refcount);
+ return stats;
+}
+
+static inline void v3d_stats_put(struct v3d_stats *stats)
+{
+ kref_put(&stats->refcount, v3d_stats_release);
+}
+
/* v3d_perfmon.c */
void v3d_perfmon_init(struct v3d_dev *v3d);
void v3d_perfmon_get(struct v3d_perfmon *perfmon);
diff --git a/drivers/gpu/drm/v3d/v3d_fence.c b/drivers/gpu/drm/v3d/v3d_fence.c
index 3c999f60003c..c500136d0455 100644
--- a/drivers/gpu/drm/v3d/v3d_fence.c
+++ b/drivers/gpu/drm/v3d/v3d_fence.c
@@ -15,7 +15,7 @@ struct dma_fence *v3d_fence_create(struct v3d_dev *v3d, enum v3d_queue q)
fence->dev = &v3d->drm;
fence->queue = q;
fence->seqno = ++queue->emit_seqno;
- dma_fence_init(&fence->base, &v3d_fence_ops, &queue->fence_lock,
+ dma_fence_init(&fence->base, &v3d_fence_ops, &queue->queue_lock,
queue->fence_context, fence->seqno);
return &fence->base;
diff --git a/drivers/gpu/drm/v3d/v3d_gem.c b/drivers/gpu/drm/v3d/v3d_gem.c
index 57965c0d6f6e..75d9eccd7966 100644
--- a/drivers/gpu/drm/v3d/v3d_gem.c
+++ b/drivers/gpu/drm/v3d/v3d_gem.c
@@ -287,27 +287,30 @@ v3d_gem_init(struct drm_device *dev)
for (i = 0; i < V3D_MAX_QUEUES; i++) {
struct v3d_queue_state *queue = &v3d->queue[i];
+ queue->stats = v3d_stats_alloc();
+ if (!queue->stats) {
+ ret = -ENOMEM;
+ goto err_stats;
+ }
+
queue->fence_context = dma_fence_context_alloc(1);
- memset(&queue->stats, 0, sizeof(queue->stats));
- seqcount_init(&queue->stats.lock);
spin_lock_init(&queue->queue_lock);
- spin_lock_init(&queue->fence_lock);
}
spin_lock_init(&v3d->mm_lock);
ret = drmm_mutex_init(dev, &v3d->bo_lock);
if (ret)
- return ret;
+ goto err_stats;
ret = drmm_mutex_init(dev, &v3d->reset_lock);
if (ret)
- return ret;
+ goto err_stats;
ret = drmm_mutex_init(dev, &v3d->sched_lock);
if (ret)
- return ret;
+ goto err_stats;
ret = drmm_mutex_init(dev, &v3d->cache_clean_lock);
if (ret)
- return ret;
+ goto err_stats;
/* Note: We don't allocate address 0. Various bits of HW
* treat 0 as special, such as the occlusion query counters
@@ -319,10 +322,10 @@ v3d_gem_init(struct drm_device *dev)
&v3d->pt_paddr,
GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO);
if (!v3d->pt) {
- drm_mm_takedown(&v3d->mm);
dev_err(v3d->drm.dev,
"Failed to allocate page tables. Please ensure you have DMA enabled.\n");
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto err_dma_alloc;
}
v3d_init_hw_state(v3d);
@@ -331,14 +334,20 @@ v3d_gem_init(struct drm_device *dev)
v3d_huge_mnt_init(v3d);
ret = v3d_sched_init(v3d);
- if (ret) {
- drm_mm_takedown(&v3d->mm);
- dma_free_coherent(v3d->drm.dev, pt_size, (void *)v3d->pt,
- v3d->pt_paddr);
- return ret;
- }
+ if (ret)
+ goto err_sched;
return 0;
+
+err_sched:
+ dma_free_coherent(v3d->drm.dev, pt_size, (void *)v3d->pt, v3d->pt_paddr);
+err_dma_alloc:
+ drm_mm_takedown(&v3d->mm);
+err_stats:
+ for (i--; i >= 0; i--)
+ v3d_stats_put(v3d->queue[i].stats);
+
+ return ret;
}
void
@@ -352,8 +361,10 @@ v3d_gem_destroy(struct drm_device *dev)
/* Waiting for jobs to finish would need to be done before
* unregistering V3D.
*/
- for (q = 0; q < V3D_MAX_QUEUES; q++)
+ for (q = 0; q < V3D_MAX_QUEUES; q++) {
WARN_ON(v3d->queue[q].active_job);
+ v3d_stats_put(v3d->queue[q].stats);
+ }
drm_mm_takedown(&v3d->mm);
diff --git a/drivers/gpu/drm/v3d/v3d_irq.c b/drivers/gpu/drm/v3d/v3d_irq.c
index 1249f6e64b97..c28e74ab5442 100644
--- a/drivers/gpu/drm/v3d/v3d_irq.c
+++ b/drivers/gpu/drm/v3d/v3d_irq.c
@@ -92,7 +92,7 @@ v3d_irq_signal_fence(struct v3d_dev *v3d, enum v3d_queue q,
struct v3d_queue_state *queue = &v3d->queue[q];
struct v3d_fence *fence = to_v3d_fence(queue->active_job->irq_fence);
- v3d_job_update_stats(queue->active_job, q);
+ v3d_job_update_stats(queue->active_job);
trace_irq(&v3d->drm, fence->seqno);
queue->active_job = NULL;
diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c
index 6dc871fc9a62..1855ef5b3b5f 100644
--- a/drivers/gpu/drm/v3d/v3d_sched.c
+++ b/drivers/gpu/drm/v3d/v3d_sched.c
@@ -66,6 +66,27 @@ to_cpu_job(struct drm_sched_job *sched_job)
return container_of(sched_job, struct v3d_cpu_job, base.base);
}
+void v3d_stats_release(struct kref *refcount)
+{
+ struct v3d_stats *stats = container_of(refcount, typeof(*stats), refcount);
+
+ kfree(stats);
+}
+
+struct v3d_stats *v3d_stats_alloc(void)
+{
+ struct v3d_stats *stats;
+
+ stats = kzalloc_obj(*stats);
+ if (!stats)
+ return NULL;
+
+ kref_init(&stats->refcount);
+ seqcount_init(&stats->lock);
+
+ return stats;
+}
+
static void
v3d_sched_job_free(struct drm_sched_job *sched_job)
{
@@ -137,90 +158,43 @@ v3d_switch_perfmon(struct v3d_dev *v3d, struct v3d_job *job)
}
static void
-v3d_job_start_stats(struct v3d_job *job, enum v3d_queue queue)
+v3d_stats_start(struct v3d_stats *stats, u64 now)
{
- struct v3d_dev *v3d = job->v3d;
- struct v3d_file_priv *file = job->file_priv;
- struct v3d_stats *global_stats = &v3d->queue[queue].stats;
- struct v3d_stats *local_stats = &file->stats[queue];
- u64 now = local_clock();
- unsigned long flags;
-
- /*
- * We only need to disable local interrupts to appease lockdep who
- * otherwise would think v3d_job_start_stats vs v3d_stats_update has an
- * unsafe in-irq vs no-irq-off usage problem. This is a false positive
- * because all the locks are per queue and stats type, and all jobs are
- * completely one at a time serialised. More specifically:
- *
- * 1. Locks for GPU queues are updated from interrupt handlers under a
- * spin lock and started here with preemption disabled.
- *
- * 2. Locks for CPU queues are updated from the worker with preemption
- * disabled and equally started here with preemption disabled.
- *
- * Therefore both are consistent.
- *
- * 3. Because next job can only be queued after the previous one has
- * been signaled, and locks are per queue, there is also no scope for
- * the start part to race with the update part.
- */
- if (IS_ENABLED(CONFIG_LOCKDEP))
- local_irq_save(flags);
- else
- preempt_disable();
-
- write_seqcount_begin(&local_stats->lock);
- local_stats->start_ns = now;
- write_seqcount_end(&local_stats->lock);
+ raw_write_seqcount_begin(&stats->lock);
+ stats->start_ns = now;
+ raw_write_seqcount_end(&stats->lock);
+}
- write_seqcount_begin(&global_stats->lock);
- global_stats->start_ns = now;
- write_seqcount_end(&global_stats->lock);
+static void
+v3d_job_start_stats(struct v3d_job *job)
+{
+ u64 now = local_clock();
- if (IS_ENABLED(CONFIG_LOCKDEP))
- local_irq_restore(flags);
- else
- preempt_enable();
+ preempt_disable();
+ v3d_stats_start(job->client_stats, now);
+ v3d_stats_start(job->global_stats, now);
+ preempt_enable();
}
static void
v3d_stats_update(struct v3d_stats *stats, u64 now)
{
- write_seqcount_begin(&stats->lock);
+ raw_write_seqcount_begin(&stats->lock);
stats->enabled_ns += now - stats->start_ns;
stats->jobs_completed++;
stats->start_ns = 0;
- write_seqcount_end(&stats->lock);
+ raw_write_seqcount_end(&stats->lock);
}
void
-v3d_job_update_stats(struct v3d_job *job, enum v3d_queue q)
+v3d_job_update_stats(struct v3d_job *job)
{
- struct v3d_dev *v3d = job->v3d;
- struct v3d_queue_state *queue = &v3d->queue[q];
- struct v3d_stats *global_stats = &queue->stats;
u64 now = local_clock();
- unsigned long flags;
-
- /* See comment in v3d_job_start_stats() */
- if (IS_ENABLED(CONFIG_LOCKDEP))
- local_irq_save(flags);
- else
- preempt_disable();
- /* Don't update the local stats if the file context has already closed */
- spin_lock(&queue->queue_lock);
- if (job->file_priv)
- v3d_stats_update(&job->file_priv->stats[q], now);
- spin_unlock(&queue->queue_lock);
-
- v3d_stats_update(global_stats, now);
-
- if (IS_ENABLED(CONFIG_LOCKDEP))
- local_irq_restore(flags);
- else
- preempt_enable();
+ preempt_disable();
+ v3d_stats_update(job->client_stats, now);
+ v3d_stats_update(job->global_stats, now);
+ preempt_enable();
}
static struct dma_fence *v3d_bin_job_run(struct drm_sched_job *sched_job)
@@ -263,7 +237,7 @@ static struct dma_fence *v3d_bin_job_run(struct drm_sched_job *sched_job)
trace_v3d_submit_cl(dev, false, to_v3d_fence(fence)->seqno,
job->start, job->end);
- v3d_job_start_stats(&job->base, V3D_BIN);
+ v3d_job_start_stats(&job->base);
v3d_switch_perfmon(v3d, &job->base);
/* Set the current and end address of the control list.
@@ -317,7 +291,7 @@ static struct dma_fence *v3d_render_job_run(struct drm_sched_job *sched_job)
trace_v3d_submit_cl(dev, true, to_v3d_fence(fence)->seqno,
job->start, job->end);
- v3d_job_start_stats(&job->base, V3D_RENDER);
+ v3d_job_start_stats(&job->base);
v3d_switch_perfmon(v3d, &job->base);
/* XXX: Set the QCFG */
@@ -356,7 +330,7 @@ v3d_tfu_job_run(struct drm_sched_job *sched_job)
trace_v3d_submit_tfu(dev, to_v3d_fence(fence)->seqno);
- v3d_job_start_stats(&job->base, V3D_TFU);
+ v3d_job_start_stats(&job->base);
V3D_WRITE(V3D_TFU_IIA(v3d->ver), job->args.iia);
V3D_WRITE(V3D_TFU_IIS(v3d->ver), job->args.iis);
@@ -406,7 +380,7 @@ v3d_csd_job_run(struct drm_sched_job *sched_job)
trace_v3d_submit_csd(dev, to_v3d_fence(fence)->seqno);
- v3d_job_start_stats(&job->base, V3D_CSD);
+ v3d_job_start_stats(&job->base);
v3d_switch_perfmon(v3d, &job->base);
csd_cfg0_reg = V3D_CSD_QUEUED_CFG0(v3d->ver);
@@ -694,13 +668,13 @@ v3d_cpu_job_run(struct drm_sched_job *sched_job)
return NULL;
}
- v3d_job_start_stats(&job->base, V3D_CPU);
+ v3d_job_start_stats(&job->base);
trace_v3d_cpu_job_begin(&v3d->drm, job->job_type);
cpu_job_function[job->job_type](job);
trace_v3d_cpu_job_end(&v3d->drm, job->job_type);
- v3d_job_update_stats(&job->base, V3D_CPU);
+ v3d_job_update_stats(&job->base);
/* Synchronous operation, so no fence to wait on. */
return NULL;
@@ -712,11 +686,11 @@ v3d_cache_clean_job_run(struct drm_sched_job *sched_job)
struct v3d_job *job = to_v3d_job(sched_job);
struct v3d_dev *v3d = job->v3d;
- v3d_job_start_stats(job, V3D_CACHE_CLEAN);
+ v3d_job_start_stats(job);
v3d_clean_caches(v3d);
- v3d_job_update_stats(job, V3D_CACHE_CLEAN);
+ v3d_job_update_stats(job);
/* Synchronous operation, so no fence to wait on. */
return NULL;
@@ -727,8 +701,6 @@ v3d_gpu_reset_for_timeout(struct v3d_dev *v3d, struct drm_sched_job *sched_job,
enum v3d_queue q)
{
struct v3d_job *job = to_v3d_job(sched_job);
- struct v3d_file_priv *v3d_priv = job->file_priv;
- unsigned long irqflags;
enum v3d_queue i;
mutex_lock(&v3d->reset_lock);
@@ -743,11 +715,8 @@ v3d_gpu_reset_for_timeout(struct v3d_dev *v3d, struct drm_sched_job *sched_job,
/* get the GPU back into the init state */
v3d_reset(v3d);
- v3d->reset_counter++;
- spin_lock_irqsave(&v3d->queue[q].queue_lock, irqflags);
- if (v3d_priv)
- v3d_priv->reset_counter++;
- spin_unlock_irqrestore(&v3d->queue[q].queue_lock, irqflags);
+ atomic_inc(&v3d->reset_counter);
+ atomic_inc(&job->client_stats->reset_counter);
for (i = 0; i < V3D_MAX_QUEUES; i++)
drm_sched_resubmit_jobs(&v3d->queue[i].sched);
diff --git a/drivers/gpu/drm/v3d/v3d_submit.c b/drivers/gpu/drm/v3d/v3d_submit.c
index 18f2bf1fe89f..8f061b6a05c6 100644
--- a/drivers/gpu/drm/v3d/v3d_submit.c
+++ b/drivers/gpu/drm/v3d/v3d_submit.c
@@ -103,6 +103,9 @@ v3d_job_free(struct kref *ref)
if (job->perfmon)
v3d_perfmon_put(job->perfmon);
+ v3d_stats_put(job->client_stats);
+ v3d_stats_put(job->global_stats);
+
kfree(job);
}
@@ -203,6 +206,9 @@ v3d_job_init(struct v3d_dev *v3d, struct drm_file *file_priv,
kref_init(&job->refcount);
+ job->client_stats = v3d_stats_get(v3d_priv->stats[queue]);
+ job->global_stats = v3d_stats_get(v3d->queue[queue].stats);
+
return 0;
fail_deps:
diff --git a/drivers/gpu/drm/v3d/v3d_sysfs.c b/drivers/gpu/drm/v3d/v3d_sysfs.c
index d610e355964f..b45a9b3db42d 100644
--- a/drivers/gpu/drm/v3d/v3d_sysfs.c
+++ b/drivers/gpu/drm/v3d/v3d_sysfs.c
@@ -20,7 +20,7 @@ gpu_stats_show(struct device *dev, struct device_attribute *attr, char *buf)
len += sysfs_emit(buf, "queue\ttimestamp\tjobs\truntime\n");
for (queue = 0; queue < V3D_MAX_QUEUES; queue++) {
- struct v3d_stats *stats = &v3d->queue[queue].stats;
+ struct v3d_stats *stats = v3d->queue[queue].stats;
u64 active_runtime, jobs_completed;
v3d_get_stats(stats, timestamp, &active_runtime, &jobs_completed);
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 9898e5451a07..a99f53dadb28 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -133,7 +133,7 @@ static bool vc4_hdmi_supports_scrambling(struct vc4_hdmi *vc4_hdmi)
static bool vc4_hdmi_mode_needs_scrambling(const struct drm_display_mode *mode,
unsigned int bpc,
- enum hdmi_colorspace fmt)
+ enum drm_output_color_format fmt)
{
unsigned long long clock = drm_hdmi_compute_mode_clock(mode, bpc, fmt);
@@ -444,7 +444,7 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
const struct drm_display_mode *mode;
list_for_each_entry(mode, &connector->probed_modes, head) {
- if (vc4_hdmi_mode_needs_scrambling(mode, 8, HDMI_COLORSPACE_RGB)) {
+ if (vc4_hdmi_mode_needs_scrambling(mode, 8, DRM_OUTPUT_COLOR_FORMAT_RGB444)) {
drm_warn_once(drm, "The core clock cannot reach frequencies high enough to support 4k @ 60Hz.");
drm_warn_once(drm, "Please change your config.txt file to add hdmi_enable_4kp60.");
}
@@ -547,9 +547,9 @@ static int vc4_hdmi_connector_init(struct drm_device *dev,
&vc4_hdmi_hdmi_connector_funcs,
DRM_MODE_CONNECTOR_HDMIA,
vc4_hdmi->ddc,
- BIT(HDMI_COLORSPACE_RGB) |
- BIT(HDMI_COLORSPACE_YUV422) |
- BIT(HDMI_COLORSPACE_YUV444),
+ BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444) |
+ BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422) |
+ BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444),
max_bpc);
if (ret)
return ret;
@@ -1214,13 +1214,13 @@ static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi,
spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
switch (state->hdmi.output_format) {
- case HDMI_COLORSPACE_YUV444:
+ case DRM_OUTPUT_COLOR_FORMAT_YCBCR444:
csc = vc5_hdmi_find_yuv_csc_coeffs(vc4_hdmi, state->colorspace, !!lim_range);
vc5_hdmi_set_csc_coeffs_swap(vc4_hdmi, csc);
break;
- case HDMI_COLORSPACE_YUV422:
+ case DRM_OUTPUT_COLOR_FORMAT_YCBCR422:
csc = vc5_hdmi_find_yuv_csc_coeffs(vc4_hdmi, state->colorspace, !!lim_range);
csc_ctl |= VC4_SET_FIELD(VC5_MT_CP_CSC_CTL_FILTER_MODE_444_TO_422_STANDARD,
@@ -1237,7 +1237,7 @@ static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi,
vc5_hdmi_set_csc_coeffs(vc4_hdmi, csc);
break;
- case HDMI_COLORSPACE_RGB:
+ case DRM_OUTPUT_COLOR_FORMAT_RGB444:
if_xbar = 0x354021;
vc5_hdmi_set_csc_coeffs(vc4_hdmi, vc5_hdmi_csc_full_rgb_to_rgb[lim_range]);
@@ -1394,7 +1394,7 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
* YCC422 is always 36-bit and not considered deep colour so
* doesn't signal in GCP.
*/
- if (state->hdmi.output_format == HDMI_COLORSPACE_YUV422) {
+ if (state->hdmi.output_format == DRM_OUTPUT_COLOR_FORMAT_YCBCR422) {
gcp = 0;
}
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 8d069718df00..29d461d4ee49 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -210,7 +210,7 @@ struct vc4_hdmi {
* @drm_connector_state.hdmi.output_format for use outside of
* KMS hooks. Protected by @mutex.
*/
- enum hdmi_colorspace output_format;
+ enum drm_output_color_format output_format;
/**
* @hdmi_jack: Represents the connection state of the HDMI plug, for
diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
index 0507f24adcdd..264b5e80c24d 100644
--- a/drivers/gpu/drm/vc4/vc4_kms.c
+++ b/drivers/gpu/drm/vc4/vc4_kms.c
@@ -116,7 +116,7 @@ static int vc4_ctm_obj_init(struct vc4_dev *vc4)
{
drm_modeset_lock_init(&vc4->ctm_state_lock);
- drm_atomic_private_obj_init(&vc4->base, &vc4->ctm_manager, NULL,
+ drm_atomic_private_obj_init(&vc4->base, &vc4->ctm_manager,
&vc4_ctm_state_funcs);
return drmm_add_action_or_reset(&vc4->base, vc4_ctm_obj_fini, NULL);
@@ -757,7 +757,6 @@ static void vc4_load_tracker_obj_fini(struct drm_device *dev, void *unused)
static int vc4_load_tracker_obj_init(struct vc4_dev *vc4)
{
drm_atomic_private_obj_init(&vc4->base, &vc4->load_tracker,
- NULL,
&vc4_load_tracker_state_funcs);
return drmm_add_action_or_reset(&vc4->base, vc4_load_tracker_obj_fini, NULL);
@@ -849,7 +848,6 @@ static void vc4_hvs_channels_obj_fini(struct drm_device *dev, void *unused)
static int vc4_hvs_channels_obj_init(struct vc4_dev *vc4)
{
drm_atomic_private_obj_init(&vc4->base, &vc4->hvs_channels,
- NULL,
&vc4_hvs_state_funcs);
return drmm_add_action_or_reset(&vc4->base, vc4_hvs_channels_obj_fini, NULL);
diff --git a/drivers/gpu/drm/verisilicon/vs_dc.c b/drivers/gpu/drm/verisilicon/vs_dc.c
index 5f629d2d4bea..dad9967bc10b 100644
--- a/drivers/gpu/drm/verisilicon/vs_dc.c
+++ b/drivers/gpu/drm/verisilicon/vs_dc.c
@@ -190,7 +190,7 @@ static void vs_dc_shutdown(struct platform_device *pdev)
vs_drm_shutdown_handler(dc);
}
-struct platform_driver vs_dc_platform_driver = {
+static struct platform_driver vs_dc_platform_driver = {
.probe = vs_dc_probe,
.remove = vs_dc_remove,
.shutdown = vs_dc_shutdown,
diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c
index cd85de4ffd03..83d217085ad0 100644
--- a/drivers/gpu/drm/vkms/vkms_composer.c
+++ b/drivers/gpu/drm/vkms/vkms_composer.c
@@ -475,8 +475,14 @@ static void blend(struct vkms_writeback_job *wb,
{
struct vkms_plane_state **plane = crtc_state->active_planes;
u32 n_active_planes = crtc_state->num_active_planes;
-
- const struct pixel_argb_u16 background_color = { .a = 0xffff };
+ u64 bgcolor = crtc_state->base.background_color;
+
+ const struct pixel_argb_u16 background_color = {
+ .a = 0xffff,
+ .r = DRM_ARGB64_GETR(bgcolor),
+ .g = DRM_ARGB64_GETG(bgcolor),
+ .b = DRM_ARGB64_GETB(bgcolor),
+ };
int crtc_y_limit = crtc_state->base.mode.vdisplay;
int crtc_x_limit = crtc_state->base.mode.hdisplay;
diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c b/drivers/gpu/drm/vkms/vkms_crtc.c
index ba2ff353e1a9..35ddc553a5e6 100644
--- a/drivers/gpu/drm/vkms/vkms_crtc.c
+++ b/drivers/gpu/drm/vkms/vkms_crtc.c
@@ -4,6 +4,7 @@
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
+#include <drm/drm_blend.h>
#include <drm/drm_managed.h>
#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
@@ -227,6 +228,8 @@ struct vkms_output *vkms_crtc_init(struct drm_device *dev, struct drm_plane *pri
drm_crtc_enable_color_mgmt(crtc, 0, false, VKMS_LUT_SIZE);
+ drm_crtc_attach_background_color_property(crtc);
+
spin_lock_init(&vkms_out->lock);
spin_lock_init(&vkms_out->composer_lock);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index f2abaf1bda6a..57465f69c687 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -96,12 +96,17 @@ struct vmwgfx_hash_item {
struct vmw_res_func;
+struct vmw_bo;
+struct vmw_bo;
+struct vmw_resource_dirty;
+
/**
- * struct vmw-resource - base class for hardware resources
+ * struct vmw_resource - base class for hardware resources
*
* @kref: For refcounting.
* @dev_priv: Pointer to the device private for this resource. Immutable.
* @id: Device id. Protected by @dev_priv::resource_lock.
+ * @used_prio: Priority for this resource.
* @guest_memory_size: Guest memory buffer size. Immutable.
* @res_dirty: Resource contains data not yet in the guest memory buffer.
* Protected by resource reserved.
@@ -117,18 +122,16 @@ struct vmw_res_func;
* pin-count greater than zero. It is not on the resource LRU lists and its
* guest memory buffer is pinned. Hence it can't be evicted.
* @func: Method vtable for this resource. Immutable.
- * @mob_node; Node for the MOB guest memory rbtree. Protected by
+ * @mob_node: Node for the MOB guest memory rbtree. Protected by
* @guest_memory_bo reserved.
* @lru_head: List head for the LRU list. Protected by @dev_priv::resource_lock.
* @binding_head: List head for the context binding list. Protected by
* the @dev_priv::binding_mutex
+ * @dirty: resource's dirty tracker
* @res_free: The resource destructor.
* @hw_destroy: Callback to destroy the resource on the device, as part of
* resource destruction.
*/
-struct vmw_bo;
-struct vmw_bo;
-struct vmw_resource_dirty;
struct vmw_resource {
struct kref kref;
struct vmw_private *dev_priv;
@@ -196,8 +199,8 @@ struct vmw_surface_offset;
* @quality_level: Quality level.
* @autogen_filter: Filter for automatically generated mipmaps.
* @array_size: Number of array elements for a 1D/2D texture. For cubemap
- texture number of faces * array_size. This should be 0 for pre
- SM4 device.
+ * texture number of faces * array_size. This should be 0 for pre
+ * SM4 device.
* @buffer_byte_stride: Buffer byte stride.
* @num_sizes: Size of @sizes. For GB surface this should always be 1.
* @base_size: Surface dimension.
@@ -265,18 +268,24 @@ struct vmw_fifo_state {
struct vmw_res_cache_entry {
uint32_t handle;
struct vmw_resource *res;
+ /* private: */
void *private;
+ /* public: */
unsigned short valid_handle;
unsigned short valid;
};
/**
* enum vmw_dma_map_mode - indicate how to perform TTM page dma mappings.
+ * @vmw_dma_alloc_coherent: Use TTM coherent pages
+ * @vmw_dma_map_populate: Unmap from DMA just after unpopulate
+ * @vmw_dma_map_bind: Unmap from DMA just before unbind
*/
enum vmw_dma_map_mode {
- vmw_dma_alloc_coherent, /* Use TTM coherent pages */
- vmw_dma_map_populate, /* Unmap from DMA just after unpopulate */
- vmw_dma_map_bind, /* Unmap from DMA just before unbind */
+ vmw_dma_alloc_coherent,
+ vmw_dma_map_populate,
+ vmw_dma_map_bind,
+ /* private: */
vmw_dma_map_max
};
@@ -284,8 +293,11 @@ enum vmw_dma_map_mode {
* struct vmw_sg_table - Scatter/gather table for binding, with additional
* device-specific information.
*
+ * @mode: which page mapping mode to use
+ * @pages: Array of page pointers to the pages.
+ * @addrs: DMA addresses to the pages if coherent pages are used.
* @sgt: Pointer to a struct sg_table with binding information
- * @num_regions: Number of regions with device-address contiguous pages
+ * @num_pages: Number of @pages
*/
struct vmw_sg_table {
enum vmw_dma_map_mode mode;
@@ -353,6 +365,7 @@ struct vmw_ctx_validation_info;
* than from user-space
* @fp: If @kernel is false, points to the file of the client. Otherwise
* NULL
+ * @filp: DRM state for this file
* @cmd_bounce: Command bounce buffer used for command validation before
* copying to fifo space
* @cmd_bounce_size: Current command bounce buffer size
@@ -729,7 +742,7 @@ extern void vmw_svga_disable(struct vmw_private *dev_priv);
bool vmwgfx_supported(struct vmw_private *vmw);
-/**
+/*
* GMR utilities - vmwgfx_gmr.c
*/
@@ -739,7 +752,7 @@ extern int vmw_gmr_bind(struct vmw_private *dev_priv,
int gmr_id);
extern void vmw_gmr_unbind(struct vmw_private *dev_priv, int gmr_id);
-/**
+/*
* User handles
*/
struct vmw_user_object {
@@ -759,7 +772,7 @@ void *vmw_user_object_map_size(struct vmw_user_object *uo, size_t size);
void vmw_user_object_unmap(struct vmw_user_object *uo);
bool vmw_user_object_is_mapped(struct vmw_user_object *uo);
-/**
+/*
* Resource utilities - vmwgfx_resource.c
*/
struct vmw_user_resource_conv;
@@ -819,7 +832,7 @@ static inline bool vmw_resource_mob_attached(const struct vmw_resource *res)
return !RB_EMPTY_NODE(&res->mob_node);
}
-/**
+/*
* GEM related functionality - vmwgfx_gem.c
*/
struct vmw_bo_params;
@@ -833,7 +846,7 @@ extern int vmw_gem_object_create_ioctl(struct drm_device *dev, void *data,
struct drm_file *filp);
extern void vmw_debugfs_gem_init(struct vmw_private *vdev);
-/**
+/*
* Misc Ioctl functionality - vmwgfx_ioctl.c
*/
@@ -846,7 +859,7 @@ extern int vmw_present_ioctl(struct drm_device *dev, void *data,
extern int vmw_present_readback_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
-/**
+/*
* Fifo utilities - vmwgfx_fifo.c
*/
@@ -880,9 +893,11 @@ extern int vmw_cmd_flush(struct vmw_private *dev_priv,
/**
- * vmw_fifo_caps - Returns the capabilities of the FIFO command
+ * vmw_fifo_caps - Get the capabilities of the FIFO command
* queue or 0 if fifo memory isn't present.
* @dev_priv: The device private context
+ *
+ * Returns: capabilities of the FIFO command or %0 if fifo memory not present
*/
static inline uint32_t vmw_fifo_caps(const struct vmw_private *dev_priv)
{
@@ -893,9 +908,11 @@ static inline uint32_t vmw_fifo_caps(const struct vmw_private *dev_priv)
/**
- * vmw_is_cursor_bypass3_enabled - Returns TRUE iff Cursor Bypass 3
- * is enabled in the FIFO.
+ * vmw_is_cursor_bypass3_enabled - check Cursor Bypass 3 enabled setting
+ * in the FIFO.
* @dev_priv: The device private context
+ *
+ * Returns: %true iff Cursor Bypass 3 is enabled in the FIFO
*/
static inline bool
vmw_is_cursor_bypass3_enabled(const struct vmw_private *dev_priv)
@@ -903,7 +920,7 @@ vmw_is_cursor_bypass3_enabled(const struct vmw_private *dev_priv)
return (vmw_fifo_caps(dev_priv) & SVGA_FIFO_CAP_CURSOR_BYPASS_3) != 0;
}
-/**
+/*
* TTM buffer object driver - vmwgfx_ttm_buffer.c
*/
@@ -927,7 +944,7 @@ extern void vmw_piter_start(struct vmw_piter *viter,
*
* @viter: Pointer to the iterator to advance.
*
- * Returns false if past the list of pages, true otherwise.
+ * Returns: false if past the list of pages, true otherwise.
*/
static inline bool vmw_piter_next(struct vmw_piter *viter)
{
@@ -939,7 +956,7 @@ static inline bool vmw_piter_next(struct vmw_piter *viter)
*
* @viter: Pointer to the iterator
*
- * Returns the DMA address of the page pointed to by @viter.
+ * Returns: the DMA address of the page pointed to by @viter.
*/
static inline dma_addr_t vmw_piter_dma_addr(struct vmw_piter *viter)
{
@@ -951,14 +968,14 @@ static inline dma_addr_t vmw_piter_dma_addr(struct vmw_piter *viter)
*
* @viter: Pointer to the iterator
*
- * Returns the DMA address of the page pointed to by @viter.
+ * Returns: the DMA address of the page pointed to by @viter.
*/
static inline struct page *vmw_piter_page(struct vmw_piter *viter)
{
return viter->pages[viter->i];
}
-/**
+/*
* Command submission - vmwgfx_execbuf.c
*/
@@ -993,7 +1010,7 @@ extern int vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv,
int32_t out_fence_fd);
bool vmw_cmd_describe(const void *buf, u32 *size, char const **cmd);
-/**
+/*
* IRQs and wating - vmwgfx_irq.c
*/
@@ -1016,7 +1033,7 @@ bool vmw_generic_waiter_add(struct vmw_private *dev_priv, u32 flag,
bool vmw_generic_waiter_remove(struct vmw_private *dev_priv,
u32 flag, int *waiter_count);
-/**
+/*
* Kernel modesetting - vmwgfx_kms.c
*/
@@ -1048,7 +1065,7 @@ extern int vmw_resource_pin(struct vmw_resource *res, bool interruptible);
extern void vmw_resource_unpin(struct vmw_resource *res);
extern enum vmw_res_type vmw_res_type(const struct vmw_resource *res);
-/**
+/*
* Overlay control - vmwgfx_overlay.c
*/
@@ -1063,20 +1080,20 @@ int vmw_overlay_unref(struct vmw_private *dev_priv, uint32_t stream_id);
int vmw_overlay_num_overlays(struct vmw_private *dev_priv);
int vmw_overlay_num_free_overlays(struct vmw_private *dev_priv);
-/**
+/*
* GMR Id manager
*/
int vmw_gmrid_man_init(struct vmw_private *dev_priv, int type);
void vmw_gmrid_man_fini(struct vmw_private *dev_priv, int type);
-/**
+/*
* System memory manager
*/
int vmw_sys_man_init(struct vmw_private *dev_priv);
void vmw_sys_man_fini(struct vmw_private *dev_priv);
-/**
+/*
* Prime - vmwgfx_prime.c
*/
@@ -1292,7 +1309,7 @@ extern void vmw_cmdbuf_irqthread(struct vmw_cmdbuf_man *man);
* @line: The current line of the blit.
* @line_offset: Offset of the current line segment.
* @cpp: Bytes per pixel (granularity information).
- * @memcpy: Which memcpy function to use.
+ * @do_cpy: Which memcpy function to use.
*/
struct vmw_diff_cpy {
struct drm_rect rect;
@@ -1380,13 +1397,14 @@ vm_fault_t vmw_bo_vm_mkwrite(struct vm_fault *vmf);
/**
* VMW_DEBUG_KMS - Debug output for kernel mode-setting
+ * @fmt: format string for the args
*
* This macro is for debugging vmwgfx mode-setting code.
*/
#define VMW_DEBUG_KMS(fmt, ...) \
DRM_DEBUG_DRIVER(fmt, ##__VA_ARGS__)
-/**
+/*
* Inline helper functions
*/
@@ -1417,11 +1435,13 @@ static inline void vmw_fifo_resource_dec(struct vmw_private *dev_priv)
/**
* vmw_fifo_mem_read - Perform a MMIO read from the fifo memory
- *
+ * @vmw: The device private structure
* @fifo_reg: The fifo register to read from
*
* This function is intended to be equivalent to ioread32() on
* memremap'd memory, but without byteswapping.
+ *
+ * Returns: the value read
*/
static inline u32 vmw_fifo_mem_read(struct vmw_private *vmw, uint32 fifo_reg)
{
@@ -1431,8 +1451,9 @@ static inline u32 vmw_fifo_mem_read(struct vmw_private *vmw, uint32 fifo_reg)
/**
* vmw_fifo_mem_write - Perform a MMIO write to volatile memory
- *
- * @addr: The fifo register to write to
+ * @vmw: The device private structure
+ * @fifo_reg: The fifo register to write to
+ * @value: The value to write
*
* This function is intended to be equivalent to iowrite32 on
* memremap'd memory, but without byteswapping.
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 55730e29d3ae..e7bddf840a79 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -771,7 +771,8 @@ err_out:
ret = vmw_bo_dirty_add(bo);
if (!ret && surface && surface->res.func->dirty_alloc) {
surface->res.coherent = true;
- ret = surface->res.func->dirty_alloc(&surface->res);
+ if (surface->res.dirty == NULL)
+ ret = surface->res.func->dirty_alloc(&surface->res);
}
ttm_bo_unreserve(&bo->tbo);
}
diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
index f9abaf687d46..9dacb0579a7d 100644
--- a/drivers/gpu/drm/xe/Makefile
+++ b/drivers/gpu/drm/xe/Makefile
@@ -253,6 +253,7 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \
i915-display/intel_dbuf_bw.o \
i915-display/intel_ddi.o \
i915-display/intel_ddi_buf_trans.o \
+ i915-display/intel_de.o \
i915-display/intel_display.o \
i915-display/intel_display_conversion.o \
i915-display/intel_display_device.o \
diff --git a/drivers/gpu/drm/xe/compat-i915-headers/intel_step.h b/drivers/gpu/drm/xe/compat-i915-headers/intel_step.h
index 2cf13a572ab0..0eabe2866f5f 100644
--- a/drivers/gpu/drm/xe/compat-i915-headers/intel_step.h
+++ b/drivers/gpu/drm/xe/compat-i915-headers/intel_step.h
@@ -6,9 +6,8 @@
#ifndef __INTEL_STEP_H__
#define __INTEL_STEP_H__
-#include "xe_step.h"
+#include "xe_step_types.h"
#define intel_step xe_step
-#define intel_step_name xe_step_name
#endif /* __INTEL_STEP_H__ */
diff --git a/drivers/gpu/drm/xe/compat-i915-headers/intel_uncore.h b/drivers/gpu/drm/xe/compat-i915-headers/intel_uncore.h
index a8cfd65119e0..08d7ab933672 100644
--- a/drivers/gpu/drm/xe/compat-i915-headers/intel_uncore.h
+++ b/drivers/gpu/drm/xe/compat-i915-headers/intel_uncore.h
@@ -98,37 +98,6 @@ static inline u32 intel_uncore_rmw(struct intel_uncore *uncore,
return xe_mmio_rmw32(__compat_uncore_to_mmio(uncore), reg, clear, set);
}
-static inline int
-__intel_wait_for_register(struct intel_uncore *uncore, i915_reg_t i915_reg,
- u32 mask, u32 value, unsigned int fast_timeout_us,
- unsigned int slow_timeout_ms, u32 *out_value)
-{
- struct xe_reg reg = XE_REG(i915_mmio_reg_offset(i915_reg));
- bool atomic;
-
- /*
- * Replicate the behavior from i915 here, in which sleep is not
- * performed if slow_timeout_ms == 0. This is necessary because
- * of some paths in display code where waits are done in atomic
- * context.
- */
- atomic = !slow_timeout_ms && fast_timeout_us > 0;
-
- return xe_mmio_wait32(__compat_uncore_to_mmio(uncore), reg, mask, value,
- fast_timeout_us + 1000 * slow_timeout_ms,
- out_value, atomic);
-}
-
-static inline int
-__intel_wait_for_register_fw(struct intel_uncore *uncore, i915_reg_t i915_reg,
- u32 mask, u32 value, unsigned int fast_timeout_us,
- unsigned int slow_timeout_ms, u32 *out_value)
-{
- return __intel_wait_for_register(uncore, i915_reg, mask, value,
- fast_timeout_us, slow_timeout_ms,
- out_value);
-}
-
static inline u32 intel_uncore_read_fw(struct intel_uncore *uncore,
i915_reg_t i915_reg)
{
diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c
index 4d4d7a35e089..cbce1d0ffe48 100644
--- a/drivers/gpu/drm/xe/xe_device.c
+++ b/drivers/gpu/drm/xe/xe_device.c
@@ -1349,8 +1349,15 @@ void xe_device_declare_wedged(struct xe_device *xe)
xe_gt_declare_wedged(gt);
if (xe_device_wedged(xe)) {
+ /*
+ * XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET is intended for debugging
+ * hangs, so wedge the device with 'none' recovery method and have
+ * it available to the user for debugging.
+ */
+ if (xe->wedged.mode == XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET)
+ xe_device_set_wedged_method(xe, DRM_WEDGE_RECOVERY_NONE);
/* If no wedge recovery method is set, use default */
- if (!xe->wedged.method)
+ else if (!xe->wedged.method)
xe_device_set_wedged_method(xe, DRM_WEDGE_RECOVERY_REBIND |
DRM_WEDGE_RECOVERY_BUS_RESET);
diff --git a/drivers/gpu/nova-core/Kconfig b/drivers/gpu/nova-core/Kconfig
index 527920f9c4d3..a4f2380654e2 100644
--- a/drivers/gpu/nova-core/Kconfig
+++ b/drivers/gpu/nova-core/Kconfig
@@ -3,8 +3,8 @@ config NOVA_CORE
depends on 64BIT
depends on PCI
depends on RUST
- select RUST_FW_LOADER_ABSTRACTIONS
select AUXILIARY_BUS
+ select RUST_FW_LOADER_ABSTRACTIONS
default n
help
Choose this if you want to build the Nova Core driver for Nvidia
diff --git a/drivers/gpu/nova-core/dma.rs b/drivers/gpu/nova-core/dma.rs
deleted file mode 100644
index 7215398969da..000000000000
--- a/drivers/gpu/nova-core/dma.rs
+++ /dev/null
@@ -1,54 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-
-//! Simple DMA object wrapper.
-
-use core::ops::{
- Deref,
- DerefMut, //
-};
-
-use kernel::{
- device,
- dma::CoherentAllocation,
- page::PAGE_SIZE,
- prelude::*, //
-};
-
-pub(crate) struct DmaObject {
- dma: CoherentAllocation<u8>,
-}
-
-impl DmaObject {
- pub(crate) fn new(dev: &device::Device<device::Bound>, len: usize) -> Result<Self> {
- let len = core::alloc::Layout::from_size_align(len, PAGE_SIZE)
- .map_err(|_| EINVAL)?
- .pad_to_align()
- .size();
- let dma = CoherentAllocation::alloc_coherent(dev, len, GFP_KERNEL | __GFP_ZERO)?;
-
- Ok(Self { dma })
- }
-
- pub(crate) fn from_data(dev: &device::Device<device::Bound>, data: &[u8]) -> Result<Self> {
- Self::new(dev, data.len()).and_then(|mut dma_obj| {
- // SAFETY: We have just allocated the DMA memory, we are the only users and
- // we haven't made the device aware of the handle yet.
- unsafe { dma_obj.write(data, 0)? }
- Ok(dma_obj)
- })
- }
-}
-
-impl Deref for DmaObject {
- type Target = CoherentAllocation<u8>;
-
- fn deref(&self) -> &Self::Target {
- &self.dma
- }
-}
-
-impl DerefMut for DmaObject {
- fn deref_mut(&mut self) -> &mut Self::Target {
- &mut self.dma
- }
-}
diff --git a/drivers/gpu/nova-core/driver.rs b/drivers/gpu/nova-core/driver.rs
index 5a4cc047bcfc..84b0e1703150 100644
--- a/drivers/gpu/nova-core/driver.rs
+++ b/drivers/gpu/nova-core/driver.rs
@@ -14,11 +14,20 @@ use kernel::{
},
prelude::*,
sizes::SZ_16M,
- sync::Arc, //
+ sync::{
+ atomic::{
+ Atomic,
+ Relaxed, //
+ },
+ Arc,
+ },
};
use crate::gpu::Gpu;
+/// Counter for generating unique auxiliary device IDs.
+static AUXILIARY_ID_COUNTER: Atomic<u32> = Atomic::new(0);
+
#[pin_data]
pub(crate) struct NovaCore {
#[pin]
@@ -70,7 +79,7 @@ impl pci::Driver for NovaCore {
fn probe(pdev: &pci::Device<Core>, _info: &Self::IdInfo) -> impl PinInit<Self, Error> {
pin_init::pin_init_scope(move || {
- dev_dbg!(pdev.as_ref(), "Probe Nova Core GPU driver.\n");
+ dev_dbg!(pdev, "Probe Nova Core GPU driver.\n");
pdev.enable_device_mem()?;
pdev.set_master();
@@ -90,7 +99,9 @@ impl pci::Driver for NovaCore {
_reg <- auxiliary::Registration::new(
pdev.as_ref(),
c"nova-drm",
- 0, // TODO[XARR]: Once it lands, use XArray; for now we don't use the ID.
+ // TODO[XARR]: Use XArray or perhaps IDA for proper ID allocation/recycling. For
+ // now, use a simple atomic counter that never recycles IDs.
+ AUXILIARY_ID_COUNTER.fetch_add(1, Relaxed),
crate::MODULE_NAME
),
}))
diff --git a/drivers/gpu/nova-core/falcon.rs b/drivers/gpu/nova-core/falcon.rs
index 37bfee1d0949..e0315fda576b 100644
--- a/drivers/gpu/nova-core/falcon.rs
+++ b/drivers/gpu/nova-core/falcon.rs
@@ -2,243 +2,135 @@
//! Falcon microprocessor base support
-use core::ops::Deref;
-
use hal::FalconHal;
use kernel::{
- device,
+ device::{
+ self,
+ Device, //
+ },
dma::{
+ Coherent,
DmaAddress,
DmaMask, //
},
- io::poll::read_poll_timeout,
+ io::{
+ poll::read_poll_timeout,
+ register::{
+ RegisterBase,
+ WithBase, //
+ },
+ Io,
+ },
prelude::*,
sync::aref::ARef,
- time::{
- Delta, //
- },
+ time::Delta,
};
use crate::{
- dma::DmaObject,
+ bounded_enum,
driver::Bar0,
falcon::hal::LoadMethod,
gpu::Chipset,
num::{
- FromSafeCast,
- IntoSafeCast, //
+ self,
+ FromSafeCast, //
},
regs,
- regs::macros::RegisterBase, //
};
pub(crate) mod gsp;
mod hal;
pub(crate) mod sec2;
-// TODO[FPRI]: Replace with `ToPrimitive`.
-macro_rules! impl_from_enum_to_u8 {
- ($enum_type:ty) => {
- impl From<$enum_type> for u8 {
- fn from(value: $enum_type) -> Self {
- value as u8
- }
- }
- };
-}
-
-/// Revision number of a falcon core, used in the [`crate::regs::NV_PFALCON_FALCON_HWCFG1`]
-/// register.
-#[repr(u8)]
-#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
-pub(crate) enum FalconCoreRev {
- #[default]
- Rev1 = 1,
- Rev2 = 2,
- Rev3 = 3,
- Rev4 = 4,
- Rev5 = 5,
- Rev6 = 6,
- Rev7 = 7,
-}
-impl_from_enum_to_u8!(FalconCoreRev);
-
-// TODO[FPRI]: replace with `FromPrimitive`.
-impl TryFrom<u8> for FalconCoreRev {
- type Error = Error;
-
- fn try_from(value: u8) -> Result<Self> {
- use FalconCoreRev::*;
-
- let rev = match value {
- 1 => Rev1,
- 2 => Rev2,
- 3 => Rev3,
- 4 => Rev4,
- 5 => Rev5,
- 6 => Rev6,
- 7 => Rev7,
- _ => return Err(EINVAL),
- };
-
- Ok(rev)
+/// Alignment (in bytes) of falcon memory blocks.
+pub(crate) const MEM_BLOCK_ALIGNMENT: usize = 256;
+
+bounded_enum! {
+ /// Revision number of a falcon core, used in the [`crate::regs::NV_PFALCON_FALCON_HWCFG1`]
+ /// register.
+ #[derive(Debug, Copy, Clone)]
+ pub(crate) enum FalconCoreRev with TryFrom<Bounded<u32, 4>> {
+ Rev1 = 1,
+ Rev2 = 2,
+ Rev3 = 3,
+ Rev4 = 4,
+ Rev5 = 5,
+ Rev6 = 6,
+ Rev7 = 7,
}
}
-/// Revision subversion number of a falcon core, used in the
-/// [`crate::regs::NV_PFALCON_FALCON_HWCFG1`] register.
-#[repr(u8)]
-#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
-pub(crate) enum FalconCoreRevSubversion {
- #[default]
- Subversion0 = 0,
- Subversion1 = 1,
- Subversion2 = 2,
- Subversion3 = 3,
-}
-impl_from_enum_to_u8!(FalconCoreRevSubversion);
-
-// TODO[FPRI]: replace with `FromPrimitive`.
-impl TryFrom<u8> for FalconCoreRevSubversion {
- type Error = Error;
-
- fn try_from(value: u8) -> Result<Self> {
- use FalconCoreRevSubversion::*;
-
- let sub_version = match value & 0b11 {
- 0 => Subversion0,
- 1 => Subversion1,
- 2 => Subversion2,
- 3 => Subversion3,
- _ => return Err(EINVAL),
- };
-
- Ok(sub_version)
+bounded_enum! {
+ /// Revision subversion number of a falcon core, used in the
+ /// [`crate::regs::NV_PFALCON_FALCON_HWCFG1`] register.
+ #[derive(Debug, Copy, Clone)]
+ pub(crate) enum FalconCoreRevSubversion with From<Bounded<u32, 2>> {
+ Subversion0 = 0,
+ Subversion1 = 1,
+ Subversion2 = 2,
+ Subversion3 = 3,
}
}
-/// Security model of a falcon core, used in the [`crate::regs::NV_PFALCON_FALCON_HWCFG1`]
-/// register.
-#[repr(u8)]
-#[derive(Debug, Default, Copy, Clone)]
-/// Security mode of the Falcon microprocessor.
-///
-/// See `falcon.rst` for more details.
-pub(crate) enum FalconSecurityModel {
- /// Non-Secure: runs unsigned code without privileges.
- #[default]
- None = 0,
- /// Light-Secured (LS): Runs signed code with some privileges.
- /// Entry into this mode is only possible from 'Heavy-secure' mode, which verifies the code's
- /// signature.
+bounded_enum! {
+ /// Security mode of the Falcon microprocessor.
///
- /// Also known as Low-Secure, Privilege Level 2 or PL2.
- Light = 2,
- /// Heavy-Secured (HS): Runs signed code with full privileges.
- /// The code's signature is verified by the Falcon Boot ROM (BROM).
- ///
- /// Also known as High-Secure, Privilege Level 3 or PL3.
- Heavy = 3,
-}
-impl_from_enum_to_u8!(FalconSecurityModel);
-
-// TODO[FPRI]: replace with `FromPrimitive`.
-impl TryFrom<u8> for FalconSecurityModel {
- type Error = Error;
-
- fn try_from(value: u8) -> Result<Self> {
- use FalconSecurityModel::*;
-
- let sec_model = match value {
- 0 => None,
- 2 => Light,
- 3 => Heavy,
- _ => return Err(EINVAL),
- };
-
- Ok(sec_model)
- }
-}
-
-/// Signing algorithm for a given firmware, used in the [`crate::regs::NV_PFALCON2_FALCON_MOD_SEL`]
-/// register. It is passed to the Falcon Boot ROM (BROM) as a parameter.
-#[repr(u8)]
-#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
-pub(crate) enum FalconModSelAlgo {
- /// AES.
- #[expect(dead_code)]
- Aes = 0,
- /// RSA3K.
- #[default]
- Rsa3k = 1,
-}
-impl_from_enum_to_u8!(FalconModSelAlgo);
-
-// TODO[FPRI]: replace with `FromPrimitive`.
-impl TryFrom<u8> for FalconModSelAlgo {
- type Error = Error;
-
- fn try_from(value: u8) -> Result<Self> {
- match value {
- 1 => Ok(FalconModSelAlgo::Rsa3k),
- _ => Err(EINVAL),
- }
+ /// See `falcon.rst` for more details.
+ #[derive(Debug, Copy, Clone)]
+ pub(crate) enum FalconSecurityModel with TryFrom<Bounded<u32, 2>> {
+ /// Non-Secure: runs unsigned code without privileges.
+ None = 0,
+ /// Light-Secured (LS): Runs signed code with some privileges.
+ /// Entry into this mode is only possible from 'Heavy-secure' mode, which verifies the
+ /// code's signature.
+ ///
+ /// Also known as Low-Secure, Privilege Level 2 or PL2.
+ Light = 2,
+ /// Heavy-Secured (HS): Runs signed code with full privileges.
+ /// The code's signature is verified by the Falcon Boot ROM (BROM).
+ ///
+ /// Also known as High-Secure, Privilege Level 3 or PL3.
+ Heavy = 3,
}
}
-/// Valid values for the `size` field of the [`crate::regs::NV_PFALCON_FALCON_DMATRFCMD`] register.
-#[repr(u8)]
-#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
-pub(crate) enum DmaTrfCmdSize {
- /// 256 bytes transfer.
- #[default]
- Size256B = 0x6,
-}
-impl_from_enum_to_u8!(DmaTrfCmdSize);
-
-// TODO[FPRI]: replace with `FromPrimitive`.
-impl TryFrom<u8> for DmaTrfCmdSize {
- type Error = Error;
-
- fn try_from(value: u8) -> Result<Self> {
- match value {
- 0x6 => Ok(Self::Size256B),
- _ => Err(EINVAL),
- }
+bounded_enum! {
+ /// Signing algorithm for a given firmware, used in the
+ /// [`crate::regs::NV_PFALCON2_FALCON_MOD_SEL`] register. It is passed to the Falcon Boot ROM
+ /// (BROM) as a parameter.
+ #[derive(Debug, Copy, Clone)]
+ pub(crate) enum FalconModSelAlgo with TryFrom<Bounded<u32, 8>> {
+ /// AES.
+ Aes = 0,
+ /// RSA3K.
+ Rsa3k = 1,
}
}
-/// Currently active core on a dual falcon/riscv (Peregrine) controller.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
-pub(crate) enum PeregrineCoreSelect {
- /// Falcon core is active.
- #[default]
- Falcon = 0,
- /// RISC-V core is active.
- Riscv = 1,
-}
-
-impl From<bool> for PeregrineCoreSelect {
- fn from(value: bool) -> Self {
- match value {
- false => PeregrineCoreSelect::Falcon,
- true => PeregrineCoreSelect::Riscv,
- }
+bounded_enum! {
+ /// Valid values for the `size` field of the [`crate::regs::NV_PFALCON_FALCON_DMATRFCMD`]
+ /// register.
+ #[derive(Debug, Copy, Clone)]
+ pub(crate) enum DmaTrfCmdSize with TryFrom<Bounded<u32, 3>> {
+ /// 256 bytes transfer.
+ Size256B = 0x6,
}
}
-impl From<PeregrineCoreSelect> for bool {
- fn from(value: PeregrineCoreSelect) -> Self {
- match value {
- PeregrineCoreSelect::Falcon => false,
- PeregrineCoreSelect::Riscv => true,
- }
+bounded_enum! {
+ /// Currently active core on a dual falcon/riscv (Peregrine) controller.
+ #[derive(Debug, Copy, Clone, PartialEq, Eq)]
+ pub(crate) enum PeregrineCoreSelect with From<Bounded<u32, 1>> {
+ /// Falcon core is active.
+ Falcon = 0,
+ /// RISC-V core is active.
+ Riscv = 1,
}
}
/// Different types of memory present in a falcon core.
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub(crate) enum FalconMem {
/// Secure Instruction Memory.
ImemSecure,
@@ -249,64 +141,29 @@ pub(crate) enum FalconMem {
Dmem,
}
-/// Defines the Framebuffer Interface (FBIF) aperture type.
-/// This determines the memory type for external memory access during a DMA transfer, which is
-/// performed by the Falcon's Framebuffer DMA (FBDMA) engine. See falcon.rst for more details.
-#[derive(Debug, Clone, Default)]
-pub(crate) enum FalconFbifTarget {
- /// VRAM.
- #[default]
- /// Local Framebuffer (GPU's VRAM memory).
- LocalFb = 0,
- /// Coherent system memory (System DRAM).
- CoherentSysmem = 1,
- /// Non-coherent system memory (System DRAM).
- NoncoherentSysmem = 2,
-}
-impl_from_enum_to_u8!(FalconFbifTarget);
-
-// TODO[FPRI]: replace with `FromPrimitive`.
-impl TryFrom<u8> for FalconFbifTarget {
- type Error = Error;
-
- fn try_from(value: u8) -> Result<Self> {
- let res = match value {
- 0 => Self::LocalFb,
- 1 => Self::CoherentSysmem,
- 2 => Self::NoncoherentSysmem,
- _ => return Err(EINVAL),
- };
-
- Ok(res)
- }
-}
-
-/// Type of memory addresses to use.
-#[derive(Debug, Clone, Default)]
-pub(crate) enum FalconFbifMemType {
- /// Virtual memory addresses.
- #[default]
- Virtual = 0,
- /// Physical memory addresses.
- Physical = 1,
-}
-
-/// Conversion from a single-bit register field.
-impl From<bool> for FalconFbifMemType {
- fn from(value: bool) -> Self {
- match value {
- false => Self::Virtual,
- true => Self::Physical,
- }
+bounded_enum! {
+ /// Defines the Framebuffer Interface (FBIF) aperture type.
+ /// This determines the memory type for external memory access during a DMA transfer, which is
+ /// performed by the Falcon's Framebuffer DMA (FBDMA) engine. See falcon.rst for more details.
+ #[derive(Debug, Copy, Clone)]
+ pub(crate) enum FalconFbifTarget with TryFrom<Bounded<u32, 2>> {
+ /// Local Framebuffer (GPU's VRAM memory).
+ LocalFb = 0,
+ /// Coherent system memory (System DRAM).
+ CoherentSysmem = 1,
+ /// Non-coherent system memory (System DRAM).
+ NoncoherentSysmem = 2,
}
}
-impl From<FalconFbifMemType> for bool {
- fn from(value: FalconFbifMemType) -> Self {
- match value {
- FalconFbifMemType::Virtual => false,
- FalconFbifMemType::Physical => true,
- }
+bounded_enum! {
+ /// Type of memory addresses to use.
+ #[derive(Debug, Copy, Clone)]
+ pub(crate) enum FalconFbifMemType with From<Bounded<u32, 1>> {
+ /// Virtual memory addresses.
+ Virtual = 0,
+ /// Physical memory addresses.
+ Physical = 1,
}
}
@@ -318,18 +175,16 @@ pub(crate) struct PFalcon2Base(());
/// Trait defining the parameters of a given Falcon engine.
///
-/// Each engine provides one base for `PFALCON` and `PFALCON2` registers. The `ID` constant is used
-/// to identify a given Falcon instance with register I/O methods.
+/// Each engine provides one base for `PFALCON` and `PFALCON2` registers.
pub(crate) trait FalconEngine:
Send + Sync + RegisterBase<PFalconBase> + RegisterBase<PFalcon2Base> + Sized
{
- /// Singleton of the engine, used to identify it with register I/O methods.
- const ID: Self;
}
-/// Represents a portion of the firmware to be loaded into a particular memory (e.g. IMEM or DMEM).
+/// Represents a portion of the firmware to be loaded into a particular memory (e.g. IMEM or DMEM)
+/// using DMA.
#[derive(Debug, Clone)]
-pub(crate) struct FalconLoadTarget {
+pub(crate) struct FalconDmaLoadTarget {
/// Offset from the start of the source object to copy from.
pub(crate) src_start: u32,
/// Offset from the start of the destination memory to copy into.
@@ -349,32 +204,155 @@ pub(crate) struct FalconBromParams {
pub(crate) ucode_id: u8,
}
-/// Trait for providing load parameters of falcon firmwares.
-pub(crate) trait FalconLoadParams {
+/// Trait implemented by falcon firmwares that can be loaded using DMA.
+pub(crate) trait FalconDmaLoadable {
+ /// Returns the firmware data as a slice of bytes.
+ fn as_slice(&self) -> &[u8];
+
/// Returns the load parameters for Secure `IMEM`.
- fn imem_sec_load_params(&self) -> FalconLoadTarget;
+ fn imem_sec_load_params(&self) -> FalconDmaLoadTarget;
/// Returns the load parameters for Non-Secure `IMEM`,
/// used only on Turing and GA100.
- fn imem_ns_load_params(&self) -> Option<FalconLoadTarget>;
+ fn imem_ns_load_params(&self) -> Option<FalconDmaLoadTarget>;
/// Returns the load parameters for `DMEM`.
- fn dmem_load_params(&self) -> FalconLoadTarget;
+ fn dmem_load_params(&self) -> FalconDmaLoadTarget;
- /// Returns the parameters to write into the BROM registers.
- fn brom_params(&self) -> FalconBromParams;
+ /// Returns an adapter that provides the required parameter to load this firmware using PIO.
+ ///
+ /// This can only fail if some `u32` fields cannot be converted to `u16`, or if the indices in
+ /// the headers are invalid.
+ fn try_as_pio_loadable(&self) -> Result<FalconDmaFirmwarePioAdapter<'_, Self>> {
+ let new_pio_imem = |params: FalconDmaLoadTarget, secure| {
+ let start = usize::from_safe_cast(params.src_start);
+ let end = start + usize::from_safe_cast(params.len);
+ let data = self.as_slice().get(start..end).ok_or(EINVAL)?;
+
+ let dst_start = u16::try_from(params.dst_start).map_err(|_| EINVAL)?;
+
+ Ok::<_, Error>(FalconPioImemLoadTarget {
+ data,
+ dst_start,
+ secure,
+ start_tag: dst_start >> 8,
+ })
+ };
- /// Returns the start address of the firmware.
- fn boot_addr(&self) -> u32;
+ let imem_sec = new_pio_imem(self.imem_sec_load_params(), true)?;
+
+ let imem_ns = if let Some(params) = self.imem_ns_load_params() {
+ Some(new_pio_imem(params, false)?)
+ } else {
+ None
+ };
+
+ let dmem = {
+ let params = self.dmem_load_params();
+ let start = usize::from_safe_cast(params.src_start);
+ let end = start + usize::from_safe_cast(params.len);
+ let data = self.as_slice().get(start..end).ok_or(EINVAL)?;
+
+ let dst_start = u16::try_from(params.dst_start).map_err(|_| EINVAL)?;
+
+ FalconPioDmemLoadTarget { data, dst_start }
+ };
+
+ Ok(FalconDmaFirmwarePioAdapter {
+ fw: self,
+ imem_sec,
+ imem_ns,
+ dmem,
+ })
+ }
+}
+
+/// Represents a portion of the firmware to be loaded into IMEM using PIO.
+#[derive(Clone)]
+pub(crate) struct FalconPioImemLoadTarget<'a> {
+ pub(crate) data: &'a [u8],
+ pub(crate) dst_start: u16,
+ pub(crate) secure: bool,
+ pub(crate) start_tag: u16,
+}
+
+/// Represents a portion of the firmware to be loaded into DMEM using PIO.
+#[derive(Clone)]
+pub(crate) struct FalconPioDmemLoadTarget<'a> {
+ pub(crate) data: &'a [u8],
+ pub(crate) dst_start: u16,
+}
+
+/// Trait for providing PIO load parameters of falcon firmwares.
+pub(crate) trait FalconPioLoadable {
+ /// Returns the load parameters for Secure `IMEM`, if any.
+ fn imem_sec_load_params(&self) -> Option<FalconPioImemLoadTarget<'_>>;
+
+ /// Returns the load parameters for Non-Secure `IMEM`, if any.
+ fn imem_ns_load_params(&self) -> Option<FalconPioImemLoadTarget<'_>>;
+
+ /// Returns the load parameters for `DMEM`.
+ fn dmem_load_params(&self) -> FalconPioDmemLoadTarget<'_>;
+}
+
+/// Adapter type that makes any DMA-loadable firmware also loadable via PIO.
+///
+/// Created using [`FalconDmaLoadable::try_as_pio_loadable`].
+pub(crate) struct FalconDmaFirmwarePioAdapter<'a, T: FalconDmaLoadable + ?Sized> {
+ /// Reference to the DMA firmware.
+ fw: &'a T,
+ /// Validated secure IMEM parameters.
+ imem_sec: FalconPioImemLoadTarget<'a>,
+ /// Validated non-secure IMEM parameters.
+ imem_ns: Option<FalconPioImemLoadTarget<'a>>,
+ /// Validated DMEM parameters.
+ dmem: FalconPioDmemLoadTarget<'a>,
+}
+
+impl<'a, T> FalconPioLoadable for FalconDmaFirmwarePioAdapter<'a, T>
+where
+ T: FalconDmaLoadable + ?Sized,
+{
+ fn imem_sec_load_params(&self) -> Option<FalconPioImemLoadTarget<'_>> {
+ Some(self.imem_sec.clone())
+ }
+
+ fn imem_ns_load_params(&self) -> Option<FalconPioImemLoadTarget<'_>> {
+ self.imem_ns.clone()
+ }
+
+ fn dmem_load_params(&self) -> FalconPioDmemLoadTarget<'_> {
+ self.dmem.clone()
+ }
+}
+
+impl<'a, T> FalconFirmware for FalconDmaFirmwarePioAdapter<'a, T>
+where
+ T: FalconDmaLoadable + FalconFirmware + ?Sized,
+{
+ type Target = <T as FalconFirmware>::Target;
+
+ fn brom_params(&self) -> FalconBromParams {
+ self.fw.brom_params()
+ }
+
+ fn boot_addr(&self) -> u32 {
+ self.fw.boot_addr()
+ }
}
/// Trait for a falcon firmware.
///
-/// A falcon firmware can be loaded on a given engine, and is presented in the form of a DMA
-/// object.
-pub(crate) trait FalconFirmware: FalconLoadParams + Deref<Target = DmaObject> {
+/// A falcon firmware can be loaded on a given engine.
+pub(crate) trait FalconFirmware {
/// Engine on which this firmware is to be loaded.
type Target: FalconEngine;
+
+ /// Returns the parameters to write into the BROM registers.
+ fn brom_params(&self) -> FalconBromParams;
+
+ /// Returns the start address of the firmware.
+ fn boot_addr(&self) -> u32;
}
/// Contains the base parameters common to all Falcon instances.
@@ -394,8 +372,14 @@ impl<E: FalconEngine + 'static> Falcon<E> {
/// Resets DMA-related registers.
pub(crate) fn dma_reset(&self, bar: &Bar0) {
- regs::NV_PFALCON_FBIF_CTL::update(bar, &E::ID, |v| v.set_allow_phys_no_ctx(true));
- regs::NV_PFALCON_FALCON_DMACTL::default().write(bar, &E::ID);
+ bar.update(regs::NV_PFALCON_FBIF_CTL::of::<E>(), |v| {
+ v.with_allow_phys_no_ctx(true)
+ });
+
+ bar.write(
+ WithBase::of::<E>(),
+ regs::NV_PFALCON_FALCON_DMACTL::zeroed(),
+ );
}
/// Reset the controller, select the falcon core, and wait for memory scrubbing to complete.
@@ -404,9 +388,111 @@ impl<E: FalconEngine + 'static> Falcon<E> {
self.hal.select_core(self, bar)?;
self.hal.reset_wait_mem_scrubbing(bar)?;
- regs::NV_PFALCON_FALCON_RM::default()
- .set_value(regs::NV_PMC_BOOT_0::read(bar).into())
- .write(bar, &E::ID);
+ bar.write(
+ WithBase::of::<E>(),
+ regs::NV_PFALCON_FALCON_RM::from(bar.read(regs::NV_PMC_BOOT_0).into_raw()),
+ );
+
+ Ok(())
+ }
+
+ /// Falcons supports up to four ports, but we only ever use one, so just hard-code it.
+ const PIO_PORT: usize = 0;
+
+ /// Write a slice to Falcon IMEM memory using programmed I/O (PIO).
+ ///
+ /// Returns `EINVAL` if `img.len()` is not a multiple of 4.
+ fn pio_wr_imem_slice(&self, bar: &Bar0, load_offsets: FalconPioImemLoadTarget<'_>) -> Result {
+ // Rejecting misaligned images here allows us to avoid checking
+ // inside the loops.
+ if load_offsets.data.len() % 4 != 0 {
+ return Err(EINVAL);
+ }
+
+ bar.write(
+ WithBase::of::<E>().at(Self::PIO_PORT),
+ regs::NV_PFALCON_FALCON_IMEMC::zeroed()
+ .with_secure(load_offsets.secure)
+ .with_aincw(true)
+ .with_offs(load_offsets.dst_start),
+ );
+
+ for (n, block) in load_offsets.data.chunks(MEM_BLOCK_ALIGNMENT).enumerate() {
+ let n = u16::try_from(n)?;
+ let tag: u16 = load_offsets.start_tag.checked_add(n).ok_or(ERANGE)?;
+ bar.write(
+ WithBase::of::<E>().at(Self::PIO_PORT),
+ regs::NV_PFALCON_FALCON_IMEMT::zeroed().with_tag(tag),
+ );
+ for word in block.chunks_exact(4) {
+ let w = [word[0], word[1], word[2], word[3]];
+ bar.write(
+ WithBase::of::<E>().at(Self::PIO_PORT),
+ regs::NV_PFALCON_FALCON_IMEMD::zeroed().with_data(u32::from_le_bytes(w)),
+ );
+ }
+ }
+
+ Ok(())
+ }
+
+ /// Write a slice to Falcon DMEM memory using programmed I/O (PIO).
+ ///
+ /// Returns `EINVAL` if `img.len()` is not a multiple of 4.
+ fn pio_wr_dmem_slice(&self, bar: &Bar0, load_offsets: FalconPioDmemLoadTarget<'_>) -> Result {
+ // Rejecting misaligned images here allows us to avoid checking
+ // inside the loops.
+ if load_offsets.data.len() % 4 != 0 {
+ return Err(EINVAL);
+ }
+
+ bar.write(
+ WithBase::of::<E>().at(Self::PIO_PORT),
+ regs::NV_PFALCON_FALCON_DMEMC::zeroed()
+ .with_aincw(true)
+ .with_offs(load_offsets.dst_start),
+ );
+
+ for word in load_offsets.data.chunks_exact(4) {
+ let w = [word[0], word[1], word[2], word[3]];
+ bar.write(
+ WithBase::of::<E>().at(Self::PIO_PORT),
+ regs::NV_PFALCON_FALCON_DMEMD::zeroed().with_data(u32::from_le_bytes(w)),
+ );
+ }
+
+ Ok(())
+ }
+
+ /// Perform a PIO copy into `IMEM` and `DMEM` of `fw`, and prepare the falcon to run it.
+ pub(crate) fn pio_load<F: FalconFirmware<Target = E> + FalconPioLoadable>(
+ &self,
+ bar: &Bar0,
+ fw: &F,
+ ) -> Result {
+ bar.update(regs::NV_PFALCON_FBIF_CTL::of::<E>(), |v| {
+ v.with_allow_phys_no_ctx(true)
+ });
+
+ bar.write(
+ WithBase::of::<E>(),
+ regs::NV_PFALCON_FALCON_DMACTL::zeroed(),
+ );
+
+ if let Some(imem_ns) = fw.imem_ns_load_params() {
+ self.pio_wr_imem_slice(bar, imem_ns)?;
+ }
+ if let Some(imem_sec) = fw.imem_sec_load_params() {
+ self.pio_wr_imem_slice(bar, imem_sec)?;
+ }
+ self.pio_wr_dmem_slice(bar, fw.dmem_load_params())?;
+
+ self.hal.program_brom(self, bar, &fw.brom_params())?;
+
+ bar.write(
+ WithBase::of::<E>(),
+ regs::NV_PFALCON_FALCON_BOOTVEC::zeroed().with_value(fw.boot_addr()),
+ );
Ok(())
}
@@ -415,14 +501,14 @@ impl<E: FalconEngine + 'static> Falcon<E> {
/// `target_mem`.
///
/// `sec` is set if the loaded firmware is expected to run in secure mode.
- fn dma_wr<F: FalconFirmware<Target = E>>(
+ fn dma_wr(
&self,
bar: &Bar0,
- fw: &F,
+ dma_obj: &Coherent<[u8]>,
target_mem: FalconMem,
- load_offsets: FalconLoadTarget,
+ load_offsets: FalconDmaLoadTarget,
) -> Result {
- const DMA_LEN: u32 = 256;
+ const DMA_LEN: u32 = num::usize_into_u32::<{ MEM_BLOCK_ALIGNMENT }>();
// For IMEM, we want to use the start offset as a virtual address tag for each page, since
// code addresses in the firmware (and the boot vector) are virtual.
@@ -430,11 +516,11 @@ impl<E: FalconEngine + 'static> Falcon<E> {
// For DMEM we can fold the start offset into the DMA handle.
let (src_start, dma_start) = match target_mem {
FalconMem::ImemSecure | FalconMem::ImemNonSecure => {
- (load_offsets.src_start, fw.dma_handle())
+ (load_offsets.src_start, dma_obj.dma_handle())
}
FalconMem::Dmem => (
0,
- fw.dma_handle_with_offset(load_offsets.src_start.into_safe_cast())?,
+ dma_obj.dma_handle() + DmaAddress::from(load_offsets.src_start),
),
};
if dma_start % DmaAddress::from(DMA_LEN) > 0 {
@@ -466,7 +552,7 @@ impl<E: FalconEngine + 'static> Falcon<E> {
dev_err!(self.dev, "DMA transfer length overflow\n");
return Err(EOVERFLOW);
}
- Some(upper_bound) if usize::from_safe_cast(upper_bound) > fw.size() => {
+ Some(upper_bound) if usize::from_safe_cast(upper_bound) > dma_obj.size() => {
dev_err!(self.dev, "DMA transfer goes beyond range of DMA object\n");
return Err(EINVAL);
}
@@ -475,36 +561,42 @@ impl<E: FalconEngine + 'static> Falcon<E> {
// Set up the base source DMA address.
- regs::NV_PFALCON_FALCON_DMATRFBASE::default()
- // CAST: `as u32` is used on purpose since we do want to strip the upper bits, which
- // will be written to `NV_PFALCON_FALCON_DMATRFBASE1`.
- .set_base((dma_start >> 8) as u32)
- .write(bar, &E::ID);
- regs::NV_PFALCON_FALCON_DMATRFBASE1::default()
- // CAST: `as u16` is used on purpose since the remaining bits are guaranteed to fit
- // within a `u16`.
- .set_base((dma_start >> 40) as u16)
- .write(bar, &E::ID);
-
- let cmd = regs::NV_PFALCON_FALCON_DMATRFCMD::default()
- .set_size(DmaTrfCmdSize::Size256B)
+ bar.write(
+ WithBase::of::<E>(),
+ regs::NV_PFALCON_FALCON_DMATRFBASE::zeroed().with_base(
+ // CAST: `as u32` is used on purpose since we do want to strip the upper bits,
+ // which will be written to `NV_PFALCON_FALCON_DMATRFBASE1`.
+ (dma_start >> 8) as u32,
+ ),
+ );
+ bar.write(
+ WithBase::of::<E>(),
+ regs::NV_PFALCON_FALCON_DMATRFBASE1::zeroed().try_with_base(dma_start >> 40)?,
+ );
+
+ let cmd = regs::NV_PFALCON_FALCON_DMATRFCMD::zeroed()
+ .with_size(DmaTrfCmdSize::Size256B)
.with_falcon_mem(target_mem);
for pos in (0..num_transfers).map(|i| i * DMA_LEN) {
// Perform a transfer of size `DMA_LEN`.
- regs::NV_PFALCON_FALCON_DMATRFMOFFS::default()
- .set_offs(load_offsets.dst_start + pos)
- .write(bar, &E::ID);
- regs::NV_PFALCON_FALCON_DMATRFFBOFFS::default()
- .set_offs(src_start + pos)
- .write(bar, &E::ID);
- cmd.write(bar, &E::ID);
+ bar.write(
+ WithBase::of::<E>(),
+ regs::NV_PFALCON_FALCON_DMATRFMOFFS::zeroed()
+ .try_with_offs(load_offsets.dst_start + pos)?,
+ );
+ bar.write(
+ WithBase::of::<E>(),
+ regs::NV_PFALCON_FALCON_DMATRFFBOFFS::zeroed().with_offs(src_start + pos),
+ );
+
+ bar.write(WithBase::of::<E>(), cmd);
// Wait for the transfer to complete.
// TIMEOUT: arbitrarily large value, no DMA transfer to the falcon's small memories
// should ever take that long.
read_poll_timeout(
- || Ok(regs::NV_PFALCON_FALCON_DMATRFCMD::read(bar, &E::ID)),
+ || Ok(bar.read(regs::NV_PFALCON_FALCON_DMATRFCMD::of::<E>())),
|r| r.idle(),
Delta::ZERO,
Delta::from_secs(2),
@@ -515,29 +607,36 @@ impl<E: FalconEngine + 'static> Falcon<E> {
}
/// Perform a DMA load into `IMEM` and `DMEM` of `fw`, and prepare the falcon to run it.
- fn dma_load<F: FalconFirmware<Target = E>>(&self, bar: &Bar0, fw: &F) -> Result {
- // The Non-Secure section only exists on firmware used by Turing and GA100, and
- // those platforms do not use DMA.
- if fw.imem_ns_load_params().is_some() {
- debug_assert!(false);
- return Err(EINVAL);
- }
+ fn dma_load<F: FalconFirmware<Target = E> + FalconDmaLoadable>(
+ &self,
+ dev: &Device<device::Bound>,
+ bar: &Bar0,
+ fw: &F,
+ ) -> Result {
+ // Create DMA object with firmware content as the source of the DMA engine.
+ let dma_obj = Coherent::from_slice(dev, fw.as_slice(), GFP_KERNEL)?;
self.dma_reset(bar);
- regs::NV_PFALCON_FBIF_TRANSCFG::update(bar, &E::ID, 0, |v| {
- v.set_target(FalconFbifTarget::CoherentSysmem)
- .set_mem_type(FalconFbifMemType::Physical)
+ bar.update(regs::NV_PFALCON_FBIF_TRANSCFG::of::<E>().at(0), |v| {
+ v.with_target(FalconFbifTarget::CoherentSysmem)
+ .with_mem_type(FalconFbifMemType::Physical)
});
- self.dma_wr(bar, fw, FalconMem::ImemSecure, fw.imem_sec_load_params())?;
- self.dma_wr(bar, fw, FalconMem::Dmem, fw.dmem_load_params())?;
+ self.dma_wr(
+ bar,
+ &dma_obj,
+ FalconMem::ImemSecure,
+ fw.imem_sec_load_params(),
+ )?;
+ self.dma_wr(bar, &dma_obj, FalconMem::Dmem, fw.dmem_load_params())?;
self.hal.program_brom(self, bar, &fw.brom_params())?;
// Set `BootVec` to start of non-secure code.
- regs::NV_PFALCON_FALCON_BOOTVEC::default()
- .set_value(fw.boot_addr())
- .write(bar, &E::ID);
+ bar.write(
+ WithBase::of::<E>(),
+ regs::NV_PFALCON_FALCON_BOOTVEC::zeroed().with_value(fw.boot_addr()),
+ );
Ok(())
}
@@ -546,7 +645,7 @@ impl<E: FalconEngine + 'static> Falcon<E> {
pub(crate) fn wait_till_halted(&self, bar: &Bar0) -> Result<()> {
// TIMEOUT: arbitrarily large value, firmwares should complete in less than 2 seconds.
read_poll_timeout(
- || Ok(regs::NV_PFALCON_FALCON_CPUCTL::read(bar, &E::ID)),
+ || Ok(bar.read(regs::NV_PFALCON_FALCON_CPUCTL::of::<E>())),
|r| r.halted(),
Delta::ZERO,
Delta::from_secs(2),
@@ -557,13 +656,18 @@ impl<E: FalconEngine + 'static> Falcon<E> {
/// Start the falcon CPU.
pub(crate) fn start(&self, bar: &Bar0) -> Result<()> {
- match regs::NV_PFALCON_FALCON_CPUCTL::read(bar, &E::ID).alias_en() {
- true => regs::NV_PFALCON_FALCON_CPUCTL_ALIAS::default()
- .set_startcpu(true)
- .write(bar, &E::ID),
- false => regs::NV_PFALCON_FALCON_CPUCTL::default()
- .set_startcpu(true)
- .write(bar, &E::ID),
+ match bar
+ .read(regs::NV_PFALCON_FALCON_CPUCTL::of::<E>())
+ .alias_en()
+ {
+ true => bar.write(
+ WithBase::of::<E>(),
+ regs::NV_PFALCON_FALCON_CPUCTL_ALIAS::zeroed().with_startcpu(true),
+ ),
+ false => bar.write(
+ WithBase::of::<E>(),
+ regs::NV_PFALCON_FALCON_CPUCTL::zeroed().with_startcpu(true),
+ ),
}
Ok(())
@@ -572,26 +676,30 @@ impl<E: FalconEngine + 'static> Falcon<E> {
/// Writes values to the mailbox registers if provided.
pub(crate) fn write_mailboxes(&self, bar: &Bar0, mbox0: Option<u32>, mbox1: Option<u32>) {
if let Some(mbox0) = mbox0 {
- regs::NV_PFALCON_FALCON_MAILBOX0::default()
- .set_value(mbox0)
- .write(bar, &E::ID);
+ bar.write(
+ WithBase::of::<E>(),
+ regs::NV_PFALCON_FALCON_MAILBOX0::zeroed().with_value(mbox0),
+ );
}
if let Some(mbox1) = mbox1 {
- regs::NV_PFALCON_FALCON_MAILBOX1::default()
- .set_value(mbox1)
- .write(bar, &E::ID);
+ bar.write(
+ WithBase::of::<E>(),
+ regs::NV_PFALCON_FALCON_MAILBOX1::zeroed().with_value(mbox1),
+ );
}
}
/// Reads the value from `mbox0` register.
pub(crate) fn read_mailbox0(&self, bar: &Bar0) -> u32 {
- regs::NV_PFALCON_FALCON_MAILBOX0::read(bar, &E::ID).value()
+ bar.read(regs::NV_PFALCON_FALCON_MAILBOX0::of::<E>())
+ .value()
}
/// Reads the value from `mbox1` register.
pub(crate) fn read_mailbox1(&self, bar: &Bar0) -> u32 {
- regs::NV_PFALCON_FALCON_MAILBOX1::read(bar, &E::ID).value()
+ bar.read(regs::NV_PFALCON_FALCON_MAILBOX1::of::<E>())
+ .value()
}
/// Reads values from both mailbox registers.
@@ -640,18 +748,25 @@ impl<E: FalconEngine + 'static> Falcon<E> {
self.hal.is_riscv_active(bar)
}
- // Load a firmware image into Falcon memory
- pub(crate) fn load<F: FalconFirmware<Target = E>>(&self, bar: &Bar0, fw: &F) -> Result {
+ /// Load a firmware image into Falcon memory, using the preferred method for the current
+ /// chipset.
+ pub(crate) fn load<F: FalconFirmware<Target = E> + FalconDmaLoadable>(
+ &self,
+ dev: &Device<device::Bound>,
+ bar: &Bar0,
+ fw: &F,
+ ) -> Result {
match self.hal.load_method() {
- LoadMethod::Dma => self.dma_load(bar, fw),
- LoadMethod::Pio => Err(ENOTSUPP),
+ LoadMethod::Dma => self.dma_load(dev, bar, fw),
+ LoadMethod::Pio => self.pio_load(bar, &fw.try_as_pio_loadable()?),
}
}
/// Write the application version to the OS register.
pub(crate) fn write_os_version(&self, bar: &Bar0, app_version: u32) {
- regs::NV_PFALCON_FALCON_OS::default()
- .set_value(app_version)
- .write(bar, &E::ID);
+ bar.write(
+ WithBase::of::<E>(),
+ regs::NV_PFALCON_FALCON_OS::zeroed().with_value(app_version),
+ );
}
}
diff --git a/drivers/gpu/nova-core/falcon/gsp.rs b/drivers/gpu/nova-core/falcon/gsp.rs
index 67edef3636c1..df6d5a382c7a 100644
--- a/drivers/gpu/nova-core/falcon/gsp.rs
+++ b/drivers/gpu/nova-core/falcon/gsp.rs
@@ -1,7 +1,14 @@
// SPDX-License-Identifier: GPL-2.0
use kernel::{
- io::poll::read_poll_timeout,
+ io::{
+ poll::read_poll_timeout,
+ register::{
+ RegisterBase,
+ WithBase, //
+ },
+ Io,
+ },
prelude::*,
time::Delta, //
};
@@ -14,10 +21,7 @@ use crate::{
PFalcon2Base,
PFalconBase, //
},
- regs::{
- self,
- macros::RegisterBase, //
- },
+ regs,
};
/// Type specifying the `Gsp` falcon engine. Cannot be instantiated.
@@ -31,23 +35,22 @@ impl RegisterBase<PFalcon2Base> for Gsp {
const BASE: usize = 0x00111000;
}
-impl FalconEngine for Gsp {
- const ID: Self = Gsp(());
-}
+impl FalconEngine for Gsp {}
impl Falcon<Gsp> {
/// Clears the SWGEN0 bit in the Falcon's IRQ status clear register to
/// allow GSP to signal CPU for processing new messages in message queue.
pub(crate) fn clear_swgen0_intr(&self, bar: &Bar0) {
- regs::NV_PFALCON_FALCON_IRQSCLR::default()
- .set_swgen0(true)
- .write(bar, &Gsp::ID);
+ bar.write(
+ WithBase::of::<Gsp>(),
+ regs::NV_PFALCON_FALCON_IRQSCLR::zeroed().with_swgen0(true),
+ );
}
/// Checks if GSP reload/resume has completed during the boot process.
pub(crate) fn check_reload_completed(&self, bar: &Bar0, timeout: Delta) -> Result<bool> {
read_poll_timeout(
- || Ok(regs::NV_PGC6_BSI_SECURE_SCRATCH_14::read(bar)),
+ || Ok(bar.read(regs::NV_PGC6_BSI_SECURE_SCRATCH_14)),
|val| val.boot_stage_3_handoff(),
Delta::ZERO,
timeout,
diff --git a/drivers/gpu/nova-core/falcon/hal.rs b/drivers/gpu/nova-core/falcon/hal.rs
index 89babd5f9325..a7e5ea8d0272 100644
--- a/drivers/gpu/nova-core/falcon/hal.rs
+++ b/drivers/gpu/nova-core/falcon/hal.rs
@@ -58,7 +58,11 @@ pub(crate) trait FalconHal<E: FalconEngine>: Send + Sync {
/// Reset the falcon engine.
fn reset_eng(&self, bar: &Bar0) -> Result;
- /// returns the method needed to load data into Falcon memory
+ /// Returns the method used to load data into the falcon's memory.
+ ///
+ /// The only chipsets supporting PIO are those < GA102, and PIO is the preferred method for
+ /// these. For anything above, the PIO registers appear to be masked to the CPU, so DMA is the
+ /// only usable method.
fn load_method(&self) -> LoadMethod;
}
diff --git a/drivers/gpu/nova-core/falcon/hal/ga102.rs b/drivers/gpu/nova-core/falcon/hal/ga102.rs
index 8f62df10da0a..8368a61ddeef 100644
--- a/drivers/gpu/nova-core/falcon/hal/ga102.rs
+++ b/drivers/gpu/nova-core/falcon/hal/ga102.rs
@@ -4,7 +4,14 @@ use core::marker::PhantomData;
use kernel::{
device,
- io::poll::read_poll_timeout,
+ io::{
+ poll::read_poll_timeout,
+ register::{
+ Array,
+ WithBase, //
+ },
+ Io, //
+ },
prelude::*,
time::Delta, //
};
@@ -25,15 +32,16 @@ use crate::{
use super::FalconHal;
fn select_core_ga102<E: FalconEngine>(bar: &Bar0) -> Result {
- let bcr_ctrl = regs::NV_PRISCV_RISCV_BCR_CTRL::read(bar, &E::ID);
+ let bcr_ctrl = bar.read(regs::NV_PRISCV_RISCV_BCR_CTRL::of::<E>());
if bcr_ctrl.core_select() != PeregrineCoreSelect::Falcon {
- regs::NV_PRISCV_RISCV_BCR_CTRL::default()
- .set_core_select(PeregrineCoreSelect::Falcon)
- .write(bar, &E::ID);
+ bar.write(
+ WithBase::of::<E>(),
+ regs::NV_PRISCV_RISCV_BCR_CTRL::zeroed().with_core_select(PeregrineCoreSelect::Falcon),
+ );
// TIMEOUT: falcon core should take less than 10ms to report being enabled.
read_poll_timeout(
- || Ok(regs::NV_PRISCV_RISCV_BCR_CTRL::read(bar, &E::ID)),
+ || Ok(bar.read(regs::NV_PRISCV_RISCV_BCR_CTRL::of::<E>())),
|r| r.valid(),
Delta::ZERO,
Delta::from_millis(10),
@@ -60,12 +68,15 @@ fn signature_reg_fuse_version_ga102(
// `ucode_idx` is guaranteed to be in the range [0..15], making the `read` calls provable valid
// at build-time.
- let reg_fuse_version = if engine_id_mask & 0x0001 != 0 {
- regs::NV_FUSE_OPT_FPF_SEC2_UCODE1_VERSION::read(bar, ucode_idx).data()
+ let reg_fuse_version: u16 = if engine_id_mask & 0x0001 != 0 {
+ bar.read(regs::NV_FUSE_OPT_FPF_SEC2_UCODE1_VERSION::at(ucode_idx))
+ .data()
} else if engine_id_mask & 0x0004 != 0 {
- regs::NV_FUSE_OPT_FPF_NVDEC_UCODE1_VERSION::read(bar, ucode_idx).data()
+ bar.read(regs::NV_FUSE_OPT_FPF_NVDEC_UCODE1_VERSION::at(ucode_idx))
+ .data()
} else if engine_id_mask & 0x0400 != 0 {
- regs::NV_FUSE_OPT_FPF_GSP_UCODE1_VERSION::read(bar, ucode_idx).data()
+ bar.read(regs::NV_FUSE_OPT_FPF_GSP_UCODE1_VERSION::at(ucode_idx))
+ .data()
} else {
dev_err!(dev, "unexpected engine_id_mask {:#x}\n", engine_id_mask);
return Err(EINVAL);
@@ -76,18 +87,23 @@ fn signature_reg_fuse_version_ga102(
}
fn program_brom_ga102<E: FalconEngine>(bar: &Bar0, params: &FalconBromParams) -> Result {
- regs::NV_PFALCON2_FALCON_BROM_PARAADDR::default()
- .set_value(params.pkc_data_offset)
- .write(bar, &E::ID, 0);
- regs::NV_PFALCON2_FALCON_BROM_ENGIDMASK::default()
- .set_value(u32::from(params.engine_id_mask))
- .write(bar, &E::ID);
- regs::NV_PFALCON2_FALCON_BROM_CURR_UCODE_ID::default()
- .set_ucode_id(params.ucode_id)
- .write(bar, &E::ID);
- regs::NV_PFALCON2_FALCON_MOD_SEL::default()
- .set_algo(FalconModSelAlgo::Rsa3k)
- .write(bar, &E::ID);
+ bar.write(
+ WithBase::of::<E>().at(0),
+ regs::NV_PFALCON2_FALCON_BROM_PARAADDR::zeroed().with_value(params.pkc_data_offset),
+ );
+ bar.write(
+ WithBase::of::<E>(),
+ regs::NV_PFALCON2_FALCON_BROM_ENGIDMASK::zeroed()
+ .with_value(u32::from(params.engine_id_mask)),
+ );
+ bar.write(
+ WithBase::of::<E>(),
+ regs::NV_PFALCON2_FALCON_BROM_CURR_UCODE_ID::zeroed().with_ucode_id(params.ucode_id),
+ );
+ bar.write(
+ WithBase::of::<E>(),
+ regs::NV_PFALCON2_FALCON_MOD_SEL::zeroed().with_algo(FalconModSelAlgo::Rsa3k),
+ );
Ok(())
}
@@ -120,14 +136,14 @@ impl<E: FalconEngine> FalconHal<E> for Ga102<E> {
}
fn is_riscv_active(&self, bar: &Bar0) -> bool {
- let cpuctl = regs::NV_PRISCV_RISCV_CPUCTL::read(bar, &E::ID);
- cpuctl.active_stat()
+ bar.read(regs::NV_PRISCV_RISCV_CPUCTL::of::<E>())
+ .active_stat()
}
fn reset_wait_mem_scrubbing(&self, bar: &Bar0) -> Result {
// TIMEOUT: memory scrubbing should complete in less than 20ms.
read_poll_timeout(
- || Ok(regs::NV_PFALCON_FALCON_HWCFG2::read(bar, &E::ID)),
+ || Ok(bar.read(regs::NV_PFALCON_FALCON_HWCFG2::of::<E>())),
|r| r.mem_scrubbing_done(),
Delta::ZERO,
Delta::from_millis(20),
@@ -136,12 +152,12 @@ impl<E: FalconEngine> FalconHal<E> for Ga102<E> {
}
fn reset_eng(&self, bar: &Bar0) -> Result {
- let _ = regs::NV_PFALCON_FALCON_HWCFG2::read(bar, &E::ID);
+ let _ = bar.read(regs::NV_PFALCON_FALCON_HWCFG2::of::<E>());
// According to OpenRM's `kflcnPreResetWait_GA102` documentation, HW sometimes does not set
// RESET_READY so a non-failing timeout is used.
let _ = read_poll_timeout(
- || Ok(regs::NV_PFALCON_FALCON_HWCFG2::read(bar, &E::ID)),
+ || Ok(bar.read(regs::NV_PFALCON_FALCON_HWCFG2::of::<E>())),
|r| r.reset_ready(),
Delta::ZERO,
Delta::from_micros(150),
diff --git a/drivers/gpu/nova-core/falcon/hal/tu102.rs b/drivers/gpu/nova-core/falcon/hal/tu102.rs
index 7de6f24cc0a0..c7a90266cb44 100644
--- a/drivers/gpu/nova-core/falcon/hal/tu102.rs
+++ b/drivers/gpu/nova-core/falcon/hal/tu102.rs
@@ -3,7 +3,11 @@
use core::marker::PhantomData;
use kernel::{
- io::poll::read_poll_timeout,
+ io::{
+ poll::read_poll_timeout,
+ register::WithBase,
+ Io, //
+ },
prelude::*,
time::Delta, //
};
@@ -49,14 +53,14 @@ impl<E: FalconEngine> FalconHal<E> for Tu102<E> {
}
fn is_riscv_active(&self, bar: &Bar0) -> bool {
- let cpuctl = regs::NV_PRISCV_RISCV_CORE_SWITCH_RISCV_STATUS::read(bar, &E::ID);
- cpuctl.active_stat()
+ bar.read(regs::NV_PRISCV_RISCV_CORE_SWITCH_RISCV_STATUS::of::<E>())
+ .active_stat()
}
fn reset_wait_mem_scrubbing(&self, bar: &Bar0) -> Result {
// TIMEOUT: memory scrubbing should complete in less than 10ms.
read_poll_timeout(
- || Ok(regs::NV_PFALCON_FALCON_DMACTL::read(bar, &E::ID)),
+ || Ok(bar.read(regs::NV_PFALCON_FALCON_DMACTL::of::<E>())),
|r| r.mem_scrubbing_done(),
Delta::ZERO,
Delta::from_millis(10),
diff --git a/drivers/gpu/nova-core/falcon/sec2.rs b/drivers/gpu/nova-core/falcon/sec2.rs
index b57d362e576a..91ec7d49c1f5 100644
--- a/drivers/gpu/nova-core/falcon/sec2.rs
+++ b/drivers/gpu/nova-core/falcon/sec2.rs
@@ -1,12 +1,11 @@
// SPDX-License-Identifier: GPL-2.0
-use crate::{
- falcon::{
- FalconEngine,
- PFalcon2Base,
- PFalconBase, //
- },
- regs::macros::RegisterBase,
+use kernel::io::register::RegisterBase;
+
+use crate::falcon::{
+ FalconEngine,
+ PFalcon2Base,
+ PFalconBase, //
};
/// Type specifying the `Sec2` falcon engine. Cannot be instantiated.
@@ -20,6 +19,4 @@ impl RegisterBase<PFalcon2Base> for Sec2 {
const BASE: usize = 0x00841000;
}
-impl FalconEngine for Sec2 {
- const ID: Self = Sec2(());
-}
+impl FalconEngine for Sec2 {}
diff --git a/drivers/gpu/nova-core/fb.rs b/drivers/gpu/nova-core/fb.rs
index c62abcaed547..bdd5eed760e1 100644
--- a/drivers/gpu/nova-core/fb.rs
+++ b/drivers/gpu/nova-core/fb.rs
@@ -1,9 +1,15 @@
// SPDX-License-Identifier: GPL-2.0
-use core::ops::Range;
+use core::ops::{
+ Deref,
+ Range, //
+};
use kernel::{
device,
+ dma::CoherentHandle,
+ fmt,
+ io::Io,
prelude::*,
ptr::{
Alignable,
@@ -14,7 +20,6 @@ use kernel::{
};
use crate::{
- dma::DmaObject,
driver::Bar0,
firmware::gsp::GspFirmware,
gpu::Chipset,
@@ -48,7 +53,7 @@ pub(crate) struct SysmemFlush {
chipset: Chipset,
device: ARef<device::Device>,
/// Keep the page alive as long as we need it.
- page: DmaObject,
+ page: CoherentHandle,
}
impl SysmemFlush {
@@ -58,7 +63,7 @@ impl SysmemFlush {
bar: &Bar0,
chipset: Chipset,
) -> Result<Self> {
- let page = DmaObject::new(dev, kernel::page::PAGE_SIZE)?;
+ let page = CoherentHandle::alloc(dev, kernel::page::PAGE_SIZE, GFP_KERNEL)?;
hal::fb_hal(chipset).write_sysmem_flush_page(bar, page.dma_handle())?;
@@ -94,26 +99,77 @@ impl SysmemFlush {
}
}
+pub(crate) struct FbRange(Range<u64>);
+
+impl FbRange {
+ pub(crate) fn len(&self) -> u64 {
+ self.0.end - self.0.start
+ }
+}
+
+impl From<Range<u64>> for FbRange {
+ fn from(range: Range<u64>) -> Self {
+ Self(range)
+ }
+}
+
+impl Deref for FbRange {
+ type Target = Range<u64>;
+
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+impl fmt::Debug for FbRange {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ // Use alternate format ({:#?}) to include size, compact format ({:?}) for just the range.
+ if f.alternate() {
+ let size = self.len();
+
+ if size < usize_as_u64(SZ_1M) {
+ let size_kib = size / usize_as_u64(SZ_1K);
+ f.write_fmt(fmt!(
+ "{:#x}..{:#x} ({} KiB)",
+ self.0.start,
+ self.0.end,
+ size_kib
+ ))
+ } else {
+ let size_mib = size / usize_as_u64(SZ_1M);
+ f.write_fmt(fmt!(
+ "{:#x}..{:#x} ({} MiB)",
+ self.0.start,
+ self.0.end,
+ size_mib
+ ))
+ }
+ } else {
+ f.write_fmt(fmt!("{:#x}..{:#x}", self.0.start, self.0.end))
+ }
+ }
+}
+
/// Layout of the GPU framebuffer memory.
///
/// Contains ranges of GPU memory reserved for a given purpose during the GSP boot process.
#[derive(Debug)]
pub(crate) struct FbLayout {
/// Range of the framebuffer. Starts at `0`.
- pub(crate) fb: Range<u64>,
+ pub(crate) fb: FbRange,
/// VGA workspace, small area of reserved memory at the end of the framebuffer.
- pub(crate) vga_workspace: Range<u64>,
+ pub(crate) vga_workspace: FbRange,
/// FRTS range.
- pub(crate) frts: Range<u64>,
+ pub(crate) frts: FbRange,
/// Memory area containing the GSP bootloader image.
- pub(crate) boot: Range<u64>,
+ pub(crate) boot: FbRange,
/// Memory area containing the GSP firmware image.
- pub(crate) elf: Range<u64>,
+ pub(crate) elf: FbRange,
/// WPR2 heap.
- pub(crate) wpr2_heap: Range<u64>,
+ pub(crate) wpr2_heap: FbRange,
/// WPR2 region range, starting with an instance of `GspFwWprMeta`.
- pub(crate) wpr2: Range<u64>,
- pub(crate) heap: Range<u64>,
+ pub(crate) wpr2: FbRange,
+ pub(crate) heap: FbRange,
pub(crate) vf_partition_count: u8,
}
@@ -125,7 +181,7 @@ impl FbLayout {
let fb = {
let fb_size = hal.vidmem_size(bar);
- 0..fb_size
+ FbRange(0..fb_size)
};
let vga_workspace = {
@@ -134,7 +190,10 @@ impl FbLayout {
let base = fb.end - NV_PRAMIN_SIZE;
if hal.supports_display(bar) {
- match regs::NV_PDISP_VGA_WORKSPACE_BASE::read(bar).vga_workspace_addr() {
+ match bar
+ .read(regs::NV_PDISP_VGA_WORKSPACE_BASE)
+ .vga_workspace_addr()
+ {
Some(addr) => {
if addr < base {
const VBIOS_WORKSPACE_SIZE: u64 = usize_as_u64(SZ_128K);
@@ -152,7 +211,7 @@ impl FbLayout {
}
};
- vga_base..fb.end
+ FbRange(vga_base..fb.end)
};
let frts = {
@@ -160,7 +219,7 @@ impl FbLayout {
const FRTS_SIZE: u64 = usize_as_u64(SZ_1M);
let frts_base = vga_workspace.start.align_down(FRTS_DOWN_ALIGN) - FRTS_SIZE;
- frts_base..frts_base + FRTS_SIZE
+ FbRange(frts_base..frts_base + FRTS_SIZE)
};
let boot = {
@@ -168,7 +227,7 @@ impl FbLayout {
let bootloader_size = u64::from_safe_cast(gsp_fw.bootloader.ucode.size());
let bootloader_base = (frts.start - bootloader_size).align_down(BOOTLOADER_DOWN_ALIGN);
- bootloader_base..bootloader_base + bootloader_size
+ FbRange(bootloader_base..bootloader_base + bootloader_size)
};
let elf = {
@@ -176,7 +235,7 @@ impl FbLayout {
let elf_size = u64::from_safe_cast(gsp_fw.size);
let elf_addr = (boot.start - elf_size).align_down(ELF_DOWN_ALIGN);
- elf_addr..elf_addr + elf_size
+ FbRange(elf_addr..elf_addr + elf_size)
};
let wpr2_heap = {
@@ -185,7 +244,7 @@ impl FbLayout {
gsp::LibosParams::from_chipset(chipset).wpr_heap_size(chipset, fb.end);
let wpr2_heap_addr = (elf.start - wpr2_heap_size).align_down(WPR2_HEAP_DOWN_ALIGN);
- wpr2_heap_addr..(elf.start).align_down(WPR2_HEAP_DOWN_ALIGN)
+ FbRange(wpr2_heap_addr..(elf.start).align_down(WPR2_HEAP_DOWN_ALIGN))
};
let wpr2 = {
@@ -193,13 +252,13 @@ impl FbLayout {
let wpr2_addr = (wpr2_heap.start - u64::from_safe_cast(size_of::<gsp::GspFwWprMeta>()))
.align_down(WPR2_DOWN_ALIGN);
- wpr2_addr..frts.end
+ FbRange(wpr2_addr..frts.end)
};
let heap = {
const HEAP_SIZE: u64 = usize_as_u64(SZ_1M);
- wpr2.start - HEAP_SIZE..wpr2.start
+ FbRange(wpr2.start - HEAP_SIZE..wpr2.start)
};
Ok(Self {
diff --git a/drivers/gpu/nova-core/fb/hal/ga100.rs b/drivers/gpu/nova-core/fb/hal/ga100.rs
index e0acc41aa7cd..1c03783cddef 100644
--- a/drivers/gpu/nova-core/fb/hal/ga100.rs
+++ b/drivers/gpu/nova-core/fb/hal/ga100.rs
@@ -1,6 +1,10 @@
// SPDX-License-Identifier: GPL-2.0
-use kernel::prelude::*;
+use kernel::{
+ io::Io,
+ num::Bounded,
+ prelude::*, //
+};
use crate::{
driver::Bar0,
@@ -13,26 +17,31 @@ use super::tu102::FLUSH_SYSMEM_ADDR_SHIFT;
struct Ga100;
pub(super) fn read_sysmem_flush_page_ga100(bar: &Bar0) -> u64 {
- u64::from(regs::NV_PFB_NISO_FLUSH_SYSMEM_ADDR::read(bar).adr_39_08()) << FLUSH_SYSMEM_ADDR_SHIFT
- | u64::from(regs::NV_PFB_NISO_FLUSH_SYSMEM_ADDR_HI::read(bar).adr_63_40())
+ u64::from(bar.read(regs::NV_PFB_NISO_FLUSH_SYSMEM_ADDR).adr_39_08()) << FLUSH_SYSMEM_ADDR_SHIFT
+ | u64::from(bar.read(regs::NV_PFB_NISO_FLUSH_SYSMEM_ADDR_HI).adr_63_40())
<< FLUSH_SYSMEM_ADDR_SHIFT_HI
}
pub(super) fn write_sysmem_flush_page_ga100(bar: &Bar0, addr: u64) {
- regs::NV_PFB_NISO_FLUSH_SYSMEM_ADDR_HI::default()
- // CAST: `as u32` is used on purpose since the remaining bits are guaranteed to fit within
- // a `u32`.
- .set_adr_63_40((addr >> FLUSH_SYSMEM_ADDR_SHIFT_HI) as u32)
- .write(bar);
- regs::NV_PFB_NISO_FLUSH_SYSMEM_ADDR::default()
- // CAST: `as u32` is used on purpose since we want to strip the upper bits that have been
- // written to `NV_PFB_NISO_FLUSH_SYSMEM_ADDR_HI`.
- .set_adr_39_08((addr >> FLUSH_SYSMEM_ADDR_SHIFT) as u32)
- .write(bar);
+ bar.write_reg(
+ regs::NV_PFB_NISO_FLUSH_SYSMEM_ADDR_HI::zeroed().with_adr_63_40(
+ Bounded::<u64, _>::from(addr)
+ .shr::<FLUSH_SYSMEM_ADDR_SHIFT_HI, _>()
+ .cast(),
+ ),
+ );
+
+ bar.write_reg(
+ regs::NV_PFB_NISO_FLUSH_SYSMEM_ADDR::zeroed()
+ // CAST: `as u32` is used on purpose since we want to strip the upper bits that have
+ // been written to `NV_PFB_NISO_FLUSH_SYSMEM_ADDR_HI`.
+ .with_adr_39_08((addr >> FLUSH_SYSMEM_ADDR_SHIFT) as u32),
+ );
}
pub(super) fn display_enabled_ga100(bar: &Bar0) -> bool {
- !regs::ga100::NV_FUSE_STATUS_OPT_DISPLAY::read(bar).display_disabled()
+ !bar.read(regs::ga100::NV_FUSE_STATUS_OPT_DISPLAY)
+ .display_disabled()
}
/// Shift applied to the sysmem address before it is written into
diff --git a/drivers/gpu/nova-core/fb/hal/ga102.rs b/drivers/gpu/nova-core/fb/hal/ga102.rs
index 734605905031..4b9f0f74d0e7 100644
--- a/drivers/gpu/nova-core/fb/hal/ga102.rs
+++ b/drivers/gpu/nova-core/fb/hal/ga102.rs
@@ -1,6 +1,9 @@
// SPDX-License-Identifier: GPL-2.0
-use kernel::prelude::*;
+use kernel::{
+ io::Io,
+ prelude::*, //
+};
use crate::{
driver::Bar0,
@@ -9,7 +12,7 @@ use crate::{
};
fn vidmem_size_ga102(bar: &Bar0) -> u64 {
- regs::NV_USABLE_FB_SIZE_IN_MB::read(bar).usable_fb_size()
+ bar.read(regs::NV_USABLE_FB_SIZE_IN_MB).usable_fb_size()
}
struct Ga102;
diff --git a/drivers/gpu/nova-core/fb/hal/tu102.rs b/drivers/gpu/nova-core/fb/hal/tu102.rs
index eec984f4e816..281bb796e198 100644
--- a/drivers/gpu/nova-core/fb/hal/tu102.rs
+++ b/drivers/gpu/nova-core/fb/hal/tu102.rs
@@ -1,6 +1,9 @@
// SPDX-License-Identifier: GPL-2.0
-use kernel::prelude::*;
+use kernel::{
+ io::Io,
+ prelude::*, //
+};
use crate::{
driver::Bar0,
@@ -13,7 +16,7 @@ use crate::{
pub(super) const FLUSH_SYSMEM_ADDR_SHIFT: u32 = 8;
pub(super) fn read_sysmem_flush_page_gm107(bar: &Bar0) -> u64 {
- u64::from(regs::NV_PFB_NISO_FLUSH_SYSMEM_ADDR::read(bar).adr_39_08()) << FLUSH_SYSMEM_ADDR_SHIFT
+ u64::from(bar.read(regs::NV_PFB_NISO_FLUSH_SYSMEM_ADDR).adr_39_08()) << FLUSH_SYSMEM_ADDR_SHIFT
}
pub(super) fn write_sysmem_flush_page_gm107(bar: &Bar0, addr: u64) -> Result {
@@ -21,18 +24,18 @@ pub(super) fn write_sysmem_flush_page_gm107(bar: &Bar0, addr: u64) -> Result {
u32::try_from(addr >> FLUSH_SYSMEM_ADDR_SHIFT)
.map_err(|_| EINVAL)
.map(|addr| {
- regs::NV_PFB_NISO_FLUSH_SYSMEM_ADDR::default()
- .set_adr_39_08(addr)
- .write(bar)
+ bar.write_reg(regs::NV_PFB_NISO_FLUSH_SYSMEM_ADDR::zeroed().with_adr_39_08(addr))
})
}
pub(super) fn display_enabled_gm107(bar: &Bar0) -> bool {
- !regs::gm107::NV_FUSE_STATUS_OPT_DISPLAY::read(bar).display_disabled()
+ !bar.read(regs::gm107::NV_FUSE_STATUS_OPT_DISPLAY)
+ .display_disabled()
}
pub(super) fn vidmem_size_gp102(bar: &Bar0) -> u64 {
- regs::NV_PFB_PRI_MMU_LOCAL_MEMORY_RANGE::read(bar).usable_fb_size()
+ bar.read(regs::NV_PFB_PRI_MMU_LOCAL_MEMORY_RANGE)
+ .usable_fb_size()
}
struct Tu102;
diff --git a/drivers/gpu/nova-core/firmware.rs b/drivers/gpu/nova-core/firmware.rs
index 68779540aa28..6c2ab69cb605 100644
--- a/drivers/gpu/nova-core/firmware.rs
+++ b/drivers/gpu/nova-core/firmware.rs
@@ -15,10 +15,9 @@ use kernel::{
};
use crate::{
- dma::DmaObject,
falcon::{
- FalconFirmware,
- FalconLoadTarget, //
+ FalconDmaLoadTarget,
+ FalconFirmware, //
},
gpu,
num::{
@@ -64,7 +63,8 @@ pub(crate) struct FalconUCodeDescV2 {
pub(crate) interface_offset: u32,
/// Base address at which to load the code segment into 'IMEM'.
pub(crate) imem_phys_base: u32,
- /// Size in bytes of the code to copy into 'IMEM'.
+ /// Size in bytes of the code to copy into 'IMEM' (includes both secure and non-secure
+ /// segments).
pub(crate) imem_load_size: u32,
/// Virtual 'IMEM' address (i.e. 'tag') at which the code should start.
pub(crate) imem_virt_base: u32,
@@ -171,9 +171,9 @@ pub(crate) trait FalconUCodeDescriptor {
((hdr & HDR_SIZE_MASK) >> HDR_SIZE_SHIFT).into_safe_cast()
}
- fn imem_sec_load_params(&self) -> FalconLoadTarget;
- fn imem_ns_load_params(&self) -> Option<FalconLoadTarget>;
- fn dmem_load_params(&self) -> FalconLoadTarget;
+ fn imem_sec_load_params(&self) -> FalconDmaLoadTarget;
+ fn imem_ns_load_params(&self) -> Option<FalconDmaLoadTarget>;
+ fn dmem_load_params(&self) -> FalconDmaLoadTarget;
}
impl FalconUCodeDescriptor for FalconUCodeDescV2 {
@@ -205,24 +205,31 @@ impl FalconUCodeDescriptor for FalconUCodeDescV2 {
0
}
- fn imem_sec_load_params(&self) -> FalconLoadTarget {
- FalconLoadTarget {
- src_start: 0,
- dst_start: self.imem_sec_base,
+ fn imem_sec_load_params(&self) -> FalconDmaLoadTarget {
+ // `imem_sec_base` is the *virtual* start address of the secure IMEM segment, so subtract
+ // `imem_virt_base` to get its physical offset.
+ let imem_sec_start = self.imem_sec_base.saturating_sub(self.imem_virt_base);
+
+ FalconDmaLoadTarget {
+ src_start: imem_sec_start,
+ dst_start: self.imem_phys_base.saturating_add(imem_sec_start),
len: self.imem_sec_size,
}
}
- fn imem_ns_load_params(&self) -> Option<FalconLoadTarget> {
- Some(FalconLoadTarget {
+ fn imem_ns_load_params(&self) -> Option<FalconDmaLoadTarget> {
+ Some(FalconDmaLoadTarget {
+ // Non-secure code always starts at offset 0.
src_start: 0,
dst_start: self.imem_phys_base,
- len: self.imem_load_size.checked_sub(self.imem_sec_size)?,
+ // `imem_load_size` includes the size of the secure segment, so subtract it to
+ // get the correct amount of data to copy.
+ len: self.imem_load_size.saturating_sub(self.imem_sec_size),
})
}
- fn dmem_load_params(&self) -> FalconLoadTarget {
- FalconLoadTarget {
+ fn dmem_load_params(&self) -> FalconDmaLoadTarget {
+ FalconDmaLoadTarget {
src_start: self.dmem_offset,
dst_start: self.dmem_phys_base,
len: self.dmem_load_size,
@@ -259,21 +266,23 @@ impl FalconUCodeDescriptor for FalconUCodeDescV3 {
self.signature_versions
}
- fn imem_sec_load_params(&self) -> FalconLoadTarget {
- FalconLoadTarget {
+ fn imem_sec_load_params(&self) -> FalconDmaLoadTarget {
+ FalconDmaLoadTarget {
+ // IMEM segment always starts at offset 0.
src_start: 0,
dst_start: self.imem_phys_base,
len: self.imem_load_size,
}
}
- fn imem_ns_load_params(&self) -> Option<FalconLoadTarget> {
+ fn imem_ns_load_params(&self) -> Option<FalconDmaLoadTarget> {
// Not used on V3 platforms
None
}
- fn dmem_load_params(&self) -> FalconLoadTarget {
- FalconLoadTarget {
+ fn dmem_load_params(&self) -> FalconDmaLoadTarget {
+ FalconDmaLoadTarget {
+ // DMEM segment starts right after the IMEM one.
src_start: self.imem_load_size,
dst_start: self.dmem_phys_base,
len: self.dmem_load_size,
@@ -292,7 +301,7 @@ impl SignedState for Unsigned {}
struct Signed;
impl SignedState for Signed {}
-/// A [`DmaObject`] containing a specific microcode ready to be loaded into a falcon.
+/// Microcode to be loaded into a specific falcon.
///
/// This is module-local and meant for sub-modules to use internally.
///
@@ -300,34 +309,35 @@ impl SignedState for Signed {}
/// before it can be loaded (with an exception for development hardware). The
/// [`Self::patch_signature`] and [`Self::no_patch_signature`] methods are used to transition the
/// firmware to its [`Signed`] state.
-struct FirmwareDmaObject<F: FalconFirmware, S: SignedState>(DmaObject, PhantomData<(F, S)>);
+// TODO: Consider replacing this with a coherent memory object once `CoherentAllocation` supports
+// temporary CPU-exclusive access to the object without unsafe methods.
+struct FirmwareObject<F: FalconFirmware, S: SignedState>(KVVec<u8>, PhantomData<(F, S)>);
/// Trait for signatures to be patched directly into a given firmware.
///
/// This is module-local and meant for sub-modules to use internally.
trait FirmwareSignature<F: FalconFirmware>: AsRef<[u8]> {}
-impl<F: FalconFirmware> FirmwareDmaObject<F, Unsigned> {
- /// Patches the firmware at offset `sig_base_img` with `signature`.
+impl<F: FalconFirmware> FirmwareObject<F, Unsigned> {
+ /// Patches the firmware at offset `signature_start` with `signature`.
fn patch_signature<S: FirmwareSignature<F>>(
mut self,
signature: &S,
- sig_base_img: usize,
- ) -> Result<FirmwareDmaObject<F, Signed>> {
+ signature_start: usize,
+ ) -> Result<FirmwareObject<F, Signed>> {
let signature_bytes = signature.as_ref();
- if sig_base_img + signature_bytes.len() > self.0.size() {
- return Err(EINVAL);
- }
+ let signature_end = signature_start
+ .checked_add(signature_bytes.len())
+ .ok_or(EOVERFLOW)?;
+ let dst = self
+ .0
+ .get_mut(signature_start..signature_end)
+ .ok_or(EINVAL)?;
- // SAFETY: We are the only user of this object, so there cannot be any race.
- let dst = unsafe { self.0.start_ptr_mut().add(sig_base_img) };
-
- // SAFETY: `signature` and `dst` are valid, properly aligned, and do not overlap.
- unsafe {
- core::ptr::copy_nonoverlapping(signature_bytes.as_ptr(), dst, signature_bytes.len())
- };
+ // PANIC: `dst` and `signature_bytes` have the same length.
+ dst.copy_from_slice(signature_bytes);
- Ok(FirmwareDmaObject(self.0, PhantomData))
+ Ok(FirmwareObject(self.0, PhantomData))
}
/// Mark the firmware as signed without patching it.
@@ -335,8 +345,8 @@ impl<F: FalconFirmware> FirmwareDmaObject<F, Unsigned> {
/// This method is used to explicitly confirm that we do not need to sign the firmware, while
/// allowing us to continue as if it was. This is typically only needed for development
/// hardware.
- fn no_patch_signature(self) -> FirmwareDmaObject<F, Signed> {
- FirmwareDmaObject(self.0, PhantomData)
+ fn no_patch_signature(self) -> FirmwareObject<F, Signed> {
+ FirmwareObject(self.0, PhantomData)
}
}
@@ -394,8 +404,9 @@ impl<'a> BinFirmware<'a> {
fn data(&self) -> Option<&[u8]> {
let fw_start = usize::from_safe_cast(self.hdr.data_offset);
let fw_size = usize::from_safe_cast(self.hdr.data_size);
+ let fw_end = fw_start.checked_add(fw_size)?;
- self.fw.get(fw_start..fw_start + fw_size)
+ self.fw.get(fw_start..fw_end)
}
}
@@ -416,24 +427,111 @@ impl<const N: usize> ModInfoBuilder<N> {
)
}
- const fn make_entry_chipset(self, chipset: &str) -> Self {
- self.make_entry_file(chipset, "booter_load")
- .make_entry_file(chipset, "booter_unload")
- .make_entry_file(chipset, "bootloader")
- .make_entry_file(chipset, "gsp")
+ const fn make_entry_chipset(self, chipset: gpu::Chipset) -> Self {
+ let name = chipset.name();
+
+ let this = self
+ .make_entry_file(name, "booter_load")
+ .make_entry_file(name, "booter_unload")
+ .make_entry_file(name, "bootloader")
+ .make_entry_file(name, "gsp");
+
+ if chipset.needs_fwsec_bootloader() {
+ this.make_entry_file(name, "gen_bootloader")
+ } else {
+ this
+ }
}
pub(crate) const fn create(
- module_name: &'static kernel::str::CStr,
+ module_name: &'static core::ffi::CStr,
) -> firmware::ModInfoBuilder<N> {
let mut this = Self(firmware::ModInfoBuilder::new(module_name));
let mut i = 0;
while i < gpu::Chipset::ALL.len() {
- this = this.make_entry_chipset(gpu::Chipset::ALL[i].name());
+ this = this.make_entry_chipset(gpu::Chipset::ALL[i]);
i += 1;
}
this.0
}
}
+
+/// Ad-hoc and temporary module to extract sections from ELF images.
+///
+/// Some firmware images are currently packaged as ELF files, where sections names are used as keys
+/// to specific and related bits of data. Future firmware versions are scheduled to move away from
+/// that scheme before nova-core becomes stable, which means this module will eventually be
+/// removed.
+mod elf {
+ use core::mem::size_of;
+
+ use kernel::{
+ bindings,
+ str::CStr,
+ transmute::FromBytes, //
+ };
+
+ /// Newtype to provide a [`FromBytes`] implementation.
+ #[repr(transparent)]
+ struct Elf64Hdr(bindings::elf64_hdr);
+ // SAFETY: all bit patterns are valid for this type, and it doesn't use interior mutability.
+ unsafe impl FromBytes for Elf64Hdr {}
+
+ #[repr(transparent)]
+ struct Elf64SHdr(bindings::elf64_shdr);
+ // SAFETY: all bit patterns are valid for this type, and it doesn't use interior mutability.
+ unsafe impl FromBytes for Elf64SHdr {}
+
+ /// Returns a NULL-terminated string from the ELF image at `offset`.
+ fn elf_str(elf: &[u8], offset: u64) -> Option<&str> {
+ let idx = usize::try_from(offset).ok()?;
+ let bytes = elf.get(idx..)?;
+ CStr::from_bytes_until_nul(bytes).ok()?.to_str().ok()
+ }
+
+ /// Tries to extract section with name `name` from the ELF64 image `elf`, and returns it.
+ pub(super) fn elf64_section<'a, 'b>(elf: &'a [u8], name: &'b str) -> Option<&'a [u8]> {
+ let hdr = &elf
+ .get(0..size_of::<bindings::elf64_hdr>())
+ .and_then(Elf64Hdr::from_bytes)?
+ .0;
+
+ // Get all the section headers.
+ let mut shdr = {
+ let shdr_num = usize::from(hdr.e_shnum);
+ let shdr_start = usize::try_from(hdr.e_shoff).ok()?;
+ let shdr_end = shdr_num
+ .checked_mul(size_of::<Elf64SHdr>())
+ .and_then(|v| v.checked_add(shdr_start))?;
+
+ elf.get(shdr_start..shdr_end)
+ .map(|slice| slice.chunks_exact(size_of::<Elf64SHdr>()))?
+ };
+
+ // Get the strings table.
+ let strhdr = shdr
+ .clone()
+ .nth(usize::from(hdr.e_shstrndx))
+ .and_then(Elf64SHdr::from_bytes)?;
+
+ // Find the section which name matches `name` and return it.
+ shdr.find_map(|sh| {
+ let hdr = Elf64SHdr::from_bytes(sh)?;
+ let name_offset = strhdr.0.sh_offset.checked_add(u64::from(hdr.0.sh_name))?;
+ let section_name = elf_str(elf, name_offset)?;
+
+ if section_name != name {
+ return None;
+ }
+
+ let start = usize::try_from(hdr.0.sh_offset).ok()?;
+ let end = usize::try_from(hdr.0.sh_size)
+ .ok()
+ .and_then(|sh_size| start.checked_add(sh_size))?;
+
+ elf.get(start..end)
+ })
+ }
+}
diff --git a/drivers/gpu/nova-core/firmware/booter.rs b/drivers/gpu/nova-core/firmware/booter.rs
index 86556cee8e67..de2a4536b532 100644
--- a/drivers/gpu/nova-core/firmware/booter.rs
+++ b/drivers/gpu/nova-core/firmware/booter.rs
@@ -4,10 +4,7 @@
//! running on [`Sec2`], that is used on Turing/Ampere to load the GSP firmware into the GSP falcon
//! (and optionally unload it through a separate firmware image).
-use core::{
- marker::PhantomData,
- ops::Deref, //
-};
+use core::marker::PhantomData;
use kernel::{
device,
@@ -16,19 +13,18 @@ use kernel::{
};
use crate::{
- dma::DmaObject,
driver::Bar0,
falcon::{
sec2::Sec2,
Falcon,
FalconBromParams,
- FalconFirmware,
- FalconLoadParams,
- FalconLoadTarget, //
+ FalconDmaLoadTarget,
+ FalconDmaLoadable,
+ FalconFirmware, //
},
firmware::{
BinFirmware,
- FirmwareDmaObject,
+ FirmwareObject,
FirmwareSignature,
Signed,
Unsigned, //
@@ -43,8 +39,9 @@ use crate::{
/// Local convenience function to return a copy of `S` by reinterpreting the bytes starting at
/// `offset` in `slice`.
fn frombytes_at<S: FromBytes + Sized>(slice: &[u8], offset: usize) -> Result<S> {
+ let end = offset.checked_add(size_of::<S>()).ok_or(EINVAL)?;
slice
- .get(offset..offset + size_of::<S>())
+ .get(offset..end)
.and_then(S::from_bytes_copy)
.ok_or(EINVAL)
}
@@ -119,14 +116,21 @@ impl<'a> HsFirmwareV2<'a> {
Some(sig_size) => {
let patch_sig =
frombytes_at::<u32>(self.fw, self.hdr.patch_sig_offset.into_safe_cast())?;
- let signatures_start = usize::from_safe_cast(self.hdr.sig_prod_offset + patch_sig);
+
+ let signatures_start = self
+ .hdr
+ .sig_prod_offset
+ .checked_add(patch_sig)
+ .map(usize::from_safe_cast)
+ .ok_or(EINVAL)?;
+
+ let signatures_end = signatures_start
+ .checked_add(usize::from_safe_cast(self.hdr.sig_prod_size))
+ .ok_or(EINVAL)?;
self.fw
// Get signatures range.
- .get(
- signatures_start
- ..signatures_start + usize::from_safe_cast(self.hdr.sig_prod_size),
- )
+ .get(signatures_start..signatures_end)
.ok_or(EINVAL)?
.chunks_exact(sig_size.into_safe_cast())
}
@@ -252,21 +256,24 @@ impl<'a> FirmwareSignature<BooterFirmware> for BooterSignature<'a> {}
/// The `Booter` loader firmware, responsible for loading the GSP.
pub(crate) struct BooterFirmware {
// Load parameters for Secure `IMEM` falcon memory.
- imem_sec_load_target: FalconLoadTarget,
+ imem_sec_load_target: FalconDmaLoadTarget,
// Load parameters for Non-Secure `IMEM` falcon memory,
// used only on Turing and GA100
- imem_ns_load_target: Option<FalconLoadTarget>,
+ imem_ns_load_target: Option<FalconDmaLoadTarget>,
// Load parameters for `DMEM` falcon memory.
- dmem_load_target: FalconLoadTarget,
+ dmem_load_target: FalconDmaLoadTarget,
// BROM falcon parameters.
brom_params: FalconBromParams,
// Device-mapped firmware image.
- ucode: FirmwareDmaObject<Self, Signed>,
+ ucode: FirmwareObject<Self, Signed>,
}
-impl FirmwareDmaObject<BooterFirmware, Unsigned> {
- fn new_booter(dev: &device::Device<device::Bound>, data: &[u8]) -> Result<Self> {
- DmaObject::from_data(dev, data).map(|ucode| Self(ucode, PhantomData))
+impl FirmwareObject<BooterFirmware, Unsigned> {
+ fn new_booter(data: &[u8]) -> Result<Self> {
+ let mut ucode = KVVec::new();
+ ucode.extend_from_slice(data, GFP_KERNEL)?;
+
+ Ok(Self(ucode, PhantomData))
}
}
@@ -320,7 +327,7 @@ impl BooterFirmware {
let ucode = bin_fw
.data()
.ok_or(EINVAL)
- .and_then(|data| FirmwareDmaObject::<Self, _>::new_booter(dev, data))?;
+ .and_then(FirmwareObject::<Self, _>::new_booter)?;
let ucode_signed = {
let mut signatures = hs_fw.signatures_iter()?.peekable();
@@ -363,7 +370,7 @@ impl BooterFirmware {
let (imem_sec_dst_start, imem_ns_load_target) = if chipset <= Chipset::GA100 {
(
app0.offset,
- Some(FalconLoadTarget {
+ Some(FalconDmaLoadTarget {
src_start: 0,
dst_start: load_hdr.os_code_offset,
len: load_hdr.os_code_size,
@@ -374,13 +381,13 @@ impl BooterFirmware {
};
Ok(Self {
- imem_sec_load_target: FalconLoadTarget {
+ imem_sec_load_target: FalconDmaLoadTarget {
src_start: app0.offset,
dst_start: imem_sec_dst_start,
len: app0.len,
},
imem_ns_load_target,
- dmem_load_target: FalconLoadTarget {
+ dmem_load_target: FalconDmaLoadTarget {
src_start: load_hdr.os_data_offset,
dst_start: 0,
len: load_hdr.os_data_size,
@@ -391,18 +398,26 @@ impl BooterFirmware {
}
}
-impl FalconLoadParams for BooterFirmware {
- fn imem_sec_load_params(&self) -> FalconLoadTarget {
+impl FalconDmaLoadable for BooterFirmware {
+ fn as_slice(&self) -> &[u8] {
+ self.ucode.0.as_slice()
+ }
+
+ fn imem_sec_load_params(&self) -> FalconDmaLoadTarget {
self.imem_sec_load_target.clone()
}
- fn imem_ns_load_params(&self) -> Option<FalconLoadTarget> {
+ fn imem_ns_load_params(&self) -> Option<FalconDmaLoadTarget> {
self.imem_ns_load_target.clone()
}
- fn dmem_load_params(&self) -> FalconLoadTarget {
+ fn dmem_load_params(&self) -> FalconDmaLoadTarget {
self.dmem_load_target.clone()
}
+}
+
+impl FalconFirmware for BooterFirmware {
+ type Target = Sec2;
fn brom_params(&self) -> FalconBromParams {
self.brom_params.clone()
@@ -416,15 +431,3 @@ impl FalconLoadParams for BooterFirmware {
}
}
}
-
-impl Deref for BooterFirmware {
- type Target = DmaObject;
-
- fn deref(&self) -> &Self::Target {
- &self.ucode.0
- }
-}
-
-impl FalconFirmware for BooterFirmware {
- type Target = Sec2;
-}
diff --git a/drivers/gpu/nova-core/firmware/fwsec.rs b/drivers/gpu/nova-core/firmware/fwsec.rs
index bfb7b06b13d1..8810cb49db67 100644
--- a/drivers/gpu/nova-core/firmware/fwsec.rs
+++ b/drivers/gpu/nova-core/firmware/fwsec.rs
@@ -10,10 +10,9 @@
//! - The command to be run, as this firmware can perform several tasks ;
//! - The ucode signature, so the GSP falcon can run FWSEC in HS mode.
-use core::{
- marker::PhantomData,
- ops::Deref, //
-};
+pub(crate) mod bootloader;
+
+use core::marker::PhantomData;
use kernel::{
device::{
@@ -28,27 +27,23 @@ use kernel::{
};
use crate::{
- dma::DmaObject,
driver::Bar0,
falcon::{
gsp::Gsp,
Falcon,
FalconBromParams,
- FalconFirmware,
- FalconLoadParams,
- FalconLoadTarget, //
+ FalconDmaLoadTarget,
+ FalconDmaLoadable,
+ FalconFirmware, //
},
firmware::{
FalconUCodeDesc,
- FirmwareDmaObject,
+ FirmwareObject,
FirmwareSignature,
Signed,
Unsigned, //
},
- num::{
- FromSafeCast,
- IntoSafeCast, //
- },
+ num::FromSafeCast,
vbios::Vbios,
};
@@ -177,63 +172,36 @@ impl AsRef<[u8]> for Bcrt30Rsa3kSignature {
impl FirmwareSignature<FwsecFirmware> for Bcrt30Rsa3kSignature {}
-/// Reinterpret the area starting from `offset` in `fw` as an instance of `T` (which must implement
-/// [`FromBytes`]) and return a reference to it.
-///
-/// # Safety
-///
-/// * Callers must ensure that the device does not read/write to/from memory while the returned
-/// reference is live.
-/// * Callers must ensure that this call does not race with a write to the same region while
-/// the returned reference is live.
-unsafe fn transmute<T: Sized + FromBytes>(fw: &DmaObject, offset: usize) -> Result<&T> {
- // SAFETY: The safety requirements of the function guarantee the device won't read
- // or write to memory while the reference is alive and that this call won't race
- // with writes to the same memory region.
- T::from_bytes(unsafe { fw.as_slice(offset, size_of::<T>())? }).ok_or(EINVAL)
-}
-
-/// Reinterpret the area starting from `offset` in `fw` as a mutable instance of `T` (which must
-/// implement [`FromBytes`]) and return a reference to it.
-///
-/// # Safety
-///
-/// * Callers must ensure that the device does not read/write to/from memory while the returned
-/// slice is live.
-/// * Callers must ensure that this call does not race with a read or write to the same region
-/// while the returned slice is live.
-unsafe fn transmute_mut<T: Sized + FromBytes + AsBytes>(
- fw: &mut DmaObject,
- offset: usize,
-) -> Result<&mut T> {
- // SAFETY: The safety requirements of the function guarantee the device won't read
- // or write to memory while the reference is alive and that this call won't race
- // with writes or reads to the same memory region.
- T::from_bytes_mut(unsafe { fw.as_slice_mut(offset, size_of::<T>())? }).ok_or(EINVAL)
-}
-
/// The FWSEC microcode, extracted from the BIOS and to be run on the GSP falcon.
///
/// It is responsible for e.g. carving out the WPR2 region as the first step of the GSP bootflow.
pub(crate) struct FwsecFirmware {
/// Descriptor of the firmware.
desc: FalconUCodeDesc,
- /// GPU-accessible DMA object containing the firmware.
- ucode: FirmwareDmaObject<Self, Signed>,
+ /// Object containing the firmware binary.
+ ucode: FirmwareObject<Self, Signed>,
}
-impl FalconLoadParams for FwsecFirmware {
- fn imem_sec_load_params(&self) -> FalconLoadTarget {
+impl FalconDmaLoadable for FwsecFirmware {
+ fn as_slice(&self) -> &[u8] {
+ self.ucode.0.as_slice()
+ }
+
+ fn imem_sec_load_params(&self) -> FalconDmaLoadTarget {
self.desc.imem_sec_load_params()
}
- fn imem_ns_load_params(&self) -> Option<FalconLoadTarget> {
+ fn imem_ns_load_params(&self) -> Option<FalconDmaLoadTarget> {
self.desc.imem_ns_load_params()
}
- fn dmem_load_params(&self) -> FalconLoadTarget {
+ fn dmem_load_params(&self) -> FalconDmaLoadTarget {
self.desc.dmem_load_params()
}
+}
+
+impl FalconFirmware for FwsecFirmware {
+ type Target = Gsp;
fn brom_params(&self) -> FalconBromParams {
FalconBromParams {
@@ -248,27 +216,23 @@ impl FalconLoadParams for FwsecFirmware {
}
}
-impl Deref for FwsecFirmware {
- type Target = DmaObject;
-
- fn deref(&self) -> &Self::Target {
- &self.ucode.0
- }
-}
-
-impl FalconFirmware for FwsecFirmware {
- type Target = Gsp;
-}
-
-impl FirmwareDmaObject<FwsecFirmware, Unsigned> {
- fn new_fwsec(dev: &Device<device::Bound>, bios: &Vbios, cmd: FwsecCommand) -> Result<Self> {
+impl FirmwareObject<FwsecFirmware, Unsigned> {
+ fn new_fwsec(bios: &Vbios, cmd: FwsecCommand) -> Result<Self> {
let desc = bios.fwsec_image().header()?;
- let ucode = bios.fwsec_image().ucode(&desc)?;
- let mut dma_object = DmaObject::from_data(dev, ucode)?;
+ let mut ucode = KVVec::new();
+ ucode.extend_from_slice(bios.fwsec_image().ucode(&desc)?, GFP_KERNEL)?;
- let hdr_offset = usize::from_safe_cast(desc.imem_load_size() + desc.interface_offset());
- // SAFETY: we have exclusive access to `dma_object`.
- let hdr: &FalconAppifHdrV1 = unsafe { transmute(&dma_object, hdr_offset) }?;
+ let hdr_offset = desc
+ .imem_load_size()
+ .checked_add(desc.interface_offset())
+ .map(usize::from_safe_cast)
+ .ok_or(EINVAL)?;
+
+ let hdr = ucode
+ .get(hdr_offset..)
+ .and_then(FalconAppifHdrV1::from_bytes_prefix)
+ .ok_or(EINVAL)?
+ .0;
if hdr.version != 1 {
return Err(EINVAL);
@@ -276,26 +240,34 @@ impl FirmwareDmaObject<FwsecFirmware, Unsigned> {
// Find the DMEM mapper section in the firmware.
for i in 0..usize::from(hdr.entry_count) {
- // SAFETY: we have exclusive access to `dma_object`.
- let app: &FalconAppifV1 = unsafe {
- transmute(
- &dma_object,
- hdr_offset + usize::from(hdr.header_size) + i * usize::from(hdr.entry_size),
- )
- }?;
+ // CALC: hdr_offset + header_size + i * entry_size.
+ let entry_offset = hdr_offset
+ .checked_add(usize::from(hdr.header_size))
+ .and_then(|o| o.checked_add(i.checked_mul(usize::from(hdr.entry_size))?))
+ .ok_or(EINVAL)?;
+
+ let app = ucode
+ .get(entry_offset..)
+ .and_then(FalconAppifV1::from_bytes_prefix)
+ .ok_or(EINVAL)?
+ .0;
if app.id != NVFW_FALCON_APPIF_ID_DMEMMAPPER {
continue;
}
let dmem_base = app.dmem_base;
- // SAFETY: we have exclusive access to `dma_object`.
- let dmem_mapper: &mut FalconAppifDmemmapperV3 = unsafe {
- transmute_mut(
- &mut dma_object,
- (desc.imem_load_size() + dmem_base).into_safe_cast(),
- )
- }?;
+ let dmem_mapper_offset = desc
+ .imem_load_size()
+ .checked_add(dmem_base)
+ .map(usize::from_safe_cast)
+ .ok_or(EINVAL)?;
+
+ let dmem_mapper = ucode
+ .get_mut(dmem_mapper_offset..)
+ .and_then(FalconAppifDmemmapperV3::from_bytes_mut_prefix)
+ .ok_or(EINVAL)?
+ .0;
dmem_mapper.init_cmd = match cmd {
FwsecCommand::Frts { .. } => NVFW_FALCON_APPIF_DMEMMAPPER_CMD_FRTS,
@@ -303,13 +275,17 @@ impl FirmwareDmaObject<FwsecFirmware, Unsigned> {
};
let cmd_in_buffer_offset = dmem_mapper.cmd_in_buffer_offset;
- // SAFETY: we have exclusive access to `dma_object`.
- let frts_cmd: &mut FrtsCmd = unsafe {
- transmute_mut(
- &mut dma_object,
- (desc.imem_load_size() + cmd_in_buffer_offset).into_safe_cast(),
- )
- }?;
+ let frts_cmd_offset = desc
+ .imem_load_size()
+ .checked_add(cmd_in_buffer_offset)
+ .map(usize::from_safe_cast)
+ .ok_or(EINVAL)?;
+
+ let frts_cmd = ucode
+ .get_mut(frts_cmd_offset..)
+ .and_then(FrtsCmd::from_bytes_mut_prefix)
+ .ok_or(EINVAL)?
+ .0;
frts_cmd.read_vbios = ReadVbios {
ver: 1,
@@ -333,7 +309,7 @@ impl FirmwareDmaObject<FwsecFirmware, Unsigned> {
}
// Return early as we found and patched the DMEMMAPPER region.
- return Ok(Self(dma_object, PhantomData));
+ return Ok(Self(ucode, PhantomData));
}
Err(ENOTSUPP)
@@ -350,13 +326,16 @@ impl FwsecFirmware {
bios: &Vbios,
cmd: FwsecCommand,
) -> Result<Self> {
- let ucode_dma = FirmwareDmaObject::<Self, _>::new_fwsec(dev, bios, cmd)?;
+ let ucode_dma = FirmwareObject::<Self, _>::new_fwsec(bios, cmd)?;
// Patch signature if needed.
let desc = bios.fwsec_image().header()?;
let ucode_signed = if desc.signature_count() != 0 {
- let sig_base_img =
- usize::from_safe_cast(desc.imem_load_size() + desc.pkc_data_offset());
+ let sig_base_img = desc
+ .imem_load_size()
+ .checked_add(desc.pkc_data_offset())
+ .map(usize::from_safe_cast)
+ .ok_or(EINVAL)?;
let desc_sig_versions = u32::from(desc.signature_versions());
let reg_fuse_version =
falcon.signature_reg_fuse_version(bar, desc.engine_id_mask(), desc.ucode_id())?;
@@ -408,6 +387,10 @@ impl FwsecFirmware {
}
/// Loads the FWSEC firmware into `falcon` and execute it.
+ ///
+ /// This must only be called on chipsets that do not need the FWSEC bootloader (i.e., where
+ /// [`Chipset::needs_fwsec_bootloader()`](crate::gpu::Chipset::needs_fwsec_bootloader) returns
+ /// `false`). On chipsets that do, use [`bootloader::FwsecFirmwareWithBl`] instead.
pub(crate) fn run(
&self,
dev: &Device<device::Bound>,
@@ -419,7 +402,7 @@ impl FwsecFirmware {
.reset(bar)
.inspect_err(|e| dev_err!(dev, "Failed to reset GSP falcon: {:?}\n", e))?;
falcon
- .load(bar, self)
+ .load(dev, bar, self)
.inspect_err(|e| dev_err!(dev, "Failed to load FWSEC firmware: {:?}\n", e))?;
let (mbox0, _) = falcon
.boot(bar, Some(0), None)
diff --git a/drivers/gpu/nova-core/firmware/fwsec/bootloader.rs b/drivers/gpu/nova-core/firmware/fwsec/bootloader.rs
new file mode 100644
index 000000000000..bcb713a868e2
--- /dev/null
+++ b/drivers/gpu/nova-core/firmware/fwsec/bootloader.rs
@@ -0,0 +1,350 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Bootloader support for the FWSEC firmware.
+//!
+//! On Turing, the FWSEC firmware is not loaded directly, but is instead loaded through a small
+//! bootloader program that performs the required DMA operations. This bootloader itself needs to
+//! be loaded using PIO.
+
+use kernel::{
+ alloc::KVec,
+ device::{
+ self,
+ Device, //
+ },
+ dma::Coherent,
+ io::{
+ register::WithBase, //
+ Io,
+ },
+ prelude::*,
+ ptr::{
+ Alignable,
+ Alignment, //
+ },
+ sizes,
+ transmute::{
+ AsBytes,
+ FromBytes, //
+ },
+};
+
+use crate::{
+ driver::Bar0,
+ falcon::{
+ self,
+ gsp::Gsp,
+ Falcon,
+ FalconBromParams,
+ FalconDmaLoadable,
+ FalconFbifMemType,
+ FalconFbifTarget,
+ FalconFirmware,
+ FalconPioDmemLoadTarget,
+ FalconPioImemLoadTarget,
+ FalconPioLoadable, //
+ },
+ firmware::{
+ fwsec::FwsecFirmware,
+ request_firmware,
+ BinHdr,
+ FIRMWARE_VERSION, //
+ },
+ gpu::Chipset,
+ num::FromSafeCast,
+ regs,
+};
+
+/// Descriptor used by RM to figure out the requirements of the boot loader.
+///
+/// Most of its fields appear to be legacy and carry incorrect values, so they are left unused.
+#[repr(C)]
+#[derive(Debug, Clone)]
+struct BootloaderDesc {
+ /// Starting tag of bootloader.
+ start_tag: u32,
+ /// DMEM load offset - unused here as we always load at offset `0`.
+ _dmem_load_off: u32,
+ /// Offset of code section in the image. Unused as there is only one section in the bootloader
+ /// binary.
+ _code_off: u32,
+ /// Size of code section in the image.
+ code_size: u32,
+ /// Offset of data section in the image. Unused as we build the data section ourselves.
+ _data_off: u32,
+ /// Size of data section in the image. Unused as we build the data section ourselves.
+ _data_size: u32,
+}
+// SAFETY: any byte sequence is valid for this struct.
+unsafe impl FromBytes for BootloaderDesc {}
+
+/// Structure used by the boot-loader to load the rest of the code.
+///
+/// This has to be filled by the GPU driver and copied into DMEM at offset
+/// [`BootloaderDesc.dmem_load_off`].
+#[repr(C, packed)]
+#[derive(Debug, Clone)]
+struct BootloaderDmemDescV2 {
+ /// Reserved, should always be first element.
+ reserved: [u32; 4],
+ /// 16B signature for secure code, 0s if no secure code.
+ signature: [u32; 4],
+ /// DMA context used by the bootloader while loading code/data.
+ ctx_dma: u32,
+ /// 256B-aligned physical FB address where code is located.
+ code_dma_base: u64,
+ /// Offset from `code_dma_base` where the non-secure code is located.
+ ///
+ /// Also used as destination IMEM offset of non-secure code as the DMA firmware object is
+ /// expected to be a mirror image of its loaded state.
+ ///
+ /// Must be multiple of 256.
+ non_sec_code_off: u32,
+ /// Size of the non-secure code part.
+ non_sec_code_size: u32,
+ /// Offset from `code_dma_base` where the secure code is located (must be multiple of 256).
+ ///
+ /// Also used as destination IMEM offset of secure code as the DMA firmware object is expected
+ /// to be a mirror image of its loaded state.
+ ///
+ /// Must be multiple of 256.
+ sec_code_off: u32,
+ /// Size of the secure code part.
+ sec_code_size: u32,
+ /// Code entry point invoked by the bootloader after code is loaded.
+ code_entry_point: u32,
+ /// 256B-aligned physical FB address where data is located.
+ data_dma_base: u64,
+ /// Size of data block (should be multiple of 256B).
+ data_size: u32,
+ /// Number of arguments to be passed to the target firmware being loaded.
+ argc: u32,
+ /// Arguments to be passed to the target firmware being loaded.
+ argv: u32,
+}
+// SAFETY: This struct doesn't contain uninitialized bytes and doesn't have interior mutability.
+unsafe impl AsBytes for BootloaderDmemDescV2 {}
+
+/// Wrapper for [`FwsecFirmware`] that includes the bootloader performing the actual load
+/// operation.
+pub(crate) struct FwsecFirmwareWithBl {
+ /// DMA object the bootloader will copy the firmware from.
+ _firmware_dma: Coherent<[u8]>,
+ /// Code of the bootloader to be loaded into non-secure IMEM.
+ ucode: KVec<u8>,
+ /// Descriptor to be loaded into DMEM for the bootloader to read.
+ dmem_desc: BootloaderDmemDescV2,
+ /// Range-validated start offset of the firmware code in IMEM.
+ imem_dst_start: u16,
+ /// BROM parameters of the loaded firmware.
+ brom_params: FalconBromParams,
+ /// Range-validated `desc.start_tag`.
+ start_tag: u16,
+}
+
+impl FwsecFirmwareWithBl {
+ /// Loads the bootloader firmware for `dev` and `chipset`, and wrap `firmware` so it can be
+ /// loaded using it.
+ pub(crate) fn new(
+ firmware: FwsecFirmware,
+ dev: &Device<device::Bound>,
+ chipset: Chipset,
+ ) -> Result<Self> {
+ let fw = request_firmware(dev, chipset, "gen_bootloader", FIRMWARE_VERSION)?;
+ let hdr = fw
+ .data()
+ .get(0..size_of::<BinHdr>())
+ .and_then(BinHdr::from_bytes_copy)
+ .ok_or(EINVAL)?;
+
+ let desc = {
+ let desc_offset = usize::from_safe_cast(hdr.header_offset);
+
+ fw.data()
+ .get(desc_offset..)
+ .and_then(BootloaderDesc::from_bytes_copy_prefix)
+ .ok_or(EINVAL)?
+ .0
+ };
+
+ let ucode = {
+ let ucode_start = usize::from_safe_cast(hdr.data_offset);
+ let code_size = usize::from_safe_cast(desc.code_size);
+ // Align to falcon block size (256 bytes).
+ let aligned_code_size = code_size
+ .align_up(Alignment::new::<{ falcon::MEM_BLOCK_ALIGNMENT }>())
+ .ok_or(EINVAL)?;
+
+ let mut ucode = KVec::with_capacity(aligned_code_size, GFP_KERNEL)?;
+ ucode.extend_from_slice(
+ fw.data()
+ .get(ucode_start..ucode_start + code_size)
+ .ok_or(EINVAL)?,
+ GFP_KERNEL,
+ )?;
+ ucode.resize(aligned_code_size, 0, GFP_KERNEL)?;
+
+ ucode
+ };
+
+ // `BootloaderDmemDescV2` expects the source to be a mirror image of the destination and
+ // uses the same offset parameter for both.
+ //
+ // Thus, the start of the source object needs to be padded with the difference between the
+ // destination and source offsets.
+ //
+ // In practice, this is expected to always be zero but is required for code correctness.
+ let (align_padding, firmware_dma) = {
+ let align_padding = {
+ let imem_sec = firmware.imem_sec_load_params();
+
+ imem_sec
+ .dst_start
+ .checked_sub(imem_sec.src_start)
+ .map(usize::from_safe_cast)
+ .ok_or(EOVERFLOW)?
+ };
+
+ let mut firmware_obj = KVVec::new();
+ firmware_obj.extend_with(align_padding, 0u8, GFP_KERNEL)?;
+ firmware_obj.extend_from_slice(firmware.ucode.0.as_slice(), GFP_KERNEL)?;
+
+ (
+ align_padding,
+ Coherent::from_slice(dev, firmware_obj.as_slice(), GFP_KERNEL)?,
+ )
+ };
+
+ let dmem_desc = {
+ // Bootloader payload is in non-coherent system memory.
+ const FALCON_DMAIDX_PHYS_SYS_NCOH: u32 = 4;
+
+ let imem_sec = firmware.imem_sec_load_params();
+ let imem_ns = firmware.imem_ns_load_params().ok_or(EINVAL)?;
+ let dmem = firmware.dmem_load_params();
+
+ // The bootloader does not have a data destination offset field and copies the data at
+ // the start of DMEM, so it can only be used if the destination offset of the firmware
+ // is 0.
+ if dmem.dst_start != 0 {
+ return Err(EINVAL);
+ }
+
+ BootloaderDmemDescV2 {
+ reserved: [0; 4],
+ signature: [0; 4],
+ ctx_dma: FALCON_DMAIDX_PHYS_SYS_NCOH,
+ code_dma_base: firmware_dma.dma_handle(),
+ // `dst_start` is also valid as the source offset since the firmware DMA object is
+ // a mirror image of the target IMEM layout.
+ non_sec_code_off: imem_ns.dst_start,
+ non_sec_code_size: imem_ns.len,
+ // `dst_start` is also valid as the source offset since the firmware DMA object is
+ // a mirror image of the target IMEM layout.
+ sec_code_off: imem_sec.dst_start,
+ sec_code_size: imem_sec.len,
+ code_entry_point: 0,
+ // Start of data section is the added padding + the DMEM `src_start` field.
+ data_dma_base: firmware_dma
+ .dma_handle()
+ .checked_add(u64::from_safe_cast(align_padding))
+ .and_then(|offset| offset.checked_add(dmem.src_start.into()))
+ .ok_or(EOVERFLOW)?,
+ data_size: dmem.len,
+ argc: 0,
+ argv: 0,
+ }
+ };
+
+ // The bootloader's code must be loaded in the area right below the first 64K of IMEM.
+ const BOOTLOADER_LOAD_CEILING: usize = sizes::SZ_64K;
+ let imem_dst_start = BOOTLOADER_LOAD_CEILING
+ .checked_sub(ucode.len())
+ .ok_or(EOVERFLOW)?;
+
+ Ok(Self {
+ _firmware_dma: firmware_dma,
+ ucode,
+ dmem_desc,
+ brom_params: firmware.brom_params(),
+ imem_dst_start: u16::try_from(imem_dst_start)?,
+ start_tag: u16::try_from(desc.start_tag)?,
+ })
+ }
+
+ /// Loads the bootloader into `falcon` and execute it.
+ ///
+ /// The bootloader will load the FWSEC firmware and then execute it. This function returns
+ /// after FWSEC has reached completion.
+ pub(crate) fn run(
+ &self,
+ dev: &Device<device::Bound>,
+ falcon: &Falcon<Gsp>,
+ bar: &Bar0,
+ ) -> Result<()> {
+ // Reset falcon, load the firmware, and run it.
+ falcon
+ .reset(bar)
+ .inspect_err(|e| dev_err!(dev, "Failed to reset GSP falcon: {:?}\n", e))?;
+ falcon
+ .pio_load(bar, self)
+ .inspect_err(|e| dev_err!(dev, "Failed to load FWSEC firmware: {:?}\n", e))?;
+
+ // Configure DMA index for the bootloader to fetch the FWSEC firmware from system memory.
+ bar.update(
+ regs::NV_PFALCON_FBIF_TRANSCFG::of::<Gsp>()
+ .try_at(usize::from_safe_cast(self.dmem_desc.ctx_dma))
+ .ok_or(EINVAL)?,
+ |v| {
+ v.with_target(FalconFbifTarget::CoherentSysmem)
+ .with_mem_type(FalconFbifMemType::Physical)
+ },
+ );
+
+ let (mbox0, _) = falcon
+ .boot(bar, Some(0), None)
+ .inspect_err(|e| dev_err!(dev, "Failed to boot FWSEC firmware: {:?}\n", e))?;
+ if mbox0 != 0 {
+ dev_err!(dev, "FWSEC firmware returned error {}\n", mbox0);
+ Err(EIO)
+ } else {
+ Ok(())
+ }
+ }
+}
+
+impl FalconFirmware for FwsecFirmwareWithBl {
+ type Target = Gsp;
+
+ fn brom_params(&self) -> FalconBromParams {
+ self.brom_params.clone()
+ }
+
+ fn boot_addr(&self) -> u32 {
+ // On V2 platforms, the boot address is extracted from the generic bootloader, because the
+ // gbl is what actually copies FWSEC into memory, so that is what needs to be booted.
+ u32::from(self.start_tag) << 8
+ }
+}
+
+impl FalconPioLoadable for FwsecFirmwareWithBl {
+ fn imem_sec_load_params(&self) -> Option<FalconPioImemLoadTarget<'_>> {
+ None
+ }
+
+ fn imem_ns_load_params(&self) -> Option<FalconPioImemLoadTarget<'_>> {
+ Some(FalconPioImemLoadTarget {
+ data: self.ucode.as_ref(),
+ dst_start: self.imem_dst_start,
+ secure: false,
+ start_tag: self.start_tag,
+ })
+ }
+
+ fn dmem_load_params(&self) -> FalconPioDmemLoadTarget<'_> {
+ FalconPioDmemLoadTarget {
+ data: self.dmem_desc.as_bytes(),
+ dst_start: 0,
+ }
+ }
+}
diff --git a/drivers/gpu/nova-core/firmware/gsp.rs b/drivers/gpu/nova-core/firmware/gsp.rs
index 9488a626352f..2fcc255c3bc8 100644
--- a/drivers/gpu/nova-core/firmware/gsp.rs
+++ b/drivers/gpu/nova-core/firmware/gsp.rs
@@ -3,10 +3,11 @@
use kernel::{
device,
dma::{
+ Coherent,
+ CoherentBox,
DataDirection,
DmaAddress, //
},
- kvec,
prelude::*,
scatterlist::{
Owned,
@@ -15,8 +16,10 @@ use kernel::{
};
use crate::{
- dma::DmaObject,
- firmware::riscv::RiscvFirmware,
+ firmware::{
+ elf,
+ riscv::RiscvFirmware, //
+ },
gpu::{
Architecture,
Chipset, //
@@ -25,92 +28,6 @@ use crate::{
num::FromSafeCast,
};
-/// Ad-hoc and temporary module to extract sections from ELF images.
-///
-/// Some firmware images are currently packaged as ELF files, where sections names are used as keys
-/// to specific and related bits of data. Future firmware versions are scheduled to move away from
-/// that scheme before nova-core becomes stable, which means this module will eventually be
-/// removed.
-mod elf {
- use kernel::{
- bindings,
- prelude::*,
- transmute::FromBytes, //
- };
-
- /// Newtype to provide a [`FromBytes`] implementation.
- #[repr(transparent)]
- struct Elf64Hdr(bindings::elf64_hdr);
- // SAFETY: all bit patterns are valid for this type, and it doesn't use interior mutability.
- unsafe impl FromBytes for Elf64Hdr {}
-
- #[repr(transparent)]
- struct Elf64SHdr(bindings::elf64_shdr);
- // SAFETY: all bit patterns are valid for this type, and it doesn't use interior mutability.
- unsafe impl FromBytes for Elf64SHdr {}
-
- /// Tries to extract section with name `name` from the ELF64 image `elf`, and returns it.
- pub(super) fn elf64_section<'a, 'b>(elf: &'a [u8], name: &'b str) -> Option<&'a [u8]> {
- let hdr = &elf
- .get(0..size_of::<bindings::elf64_hdr>())
- .and_then(Elf64Hdr::from_bytes)?
- .0;
-
- // Get all the section headers.
- let mut shdr = {
- let shdr_num = usize::from(hdr.e_shnum);
- let shdr_start = usize::try_from(hdr.e_shoff).ok()?;
- let shdr_end = shdr_num
- .checked_mul(size_of::<Elf64SHdr>())
- .and_then(|v| v.checked_add(shdr_start))?;
-
- elf.get(shdr_start..shdr_end)
- .map(|slice| slice.chunks_exact(size_of::<Elf64SHdr>()))?
- };
-
- // Get the strings table.
- let strhdr = shdr
- .clone()
- .nth(usize::from(hdr.e_shstrndx))
- .and_then(Elf64SHdr::from_bytes)?;
-
- // Find the section which name matches `name` and return it.
- shdr.find(|&sh| {
- let Some(hdr) = Elf64SHdr::from_bytes(sh) else {
- return false;
- };
-
- let Some(name_idx) = strhdr
- .0
- .sh_offset
- .checked_add(u64::from(hdr.0.sh_name))
- .and_then(|idx| usize::try_from(idx).ok())
- else {
- return false;
- };
-
- // Get the start of the name.
- elf.get(name_idx..)
- .and_then(|nstr| CStr::from_bytes_until_nul(nstr).ok())
- // Convert into str.
- .and_then(|c_str| c_str.to_str().ok())
- // Check that the name matches.
- .map(|str| str == name)
- .unwrap_or(false)
- })
- // Return the slice containing the section.
- .and_then(|sh| {
- let hdr = Elf64SHdr::from_bytes(sh)?;
- let start = usize::try_from(hdr.0.sh_offset).ok()?;
- let end = usize::try_from(hdr.0.sh_size)
- .ok()
- .and_then(|sh_size| start.checked_add(sh_size))?;
-
- elf.get(start..end)
- })
- }
-}
-
/// GSP firmware with 3-level radix page tables for the GSP bootloader.
///
/// The bootloader expects firmware to be mapped starting at address 0 in GSP's virtual address
@@ -136,11 +53,11 @@ pub(crate) struct GspFirmware {
#[pin]
level1: SGTable<Owned<VVec<u8>>>,
/// Level 0 page table (single 4KB page) with one entry: DMA address of first level 1 page.
- level0: DmaObject,
+ level0: Coherent<[u64]>,
/// Size in bytes of the firmware contained in [`Self::fw`].
pub(crate) size: usize,
/// Device-mapped GSP signatures matching the GPU's [`Chipset`].
- pub(crate) signatures: DmaObject,
+ pub(crate) signatures: Coherent<[u8]>,
/// GSP bootloader, verifies the GSP firmware before loading and running it.
pub(crate) bootloader: RiscvFirmware,
}
@@ -197,17 +114,20 @@ impl GspFirmware {
// Allocate the level 0 page table as a device-visible DMA object, and map the
// level 1 page table onto it.
- // Level 0 page table data.
- let mut level0_data = kvec![0u8; GSP_PAGE_SIZE]?;
-
// Fill level 1 page entry.
let level1_entry = level1.iter().next().ok_or(EINVAL)?;
let level1_entry_addr = level1_entry.dma_address();
- let dst = &mut level0_data[..size_of_val(&level1_entry_addr)];
- dst.copy_from_slice(&level1_entry_addr.to_le_bytes());
- // Turn the level0 page table into a [`DmaObject`].
- DmaObject::from_data(dev, &level0_data)?
+ // Create level 0 page table data and fill its first entry with the level 1
+ // table.
+ let mut level0 = CoherentBox::<[u64]>::zeroed_slice(
+ dev,
+ GSP_PAGE_SIZE / size_of::<u64>(),
+ GFP_KERNEL
+ )?;
+ level0[0] = level1_entry_addr.to_le();
+
+ level0.into()
},
size,
signatures: {
@@ -226,7 +146,7 @@ impl GspFirmware {
elf::elf64_section(firmware.data(), sigs_section)
.ok_or(EINVAL)
- .and_then(|data| DmaObject::from_data(dev, data))?
+ .and_then(|data| Coherent::from_slice(dev, data, GFP_KERNEL))?
},
bootloader: {
let bl = super::request_firmware(dev, chipset, "bootloader", ver)?;
diff --git a/drivers/gpu/nova-core/firmware/riscv.rs b/drivers/gpu/nova-core/firmware/riscv.rs
index 4bdd89bd0757..2afa7f36404e 100644
--- a/drivers/gpu/nova-core/firmware/riscv.rs
+++ b/drivers/gpu/nova-core/firmware/riscv.rs
@@ -5,13 +5,13 @@
use kernel::{
device,
+ dma::Coherent,
firmware::Firmware,
prelude::*,
transmute::FromBytes, //
};
use crate::{
- dma::DmaObject,
firmware::BinFirmware,
num::FromSafeCast, //
};
@@ -45,10 +45,11 @@ impl RmRiscvUCodeDesc {
/// Fails if the header pointed at by `bin_fw` is not within the bounds of the firmware image.
fn new(bin_fw: &BinFirmware<'_>) -> Result<Self> {
let offset = usize::from_safe_cast(bin_fw.hdr.header_offset);
+ let end = offset.checked_add(size_of::<Self>()).ok_or(EINVAL)?;
bin_fw
.fw
- .get(offset..offset + size_of::<Self>())
+ .get(offset..end)
.and_then(Self::from_bytes_copy)
.ok_or(EINVAL)
}
@@ -65,7 +66,7 @@ pub(crate) struct RiscvFirmware {
/// Application version.
pub(crate) app_version: u32,
/// Device-mapped firmware image.
- pub(crate) ucode: DmaObject,
+ pub(crate) ucode: Coherent<[u8]>,
}
impl RiscvFirmware {
@@ -78,8 +79,9 @@ impl RiscvFirmware {
let ucode = {
let start = usize::from_safe_cast(bin_fw.hdr.data_offset);
let len = usize::from_safe_cast(bin_fw.hdr.data_size);
+ let end = start.checked_add(len).ok_or(EINVAL)?;
- DmaObject::from_data(dev, fw.data().get(start..start + len).ok_or(EINVAL)?)?
+ Coherent::from_slice(dev, fw.data().get(start..end).ok_or(EINVAL)?, GFP_KERNEL)?
};
Ok(Self {
diff --git a/drivers/gpu/nova-core/gfw.rs b/drivers/gpu/nova-core/gfw.rs
index 9121f400046d..fb75dd10a172 100644
--- a/drivers/gpu/nova-core/gfw.rs
+++ b/drivers/gpu/nova-core/gfw.rs
@@ -19,7 +19,10 @@
//! Note that the devinit sequence also needs to run during suspend/resume.
use kernel::{
- io::poll::read_poll_timeout,
+ io::{
+ poll::read_poll_timeout,
+ Io, //
+ },
prelude::*,
time::Delta, //
};
@@ -58,9 +61,11 @@ pub(crate) fn wait_gfw_boot_completion(bar: &Bar0) -> Result {
Ok(
// Check that FWSEC has lowered its protection level before reading the GFW_BOOT
// status.
- regs::NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_PRIV_LEVEL_MASK::read(bar)
+ bar.read(regs::NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_PRIV_LEVEL_MASK)
.read_protection_level0()
- && regs::NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_0_GFW_BOOT::read(bar).completed(),
+ && bar
+ .read(regs::NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_0_GFW_BOOT)
+ .completed(),
)
},
|&gfw_booted| gfw_booted,
diff --git a/drivers/gpu/nova-core/gpu.rs b/drivers/gpu/nova-core/gpu.rs
index 9b042ef1a308..0f6fe9a1b955 100644
--- a/drivers/gpu/nova-core/gpu.rs
+++ b/drivers/gpu/nova-core/gpu.rs
@@ -4,12 +4,15 @@ use kernel::{
device,
devres::Devres,
fmt,
+ io::Io,
+ num::Bounded,
pci,
prelude::*,
sync::Arc, //
};
use crate::{
+ bounded_enum,
driver::Bar0,
falcon::{
gsp::Gsp as GspFalcon,
@@ -92,7 +95,7 @@ define_chipset!({
});
impl Chipset {
- pub(crate) fn arch(&self) -> Architecture {
+ pub(crate) const fn arch(self) -> Architecture {
match self {
Self::TU102 | Self::TU104 | Self::TU106 | Self::TU117 | Self::TU116 => {
Architecture::Turing
@@ -105,6 +108,13 @@ impl Chipset {
}
}
}
+
+ /// Returns `true` if this chipset requires the PIO-loaded bootloader in order to boot FWSEC.
+ ///
+ /// This includes all chipsets < GA102.
+ pub(crate) const fn needs_fwsec_bootloader(self) -> bool {
+ matches!(self.arch(), Architecture::Turing) || matches!(self, Self::GA100)
+ }
}
// TODO
@@ -121,50 +131,26 @@ impl fmt::Display for Chipset {
}
}
-/// Enum representation of the GPU generation.
-///
-/// TODO: remove the `Default` trait implementation, and the `#[default]`
-/// attribute, once the register!() macro (which creates Architecture items) no
-/// longer requires it for read-only fields.
-#[derive(fmt::Debug, Default, Copy, Clone)]
-#[repr(u8)]
-pub(crate) enum Architecture {
- #[default]
- Turing = 0x16,
- Ampere = 0x17,
- Ada = 0x19,
-}
-
-impl TryFrom<u8> for Architecture {
- type Error = Error;
-
- fn try_from(value: u8) -> Result<Self> {
- match value {
- 0x16 => Ok(Self::Turing),
- 0x17 => Ok(Self::Ampere),
- 0x19 => Ok(Self::Ada),
- _ => Err(ENODEV),
- }
- }
-}
-
-impl From<Architecture> for u8 {
- fn from(value: Architecture) -> Self {
- // CAST: `Architecture` is `repr(u8)`, so this cast is always lossless.
- value as u8
+bounded_enum! {
+ /// Enum representation of the GPU generation.
+ #[derive(fmt::Debug, Copy, Clone)]
+ pub(crate) enum Architecture with TryFrom<Bounded<u32, 6>> {
+ Turing = 0x16,
+ Ampere = 0x17,
+ Ada = 0x19,
}
}
pub(crate) struct Revision {
- major: u8,
- minor: u8,
+ major: Bounded<u8, 4>,
+ minor: Bounded<u8, 4>,
}
impl From<regs::NV_PMC_BOOT_42> for Revision {
fn from(boot0: regs::NV_PMC_BOOT_42) -> Self {
Self {
- major: boot0.major_revision(),
- minor: boot0.minor_revision(),
+ major: boot0.major_revision().cast(),
+ minor: boot0.minor_revision().cast(),
}
}
}
@@ -201,13 +187,13 @@ impl Spec {
// from an earlier (pre-Fermi) era, and then using boot42 to precisely identify the GPU.
// Somewhere in the Rubin timeframe, boot0 will no longer have space to add new GPU IDs.
- let boot0 = regs::NV_PMC_BOOT_0::read(bar);
+ let boot0 = bar.read(regs::NV_PMC_BOOT_0);
if boot0.is_older_than_fermi() {
return Err(ENODEV);
}
- let boot42 = regs::NV_PMC_BOOT_42::read(bar);
+ let boot42 = bar.read(regs::NV_PMC_BOOT_42);
Spec::try_from(boot42).inspect_err(|_| {
dev_err!(dev, "Unsupported chipset: {}\n", boot42);
})
@@ -262,13 +248,13 @@ impl Gpu {
) -> impl PinInit<Self, Error> + 'a {
try_pin_init!(Self {
spec: Spec::new(pdev.as_ref(), bar).inspect(|spec| {
- dev_info!(pdev.as_ref(),"NVIDIA ({})\n", spec);
+ dev_info!(pdev,"NVIDIA ({})\n", spec);
})?,
// We must wait for GFW_BOOT completion before doing any significant setup on the GPU.
_: {
gfw::wait_gfw_boot_completion(bar)
- .inspect_err(|_| dev_err!(pdev.as_ref(), "GFW boot did not complete\n"))?;
+ .inspect_err(|_| dev_err!(pdev, "GFW boot did not complete\n"))?;
},
sysmem_flush: SysmemFlush::register(pdev.as_ref(), bar, spec.chipset)?,
diff --git a/drivers/gpu/nova-core/gsp.rs b/drivers/gpu/nova-core/gsp.rs
index 174feaca0a6b..ba5b7f990031 100644
--- a/drivers/gpu/nova-core/gsp.rs
+++ b/drivers/gpu/nova-core/gsp.rs
@@ -3,15 +3,19 @@
mod boot;
use kernel::{
+ debugfs,
device,
dma::{
- CoherentAllocation,
+ Coherent,
+ CoherentBox,
DmaAddress, //
},
- dma_write,
pci,
prelude::*,
- transmute::AsBytes, //
+ transmute::{
+ AsBytes,
+ FromBytes, //
+ }, //
};
pub(crate) mod cmdq;
@@ -38,25 +42,25 @@ pub(crate) const GSP_PAGE_SIZE: usize = 1 << GSP_PAGE_SHIFT;
/// Number of GSP pages to use in a RM log buffer.
const RM_LOG_BUFFER_NUM_PAGES: usize = 0x10;
+const LOG_BUFFER_SIZE: usize = RM_LOG_BUFFER_NUM_PAGES * GSP_PAGE_SIZE;
/// Array of page table entries, as understood by the GSP bootloader.
#[repr(C)]
struct PteArray<const NUM_ENTRIES: usize>([u64; NUM_ENTRIES]);
+/// SAFETY: arrays of `u64` implement `FromBytes` and we are but a wrapper around one.
+unsafe impl<const NUM_ENTRIES: usize> FromBytes for PteArray<NUM_ENTRIES> {}
+
/// SAFETY: arrays of `u64` implement `AsBytes` and we are but a wrapper around one.
unsafe impl<const NUM_ENTRIES: usize> AsBytes for PteArray<NUM_ENTRIES> {}
impl<const NUM_PAGES: usize> PteArray<NUM_PAGES> {
- /// Creates a new page table array mapping `NUM_PAGES` GSP pages starting at address `start`.
- fn new(start: DmaAddress) -> Result<Self> {
- let mut ptes = [0u64; NUM_PAGES];
- for (i, pte) in ptes.iter_mut().enumerate() {
- *pte = start
- .checked_add(num::usize_as_u64(i) << GSP_PAGE_SHIFT)
- .ok_or(EOVERFLOW)?;
- }
-
- Ok(Self(ptes))
+ /// Returns the page table entry for `index`, for a mapping starting at `start`.
+ // TODO: Replace with `IoView` projection once available.
+ fn entry(start: DmaAddress, index: usize) -> Result<u64> {
+ start
+ .checked_add(num::usize_as_u64(index) << GSP_PAGE_SHIFT)
+ .ok_or(EOVERFLOW)
}
}
@@ -74,47 +78,53 @@ impl<const NUM_PAGES: usize> PteArray<NUM_PAGES> {
/// then pp points to index into the buffer where the next logging entry will
/// be written. Therefore, the logging data is valid if:
/// 1 <= pp < sizeof(buffer)/sizeof(u64)
-struct LogBuffer(CoherentAllocation<u8>);
+struct LogBuffer(Coherent<[u8; LOG_BUFFER_SIZE]>);
impl LogBuffer {
/// Creates a new `LogBuffer` mapped on `dev`.
fn new(dev: &device::Device<device::Bound>) -> Result<Self> {
- const NUM_PAGES: usize = RM_LOG_BUFFER_NUM_PAGES;
+ let obj = Self(Coherent::zeroed(dev, GFP_KERNEL)?);
- let mut obj = Self(CoherentAllocation::<u8>::alloc_coherent(
- dev,
- NUM_PAGES * GSP_PAGE_SIZE,
- GFP_KERNEL | __GFP_ZERO,
- )?);
- let ptes = PteArray::<NUM_PAGES>::new(obj.0.dma_handle())?;
+ let start_addr = obj.0.dma_handle();
// SAFETY: `obj` has just been created and we are its sole user.
- unsafe {
- // Copy the self-mapping PTE at the expected location.
- obj.0
- .as_slice_mut(size_of::<u64>(), size_of_val(&ptes))?
- .copy_from_slice(ptes.as_bytes())
+ let pte_region = unsafe {
+ &mut obj.0.as_mut()[size_of::<u64>()..][..RM_LOG_BUFFER_NUM_PAGES * size_of::<u64>()]
};
+ // Write values one by one to avoid an on-stack instance of `PteArray`.
+ for (i, chunk) in pte_region.chunks_exact_mut(size_of::<u64>()).enumerate() {
+ let pte_value = PteArray::<0>::entry(start_addr, i)?;
+
+ chunk.copy_from_slice(&pte_value.to_ne_bytes());
+ }
+
Ok(obj)
}
}
-/// GSP runtime data.
-#[pin_data]
-pub(crate) struct Gsp {
- /// Libos arguments.
- pub(crate) libos: CoherentAllocation<LibosMemoryRegionInitArgument>,
+struct LogBuffers {
/// Init log buffer.
loginit: LogBuffer,
/// Interrupts log buffer.
logintr: LogBuffer,
/// RM log buffer.
logrm: LogBuffer,
+}
+
+/// GSP runtime data.
+#[pin_data]
+pub(crate) struct Gsp {
+ /// Libos arguments.
+ pub(crate) libos: Coherent<[LibosMemoryRegionInitArgument]>,
+ /// Log buffers, optionally exposed via debugfs.
+ #[pin]
+ logs: debugfs::Scope<LogBuffers>,
/// Command queue.
+ #[pin]
pub(crate) cmdq: Cmdq,
/// RM arguments.
- rmargs: CoherentAllocation<GspArgumentsPadded>,
+ rmargs: Coherent<GspArgumentsPadded>,
}
impl Gsp {
@@ -123,34 +133,52 @@ impl Gsp {
pin_init::pin_init_scope(move || {
let dev = pdev.as_ref();
+ let loginit = LogBuffer::new(dev)?;
+ let logintr = LogBuffer::new(dev)?;
+ let logrm = LogBuffer::new(dev)?;
+
+ // Initialise the logging structures. The OpenRM equivalents are in:
+ // _kgspInitLibosLoggingStructures (allocates memory for buffers)
+ // kgspSetupLibosInitArgs_IMPL (creates pLibosInitArgs[] array)
Ok(try_pin_init!(Self {
- libos: CoherentAllocation::<LibosMemoryRegionInitArgument>::alloc_coherent(
- dev,
- GSP_PAGE_SIZE / size_of::<LibosMemoryRegionInitArgument>(),
- GFP_KERNEL | __GFP_ZERO,
- )?,
- loginit: LogBuffer::new(dev)?,
- logintr: LogBuffer::new(dev)?,
- logrm: LogBuffer::new(dev)?,
- cmdq: Cmdq::new(dev)?,
- rmargs: CoherentAllocation::<GspArgumentsPadded>::alloc_coherent(
- dev,
- 1,
- GFP_KERNEL | __GFP_ZERO,
- )?,
- _: {
- // Initialise the logging structures. The OpenRM equivalents are in:
- // _kgspInitLibosLoggingStructures (allocates memory for buffers)
- // kgspSetupLibosInitArgs_IMPL (creates pLibosInitArgs[] array)
- dma_write!(
- libos[0] = LibosMemoryRegionInitArgument::new("LOGINIT", &loginit.0)
- )?;
- dma_write!(
- libos[1] = LibosMemoryRegionInitArgument::new("LOGINTR", &logintr.0)
+ cmdq <- Cmdq::new(dev),
+ rmargs: Coherent::init(dev, GFP_KERNEL, GspArgumentsPadded::new(&cmdq))?,
+ libos: {
+ let mut libos = CoherentBox::zeroed_slice(
+ dev,
+ GSP_PAGE_SIZE / size_of::<LibosMemoryRegionInitArgument>(),
+ GFP_KERNEL,
)?;
- dma_write!(libos[2] = LibosMemoryRegionInitArgument::new("LOGRM", &logrm.0))?;
- dma_write!(rmargs[0].inner = fw::GspArgumentsCached::new(cmdq))?;
- dma_write!(libos[3] = LibosMemoryRegionInitArgument::new("RMARGS", rmargs))?;
+
+ libos.init_at(0, LibosMemoryRegionInitArgument::new("LOGINIT", &loginit.0))?;
+ libos.init_at(1, LibosMemoryRegionInitArgument::new("LOGINTR", &logintr.0))?;
+ libos.init_at(2, LibosMemoryRegionInitArgument::new("LOGRM", &logrm.0))?;
+ libos.init_at(3, LibosMemoryRegionInitArgument::new("RMARGS", rmargs))?;
+
+ libos.into()
+ },
+ logs <- {
+ let log_buffers = LogBuffers {
+ loginit,
+ logintr,
+ logrm,
+ };
+
+ #[allow(static_mut_refs)]
+ // SAFETY: `DEBUGFS_ROOT` is created before driver registration and cleared
+ // after driver unregistration, so no probe() can race with its modification.
+ //
+ // PANIC: `DEBUGFS_ROOT` cannot be `None` here. It is set before driver
+ // registration and cleared after driver unregistration, so it is always
+ // `Some` for the entire lifetime that probe() can be called.
+ let log_parent: &debugfs::Dir = unsafe { crate::DEBUGFS_ROOT.as_ref() }
+ .expect("DEBUGFS_ROOT not initialized");
+
+ log_parent.scope(log_buffers, dev.name(), |logs, dir| {
+ dir.read_binary_file(c"loginit", &logs.loginit.0);
+ dir.read_binary_file(c"logintr", &logs.logintr.0);
+ dir.read_binary_file(c"logrm", &logs.logrm.0);
+ })
},
}))
})
diff --git a/drivers/gpu/nova-core/gsp/boot.rs b/drivers/gpu/nova-core/gsp/boot.rs
index be427fe26a58..6f707b3d1a54 100644
--- a/drivers/gpu/nova-core/gsp/boot.rs
+++ b/drivers/gpu/nova-core/gsp/boot.rs
@@ -2,9 +2,9 @@
use kernel::{
device,
- dma::CoherentAllocation,
- dma_write,
+ dma::Coherent,
io::poll::read_poll_timeout,
+ io::Io,
pci,
prelude::*,
time::Delta, //
@@ -24,6 +24,7 @@ use crate::{
BooterKind, //
},
fwsec::{
+ bootloader::FwsecFirmwareWithBl,
FwsecCommand,
FwsecFirmware, //
},
@@ -48,6 +49,7 @@ impl super::Gsp {
/// created the WPR2 region.
fn run_fwsec_frts(
dev: &device::Device<device::Bound>,
+ chipset: Chipset,
falcon: &Falcon<Gsp>,
bar: &Bar0,
bios: &Vbios,
@@ -55,7 +57,7 @@ impl super::Gsp {
) -> Result<()> {
// Check that the WPR2 region does not already exists - if it does, we cannot run
// FWSEC-FRTS until the GPU is reset.
- if regs::NV_PFB_PRI_MMU_WPR2_ADDR_HI::read(bar).higher_bound() != 0 {
+ if bar.read(regs::NV_PFB_PRI_MMU_WPR2_ADDR_HI).higher_bound() != 0 {
dev_err!(
dev,
"WPR2 region already exists - GPU needs to be reset to proceed\n"
@@ -63,6 +65,7 @@ impl super::Gsp {
return Err(EBUSY);
}
+ // FWSEC-FRTS will create the WPR2 region.
let fwsec_frts = FwsecFirmware::new(
dev,
falcon,
@@ -70,15 +73,23 @@ impl super::Gsp {
bios,
FwsecCommand::Frts {
frts_addr: fb_layout.frts.start,
- frts_size: fb_layout.frts.end - fb_layout.frts.start,
+ frts_size: fb_layout.frts.len(),
},
)?;
- // Run FWSEC-FRTS to create the WPR2 region.
- fwsec_frts.run(dev, falcon, bar)?;
+ if chipset.needs_fwsec_bootloader() {
+ let fwsec_frts_bl = FwsecFirmwareWithBl::new(fwsec_frts, dev, chipset)?;
+ // Load and run the bootloader, which will load FWSEC-FRTS and run it.
+ fwsec_frts_bl.run(dev, falcon, bar)?;
+ } else {
+ // Load and run FWSEC-FRTS directly.
+ fwsec_frts.run(dev, falcon, bar)?;
+ }
// SCRATCH_E contains the error code for FWSEC-FRTS.
- let frts_status = regs::NV_PBUS_SW_SCRATCH_0E_FRTS_ERR::read(bar).frts_err_code();
+ let frts_status = bar
+ .read(regs::NV_PBUS_SW_SCRATCH_0E_FRTS_ERR)
+ .frts_err_code();
if frts_status != 0 {
dev_err!(
dev,
@@ -91,8 +102,8 @@ impl super::Gsp {
// Check that the WPR2 region has been created as we requested.
let (wpr2_lo, wpr2_hi) = (
- regs::NV_PFB_PRI_MMU_WPR2_ADDR_LO::read(bar).lower_bound(),
- regs::NV_PFB_PRI_MMU_WPR2_ADDR_HI::read(bar).higher_bound(),
+ bar.read(regs::NV_PFB_PRI_MMU_WPR2_ADDR_LO).lower_bound(),
+ bar.read(regs::NV_PFB_PRI_MMU_WPR2_ADDR_HI).higher_bound(),
);
match (wpr2_lo, wpr2_hi) {
@@ -128,7 +139,7 @@ impl super::Gsp {
///
/// Upon return, the GSP is up and running, and its runtime object given as return value.
pub(crate) fn boot(
- mut self: Pin<&mut Self>,
+ self: Pin<&mut Self>,
pdev: &pci::Device<device::Bound>,
bar: &Bar0,
chipset: Chipset,
@@ -144,7 +155,7 @@ impl super::Gsp {
let fb_layout = FbLayout::new(chipset, bar, &gsp_fw)?;
dev_dbg!(dev, "{:#x?}\n", fb_layout);
- Self::run_fwsec_frts(dev, gsp_falcon, bar, &bios, &fb_layout)?;
+ Self::run_fwsec_frts(dev, chipset, gsp_falcon, bar, &bios, &fb_layout)?;
let booter_loader = BooterFirmware::new(
dev,
@@ -155,13 +166,12 @@ impl super::Gsp {
bar,
)?;
- let wpr_meta =
- CoherentAllocation::<GspFwWprMeta>::alloc_coherent(dev, 1, GFP_KERNEL | __GFP_ZERO)?;
- dma_write!(wpr_meta[0] = GspFwWprMeta::new(&gsp_fw, &fb_layout))?;
+ let wpr_meta = Coherent::init(dev, GFP_KERNEL, GspFwWprMeta::new(&gsp_fw, &fb_layout))?;
self.cmdq
- .send_command(bar, commands::SetSystemInfo::new(pdev))?;
- self.cmdq.send_command(bar, commands::SetRegistry::new())?;
+ .send_command_no_wait(bar, commands::SetSystemInfo::new(pdev))?;
+ self.cmdq
+ .send_command_no_wait(bar, commands::SetRegistry::new())?;
gsp_falcon.reset(bar)?;
let libos_handle = self.libos.dma_handle();
@@ -170,39 +180,25 @@ impl super::Gsp {
Some(libos_handle as u32),
Some((libos_handle >> 32) as u32),
)?;
- dev_dbg!(
- pdev.as_ref(),
- "GSP MBOX0: {:#x}, MBOX1: {:#x}\n",
- mbox0,
- mbox1
- );
+ dev_dbg!(pdev, "GSP MBOX0: {:#x}, MBOX1: {:#x}\n", mbox0, mbox1);
dev_dbg!(
- pdev.as_ref(),
+ pdev,
"Using SEC2 to load and run the booter_load firmware...\n"
);
sec2_falcon.reset(bar)?;
- sec2_falcon.load(bar, &booter_loader)?;
+ sec2_falcon.load(dev, bar, &booter_loader)?;
let wpr_handle = wpr_meta.dma_handle();
let (mbox0, mbox1) = sec2_falcon.boot(
bar,
Some(wpr_handle as u32),
Some((wpr_handle >> 32) as u32),
)?;
- dev_dbg!(
- pdev.as_ref(),
- "SEC2 MBOX0: {:#x}, MBOX1{:#x}\n",
- mbox0,
- mbox1
- );
+ dev_dbg!(pdev, "SEC2 MBOX0: {:#x}, MBOX1{:#x}\n", mbox0, mbox1);
if mbox0 != 0 {
- dev_err!(
- pdev.as_ref(),
- "Booter-load failed with error {:#x}\n",
- mbox0
- );
+ dev_err!(pdev, "Booter-load failed with error {:#x}\n", mbox0);
return Err(ENODEV);
}
@@ -216,11 +212,7 @@ impl super::Gsp {
Delta::from_secs(5),
)?;
- dev_dbg!(
- pdev.as_ref(),
- "RISC-V active? {}\n",
- gsp_falcon.is_riscv_active(bar),
- );
+ dev_dbg!(pdev, "RISC-V active? {}\n", gsp_falcon.is_riscv_active(bar),);
// Create and run the GSP sequencer.
let seq_params = GspSequencerParams {
@@ -231,16 +223,16 @@ impl super::Gsp {
dev: pdev.as_ref().into(),
bar,
};
- GspSequencer::run(&mut self.cmdq, seq_params)?;
+ GspSequencer::run(&self.cmdq, seq_params)?;
// Wait until GSP is fully initialized.
- commands::wait_gsp_init_done(&mut self.cmdq)?;
+ commands::wait_gsp_init_done(&self.cmdq)?;
// Obtain and display basic GPU information.
- let info = commands::get_gsp_info(&mut self.cmdq, bar)?;
+ let info = commands::get_gsp_info(&self.cmdq, bar)?;
match info.gpu_name() {
- Ok(name) => dev_info!(pdev.as_ref(), "GPU name: {}\n", name),
- Err(e) => dev_warn!(pdev.as_ref(), "GPU name unavailable: {:?}\n", e),
+ Ok(name) => dev_info!(pdev, "GPU name: {}\n", name),
+ Err(e) => dev_warn!(pdev, "GPU name unavailable: {:?}\n", e),
}
Ok(())
diff --git a/drivers/gpu/nova-core/gsp/cmdq.rs b/drivers/gpu/nova-core/gsp/cmdq.rs
index 46819a82a51a..2224896ccc89 100644
--- a/drivers/gpu/nova-core/gsp/cmdq.rs
+++ b/drivers/gpu/nova-core/gsp/cmdq.rs
@@ -1,24 +1,26 @@
// SPDX-License-Identifier: GPL-2.0
-use core::{
- cmp,
- mem,
- sync::atomic::{
- fence,
- Ordering, //
- }, //
-};
+mod continuation;
+
+use core::mem;
use kernel::{
device,
dma::{
- CoherentAllocation,
+ Coherent,
DmaAddress, //
},
dma_write,
- io::poll::read_poll_timeout,
+ io::{
+ poll::read_poll_timeout,
+ Io, //
+ },
+ new_mutex,
prelude::*,
- sync::aref::ARef,
+ sync::{
+ aref::ARef,
+ Mutex, //
+ },
time::Delta,
transmute::{
AsBytes,
@@ -26,6 +28,13 @@ use kernel::{
},
};
+use continuation::{
+ ContinuationRecord,
+ SplitState, //
+};
+
+use pin_init::pin_init_scope;
+
use crate::{
driver::Bar0,
gsp::{
@@ -33,7 +42,8 @@ use crate::{
GspMsgElement,
MsgFunction,
MsgqRxHeader,
- MsgqTxHeader, //
+ MsgqTxHeader,
+ GSP_MSG_QUEUE_ELEMENT_SIZE_MAX, //
},
PteArray,
GSP_PAGE_SHIFT,
@@ -44,10 +54,14 @@ use crate::{
sbuffer::SBufferIter, //
};
+/// Marker type representing the absence of a reply for a command. Commands using this as their
+/// reply type are sent using [`Cmdq::send_command_no_wait`].
+pub(crate) struct NoReply;
+
/// Trait implemented by types representing a command to send to the GSP.
///
-/// The main purpose of this trait is to provide [`Cmdq::send_command`] with the information it
-/// needs to send a given command.
+/// The main purpose of this trait is to provide [`Cmdq`] with the information it needs to send
+/// a given command.
///
/// [`CommandToGsp::init`] in particular is responsible for initializing the command directly
/// into the space reserved for it in the command queue buffer.
@@ -62,6 +76,10 @@ pub(crate) trait CommandToGsp {
/// Type generated by [`CommandToGsp::init`], to be written into the command queue buffer.
type Command: FromBytes + AsBytes;
+ /// Type of the reply expected from the GSP, or [`NoReply`] for commands that don't
+ /// have a reply.
+ type Reply;
+
/// Error type returned by [`CommandToGsp::init`].
type InitError;
@@ -94,6 +112,12 @@ pub(crate) trait CommandToGsp {
) -> Result {
Ok(())
}
+
+ /// Total size of the command (including its variable-length payload) without the
+ /// [`GspMsgElement`] header.
+ fn size(&self) -> usize {
+ size_of::<Self::Command>() + self.variable_payload_len()
+ }
}
/// Trait representing messages received from the GSP.
@@ -146,30 +170,38 @@ static_assert!(align_of::<MsgqData>() == GSP_PAGE_SIZE);
#[repr(C)]
// There is no struct defined for this in the open-gpu-kernel-source headers.
// Instead it is defined by code in `GspMsgQueuesInit()`.
-struct Msgq {
+// TODO: Revert to private once `IoView` projections replace the `gsp_mem` module.
+pub(super) struct Msgq {
/// Header for sending messages, including the write pointer.
- tx: MsgqTxHeader,
+ pub(super) tx: MsgqTxHeader,
/// Header for receiving messages, including the read pointer.
- rx: MsgqRxHeader,
+ pub(super) rx: MsgqRxHeader,
/// The message queue proper.
msgq: MsgqData,
}
/// Structure shared between the driver and the GSP and containing the command and message queues.
#[repr(C)]
-struct GspMem {
+// TODO: Revert to private once `IoView` projections replace the `gsp_mem` module.
+pub(super) struct GspMem {
/// Self-mapping page table entries.
- ptes: PteArray<{ GSP_PAGE_SIZE / size_of::<u64>() }>,
+ ptes: PteArray<{ Self::PTE_ARRAY_SIZE }>,
/// CPU queue: the driver writes commands here, and the GSP reads them. It also contains the
- /// write and read pointers that the CPU updates.
+ /// write and read pointers that the CPU updates. This means that the read pointer here is an
+ /// index into the GSP queue.
///
/// This member is read-only for the GSP.
- cpuq: Msgq,
+ pub(super) cpuq: Msgq,
/// GSP queue: the GSP writes messages here, and the driver reads them. It also contains the
- /// write and read pointers that the GSP updates.
+ /// write and read pointers that the GSP updates. This means that the read pointer here is an
+ /// index into the CPU queue.
///
/// This member is read-only for the driver.
- gspq: Msgq,
+ pub(super) gspq: Msgq,
+}
+
+impl GspMem {
+ const PTE_ARRAY_SIZE: usize = GSP_PAGE_SIZE / size_of::<u64>();
}
// SAFETY: These structs don't meet the no-padding requirements of AsBytes but
@@ -180,7 +212,7 @@ unsafe impl AsBytes for GspMem {}
// that is not a problem because they are not used outside the kernel.
unsafe impl FromBytes for GspMem {}
-/// Wrapper around [`GspMem`] to share it with the GPU using a [`CoherentAllocation`].
+/// Wrapper around [`GspMem`] to share it with the GPU using a [`Coherent`].
///
/// This provides the low-level functionality to communicate with the GSP, including allocation of
/// queue space to write messages to and management of read/write pointers.
@@ -191,7 +223,7 @@ unsafe impl FromBytes for GspMem {}
/// pointer and the GSP read pointer. This region is returned by [`Self::driver_write_area`].
/// * The driver owns (i.e. can read from) the part of the GSP message queue between the CPU read
/// pointer and the GSP write pointer. This region is returned by [`Self::driver_read_area`].
-struct DmaGspMem(CoherentAllocation<GspMem>);
+struct DmaGspMem(Coherent<GspMem>);
impl DmaGspMem {
/// Allocate a new instance and map it for `dev`.
@@ -199,11 +231,20 @@ impl DmaGspMem {
const MSGQ_SIZE: u32 = num::usize_into_u32::<{ size_of::<Msgq>() }>();
const RX_HDR_OFF: u32 = num::usize_into_u32::<{ mem::offset_of!(Msgq, rx) }>();
- let gsp_mem =
- CoherentAllocation::<GspMem>::alloc_coherent(dev, 1, GFP_KERNEL | __GFP_ZERO)?;
- dma_write!(gsp_mem[0].ptes = PteArray::new(gsp_mem.dma_handle())?)?;
- dma_write!(gsp_mem[0].cpuq.tx = MsgqTxHeader::new(MSGQ_SIZE, RX_HDR_OFF, MSGQ_NUM_PAGES))?;
- dma_write!(gsp_mem[0].cpuq.rx = MsgqRxHeader::new())?;
+ let gsp_mem = Coherent::<GspMem>::zeroed(dev, GFP_KERNEL)?;
+
+ let start = gsp_mem.dma_handle();
+ // Write values one by one to avoid an on-stack instance of `PteArray`.
+ for i in 0..GspMem::PTE_ARRAY_SIZE {
+ dma_write!(gsp_mem, .ptes.0[i], PteArray::<0>::entry(start, i)?);
+ }
+
+ dma_write!(
+ gsp_mem,
+ .cpuq.tx,
+ MsgqTxHeader::new(MSGQ_SIZE, RX_HDR_OFF, MSGQ_NUM_PAGES)
+ );
+ dma_write!(gsp_mem, .cpuq.rx, MsgqRxHeader::new());
Ok(Self(gsp_mem))
}
@@ -218,31 +259,49 @@ impl DmaGspMem {
let rx = self.gsp_read_ptr() as usize;
// SAFETY:
- // - The `CoherentAllocation` contains exactly one object.
// - We will only access the driver-owned part of the shared memory.
// - Per the safety statement of the function, no concurrent access will be performed.
- let gsp_mem = &mut unsafe { self.0.as_slice_mut(0, 1) }.unwrap()[0];
- // PANIC: per the invariant of `cpu_write_ptr`, `tx` is `<= MSGQ_NUM_PAGES`.
+ let gsp_mem = unsafe { &mut *self.0.as_mut() };
+ // PANIC: per the invariant of `cpu_write_ptr`, `tx` is `< MSGQ_NUM_PAGES`.
let (before_tx, after_tx) = gsp_mem.cpuq.msgq.data.split_at_mut(tx);
- if rx <= tx {
- // The area from `tx` up to the end of the ring, and from the beginning of the ring up
- // to `rx`, minus one unit, belongs to the driver.
- if rx == 0 {
- let last = after_tx.len() - 1;
- (&mut after_tx[..last], &mut before_tx[0..0])
- } else {
- (after_tx, &mut before_tx[..rx])
- }
+ // The area starting at `tx` and ending at `rx - 2` modulo MSGQ_NUM_PAGES, inclusive,
+ // belongs to the driver for writing.
+
+ if rx == 0 {
+ // Since `rx` is zero, leave an empty slot at end of the buffer.
+ let last = after_tx.len() - 1;
+ (&mut after_tx[..last], &mut [])
+ } else if rx <= tx {
+ // The area is discontiguous and we leave an empty slot before `rx`.
+ // PANIC:
+ // - The index `rx - 1` is non-negative because `rx != 0` in this branch.
+ // - The index does not exceed `before_tx.len()` (which equals `tx`) because
+ // `rx <= tx` in this branch.
+ (after_tx, &mut before_tx[..(rx - 1)])
} else {
- // The area from `tx` to `rx`, minus one unit, belongs to the driver.
- //
- // PANIC: per the invariants of `cpu_write_ptr` and `gsp_read_ptr`, `rx` and `tx` are
- // `<= MSGQ_NUM_PAGES`, and the test above ensured that `rx > tx`.
- (after_tx.split_at_mut(rx - tx).0, &mut before_tx[0..0])
+ // The area is contiguous and we leave an empty slot before `rx`.
+ // PANIC:
+ // - The index `rx - tx - 1` is non-negative because `rx > tx` in this branch.
+ // - The index does not exceed `after_tx.len()` (which is `MSGQ_NUM_PAGES - tx`)
+ // because `rx < MSGQ_NUM_PAGES` by the `gsp_read_ptr` invariant.
+ (&mut after_tx[..(rx - tx - 1)], &mut [])
}
}
+ /// Returns the size of the region of the CPU message queue that the driver is currently allowed
+ /// to write to, in bytes.
+ fn driver_write_area_size(&self) -> usize {
+ let tx = self.cpu_write_ptr();
+ let rx = self.gsp_read_ptr();
+
+ // `rx` and `tx` are both in `0..MSGQ_NUM_PAGES` per the invariants of `gsp_read_ptr` and
+ // `cpu_write_ptr`. The minimum value case is where `rx == 0` and `tx == MSGQ_NUM_PAGES -
+ // 1`, which gives `0 + MSGQ_NUM_PAGES - (MSGQ_NUM_PAGES - 1) - 1 == 0`.
+ let slots = (rx + MSGQ_NUM_PAGES - tx - 1) % MSGQ_NUM_PAGES;
+ num::u32_as_usize(slots) * GSP_PAGE_SIZE
+ }
+
/// Returns the region of the GSP message queue that the driver is currently allowed to read
/// from.
///
@@ -253,30 +312,46 @@ impl DmaGspMem {
let rx = self.cpu_read_ptr() as usize;
// SAFETY:
- // - The `CoherentAllocation` contains exactly one object.
// - We will only access the driver-owned part of the shared memory.
// - Per the safety statement of the function, no concurrent access will be performed.
- let gsp_mem = &unsafe { self.0.as_slice(0, 1) }.unwrap()[0];
- // PANIC: per the invariant of `cpu_read_ptr`, `xx` is `<= MSGQ_NUM_PAGES`.
- let (before_rx, after_rx) = gsp_mem.gspq.msgq.data.split_at(rx);
-
- match tx.cmp(&rx) {
- cmp::Ordering::Equal => (&after_rx[0..0], &after_rx[0..0]),
- cmp::Ordering::Greater => (&after_rx[..tx], &before_rx[0..0]),
- cmp::Ordering::Less => (after_rx, &before_rx[..tx]),
+ let gsp_mem = unsafe { &*self.0.as_ptr() };
+ let data = &gsp_mem.gspq.msgq.data;
+
+ // The area starting at `rx` and ending at `tx - 1` modulo MSGQ_NUM_PAGES, inclusive,
+ // belongs to the driver for reading.
+ // PANIC:
+ // - per the invariant of `cpu_read_ptr`, `rx < MSGQ_NUM_PAGES`
+ // - per the invariant of `gsp_write_ptr`, `tx < MSGQ_NUM_PAGES`
+ if rx <= tx {
+ // The area is contiguous.
+ (&data[rx..tx], &[])
+ } else {
+ // The area is discontiguous.
+ (&data[rx..], &data[..tx])
}
}
/// Allocates a region on the command queue that is large enough to send a command of `size`
- /// bytes.
+ /// bytes, waiting for space to become available based on the provided timeout.
///
/// This returns a [`GspCommand`] ready to be written to by the caller.
///
/// # Errors
///
- /// - `EAGAIN` if the driver area is too small to hold the requested command.
+ /// - `EMSGSIZE` if the command is larger than [`GSP_MSG_QUEUE_ELEMENT_SIZE_MAX`].
+ /// - `ETIMEDOUT` if space does not become available within the timeout.
/// - `EIO` if the command header is not properly aligned.
- fn allocate_command(&mut self, size: usize) -> Result<GspCommand<'_>> {
+ fn allocate_command(&mut self, size: usize, timeout: Delta) -> Result<GspCommand<'_>> {
+ if size_of::<GspMsgElement>() + size > GSP_MSG_QUEUE_ELEMENT_SIZE_MAX {
+ return Err(EMSGSIZE);
+ }
+ read_poll_timeout(
+ || Ok(self.driver_write_area_size()),
+ |available_bytes| *available_bytes >= size_of::<GspMsgElement>() + size,
+ Delta::from_micros(1),
+ timeout,
+ )?;
+
// Get the current writable area as an array of bytes.
let (slice_1, slice_2) = {
let (slice_1, slice_2) = self.driver_write_area();
@@ -285,13 +360,6 @@ impl DmaGspMem {
(slice_1.as_flattened_mut(), slice_2.as_flattened_mut())
};
- // If the GSP is still processing previous messages the shared region
- // may be full in which case we will have to retry once the GSP has
- // processed the existing commands.
- if size_of::<GspMsgElement>() + size > slice_1.len() + slice_2.len() {
- return Err(EAGAIN);
- }
-
// Extract area for the `GspMsgElement`.
let (header, slice_1) = GspMsgElement::from_bytes_mut_prefix(slice_1).ok_or(EIO)?;
@@ -315,85 +383,46 @@ impl DmaGspMem {
//
// # Invariants
//
- // - The returned value is between `0` and `MSGQ_NUM_PAGES`.
+ // - The returned value is within `0..MSGQ_NUM_PAGES`.
fn gsp_write_ptr(&self) -> u32 {
- let gsp_mem = self.0.start_ptr();
-
- // SAFETY:
- // - The 'CoherentAllocation' contains at least one object.
- // - By the invariants of `CoherentAllocation` the pointer is valid.
- (unsafe { (*gsp_mem).gspq.tx.write_ptr() } % MSGQ_NUM_PAGES)
+ super::fw::gsp_mem::gsp_write_ptr(&self.0)
}
// Returns the index of the memory page the GSP will read the next command from.
//
// # Invariants
//
- // - The returned value is between `0` and `MSGQ_NUM_PAGES`.
+ // - The returned value is within `0..MSGQ_NUM_PAGES`.
fn gsp_read_ptr(&self) -> u32 {
- let gsp_mem = self.0.start_ptr();
-
- // SAFETY:
- // - The 'CoherentAllocation' contains at least one object.
- // - By the invariants of `CoherentAllocation` the pointer is valid.
- (unsafe { (*gsp_mem).gspq.rx.read_ptr() } % MSGQ_NUM_PAGES)
+ super::fw::gsp_mem::gsp_read_ptr(&self.0)
}
// Returns the index of the memory page the CPU can read the next message from.
//
// # Invariants
//
- // - The returned value is between `0` and `MSGQ_NUM_PAGES`.
+ // - The returned value is within `0..MSGQ_NUM_PAGES`.
fn cpu_read_ptr(&self) -> u32 {
- let gsp_mem = self.0.start_ptr();
-
- // SAFETY:
- // - The ['CoherentAllocation'] contains at least one object.
- // - By the invariants of CoherentAllocation the pointer is valid.
- (unsafe { (*gsp_mem).cpuq.rx.read_ptr() } % MSGQ_NUM_PAGES)
+ super::fw::gsp_mem::cpu_read_ptr(&self.0)
}
// Informs the GSP that it can send `elem_count` new pages into the message queue.
fn advance_cpu_read_ptr(&mut self, elem_count: u32) {
- let rptr = self.cpu_read_ptr().wrapping_add(elem_count) % MSGQ_NUM_PAGES;
-
- // Ensure read pointer is properly ordered.
- fence(Ordering::SeqCst);
-
- let gsp_mem = self.0.start_ptr_mut();
-
- // SAFETY:
- // - The 'CoherentAllocation' contains at least one object.
- // - By the invariants of `CoherentAllocation` the pointer is valid.
- unsafe { (*gsp_mem).cpuq.rx.set_read_ptr(rptr) };
+ super::fw::gsp_mem::advance_cpu_read_ptr(&self.0, elem_count)
}
// Returns the index of the memory page the CPU can write the next command to.
//
// # Invariants
//
- // - The returned value is between `0` and `MSGQ_NUM_PAGES`.
+ // - The returned value is within `0..MSGQ_NUM_PAGES`.
fn cpu_write_ptr(&self) -> u32 {
- let gsp_mem = self.0.start_ptr();
-
- // SAFETY:
- // - The 'CoherentAllocation' contains at least one object.
- // - By the invariants of `CoherentAllocation` the pointer is valid.
- (unsafe { (*gsp_mem).cpuq.tx.write_ptr() } % MSGQ_NUM_PAGES)
+ super::fw::gsp_mem::cpu_write_ptr(&self.0)
}
// Informs the GSP that it can process `elem_count` new pages from the command queue.
fn advance_cpu_write_ptr(&mut self, elem_count: u32) {
- let wptr = self.cpu_write_ptr().wrapping_add(elem_count) & MSGQ_NUM_PAGES;
- let gsp_mem = self.0.start_ptr_mut();
-
- // SAFETY:
- // - The 'CoherentAllocation' contains at least one object.
- // - By the invariants of `CoherentAllocation` the pointer is valid.
- unsafe { (*gsp_mem).cpuq.tx.set_write_ptr(wptr) };
-
- // Ensure all command data is visible before triggering the GSP read.
- fence(Ordering::SeqCst);
+ super::fw::gsp_mem::advance_cpu_write_ptr(&self.0, elem_count)
}
}
@@ -423,13 +452,13 @@ struct GspMessage<'a> {
///
/// Provides the ability to send commands and receive messages from the GSP using a shared memory
/// area.
+#[pin_data]
pub(crate) struct Cmdq {
- /// Device this command queue belongs to.
- dev: ARef<device::Device>,
- /// Current command sequence number.
- seq: u32,
- /// Memory area shared with the GSP for communicating commands and messages.
- gsp_mem: DmaGspMem,
+ /// Inner mutex-protected state.
+ #[pin]
+ inner: Mutex<CmdqInner>,
+ /// DMA handle of the command queue's shared memory region.
+ pub(super) dma_handle: DmaAddress,
}
impl Cmdq {
@@ -449,14 +478,22 @@ impl Cmdq {
/// Number of page table entries for the GSP shared region.
pub(crate) const NUM_PTES: usize = size_of::<GspMem>() >> GSP_PAGE_SHIFT;
- /// Creates a new command queue for `dev`.
- pub(crate) fn new(dev: &device::Device<device::Bound>) -> Result<Cmdq> {
- let gsp_mem = DmaGspMem::new(dev)?;
+ /// Default timeout for receiving a message from the GSP.
+ pub(super) const RECEIVE_TIMEOUT: Delta = Delta::from_secs(5);
- Ok(Cmdq {
- dev: dev.into(),
- seq: 0,
- gsp_mem,
+ /// Creates a new command queue for `dev`.
+ pub(crate) fn new(dev: &device::Device<device::Bound>) -> impl PinInit<Self, Error> + '_ {
+ pin_init_scope(move || {
+ let gsp_mem = DmaGspMem::new(dev)?;
+
+ Ok(try_pin_init!(Self {
+ dma_handle: gsp_mem.0.dma_handle(),
+ inner <- new_mutex!(CmdqInner {
+ dev: dev.into(),
+ gsp_mem,
+ seq: 0,
+ }),
+ }))
})
}
@@ -475,34 +512,115 @@ impl Cmdq {
/// Notifies the GSP that we have updated the command queue pointers.
fn notify_gsp(bar: &Bar0) {
- regs::NV_PGSP_QUEUE_HEAD::default()
- .set_address(0)
- .write(bar);
+ bar.write_reg(regs::NV_PGSP_QUEUE_HEAD::zeroed().with_address(0u32));
}
- /// Sends `command` to the GSP.
+ /// Sends `command` to the GSP and waits for the reply.
+ ///
+ /// Messages with non-matching function codes are silently consumed until the expected reply
+ /// arrives.
+ ///
+ /// The queue is locked for the entire send+receive cycle to ensure that no other command can
+ /// be interleaved.
///
/// # Errors
///
- /// - `EAGAIN` if there was not enough space in the command queue to send the command.
+ /// - `ETIMEDOUT` if space does not become available to send the command, or if the reply is
+ /// not received within the timeout.
/// - `EIO` if the variable payload requested by the command has not been entirely
/// written to by its [`CommandToGsp::init_variable_payload`] method.
///
- /// Error codes returned by the command initializers are propagated as-is.
- pub(crate) fn send_command<M>(&mut self, bar: &Bar0, command: M) -> Result
+ /// Error codes returned by the command and reply initializers are propagated as-is.
+ pub(crate) fn send_command<M>(&self, bar: &Bar0, command: M) -> Result<M::Reply>
where
M: CommandToGsp,
+ M::Reply: MessageFromGsp,
+ Error: From<M::InitError>,
+ Error: From<<M::Reply as MessageFromGsp>::InitError>,
+ {
+ let mut inner = self.inner.lock();
+ inner.send_command(bar, command)?;
+
+ loop {
+ match inner.receive_msg::<M::Reply>(Self::RECEIVE_TIMEOUT) {
+ Ok(reply) => break Ok(reply),
+ Err(ERANGE) => continue,
+ Err(e) => break Err(e),
+ }
+ }
+ }
+
+ /// Sends `command` to the GSP without waiting for a reply.
+ ///
+ /// # Errors
+ ///
+ /// - `ETIMEDOUT` if space does not become available within the timeout.
+ /// - `EIO` if the variable payload requested by the command has not been entirely
+ /// written to by its [`CommandToGsp::init_variable_payload`] method.
+ ///
+ /// Error codes returned by the command initializers are propagated as-is.
+ pub(crate) fn send_command_no_wait<M>(&self, bar: &Bar0, command: M) -> Result
+ where
+ M: CommandToGsp<Reply = NoReply>,
+ Error: From<M::InitError>,
+ {
+ self.inner.lock().send_command(bar, command)
+ }
+
+ /// Receive a message from the GSP.
+ ///
+ /// See [`CmdqInner::receive_msg`] for details.
+ pub(crate) fn receive_msg<M: MessageFromGsp>(&self, timeout: Delta) -> Result<M>
+ where
// This allows all error types, including `Infallible`, to be used for `M::InitError`.
Error: From<M::InitError>,
{
- let command_size = size_of::<M::Command>() + command.variable_payload_len();
- let dst = self.gsp_mem.allocate_command(command_size)?;
+ self.inner.lock().receive_msg(timeout)
+ }
+}
- // Extract area for the command itself.
+/// Inner mutex protected state of [`Cmdq`].
+struct CmdqInner {
+ /// Device this command queue belongs to.
+ dev: ARef<device::Device>,
+ /// Current command sequence number.
+ seq: u32,
+ /// Memory area shared with the GSP for communicating commands and messages.
+ gsp_mem: DmaGspMem,
+}
+
+impl CmdqInner {
+ /// Timeout for waiting for space on the command queue.
+ const ALLOCATE_TIMEOUT: Delta = Delta::from_secs(1);
+
+ /// Sends `command` to the GSP, without splitting it.
+ ///
+ /// # Errors
+ ///
+ /// - `EMSGSIZE` if the command exceeds the maximum queue element size.
+ /// - `ETIMEDOUT` if space does not become available within the timeout.
+ /// - `EIO` if the variable payload requested by the command has not been entirely
+ /// written to by its [`CommandToGsp::init_variable_payload`] method.
+ ///
+ /// Error codes returned by the command initializers are propagated as-is.
+ fn send_single_command<M>(&mut self, bar: &Bar0, command: M) -> Result
+ where
+ M: CommandToGsp,
+ // This allows all error types, including `Infallible`, to be used for `M::InitError`.
+ Error: From<M::InitError>,
+ {
+ let size_in_bytes = command.size();
+ let dst = self
+ .gsp_mem
+ .allocate_command(size_in_bytes, Self::ALLOCATE_TIMEOUT)?;
+
+ // Extract area for the command itself. The GSP message header and the command header
+ // together are guaranteed to fit entirely into a single page, so it's ok to only look
+ // at `dst.contents.0` here.
let (cmd, payload_1) = M::Command::from_bytes_mut_prefix(dst.contents.0).ok_or(EIO)?;
// Fill the header and command in-place.
- let msg_element = GspMsgElement::init(self.seq, command_size, M::FUNCTION);
+ let msg_element = GspMsgElement::init(self.seq, size_in_bytes, M::FUNCTION);
// SAFETY: `msg_header` and `cmd` are valid references, and not touched if the initializer
// fails.
unsafe {
@@ -510,16 +628,14 @@ impl Cmdq {
command.init().__init(core::ptr::from_mut(cmd))?;
}
- // Fill the variable-length payload.
- if command_size > size_of::<M::Command>() {
- let mut sbuffer =
- SBufferIter::new_writer([&mut payload_1[..], &mut dst.contents.1[..]]);
- command.init_variable_payload(&mut sbuffer)?;
+ // Fill the variable-length payload, which may be empty.
+ let mut sbuffer = SBufferIter::new_writer([&mut payload_1[..], &mut dst.contents.1[..]]);
+ command.init_variable_payload(&mut sbuffer)?;
- if !sbuffer.is_empty() {
- return Err(EIO);
- }
+ if !sbuffer.is_empty() {
+ return Err(EIO);
}
+ drop(sbuffer);
// Compute checksum now that the whole message is ready.
dst.header
@@ -531,7 +647,7 @@ impl Cmdq {
dev_dbg!(
&self.dev,
- "GSP RPC: send: seq# {}, function={}, length=0x{:x}\n",
+ "GSP RPC: send: seq# {}, function={:?}, length=0x{:x}\n",
self.seq,
M::FUNCTION,
dst.header.length(),
@@ -546,6 +662,37 @@ impl Cmdq {
Ok(())
}
+ /// Sends `command` to the GSP.
+ ///
+ /// The command may be split into multiple messages if it is large.
+ ///
+ /// # Errors
+ ///
+ /// - `ETIMEDOUT` if space does not become available within the timeout.
+ /// - `EIO` if the variable payload requested by the command has not been entirely
+ /// written to by its [`CommandToGsp::init_variable_payload`] method.
+ ///
+ /// Error codes returned by the command initializers are propagated as-is.
+ fn send_command<M>(&mut self, bar: &Bar0, command: M) -> Result
+ where
+ M: CommandToGsp,
+ Error: From<M::InitError>,
+ {
+ match SplitState::new(command)? {
+ SplitState::Single(command) => self.send_single_command(bar, command),
+ SplitState::Split(command, mut continuations) => {
+ self.send_single_command(bar, command)?;
+
+ while let Some(continuation) = continuations.next() {
+ // Turbofish needed because the compiler cannot infer M here.
+ self.send_single_command::<ContinuationRecord<'_>>(bar, continuation)?;
+ }
+
+ Ok(())
+ }
+ }
+ }
+
/// Wait for a message to become available on the message queue.
///
/// This works purely at the transport layer and does not interpret or validate the message
@@ -581,7 +728,7 @@ impl Cmdq {
let (header, slice_1) = GspMsgElement::from_bytes_prefix(slice_1).ok_or(EIO)?;
dev_dbg!(
- self.dev,
+ &self.dev,
"GSP RPC: receive: seq# {}, function={:?}, length=0x{:x}\n",
header.sequence(),
header.function(),
@@ -616,7 +763,7 @@ impl Cmdq {
])) != 0
{
dev_err!(
- self.dev,
+ &self.dev,
"GSP RPC: receive: Call {} - bad checksum\n",
header.sequence()
);
@@ -631,23 +778,21 @@ impl Cmdq {
/// Receive a message from the GSP.
///
- /// `init` is a closure tasked with processing the message. It receives a reference to the
- /// message in the message queue, and a [`SBufferIter`] pointing to its variable-length
- /// payload, if any.
- ///
- /// The expected message is specified using the `M` generic parameter. If the pending message
- /// is different, `EAGAIN` is returned and the unexpected message is dropped.
+ /// The expected message type is specified using the `M` generic parameter. If the pending
+ /// message has a different function code, `ERANGE` is returned and the message is consumed.
///
- /// This design is by no means final, but it is simple and will let us go through GSP
- /// initialization.
+ /// The read pointer is always advanced past the message, regardless of whether it matched.
///
/// # Errors
///
/// - `ETIMEDOUT` if `timeout` has elapsed before any message becomes available.
/// - `EIO` if there was some inconsistency (e.g. message shorter than advertised) on the
/// message queue.
- /// - `EINVAL` if the function of the message was unrecognized.
- pub(crate) fn receive_msg<M: MessageFromGsp>(&mut self, timeout: Delta) -> Result<M>
+ /// - `EINVAL` if the function code of the message was not recognized.
+ /// - `ERANGE` if the message had a recognized but non-matching function code.
+ ///
+ /// Error codes returned by [`MessageFromGsp::read`] are propagated as-is.
+ fn receive_msg<M: MessageFromGsp>(&mut self, timeout: Delta) -> Result<M>
where
// This allows all error types, including `Infallible`, to be used for `M::InitError`.
Error: From<M::InitError>,
@@ -661,7 +806,17 @@ impl Cmdq {
let (cmd, contents_1) = M::Message::from_bytes_prefix(message.contents.0).ok_or(EIO)?;
let mut sbuffer = SBufferIter::new_reader([contents_1, message.contents.1]);
- M::read(cmd, &mut sbuffer).map_err(|e| e.into())
+ M::read(cmd, &mut sbuffer)
+ .map_err(|e| e.into())
+ .inspect(|_| {
+ if !sbuffer.is_empty() {
+ dev_warn!(
+ &self.dev,
+ "GSP message {:?} has unprocessed data\n",
+ function
+ );
+ }
+ })
} else {
Err(ERANGE)
};
@@ -673,9 +828,4 @@ impl Cmdq {
result
}
-
- /// Returns the DMA handle of the command queue's shared memory region.
- pub(crate) fn dma_handle(&self) -> DmaAddress {
- self.gsp_mem.0.dma_handle()
- }
}
diff --git a/drivers/gpu/nova-core/gsp/cmdq/continuation.rs b/drivers/gpu/nova-core/gsp/cmdq/continuation.rs
new file mode 100644
index 000000000000..05e904f18097
--- /dev/null
+++ b/drivers/gpu/nova-core/gsp/cmdq/continuation.rs
@@ -0,0 +1,307 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Support for splitting large GSP commands across continuation records.
+
+use core::convert::Infallible;
+
+use kernel::prelude::*;
+
+use super::{
+ CommandToGsp,
+ NoReply, //
+};
+
+use crate::{
+ gsp::fw::{
+ GspMsgElement,
+ MsgFunction,
+ GSP_MSG_QUEUE_ELEMENT_SIZE_MAX, //
+ },
+ sbuffer::SBufferIter,
+};
+
+/// Maximum command size that fits in a single queue element.
+const MAX_CMD_SIZE: usize = GSP_MSG_QUEUE_ELEMENT_SIZE_MAX - size_of::<GspMsgElement>();
+
+/// Acts as an iterator over the continuation records for a split command.
+pub(super) struct ContinuationRecords {
+ payload: KVVec<u8>,
+ offset: usize,
+}
+
+impl ContinuationRecords {
+ /// Creates a new iterator over continuation records for the given payload.
+ fn new(payload: KVVec<u8>) -> Self {
+ Self { payload, offset: 0 }
+ }
+
+ /// Returns the next continuation record, or [`None`] if there are no more.
+ pub(super) fn next(&mut self) -> Option<ContinuationRecord<'_>> {
+ let remaining = self.payload.len() - self.offset;
+
+ if remaining > 0 {
+ let chunk_size = remaining.min(MAX_CMD_SIZE);
+ let record =
+ ContinuationRecord::new(&self.payload[self.offset..(self.offset + chunk_size)]);
+ self.offset += chunk_size;
+ Some(record)
+ } else {
+ None
+ }
+ }
+}
+
+/// The [`ContinuationRecord`] command.
+pub(super) struct ContinuationRecord<'a> {
+ data: &'a [u8],
+}
+
+impl<'a> ContinuationRecord<'a> {
+ /// Creates a new [`ContinuationRecord`] command with the given data.
+ fn new(data: &'a [u8]) -> Self {
+ Self { data }
+ }
+}
+
+impl<'a> CommandToGsp for ContinuationRecord<'a> {
+ const FUNCTION: MsgFunction = MsgFunction::ContinuationRecord;
+ type Command = ();
+ type Reply = NoReply;
+ type InitError = Infallible;
+
+ fn init(&self) -> impl Init<Self::Command, Self::InitError> {
+ <()>::init_zeroed()
+ }
+
+ fn variable_payload_len(&self) -> usize {
+ self.data.len()
+ }
+
+ fn init_variable_payload(
+ &self,
+ dst: &mut SBufferIter<core::array::IntoIter<&mut [u8], 2>>,
+ ) -> Result {
+ dst.write_all(self.data)
+ }
+}
+
+/// Whether a command needs to be split across continuation records or not.
+pub(super) enum SplitState<C: CommandToGsp> {
+ /// A command that fits in a single queue element.
+ Single(C),
+ /// A command split across continuation records.
+ Split(SplitCommand<C>, ContinuationRecords),
+}
+
+impl<C: CommandToGsp> SplitState<C> {
+ /// Maximum variable payload size that fits in the first command alongside the command header.
+ const MAX_FIRST_PAYLOAD: usize = MAX_CMD_SIZE - size_of::<C::Command>();
+
+ /// Creates a new [`SplitState`] for the given command.
+ ///
+ /// If the command is too large, it will be split into a main command and some number of
+ /// continuation records.
+ pub(super) fn new(command: C) -> Result<Self> {
+ let payload_len = command.variable_payload_len();
+
+ if command.size() > MAX_CMD_SIZE {
+ let mut command_payload =
+ KVVec::<u8>::from_elem(0u8, payload_len.min(Self::MAX_FIRST_PAYLOAD), GFP_KERNEL)?;
+ let mut continuation_payload =
+ KVVec::<u8>::from_elem(0u8, payload_len - command_payload.len(), GFP_KERNEL)?;
+ let mut sbuffer = SBufferIter::new_writer([
+ command_payload.as_mut_slice(),
+ continuation_payload.as_mut_slice(),
+ ]);
+
+ command.init_variable_payload(&mut sbuffer)?;
+ if !sbuffer.is_empty() {
+ return Err(EIO);
+ }
+ drop(sbuffer);
+
+ Ok(Self::Split(
+ SplitCommand::new(command, command_payload),
+ ContinuationRecords::new(continuation_payload),
+ ))
+ } else {
+ Ok(Self::Single(command))
+ }
+ }
+}
+
+/// A command that has been truncated to maximum accepted length of the command queue.
+///
+/// The remainder of its payload is expected to be sent using [`ContinuationRecords`].
+pub(super) struct SplitCommand<C: CommandToGsp> {
+ command: C,
+ payload: KVVec<u8>,
+}
+
+impl<C: CommandToGsp> SplitCommand<C> {
+ /// Creates a new [`SplitCommand`] wrapping `command` with the given truncated payload.
+ fn new(command: C, payload: KVVec<u8>) -> Self {
+ Self { command, payload }
+ }
+}
+
+impl<C: CommandToGsp> CommandToGsp for SplitCommand<C> {
+ const FUNCTION: MsgFunction = C::FUNCTION;
+ type Command = C::Command;
+ type Reply = C::Reply;
+ type InitError = C::InitError;
+
+ fn init(&self) -> impl Init<Self::Command, Self::InitError> {
+ self.command.init()
+ }
+
+ fn variable_payload_len(&self) -> usize {
+ self.payload.len()
+ }
+
+ fn init_variable_payload(
+ &self,
+ dst: &mut SBufferIter<core::array::IntoIter<&mut [u8], 2>>,
+ ) -> Result {
+ dst.write_all(&self.payload)
+ }
+}
+
+#[kunit_tests(nova_core_gsp_continuation)]
+mod tests {
+ use super::*;
+
+ use kernel::transmute::{
+ AsBytes,
+ FromBytes, //
+ };
+
+ /// Non-zero-sized command header for testing.
+ #[repr(C)]
+ #[derive(Clone, Copy, Zeroable)]
+ struct TestHeader([u8; 64]);
+
+ // SAFETY: `TestHeader` is a plain array of bytes for which all bit patterns are valid.
+ unsafe impl FromBytes for TestHeader {}
+
+ // SAFETY: `TestHeader` is a plain array of bytes for which all bit patterns are valid.
+ unsafe impl AsBytes for TestHeader {}
+
+ struct TestPayload {
+ data: KVVec<u8>,
+ }
+
+ impl TestPayload {
+ fn generate_pattern(len: usize) -> Result<KVVec<u8>> {
+ let mut data = KVVec::with_capacity(len, GFP_KERNEL)?;
+ for i in 0..len {
+ // Mix in higher bits so the pattern does not repeat every 256 bytes.
+ data.push((i ^ (i >> 8)) as u8, GFP_KERNEL)?;
+ }
+ Ok(data)
+ }
+
+ fn new(len: usize) -> Result<Self> {
+ Ok(Self {
+ data: Self::generate_pattern(len)?,
+ })
+ }
+ }
+
+ impl CommandToGsp for TestPayload {
+ const FUNCTION: MsgFunction = MsgFunction::Nop;
+ type Command = TestHeader;
+ type Reply = NoReply;
+ type InitError = Infallible;
+
+ fn init(&self) -> impl Init<Self::Command, Self::InitError> {
+ TestHeader::init_zeroed()
+ }
+
+ fn variable_payload_len(&self) -> usize {
+ self.data.len()
+ }
+
+ fn init_variable_payload(
+ &self,
+ dst: &mut SBufferIter<core::array::IntoIter<&mut [u8], 2>>,
+ ) -> Result {
+ dst.write_all(self.data.as_slice())
+ }
+ }
+
+ /// Maximum variable payload size that fits in the first command alongside the header.
+ const MAX_FIRST_PAYLOAD: usize = SplitState::<TestPayload>::MAX_FIRST_PAYLOAD;
+
+ fn read_payload(cmd: impl CommandToGsp) -> Result<KVVec<u8>> {
+ let len = cmd.variable_payload_len();
+ let mut buf = KVVec::from_elem(0u8, len, GFP_KERNEL)?;
+ let mut sbuf = SBufferIter::new_writer([buf.as_mut_slice(), &mut []]);
+ cmd.init_variable_payload(&mut sbuf)?;
+ drop(sbuf);
+ Ok(buf)
+ }
+
+ struct SplitTest {
+ payload_size: usize,
+ num_continuations: usize,
+ }
+
+ fn check_split(t: SplitTest) -> Result {
+ let payload = TestPayload::new(t.payload_size)?;
+ let mut num_continuations = 0;
+
+ let buf = match SplitState::new(payload)? {
+ SplitState::Single(cmd) => read_payload(cmd)?,
+ SplitState::Split(cmd, mut continuations) => {
+ let mut buf = read_payload(cmd)?;
+ assert!(size_of::<TestHeader>() + buf.len() <= MAX_CMD_SIZE);
+
+ while let Some(cont) = continuations.next() {
+ let payload = read_payload(cont)?;
+ assert!(payload.len() <= MAX_CMD_SIZE);
+ buf.extend_from_slice(&payload, GFP_KERNEL)?;
+ num_continuations += 1;
+ }
+
+ buf
+ }
+ };
+
+ assert_eq!(num_continuations, t.num_continuations);
+ assert_eq!(
+ buf.as_slice(),
+ TestPayload::generate_pattern(t.payload_size)?.as_slice()
+ );
+ Ok(())
+ }
+
+ #[test]
+ fn split_command() -> Result {
+ check_split(SplitTest {
+ payload_size: 0,
+ num_continuations: 0,
+ })?;
+ check_split(SplitTest {
+ payload_size: MAX_FIRST_PAYLOAD,
+ num_continuations: 0,
+ })?;
+ check_split(SplitTest {
+ payload_size: MAX_FIRST_PAYLOAD + 1,
+ num_continuations: 1,
+ })?;
+ check_split(SplitTest {
+ payload_size: MAX_FIRST_PAYLOAD + MAX_CMD_SIZE,
+ num_continuations: 1,
+ })?;
+ check_split(SplitTest {
+ payload_size: MAX_FIRST_PAYLOAD + MAX_CMD_SIZE + 1,
+ num_continuations: 2,
+ })?;
+ check_split(SplitTest {
+ payload_size: MAX_FIRST_PAYLOAD + MAX_CMD_SIZE * 3 + MAX_CMD_SIZE / 2,
+ num_continuations: 4,
+ })?;
+ Ok(())
+ }
+}
diff --git a/drivers/gpu/nova-core/gsp/commands.rs b/drivers/gpu/nova-core/gsp/commands.rs
index 8f270eca33be..c89c7b57a751 100644
--- a/drivers/gpu/nova-core/gsp/commands.rs
+++ b/drivers/gpu/nova-core/gsp/commands.rs
@@ -11,7 +11,6 @@ use kernel::{
device,
pci,
prelude::*,
- time::Delta,
transmute::{
AsBytes,
FromBytes, //
@@ -24,7 +23,8 @@ use crate::{
cmdq::{
Cmdq,
CommandToGsp,
- MessageFromGsp, //
+ MessageFromGsp,
+ NoReply, //
},
fw::{
commands::*,
@@ -49,6 +49,7 @@ impl<'a> SetSystemInfo<'a> {
impl<'a> CommandToGsp for SetSystemInfo<'a> {
const FUNCTION: MsgFunction = MsgFunction::GspSetSystemInfo;
type Command = GspSetSystemInfo;
+ type Reply = NoReply;
type InitError = Error;
fn init(&self) -> impl Init<Self::Command, Self::InitError> {
@@ -100,6 +101,7 @@ impl SetRegistry {
impl CommandToGsp for SetRegistry {
const FUNCTION: MsgFunction = MsgFunction::SetRegistry;
type Command = PackedRegistryTable;
+ type Reply = NoReply;
type InitError = Infallible;
fn init(&self) -> impl Init<Self::Command, Self::InitError> {
@@ -163,9 +165,9 @@ impl MessageFromGsp for GspInitDone {
}
/// Waits for GSP initialization to complete.
-pub(crate) fn wait_gsp_init_done(cmdq: &mut Cmdq) -> Result {
+pub(crate) fn wait_gsp_init_done(cmdq: &Cmdq) -> Result {
loop {
- match cmdq.receive_msg::<GspInitDone>(Delta::from_secs(10)) {
+ match cmdq.receive_msg::<GspInitDone>(Cmdq::RECEIVE_TIMEOUT) {
Ok(_) => break Ok(()),
Err(ERANGE) => continue,
Err(e) => break Err(e),
@@ -179,6 +181,7 @@ struct GetGspStaticInfo;
impl CommandToGsp for GetGspStaticInfo {
const FUNCTION: MsgFunction = MsgFunction::GetGspStaticInfo;
type Command = GspStaticConfigInfo;
+ type Reply = GetGspStaticInfoReply;
type InitError = Infallible;
fn init(&self) -> impl Init<Self::Command, Self::InitError> {
@@ -231,14 +234,6 @@ impl GetGspStaticInfoReply {
}
/// Send the [`GetGspInfo`] command and awaits for its reply.
-pub(crate) fn get_gsp_info(cmdq: &mut Cmdq, bar: &Bar0) -> Result<GetGspStaticInfoReply> {
- cmdq.send_command(bar, GetGspStaticInfo)?;
-
- loop {
- match cmdq.receive_msg::<GetGspStaticInfoReply>(Delta::from_secs(5)) {
- Ok(info) => return Ok(info),
- Err(ERANGE) => continue,
- Err(e) => return Err(e),
- }
- }
+pub(crate) fn get_gsp_info(cmdq: &Cmdq, bar: &Bar0) -> Result<GetGspStaticInfoReply> {
+ cmdq.send_command(bar, GetGspStaticInfo)
}
diff --git a/drivers/gpu/nova-core/gsp/fw.rs b/drivers/gpu/nova-core/gsp/fw.rs
index 83ff91614e36..0c8a74f0e8ac 100644
--- a/drivers/gpu/nova-core/gsp/fw.rs
+++ b/drivers/gpu/nova-core/gsp/fw.rs
@@ -9,12 +9,12 @@ use r570_144 as bindings;
use core::ops::Range;
use kernel::{
- dma::CoherentAllocation,
- fmt,
+ dma::Coherent,
prelude::*,
ptr::{
Alignable,
- Alignment, //
+ Alignment,
+ KnownSize, //
},
sizes::{
SZ_128K,
@@ -40,6 +40,63 @@ use crate::{
},
};
+// TODO: Replace with `IoView` projections once available.
+pub(super) mod gsp_mem {
+ use core::sync::atomic::{
+ fence,
+ Ordering, //
+ };
+
+ use kernel::{
+ dma::Coherent,
+ dma_read,
+ dma_write, //
+ };
+
+ use crate::gsp::cmdq::{
+ GspMem,
+ MSGQ_NUM_PAGES, //
+ };
+
+ pub(in crate::gsp) fn gsp_write_ptr(qs: &Coherent<GspMem>) -> u32 {
+ dma_read!(qs, .gspq.tx.0.writePtr) % MSGQ_NUM_PAGES
+ }
+
+ pub(in crate::gsp) fn gsp_read_ptr(qs: &Coherent<GspMem>) -> u32 {
+ dma_read!(qs, .gspq.rx.0.readPtr) % MSGQ_NUM_PAGES
+ }
+
+ pub(in crate::gsp) fn cpu_read_ptr(qs: &Coherent<GspMem>) -> u32 {
+ dma_read!(qs, .cpuq.rx.0.readPtr) % MSGQ_NUM_PAGES
+ }
+
+ pub(in crate::gsp) fn advance_cpu_read_ptr(qs: &Coherent<GspMem>, count: u32) {
+ let rptr = cpu_read_ptr(qs).wrapping_add(count) % MSGQ_NUM_PAGES;
+
+ // Ensure read pointer is properly ordered.
+ fence(Ordering::SeqCst);
+
+ dma_write!(qs, .cpuq.rx.0.readPtr, rptr);
+ }
+
+ pub(in crate::gsp) fn cpu_write_ptr(qs: &Coherent<GspMem>) -> u32 {
+ dma_read!(qs, .cpuq.tx.0.writePtr) % MSGQ_NUM_PAGES
+ }
+
+ pub(in crate::gsp) fn advance_cpu_write_ptr(qs: &Coherent<GspMem>, count: u32) {
+ let wptr = cpu_write_ptr(qs).wrapping_add(count) % MSGQ_NUM_PAGES;
+
+ dma_write!(qs, .cpuq.tx.0.writePtr, wptr);
+
+ // Ensure all command data is visible before triggering the GSP read.
+ fence(Ordering::SeqCst);
+ }
+}
+
+/// Maximum size of a single GSP message queue element in bytes.
+pub(crate) const GSP_MSG_QUEUE_ELEMENT_SIZE_MAX: usize =
+ num::u32_as_usize(bindings::GSP_MSG_QUEUE_ELEMENT_SIZE_MAX);
+
/// Empty type to group methods related to heap parameters for running the GSP firmware.
enum GspFwHeapParams {}
@@ -132,7 +189,9 @@ impl LibosParams {
/// Structure passed to the GSP bootloader, containing the framebuffer layout as well as the DMA
/// addresses of the GSP bootloader and firmware.
#[repr(transparent)]
-pub(crate) struct GspFwWprMeta(bindings::GspFwWprMeta);
+pub(crate) struct GspFwWprMeta {
+ inner: bindings::GspFwWprMeta,
+}
// SAFETY: Padding is explicit and does not contain uninitialized data.
unsafe impl AsBytes for GspFwWprMeta {}
@@ -145,10 +204,14 @@ type GspFwWprMetaBootResumeInfo = bindings::GspFwWprMeta__bindgen_ty_1;
type GspFwWprMetaBootInfo = bindings::GspFwWprMeta__bindgen_ty_1__bindgen_ty_1;
impl GspFwWprMeta {
- /// Fill in and return a `GspFwWprMeta` suitable for booting `gsp_firmware` using the
+ /// Returns an initializer for a `GspFwWprMeta` suitable for booting `gsp_firmware` using the
/// `fb_layout` layout.
- pub(crate) fn new(gsp_firmware: &GspFirmware, fb_layout: &FbLayout) -> Self {
- Self(bindings::GspFwWprMeta {
+ pub(crate) fn new<'a>(
+ gsp_firmware: &'a GspFirmware,
+ fb_layout: &'a FbLayout,
+ ) -> impl Init<Self> + 'a {
+ #[allow(non_snake_case)]
+ let init_inner = init!(bindings::GspFwWprMeta {
// CAST: we want to store the bits of `GSP_FW_WPR_META_MAGIC` unmodified.
magic: bindings::GSP_FW_WPR_META_MAGIC as u64,
revision: u64::from(bindings::GSP_FW_WPR_META_REVISION),
@@ -183,7 +246,11 @@ impl GspFwWprMeta {
fbSize: fb_layout.fb.end - fb_layout.fb.start,
vgaWorkspaceOffset: fb_layout.vga_workspace.start,
vgaWorkspaceSize: fb_layout.vga_workspace.end - fb_layout.vga_workspace.start,
- ..Default::default()
+ ..Zeroable::init_zeroed()
+ });
+
+ init!(GspFwWprMeta {
+ inner <- init_inner,
})
}
}
@@ -192,111 +259,81 @@ impl GspFwWprMeta {
#[repr(u32)]
pub(crate) enum MsgFunction {
// Common function codes
- Nop = bindings::NV_VGPU_MSG_FUNCTION_NOP,
- SetGuestSystemInfo = bindings::NV_VGPU_MSG_FUNCTION_SET_GUEST_SYSTEM_INFO,
- AllocRoot = bindings::NV_VGPU_MSG_FUNCTION_ALLOC_ROOT,
+ AllocChannelDma = bindings::NV_VGPU_MSG_FUNCTION_ALLOC_CHANNEL_DMA,
+ AllocCtxDma = bindings::NV_VGPU_MSG_FUNCTION_ALLOC_CTX_DMA,
AllocDevice = bindings::NV_VGPU_MSG_FUNCTION_ALLOC_DEVICE,
AllocMemory = bindings::NV_VGPU_MSG_FUNCTION_ALLOC_MEMORY,
- AllocCtxDma = bindings::NV_VGPU_MSG_FUNCTION_ALLOC_CTX_DMA,
- AllocChannelDma = bindings::NV_VGPU_MSG_FUNCTION_ALLOC_CHANNEL_DMA,
- MapMemory = bindings::NV_VGPU_MSG_FUNCTION_MAP_MEMORY,
- BindCtxDma = bindings::NV_VGPU_MSG_FUNCTION_BIND_CTX_DMA,
AllocObject = bindings::NV_VGPU_MSG_FUNCTION_ALLOC_OBJECT,
+ AllocRoot = bindings::NV_VGPU_MSG_FUNCTION_ALLOC_ROOT,
+ BindCtxDma = bindings::NV_VGPU_MSG_FUNCTION_BIND_CTX_DMA,
+ ContinuationRecord = bindings::NV_VGPU_MSG_FUNCTION_CONTINUATION_RECORD,
Free = bindings::NV_VGPU_MSG_FUNCTION_FREE,
- Log = bindings::NV_VGPU_MSG_FUNCTION_LOG,
GetGspStaticInfo = bindings::NV_VGPU_MSG_FUNCTION_GET_GSP_STATIC_INFO,
- SetRegistry = bindings::NV_VGPU_MSG_FUNCTION_SET_REGISTRY,
- GspSetSystemInfo = bindings::NV_VGPU_MSG_FUNCTION_GSP_SET_SYSTEM_INFO,
+ GetStaticInfo = bindings::NV_VGPU_MSG_FUNCTION_GET_STATIC_INFO,
GspInitPostObjGpu = bindings::NV_VGPU_MSG_FUNCTION_GSP_INIT_POST_OBJGPU,
GspRmControl = bindings::NV_VGPU_MSG_FUNCTION_GSP_RM_CONTROL,
- GetStaticInfo = bindings::NV_VGPU_MSG_FUNCTION_GET_STATIC_INFO,
+ GspSetSystemInfo = bindings::NV_VGPU_MSG_FUNCTION_GSP_SET_SYSTEM_INFO,
+ Log = bindings::NV_VGPU_MSG_FUNCTION_LOG,
+ MapMemory = bindings::NV_VGPU_MSG_FUNCTION_MAP_MEMORY,
+ Nop = bindings::NV_VGPU_MSG_FUNCTION_NOP,
+ SetGuestSystemInfo = bindings::NV_VGPU_MSG_FUNCTION_SET_GUEST_SYSTEM_INFO,
+ SetRegistry = bindings::NV_VGPU_MSG_FUNCTION_SET_REGISTRY,
// Event codes
GspInitDone = bindings::NV_VGPU_MSG_EVENT_GSP_INIT_DONE,
+ GspLockdownNotice = bindings::NV_VGPU_MSG_EVENT_GSP_LOCKDOWN_NOTICE,
+ GspPostNoCat = bindings::NV_VGPU_MSG_EVENT_GSP_POST_NOCAT_RECORD,
GspRunCpuSequencer = bindings::NV_VGPU_MSG_EVENT_GSP_RUN_CPU_SEQUENCER,
- PostEvent = bindings::NV_VGPU_MSG_EVENT_POST_EVENT,
- RcTriggered = bindings::NV_VGPU_MSG_EVENT_RC_TRIGGERED,
MmuFaultQueued = bindings::NV_VGPU_MSG_EVENT_MMU_FAULT_QUEUED,
OsErrorLog = bindings::NV_VGPU_MSG_EVENT_OS_ERROR_LOG,
- GspPostNoCat = bindings::NV_VGPU_MSG_EVENT_GSP_POST_NOCAT_RECORD,
- GspLockdownNotice = bindings::NV_VGPU_MSG_EVENT_GSP_LOCKDOWN_NOTICE,
+ PostEvent = bindings::NV_VGPU_MSG_EVENT_POST_EVENT,
+ RcTriggered = bindings::NV_VGPU_MSG_EVENT_RC_TRIGGERED,
UcodeLibOsPrint = bindings::NV_VGPU_MSG_EVENT_UCODE_LIBOS_PRINT,
}
-impl fmt::Display for MsgFunction {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
- // Common function codes
- MsgFunction::Nop => write!(f, "NOP"),
- MsgFunction::SetGuestSystemInfo => write!(f, "SET_GUEST_SYSTEM_INFO"),
- MsgFunction::AllocRoot => write!(f, "ALLOC_ROOT"),
- MsgFunction::AllocDevice => write!(f, "ALLOC_DEVICE"),
- MsgFunction::AllocMemory => write!(f, "ALLOC_MEMORY"),
- MsgFunction::AllocCtxDma => write!(f, "ALLOC_CTX_DMA"),
- MsgFunction::AllocChannelDma => write!(f, "ALLOC_CHANNEL_DMA"),
- MsgFunction::MapMemory => write!(f, "MAP_MEMORY"),
- MsgFunction::BindCtxDma => write!(f, "BIND_CTX_DMA"),
- MsgFunction::AllocObject => write!(f, "ALLOC_OBJECT"),
- MsgFunction::Free => write!(f, "FREE"),
- MsgFunction::Log => write!(f, "LOG"),
- MsgFunction::GetGspStaticInfo => write!(f, "GET_GSP_STATIC_INFO"),
- MsgFunction::SetRegistry => write!(f, "SET_REGISTRY"),
- MsgFunction::GspSetSystemInfo => write!(f, "GSP_SET_SYSTEM_INFO"),
- MsgFunction::GspInitPostObjGpu => write!(f, "GSP_INIT_POST_OBJGPU"),
- MsgFunction::GspRmControl => write!(f, "GSP_RM_CONTROL"),
- MsgFunction::GetStaticInfo => write!(f, "GET_STATIC_INFO"),
-
- // Event codes
- MsgFunction::GspInitDone => write!(f, "INIT_DONE"),
- MsgFunction::GspRunCpuSequencer => write!(f, "RUN_CPU_SEQUENCER"),
- MsgFunction::PostEvent => write!(f, "POST_EVENT"),
- MsgFunction::RcTriggered => write!(f, "RC_TRIGGERED"),
- MsgFunction::MmuFaultQueued => write!(f, "MMU_FAULT_QUEUED"),
- MsgFunction::OsErrorLog => write!(f, "OS_ERROR_LOG"),
- MsgFunction::GspPostNoCat => write!(f, "NOCAT"),
- MsgFunction::GspLockdownNotice => write!(f, "LOCKDOWN_NOTICE"),
- MsgFunction::UcodeLibOsPrint => write!(f, "LIBOS_PRINT"),
- }
- }
-}
-
impl TryFrom<u32> for MsgFunction {
type Error = kernel::error::Error;
fn try_from(value: u32) -> Result<MsgFunction> {
match value {
- bindings::NV_VGPU_MSG_FUNCTION_NOP => Ok(MsgFunction::Nop),
- bindings::NV_VGPU_MSG_FUNCTION_SET_GUEST_SYSTEM_INFO => {
- Ok(MsgFunction::SetGuestSystemInfo)
- }
- bindings::NV_VGPU_MSG_FUNCTION_ALLOC_ROOT => Ok(MsgFunction::AllocRoot),
+ // Common function codes
+ bindings::NV_VGPU_MSG_FUNCTION_ALLOC_CHANNEL_DMA => Ok(MsgFunction::AllocChannelDma),
+ bindings::NV_VGPU_MSG_FUNCTION_ALLOC_CTX_DMA => Ok(MsgFunction::AllocCtxDma),
bindings::NV_VGPU_MSG_FUNCTION_ALLOC_DEVICE => Ok(MsgFunction::AllocDevice),
bindings::NV_VGPU_MSG_FUNCTION_ALLOC_MEMORY => Ok(MsgFunction::AllocMemory),
- bindings::NV_VGPU_MSG_FUNCTION_ALLOC_CTX_DMA => Ok(MsgFunction::AllocCtxDma),
- bindings::NV_VGPU_MSG_FUNCTION_ALLOC_CHANNEL_DMA => Ok(MsgFunction::AllocChannelDma),
- bindings::NV_VGPU_MSG_FUNCTION_MAP_MEMORY => Ok(MsgFunction::MapMemory),
- bindings::NV_VGPU_MSG_FUNCTION_BIND_CTX_DMA => Ok(MsgFunction::BindCtxDma),
bindings::NV_VGPU_MSG_FUNCTION_ALLOC_OBJECT => Ok(MsgFunction::AllocObject),
+ bindings::NV_VGPU_MSG_FUNCTION_ALLOC_ROOT => Ok(MsgFunction::AllocRoot),
+ bindings::NV_VGPU_MSG_FUNCTION_BIND_CTX_DMA => Ok(MsgFunction::BindCtxDma),
+ bindings::NV_VGPU_MSG_FUNCTION_CONTINUATION_RECORD => {
+ Ok(MsgFunction::ContinuationRecord)
+ }
bindings::NV_VGPU_MSG_FUNCTION_FREE => Ok(MsgFunction::Free),
- bindings::NV_VGPU_MSG_FUNCTION_LOG => Ok(MsgFunction::Log),
bindings::NV_VGPU_MSG_FUNCTION_GET_GSP_STATIC_INFO => Ok(MsgFunction::GetGspStaticInfo),
- bindings::NV_VGPU_MSG_FUNCTION_SET_REGISTRY => Ok(MsgFunction::SetRegistry),
- bindings::NV_VGPU_MSG_FUNCTION_GSP_SET_SYSTEM_INFO => Ok(MsgFunction::GspSetSystemInfo),
+ bindings::NV_VGPU_MSG_FUNCTION_GET_STATIC_INFO => Ok(MsgFunction::GetStaticInfo),
bindings::NV_VGPU_MSG_FUNCTION_GSP_INIT_POST_OBJGPU => {
Ok(MsgFunction::GspInitPostObjGpu)
}
bindings::NV_VGPU_MSG_FUNCTION_GSP_RM_CONTROL => Ok(MsgFunction::GspRmControl),
- bindings::NV_VGPU_MSG_FUNCTION_GET_STATIC_INFO => Ok(MsgFunction::GetStaticInfo),
+ bindings::NV_VGPU_MSG_FUNCTION_GSP_SET_SYSTEM_INFO => Ok(MsgFunction::GspSetSystemInfo),
+ bindings::NV_VGPU_MSG_FUNCTION_LOG => Ok(MsgFunction::Log),
+ bindings::NV_VGPU_MSG_FUNCTION_MAP_MEMORY => Ok(MsgFunction::MapMemory),
+ bindings::NV_VGPU_MSG_FUNCTION_NOP => Ok(MsgFunction::Nop),
+ bindings::NV_VGPU_MSG_FUNCTION_SET_GUEST_SYSTEM_INFO => {
+ Ok(MsgFunction::SetGuestSystemInfo)
+ }
+ bindings::NV_VGPU_MSG_FUNCTION_SET_REGISTRY => Ok(MsgFunction::SetRegistry),
+
+ // Event codes
bindings::NV_VGPU_MSG_EVENT_GSP_INIT_DONE => Ok(MsgFunction::GspInitDone),
+ bindings::NV_VGPU_MSG_EVENT_GSP_LOCKDOWN_NOTICE => Ok(MsgFunction::GspLockdownNotice),
+ bindings::NV_VGPU_MSG_EVENT_GSP_POST_NOCAT_RECORD => Ok(MsgFunction::GspPostNoCat),
bindings::NV_VGPU_MSG_EVENT_GSP_RUN_CPU_SEQUENCER => {
Ok(MsgFunction::GspRunCpuSequencer)
}
- bindings::NV_VGPU_MSG_EVENT_POST_EVENT => Ok(MsgFunction::PostEvent),
- bindings::NV_VGPU_MSG_EVENT_RC_TRIGGERED => Ok(MsgFunction::RcTriggered),
bindings::NV_VGPU_MSG_EVENT_MMU_FAULT_QUEUED => Ok(MsgFunction::MmuFaultQueued),
bindings::NV_VGPU_MSG_EVENT_OS_ERROR_LOG => Ok(MsgFunction::OsErrorLog),
- bindings::NV_VGPU_MSG_EVENT_GSP_POST_NOCAT_RECORD => Ok(MsgFunction::GspPostNoCat),
- bindings::NV_VGPU_MSG_EVENT_GSP_LOCKDOWN_NOTICE => Ok(MsgFunction::GspLockdownNotice),
+ bindings::NV_VGPU_MSG_EVENT_POST_EVENT => Ok(MsgFunction::PostEvent),
+ bindings::NV_VGPU_MSG_EVENT_RC_TRIGGERED => Ok(MsgFunction::RcTriggered),
bindings::NV_VGPU_MSG_EVENT_UCODE_LIBOS_PRINT => Ok(MsgFunction::UcodeLibOsPrint),
_ => Err(EINVAL),
}
@@ -330,22 +367,6 @@ pub(crate) enum SeqBufOpcode {
RegWrite = bindings::GSP_SEQ_BUF_OPCODE_GSP_SEQ_BUF_OPCODE_REG_WRITE,
}
-impl fmt::Display for SeqBufOpcode {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
- SeqBufOpcode::CoreReset => write!(f, "CORE_RESET"),
- SeqBufOpcode::CoreResume => write!(f, "CORE_RESUME"),
- SeqBufOpcode::CoreStart => write!(f, "CORE_START"),
- SeqBufOpcode::CoreWaitForHalt => write!(f, "CORE_WAIT_FOR_HALT"),
- SeqBufOpcode::DelayUs => write!(f, "DELAY_US"),
- SeqBufOpcode::RegModify => write!(f, "REG_MODIFY"),
- SeqBufOpcode::RegPoll => write!(f, "REG_POLL"),
- SeqBufOpcode::RegStore => write!(f, "REG_STORE"),
- SeqBufOpcode::RegWrite => write!(f, "REG_WRITE"),
- }
- }
-}
-
impl TryFrom<u32> for SeqBufOpcode {
type Error = kernel::error::Error;
@@ -384,7 +405,7 @@ impl From<SeqBufOpcode> for u32 {
/// Wrapper for GSP sequencer register write payload.
#[repr(transparent)]
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug)]
pub(crate) struct RegWritePayload(bindings::GSP_SEQ_BUF_PAYLOAD_REG_WRITE);
impl RegWritePayload {
@@ -407,7 +428,7 @@ unsafe impl AsBytes for RegWritePayload {}
/// Wrapper for GSP sequencer register modify payload.
#[repr(transparent)]
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug)]
pub(crate) struct RegModifyPayload(bindings::GSP_SEQ_BUF_PAYLOAD_REG_MODIFY);
impl RegModifyPayload {
@@ -435,7 +456,7 @@ unsafe impl AsBytes for RegModifyPayload {}
/// Wrapper for GSP sequencer register poll payload.
#[repr(transparent)]
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug)]
pub(crate) struct RegPollPayload(bindings::GSP_SEQ_BUF_PAYLOAD_REG_POLL);
impl RegPollPayload {
@@ -468,7 +489,7 @@ unsafe impl AsBytes for RegPollPayload {}
/// Wrapper for GSP sequencer delay payload.
#[repr(transparent)]
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug)]
pub(crate) struct DelayUsPayload(bindings::GSP_SEQ_BUF_PAYLOAD_DELAY_US);
impl DelayUsPayload {
@@ -486,7 +507,7 @@ unsafe impl AsBytes for DelayUsPayload {}
/// Wrapper for GSP sequencer register store payload.
#[repr(transparent)]
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug)]
pub(crate) struct RegStorePayload(bindings::GSP_SEQ_BUF_PAYLOAD_REG_STORE);
impl RegStorePayload {
@@ -526,13 +547,7 @@ impl SequencerBufferCmd {
return Err(EINVAL);
}
// SAFETY: Opcode is verified to be `RegWrite`, so union contains valid `RegWritePayload`.
- let payload_bytes = unsafe {
- core::slice::from_raw_parts(
- core::ptr::addr_of!(self.0.payload.regWrite).cast::<u8>(),
- core::mem::size_of::<RegWritePayload>(),
- )
- };
- Ok(*RegWritePayload::from_bytes(payload_bytes).ok_or(EINVAL)?)
+ Ok(RegWritePayload(unsafe { self.0.payload.regWrite }))
}
/// Returns the register modify payload by value.
@@ -543,13 +558,7 @@ impl SequencerBufferCmd {
return Err(EINVAL);
}
// SAFETY: Opcode is verified to be `RegModify`, so union contains valid `RegModifyPayload`.
- let payload_bytes = unsafe {
- core::slice::from_raw_parts(
- core::ptr::addr_of!(self.0.payload.regModify).cast::<u8>(),
- core::mem::size_of::<RegModifyPayload>(),
- )
- };
- Ok(*RegModifyPayload::from_bytes(payload_bytes).ok_or(EINVAL)?)
+ Ok(RegModifyPayload(unsafe { self.0.payload.regModify }))
}
/// Returns the register poll payload by value.
@@ -560,13 +569,7 @@ impl SequencerBufferCmd {
return Err(EINVAL);
}
// SAFETY: Opcode is verified to be `RegPoll`, so union contains valid `RegPollPayload`.
- let payload_bytes = unsafe {
- core::slice::from_raw_parts(
- core::ptr::addr_of!(self.0.payload.regPoll).cast::<u8>(),
- core::mem::size_of::<RegPollPayload>(),
- )
- };
- Ok(*RegPollPayload::from_bytes(payload_bytes).ok_or(EINVAL)?)
+ Ok(RegPollPayload(unsafe { self.0.payload.regPoll }))
}
/// Returns the delay payload by value.
@@ -577,13 +580,7 @@ impl SequencerBufferCmd {
return Err(EINVAL);
}
// SAFETY: Opcode is verified to be `DelayUs`, so union contains valid `DelayUsPayload`.
- let payload_bytes = unsafe {
- core::slice::from_raw_parts(
- core::ptr::addr_of!(self.0.payload.delayUs).cast::<u8>(),
- core::mem::size_of::<DelayUsPayload>(),
- )
- };
- Ok(*DelayUsPayload::from_bytes(payload_bytes).ok_or(EINVAL)?)
+ Ok(DelayUsPayload(unsafe { self.0.payload.delayUs }))
}
/// Returns the register store payload by value.
@@ -594,13 +591,7 @@ impl SequencerBufferCmd {
return Err(EINVAL);
}
// SAFETY: Opcode is verified to be `RegStore`, so union contains valid `RegStorePayload`.
- let payload_bytes = unsafe {
- core::slice::from_raw_parts(
- core::ptr::addr_of!(self.0.payload.regStore).cast::<u8>(),
- core::mem::size_of::<RegStorePayload>(),
- )
- };
- Ok(*RegStorePayload::from_bytes(payload_bytes).ok_or(EINVAL)?)
+ Ok(RegStorePayload(unsafe { self.0.payload.regStore }))
}
}
@@ -642,7 +633,9 @@ unsafe impl AsBytes for RunCpuSequencer {}
/// The memory allocated for the arguments must remain until the GSP sends the
/// init_done RPC.
#[repr(transparent)]
-pub(crate) struct LibosMemoryRegionInitArgument(bindings::LibosMemoryRegionInitArgument);
+pub(crate) struct LibosMemoryRegionInitArgument {
+ inner: bindings::LibosMemoryRegionInitArgument,
+}
// SAFETY: Padding is explicit and does not contain uninitialized data.
unsafe impl AsBytes for LibosMemoryRegionInitArgument {}
@@ -652,10 +645,10 @@ unsafe impl AsBytes for LibosMemoryRegionInitArgument {}
unsafe impl FromBytes for LibosMemoryRegionInitArgument {}
impl LibosMemoryRegionInitArgument {
- pub(crate) fn new<A: AsBytes + FromBytes>(
+ pub(crate) fn new<'a, A: AsBytes + FromBytes + KnownSize + ?Sized>(
name: &'static str,
- obj: &CoherentAllocation<A>,
- ) -> Self {
+ obj: &'a Coherent<A>,
+ ) -> impl Init<Self> + 'a {
/// Generates the `ID8` identifier required for some GSP objects.
fn id8(name: &str) -> u64 {
let mut bytes = [0u8; core::mem::size_of::<u64>()];
@@ -667,7 +660,8 @@ impl LibosMemoryRegionInitArgument {
u64::from_ne_bytes(bytes)
}
- Self(bindings::LibosMemoryRegionInitArgument {
+ #[allow(non_snake_case)]
+ let init_inner = init!(bindings::LibosMemoryRegionInitArgument {
id8: id8(name),
pa: obj.dma_handle(),
size: num::usize_as_u64(obj.size()),
@@ -677,7 +671,11 @@ impl LibosMemoryRegionInitArgument {
loc: num::u32_into_u8::<
{ bindings::LibosMemoryRegionLoc_LIBOS_MEMORY_REGION_LOC_SYSMEM },
>(),
- ..Default::default()
+ ..Zeroable::init_zeroed()
+ });
+
+ init!(LibosMemoryRegionInitArgument {
+ inner <- init_inner,
})
}
}
@@ -708,22 +706,6 @@ impl MsgqTxHeader {
entryOff: num::usize_into_u32::<GSP_PAGE_SIZE>(),
})
}
-
- /// Returns the value of the write pointer for this queue.
- pub(crate) fn write_ptr(&self) -> u32 {
- let ptr = core::ptr::from_ref(&self.0.writePtr);
-
- // SAFETY: `ptr` is a valid pointer to a `u32`.
- unsafe { ptr.read_volatile() }
- }
-
- /// Sets the value of the write pointer for this queue.
- pub(crate) fn set_write_ptr(&mut self, val: u32) {
- let ptr = core::ptr::from_mut(&mut self.0.writePtr);
-
- // SAFETY: `ptr` is a valid pointer to a `u32`.
- unsafe { ptr.write_volatile(val) }
- }
}
// SAFETY: Padding is explicit and does not contain uninitialized data.
@@ -739,22 +721,6 @@ impl MsgqRxHeader {
pub(crate) fn new() -> Self {
Self(Default::default())
}
-
- /// Returns the value of the read pointer for this queue.
- pub(crate) fn read_ptr(&self) -> u32 {
- let ptr = core::ptr::from_ref(&self.0.readPtr);
-
- // SAFETY: `ptr` is a valid pointer to a `u32`.
- unsafe { ptr.read_volatile() }
- }
-
- /// Sets the value of the read pointer for this queue.
- pub(crate) fn set_read_ptr(&mut self, val: u32) {
- let ptr = core::ptr::from_mut(&mut self.0.readPtr);
-
- // SAFETY: `ptr` is a valid pointer to a `u32`.
- unsafe { ptr.write_volatile(val) }
- }
}
// SAFETY: Padding is explicit and does not contain uninitialized data.
@@ -888,15 +854,23 @@ unsafe impl FromBytes for GspMsgElement {}
/// Arguments for GSP startup.
#[repr(transparent)]
-pub(crate) struct GspArgumentsCached(bindings::GSP_ARGUMENTS_CACHED);
+#[derive(Zeroable)]
+pub(crate) struct GspArgumentsCached {
+ inner: bindings::GSP_ARGUMENTS_CACHED,
+}
impl GspArgumentsCached {
/// Creates the arguments for starting the GSP up using `cmdq` as its command queue.
- pub(crate) fn new(cmdq: &Cmdq) -> Self {
- Self(bindings::GSP_ARGUMENTS_CACHED {
- messageQueueInitArguments: MessageQueueInitArguments::new(cmdq).0,
+ pub(crate) fn new(cmdq: &Cmdq) -> impl Init<Self> + '_ {
+ #[allow(non_snake_case)]
+ let init_inner = init!(bindings::GSP_ARGUMENTS_CACHED {
+ messageQueueInitArguments <- MessageQueueInitArguments::new(cmdq),
bDmemStack: 1,
- ..Default::default()
+ ..Zeroable::init_zeroed()
+ });
+
+ init!(GspArgumentsCached {
+ inner <- init_inner,
})
}
}
@@ -908,11 +882,21 @@ unsafe impl AsBytes for GspArgumentsCached {}
/// must all be a multiple of GSP_PAGE_SIZE in size, so add padding to force it
/// to that size.
#[repr(C)]
+#[derive(Zeroable)]
pub(crate) struct GspArgumentsPadded {
pub(crate) inner: GspArgumentsCached,
_padding: [u8; GSP_PAGE_SIZE - core::mem::size_of::<bindings::GSP_ARGUMENTS_CACHED>()],
}
+impl GspArgumentsPadded {
+ pub(crate) fn new(cmdq: &Cmdq) -> impl Init<Self> + '_ {
+ init!(GspArgumentsPadded {
+ inner <- GspArgumentsCached::new(cmdq),
+ ..Zeroable::init_zeroed()
+ })
+ }
+}
+
// SAFETY: Padding is explicit and will not contain uninitialized data.
unsafe impl AsBytes for GspArgumentsPadded {}
@@ -921,18 +905,18 @@ unsafe impl AsBytes for GspArgumentsPadded {}
unsafe impl FromBytes for GspArgumentsPadded {}
/// Init arguments for the message queue.
-#[repr(transparent)]
-struct MessageQueueInitArguments(bindings::MESSAGE_QUEUE_INIT_ARGUMENTS);
+type MessageQueueInitArguments = bindings::MESSAGE_QUEUE_INIT_ARGUMENTS;
impl MessageQueueInitArguments {
/// Creates a new init arguments structure for `cmdq`.
- fn new(cmdq: &Cmdq) -> Self {
- Self(bindings::MESSAGE_QUEUE_INIT_ARGUMENTS {
- sharedMemPhysAddr: cmdq.dma_handle(),
+ #[allow(non_snake_case)]
+ fn new(cmdq: &Cmdq) -> impl Init<Self> + '_ {
+ init!(MessageQueueInitArguments {
+ sharedMemPhysAddr: cmdq.dma_handle,
pageTableEntryCount: num::usize_into_u32::<{ Cmdq::NUM_PTES }>(),
cmdQueueOffset: num::usize_as_u64(Cmdq::CMDQ_OFFSET),
statQueueOffset: num::usize_as_u64(Cmdq::STATQ_OFFSET),
- ..Default::default()
+ ..Zeroable::init_zeroed()
})
}
}
diff --git a/drivers/gpu/nova-core/gsp/fw/commands.rs b/drivers/gpu/nova-core/gsp/fw/commands.rs
index 21be44199693..db46276430be 100644
--- a/drivers/gpu/nova-core/gsp/fw/commands.rs
+++ b/drivers/gpu/nova-core/gsp/fw/commands.rs
@@ -1,8 +1,14 @@
// SPDX-License-Identifier: GPL-2.0
-use kernel::prelude::*;
-use kernel::transmute::{AsBytes, FromBytes};
-use kernel::{device, pci};
+use kernel::{
+ device,
+ pci,
+ prelude::*,
+ transmute::{
+ AsBytes,
+ FromBytes, //
+ }, //
+};
use crate::gsp::GSP_PAGE_SIZE;
@@ -107,6 +113,7 @@ unsafe impl FromBytes for PackedRegistryTable {}
/// Payload of the `GetGspStaticInfo` command and message.
#[repr(transparent)]
+#[derive(Zeroable)]
pub(crate) struct GspStaticConfigInfo(bindings::GspStaticConfigInfo_t);
impl GspStaticConfigInfo {
@@ -122,7 +129,3 @@ unsafe impl AsBytes for GspStaticConfigInfo {}
// SAFETY: This struct only contains integer types for which all bit patterns
// are valid.
unsafe impl FromBytes for GspStaticConfigInfo {}
-
-// SAFETY: This struct only contains integer types and fixed-size arrays for which
-// all bit patterns are valid.
-unsafe impl Zeroable for GspStaticConfigInfo {}
diff --git a/drivers/gpu/nova-core/gsp/fw/r570_144/bindings.rs b/drivers/gpu/nova-core/gsp/fw/r570_144/bindings.rs
index 6d25fe0bffa9..334e8be5fde8 100644
--- a/drivers/gpu/nova-core/gsp/fw/r570_144/bindings.rs
+++ b/drivers/gpu/nova-core/gsp/fw/r570_144/bindings.rs
@@ -43,6 +43,7 @@ pub const GSP_FW_HEAP_SIZE_OVERRIDE_LIBOS3_BAREMETAL_MAX_MB: u32 = 280;
pub const GSP_FW_WPR_META_REVISION: u32 = 1;
pub const GSP_FW_WPR_META_MAGIC: i64 = -2577556379034558285;
pub const REGISTRY_TABLE_ENTRY_TYPE_DWORD: u32 = 1;
+pub const GSP_MSG_QUEUE_ELEMENT_SIZE_MAX: u32 = 65536;
pub type __u8 = ffi::c_uchar;
pub type __u16 = ffi::c_ushort;
pub type __u32 = ffi::c_uint;
diff --git a/drivers/gpu/nova-core/gsp/sequencer.rs b/drivers/gpu/nova-core/gsp/sequencer.rs
index e415a2aa3203..474e4c8021db 100644
--- a/drivers/gpu/nova-core/gsp/sequencer.rs
+++ b/drivers/gpu/nova-core/gsp/sequencer.rs
@@ -67,6 +67,7 @@ const CMD_SIZE: usize = size_of::<fw::SequencerBufferCmd>();
/// GSP Sequencer Command types with payload data.
/// Commands have an opcode and an opcode-dependent struct.
#[allow(clippy::enum_variant_names)]
+#[derive(Debug)]
pub(crate) enum GspSeqCmd {
RegWrite(fw::RegWritePayload),
RegModify(fw::RegModifyPayload),
@@ -144,12 +145,7 @@ pub(crate) struct GspSequencer<'a> {
dev: ARef<device::Device>,
}
-/// Trait for running sequencer commands.
-pub(crate) trait GspSeqCmdRunner {
- fn run(&self, sequencer: &GspSequencer<'_>) -> Result;
-}
-
-impl GspSeqCmdRunner for fw::RegWritePayload {
+impl fw::RegWritePayload {
fn run(&self, sequencer: &GspSequencer<'_>) -> Result {
let addr = usize::from_safe_cast(self.addr());
@@ -157,7 +153,7 @@ impl GspSeqCmdRunner for fw::RegWritePayload {
}
}
-impl GspSeqCmdRunner for fw::RegModifyPayload {
+impl fw::RegModifyPayload {
fn run(&self, sequencer: &GspSequencer<'_>) -> Result {
let addr = usize::from_safe_cast(self.addr());
@@ -169,7 +165,7 @@ impl GspSeqCmdRunner for fw::RegModifyPayload {
}
}
-impl GspSeqCmdRunner for fw::RegPollPayload {
+impl fw::RegPollPayload {
fn run(&self, sequencer: &GspSequencer<'_>) -> Result {
let addr = usize::from_safe_cast(self.addr());
@@ -194,14 +190,14 @@ impl GspSeqCmdRunner for fw::RegPollPayload {
}
}
-impl GspSeqCmdRunner for fw::DelayUsPayload {
+impl fw::DelayUsPayload {
fn run(&self, _sequencer: &GspSequencer<'_>) -> Result {
fsleep(Delta::from_micros(i64::from(self.val())));
Ok(())
}
}
-impl GspSeqCmdRunner for fw::RegStorePayload {
+impl fw::RegStorePayload {
fn run(&self, sequencer: &GspSequencer<'_>) -> Result {
let addr = usize::from_safe_cast(self.addr());
@@ -209,7 +205,7 @@ impl GspSeqCmdRunner for fw::RegStorePayload {
}
}
-impl GspSeqCmdRunner for GspSeqCmd {
+impl GspSeqCmd {
fn run(&self, seq: &GspSequencer<'_>) -> Result {
match self {
GspSeqCmd::RegWrite(cmd) => cmd.run(seq),
@@ -360,9 +356,9 @@ pub(crate) struct GspSequencerParams<'a> {
}
impl<'a> GspSequencer<'a> {
- pub(crate) fn run(cmdq: &mut Cmdq, params: GspSequencerParams<'a>) -> Result {
+ pub(crate) fn run(cmdq: &Cmdq, params: GspSequencerParams<'a>) -> Result {
let seq_info = loop {
- match cmdq.receive_msg::<GspSequence>(Delta::from_secs(10)) {
+ match cmdq.receive_msg::<GspSequence>(Cmdq::RECEIVE_TIMEOUT) {
Ok(seq_info) => break seq_info,
Err(ERANGE) => continue,
Err(e) => return Err(e),
diff --git a/drivers/gpu/nova-core/nova_core.rs b/drivers/gpu/nova-core/nova_core.rs
index c1121e7c64c5..04a1fa6b25f8 100644
--- a/drivers/gpu/nova-core/nova_core.rs
+++ b/drivers/gpu/nova-core/nova_core.rs
@@ -2,10 +2,17 @@
//! Nova Core GPU Driver
+use kernel::{
+ debugfs,
+ driver::Registration,
+ pci,
+ prelude::*,
+ InPlaceModule, //
+};
+
#[macro_use]
mod bitfield;
-mod dma;
mod driver;
mod falcon;
mod fb;
@@ -13,15 +20,54 @@ mod firmware;
mod gfw;
mod gpu;
mod gsp;
+#[macro_use]
mod num;
mod regs;
mod sbuffer;
mod vbios;
-pub(crate) const MODULE_NAME: &kernel::str::CStr = <LocalModule as kernel::ModuleMetadata>::NAME;
+pub(crate) const MODULE_NAME: &core::ffi::CStr = <LocalModule as kernel::ModuleMetadata>::NAME;
+
+// TODO: Move this into per-module data once that exists.
+static mut DEBUGFS_ROOT: Option<debugfs::Dir> = None;
+
+/// Guard that clears `DEBUGFS_ROOT` when dropped.
+struct DebugfsRootGuard;
+
+impl Drop for DebugfsRootGuard {
+ fn drop(&mut self) {
+ // SAFETY: This guard is dropped after `_driver` (due to field order),
+ // so the driver is unregistered and no probe() can be running.
+ unsafe { DEBUGFS_ROOT = None };
+ }
+}
+
+#[pin_data]
+struct NovaCoreModule {
+ // Fields are dropped in declaration order, so `_driver` is dropped first,
+ // then `_debugfs_guard` clears `DEBUGFS_ROOT`.
+ #[pin]
+ _driver: Registration<pci::Adapter<driver::NovaCore>>,
+ _debugfs_guard: DebugfsRootGuard,
+}
+
+impl InPlaceModule for NovaCoreModule {
+ fn init(module: &'static kernel::ThisModule) -> impl PinInit<Self, Error> {
+ let dir = debugfs::Dir::new(kernel::c_str!("nova_core"));
+
+ // SAFETY: We are the only driver code running during init, so there
+ // cannot be any concurrent access to `DEBUGFS_ROOT`.
+ unsafe { DEBUGFS_ROOT = Some(dir) };
+
+ try_pin_init!(Self {
+ _driver <- Registration::new(MODULE_NAME, module),
+ _debugfs_guard: DebugfsRootGuard,
+ })
+ }
+}
-kernel::module_pci_driver! {
- type: driver::NovaCore,
+module! {
+ type: NovaCoreModule,
name: "NovaCore",
authors: ["Danilo Krummrich"],
description: "Nova Core GPU driver",
diff --git a/drivers/gpu/nova-core/num.rs b/drivers/gpu/nova-core/num.rs
index c952a834e662..6c824b8d7b97 100644
--- a/drivers/gpu/nova-core/num.rs
+++ b/drivers/gpu/nova-core/num.rs
@@ -215,3 +215,83 @@ impl_const_into!(usize => { u8, u16, u32 });
impl_const_into!(u64 => { u8, u16, u32 });
impl_const_into!(u32 => { u8, u16 });
impl_const_into!(u16 => { u8 });
+
+/// Creates an enum type associated to a [`Bounded`](kernel::num::Bounded), with a [`From`]
+/// conversion to the associated `Bounded` and either a [`TryFrom`] or `From` conversion from the
+/// associated `Bounded`.
+// TODO[FPRI]: This is a temporary solution to be replaced with the corresponding derive macros
+// once they land.
+#[macro_export]
+macro_rules! bounded_enum {
+ (
+ $(#[$enum_meta:meta])*
+ $vis:vis enum $enum_type:ident with $from_impl:ident<Bounded<$width:ty, $length:literal>> {
+ $( $(#[doc = $variant_doc:expr])* $variant:ident = $value:expr),* $(,)*
+ }
+ ) => {
+ $(#[$enum_meta])*
+ $vis enum $enum_type {
+ $(
+ $(#[doc = $variant_doc])*
+ $variant = $value
+ ),*
+ }
+
+ impl core::convert::From<$enum_type> for kernel::num::Bounded<$width, $length> {
+ fn from(value: $enum_type) -> Self {
+ match value {
+ $($enum_type::$variant =>
+ kernel::num::Bounded::<$width, _>::new::<{ $value }>()),*
+ }
+ }
+ }
+
+ bounded_enum!(@impl_from $enum_type with $from_impl<Bounded<$width, $length>> {
+ $($variant = $value),*
+ });
+ };
+
+ // `TryFrom` implementation from associated `Bounded` to enum type.
+ (@impl_from $enum_type:ident with TryFrom<Bounded<$width:ty, $length:literal>> {
+ $($variant:ident = $value:expr),* $(,)*
+ }) => {
+ impl core::convert::TryFrom<kernel::num::Bounded<$width, $length>> for $enum_type {
+ type Error = kernel::error::Error;
+
+ fn try_from(
+ value: kernel::num::Bounded<$width, $length>
+ ) -> kernel::error::Result<Self> {
+ match value.get() {
+ $(
+ $value => Ok($enum_type::$variant),
+ )*
+ _ => Err(kernel::error::code::EINVAL),
+ }
+ }
+ }
+ };
+
+ // `From` implementation from associated `Bounded` to enum type. Triggers a build-time error if
+ // all possible values of the `Bounded` are not covered by the enum type.
+ (@impl_from $enum_type:ident with From<Bounded<$width:ty, $length:literal>> {
+ $($variant:ident = $value:expr),* $(,)*
+ }) => {
+ impl core::convert::From<kernel::num::Bounded<$width, $length>> for $enum_type {
+ fn from(value: kernel::num::Bounded<$width, $length>) -> Self {
+ const MAX: $width = 1 << $length;
+
+ // Makes the compiler optimizer aware of the possible range of values.
+ let value = value.get() & ((1 << $length) - 1);
+ match value {
+ $(
+ $value => $enum_type::$variant,
+ )*
+ // PANIC: we cannot reach this arm as all possible variants are handled by the
+ // match arms above. It is here to make the compiler complain if `$enum_type`
+ // does not cover all values of the `0..MAX` range.
+ MAX.. => unreachable!(),
+ }
+ }
+ }
+ }
+}
diff --git a/drivers/gpu/nova-core/regs.rs b/drivers/gpu/nova-core/regs.rs
index ea0d32f5396c..2f171a4ff9ba 100644
--- a/drivers/gpu/nova-core/regs.rs
+++ b/drivers/gpu/nova-core/regs.rs
@@ -1,13 +1,11 @@
// SPDX-License-Identifier: GPL-2.0
-// Required to retain the original register names used by OpenRM, which are all capital snake case
-// but are mapped to types.
-#![allow(non_camel_case_types)]
-
-#[macro_use]
-pub(crate) mod macros;
-
use kernel::{
+ io::{
+ register,
+ register::WithBase,
+ Io, //
+ },
prelude::*,
time, //
};
@@ -37,18 +35,38 @@ use crate::{
// PMC
-register!(NV_PMC_BOOT_0 @ 0x00000000, "Basic revision information about the GPU" {
- 3:0 minor_revision as u8, "Minor revision of the chip";
- 7:4 major_revision as u8, "Major revision of the chip";
- 8:8 architecture_1 as u8, "MSB of the architecture";
- 23:20 implementation as u8, "Implementation version of the architecture";
- 28:24 architecture_0 as u8, "Lower bits of the architecture";
-});
+register! {
+ /// Basic revision information about the GPU.
+ pub(crate) NV_PMC_BOOT_0(u32) @ 0x00000000 {
+ /// Lower bits of the architecture.
+ 28:24 architecture_0;
+ /// Implementation version of the architecture.
+ 23:20 implementation;
+ /// MSB of the architecture.
+ 8:8 architecture_1;
+ /// Major revision of the chip.
+ 7:4 major_revision;
+ /// Minor revision of the chip.
+ 3:0 minor_revision;
+ }
+
+ /// Extended architecture information.
+ pub(crate) NV_PMC_BOOT_42(u32) @ 0x00000a00 {
+ /// Architecture value.
+ 29:24 architecture ?=> Architecture;
+ /// Implementation version of the architecture.
+ 23:20 implementation;
+ /// Major revision of the chip.
+ 19:16 major_revision;
+ /// Minor revision of the chip.
+ 15:12 minor_revision;
+ }
+}
impl NV_PMC_BOOT_0 {
pub(crate) fn is_older_than_fermi(self) -> bool {
// From https://github.com/NVIDIA/open-gpu-doc/tree/master/manuals :
- const NV_PMC_BOOT_0_ARCHITECTURE_GF100: u8 = 0xc;
+ const NV_PMC_BOOT_0_ARCHITECTURE_GF100: u32 = 0xc;
// Older chips left arch1 zeroed out. That, combined with an arch0 value that is less than
// GF100, means "older than Fermi".
@@ -56,13 +74,6 @@ impl NV_PMC_BOOT_0 {
}
}
-register!(NV_PMC_BOOT_42 @ 0x00000a00, "Extended architecture information" {
- 15:12 minor_revision as u8, "Minor revision of the chip";
- 19:16 major_revision as u8, "Major revision of the chip";
- 23:20 implementation as u8, "Implementation version of the architecture";
- 29:24 architecture as u8 ?=> Architecture, "Architecture value";
-});
-
impl NV_PMC_BOOT_42 {
/// Combines `architecture` and `implementation` to obtain a code unique to the chipset.
pub(crate) fn chipset(self) -> Result<Chipset> {
@@ -76,8 +87,8 @@ impl NV_PMC_BOOT_42 {
/// Returns the raw architecture value from the register.
fn architecture_raw(self) -> u8 {
- ((self.0 >> Self::ARCHITECTURE_RANGE.start()) & ((1 << Self::ARCHITECTURE_RANGE.len()) - 1))
- as u8
+ ((self.into_raw() >> Self::ARCHITECTURE_RANGE.start())
+ & ((1 << Self::ARCHITECTURE_RANGE.len()) - 1)) as u8
}
}
@@ -86,7 +97,7 @@ impl kernel::fmt::Display for NV_PMC_BOOT_42 {
write!(
f,
"boot42 = 0x{:08x} (architecture 0x{:x}, implementation 0x{:x})",
- self.0,
+ self.inner,
self.architecture_raw(),
self.implementation()
)
@@ -95,35 +106,46 @@ impl kernel::fmt::Display for NV_PMC_BOOT_42 {
// PBUS
-register!(NV_PBUS_SW_SCRATCH @ 0x00001400[64] {});
+register! {
+ pub(crate) NV_PBUS_SW_SCRATCH(u32)[64] @ 0x00001400 {}
-register!(NV_PBUS_SW_SCRATCH_0E_FRTS_ERR => NV_PBUS_SW_SCRATCH[0xe],
- "scratch register 0xe used as FRTS firmware error code" {
- 31:16 frts_err_code as u16;
-});
+ /// Scratch register 0xe used as FRTS firmware error code.
+ pub(crate) NV_PBUS_SW_SCRATCH_0E_FRTS_ERR(u32) => NV_PBUS_SW_SCRATCH[0xe] {
+ 31:16 frts_err_code;
+ }
+}
// PFB
-// The following two registers together hold the physical system memory address that is used by the
-// GPU to perform sysmembar operations (see `fb::SysmemFlush`).
+register! {
+ /// Low bits of the physical system memory address used by the GPU to perform sysmembar
+ /// operations (see [`crate::fb::SysmemFlush`]).
+ pub(crate) NV_PFB_NISO_FLUSH_SYSMEM_ADDR(u32) @ 0x00100c10 {
+ 31:0 adr_39_08;
+ }
-register!(NV_PFB_NISO_FLUSH_SYSMEM_ADDR @ 0x00100c10 {
- 31:0 adr_39_08 as u32;
-});
+ /// High bits of the physical system memory address used by the GPU to perform sysmembar
+ /// operations (see [`crate::fb::SysmemFlush`]).
+ pub(crate) NV_PFB_NISO_FLUSH_SYSMEM_ADDR_HI(u32) @ 0x00100c40 {
+ 23:0 adr_63_40;
+ }
-register!(NV_PFB_NISO_FLUSH_SYSMEM_ADDR_HI @ 0x00100c40 {
- 23:0 adr_63_40 as u32;
-});
+ pub(crate) NV_PFB_PRI_MMU_LOCAL_MEMORY_RANGE(u32) @ 0x00100ce0 {
+ 30:30 ecc_mode_enabled => bool;
+ 9:4 lower_mag;
+ 3:0 lower_scale;
+ }
-register!(NV_PFB_PRI_MMU_LOCAL_MEMORY_RANGE @ 0x00100ce0 {
- 3:0 lower_scale as u8;
- 9:4 lower_mag as u8;
- 30:30 ecc_mode_enabled as bool;
-});
+ pub(crate) NV_PFB_PRI_MMU_WPR2_ADDR_LO(u32) @ 0x001fa824 {
+ /// Bits 12..40 of the lower (inclusive) bound of the WPR2 region.
+ 31:4 lo_val;
+ }
-register!(NV_PGSP_QUEUE_HEAD @ 0x00110c00 {
- 31:0 address as u32;
-});
+ pub(crate) NV_PFB_PRI_MMU_WPR2_ADDR_HI(u32) @ 0x001fa828 {
+ /// Bits 12..40 of the higher (exclusive) bound of the WPR2 region.
+ 31:4 hi_val;
+ }
+}
impl NV_PFB_PRI_MMU_LOCAL_MEMORY_RANGE {
/// Returns the usable framebuffer size, in bytes.
@@ -140,10 +162,6 @@ impl NV_PFB_PRI_MMU_LOCAL_MEMORY_RANGE {
}
}
-register!(NV_PFB_PRI_MMU_WPR2_ADDR_LO@0x001fa824 {
- 31:4 lo_val as u32, "Bits 12..40 of the lower (inclusive) bound of the WPR2 region";
-});
-
impl NV_PFB_PRI_MMU_WPR2_ADDR_LO {
/// Returns the lower (inclusive) bound of the WPR2 region.
pub(crate) fn lower_bound(self) -> u64 {
@@ -151,10 +169,6 @@ impl NV_PFB_PRI_MMU_WPR2_ADDR_LO {
}
}
-register!(NV_PFB_PRI_MMU_WPR2_ADDR_HI@0x001fa828 {
- 31:4 hi_val as u32, "Bits 12..40 of the higher (exclusive) bound of the WPR2 region";
-});
-
impl NV_PFB_PRI_MMU_WPR2_ADDR_HI {
/// Returns the higher (exclusive) bound of the WPR2 region.
///
@@ -164,6 +178,14 @@ impl NV_PFB_PRI_MMU_WPR2_ADDR_HI {
}
}
+// PGSP
+
+register! {
+ pub(crate) NV_PGSP_QUEUE_HEAD(u32) @ 0x00110c00 {
+ 31:0 address;
+ }
+}
+
// PGC6 register space.
//
// `GC6` is a GPU low-power state where VRAM is in self-refresh and the GPU is powered down (except
@@ -173,29 +195,41 @@ impl NV_PFB_PRI_MMU_WPR2_ADDR_HI {
// These scratch registers remain powered on even in a low-power state and have a designated group
// number.
-// Boot Sequence Interface (BSI) register used to determine
-// if GSP reload/resume has completed during the boot process.
-register!(NV_PGC6_BSI_SECURE_SCRATCH_14 @ 0x001180f8 {
- 26:26 boot_stage_3_handoff as bool;
-});
+register! {
+ /// Boot Sequence Interface (BSI) register used to determine
+ /// if GSP reload/resume has completed during the boot process.
+ pub(crate) NV_PGC6_BSI_SECURE_SCRATCH_14(u32) @ 0x001180f8 {
+ 26:26 boot_stage_3_handoff => bool;
+ }
+
+ /// Privilege level mask register. It dictates whether the host CPU has privilege to access the
+ /// `PGC6_AON_SECURE_SCRATCH_GROUP_05` register (which it needs to read GFW_BOOT).
+ pub(crate) NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_PRIV_LEVEL_MASK(u32) @ 0x00118128 {
+ /// Set after FWSEC lowers its protection level.
+ 0:0 read_protection_level0 => bool;
+ }
-// Privilege level mask register. It dictates whether the host CPU has privilege to access the
-// `PGC6_AON_SECURE_SCRATCH_GROUP_05` register (which it needs to read GFW_BOOT).
-register!(NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_PRIV_LEVEL_MASK @ 0x00118128,
- "Privilege level mask register" {
- 0:0 read_protection_level0 as bool, "Set after FWSEC lowers its protection level";
-});
+ /// OpenRM defines this as a register array, but doesn't specify its size and only uses its
+ /// first element. Be conservative until we know the actual size or need to use more registers.
+ pub(crate) NV_PGC6_AON_SECURE_SCRATCH_GROUP_05(u32)[1] @ 0x00118234 {}
-// OpenRM defines this as a register array, but doesn't specify its size and only uses its first
-// element. Be conservative until we know the actual size or need to use more registers.
-register!(NV_PGC6_AON_SECURE_SCRATCH_GROUP_05 @ 0x00118234[1] {});
+ /// Scratch group 05 register 0 used as GFW boot progress indicator.
+ pub(crate) NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_0_GFW_BOOT(u32)
+ => NV_PGC6_AON_SECURE_SCRATCH_GROUP_05[0] {
+ /// Progress of GFW boot (0xff means completed).
+ 7:0 progress;
+ }
+
+ pub(crate) NV_PGC6_AON_SECURE_SCRATCH_GROUP_42(u32) @ 0x001183a4 {
+ 31:0 value;
+ }
-register!(
- NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_0_GFW_BOOT => NV_PGC6_AON_SECURE_SCRATCH_GROUP_05[0],
- "Scratch group 05 register 0 used as GFW boot progress indicator" {
- 7:0 progress as u8, "Progress of GFW boot (0xff means completed)";
+ /// Scratch group 42 register used as framebuffer size.
+ pub(crate) NV_USABLE_FB_SIZE_IN_MB(u32) => NV_PGC6_AON_SECURE_SCRATCH_GROUP_42 {
+ /// Usable framebuffer size, in megabytes.
+ 31:0 value;
}
-);
+}
impl NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_0_GFW_BOOT {
/// Returns `true` if GFW boot is completed.
@@ -204,17 +238,6 @@ impl NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_0_GFW_BOOT {
}
}
-register!(NV_PGC6_AON_SECURE_SCRATCH_GROUP_42 @ 0x001183a4 {
- 31:0 value as u32;
-});
-
-register!(
- NV_USABLE_FB_SIZE_IN_MB => NV_PGC6_AON_SECURE_SCRATCH_GROUP_42,
- "Scratch group 42 register used as framebuffer size" {
- 31:0 value as u32, "Usable framebuffer size, in megabytes";
- }
-);
-
impl NV_USABLE_FB_SIZE_IN_MB {
/// Returns the usable framebuffer size, in bytes.
pub(crate) fn usable_fb_size(self) -> u64 {
@@ -224,10 +247,14 @@ impl NV_USABLE_FB_SIZE_IN_MB {
// PDISP
-register!(NV_PDISP_VGA_WORKSPACE_BASE @ 0x00625f04 {
- 3:3 status_valid as bool, "Set if the `addr` field is valid";
- 31:8 addr as u32, "VGA workspace base address divided by 0x10000";
-});
+register! {
+ pub(crate) NV_PDISP_VGA_WORKSPACE_BASE(u32) @ 0x00625f04 {
+ /// VGA workspace base address divided by 0x10000.
+ 31:8 addr;
+ /// Set if the `addr` field is valid.
+ 3:3 status_valid => bool;
+ }
+}
impl NV_PDISP_VGA_WORKSPACE_BASE {
/// Returns the base address of the VGA workspace, or `None` if none exists.
@@ -244,73 +271,162 @@ impl NV_PDISP_VGA_WORKSPACE_BASE {
pub(crate) const NV_FUSE_OPT_FPF_SIZE: usize = 16;
-register!(NV_FUSE_OPT_FPF_NVDEC_UCODE1_VERSION @ 0x00824100[NV_FUSE_OPT_FPF_SIZE] {
- 15:0 data as u16;
-});
+register! {
+ pub(crate) NV_FUSE_OPT_FPF_NVDEC_UCODE1_VERSION(u32)[NV_FUSE_OPT_FPF_SIZE] @ 0x00824100 {
+ 15:0 data => u16;
+ }
-register!(NV_FUSE_OPT_FPF_SEC2_UCODE1_VERSION @ 0x00824140[NV_FUSE_OPT_FPF_SIZE] {
- 15:0 data as u16;
-});
+ pub(crate) NV_FUSE_OPT_FPF_SEC2_UCODE1_VERSION(u32)[NV_FUSE_OPT_FPF_SIZE] @ 0x00824140 {
+ 15:0 data => u16;
+ }
-register!(NV_FUSE_OPT_FPF_GSP_UCODE1_VERSION @ 0x008241c0[NV_FUSE_OPT_FPF_SIZE] {
- 15:0 data as u16;
-});
+ pub(crate) NV_FUSE_OPT_FPF_GSP_UCODE1_VERSION(u32)[NV_FUSE_OPT_FPF_SIZE] @ 0x008241c0 {
+ 15:0 data => u16;
+ }
+}
// PFALCON
-register!(NV_PFALCON_FALCON_IRQSCLR @ PFalconBase[0x00000004] {
- 4:4 halt as bool;
- 6:6 swgen0 as bool;
-});
+register! {
+ pub(crate) NV_PFALCON_FALCON_IRQSCLR(u32) @ PFalconBase + 0x00000004 {
+ 6:6 swgen0 => bool;
+ 4:4 halt => bool;
+ }
+
+ pub(crate) NV_PFALCON_FALCON_MAILBOX0(u32) @ PFalconBase + 0x00000040 {
+ 31:0 value => u32;
+ }
+
+ pub(crate) NV_PFALCON_FALCON_MAILBOX1(u32) @ PFalconBase + 0x00000044 {
+ 31:0 value => u32;
+ }
-register!(NV_PFALCON_FALCON_MAILBOX0 @ PFalconBase[0x00000040] {
- 31:0 value as u32;
-});
+ /// Used to store version information about the firmware running
+ /// on the Falcon processor.
+ pub(crate) NV_PFALCON_FALCON_OS(u32) @ PFalconBase + 0x00000080 {
+ 31:0 value => u32;
+ }
-register!(NV_PFALCON_FALCON_MAILBOX1 @ PFalconBase[0x00000044] {
- 31:0 value as u32;
-});
+ pub(crate) NV_PFALCON_FALCON_RM(u32) @ PFalconBase + 0x00000084 {
+ 31:0 value => u32;
+ }
-// Used to store version information about the firmware running
-// on the Falcon processor.
-register!(NV_PFALCON_FALCON_OS @ PFalconBase[0x00000080] {
- 31:0 value as u32;
-});
+ pub(crate) NV_PFALCON_FALCON_HWCFG2(u32) @ PFalconBase + 0x000000f4 {
+ /// Signal indicating that reset is completed (GA102+).
+ 31:31 reset_ready => bool;
+ /// Set to 0 after memory scrubbing is completed.
+ 12:12 mem_scrubbing => bool;
+ 10:10 riscv => bool;
+ }
-register!(NV_PFALCON_FALCON_RM @ PFalconBase[0x00000084] {
- 31:0 value as u32;
-});
+ pub(crate) NV_PFALCON_FALCON_CPUCTL(u32) @ PFalconBase + 0x00000100 {
+ 6:6 alias_en => bool;
+ 4:4 halted => bool;
+ 1:1 startcpu => bool;
+ }
-register!(NV_PFALCON_FALCON_HWCFG2 @ PFalconBase[0x000000f4] {
- 10:10 riscv as bool;
- 12:12 mem_scrubbing as bool, "Set to 0 after memory scrubbing is completed";
- 31:31 reset_ready as bool, "Signal indicating that reset is completed (GA102+)";
-});
+ pub(crate) NV_PFALCON_FALCON_BOOTVEC(u32) @ PFalconBase + 0x00000104 {
+ 31:0 value => u32;
+ }
-impl NV_PFALCON_FALCON_HWCFG2 {
- /// Returns `true` if memory scrubbing is completed.
- pub(crate) fn mem_scrubbing_done(self) -> bool {
- !self.mem_scrubbing()
+ pub(crate) NV_PFALCON_FALCON_DMACTL(u32) @ PFalconBase + 0x0000010c {
+ 7:7 secure_stat => bool;
+ 6:3 dmaq_num;
+ 2:2 imem_scrubbing => bool;
+ 1:1 dmem_scrubbing => bool;
+ 0:0 require_ctx => bool;
}
-}
-register!(NV_PFALCON_FALCON_CPUCTL @ PFalconBase[0x00000100] {
- 1:1 startcpu as bool;
- 4:4 halted as bool;
- 6:6 alias_en as bool;
-});
+ pub(crate) NV_PFALCON_FALCON_DMATRFBASE(u32) @ PFalconBase + 0x00000110 {
+ 31:0 base => u32;
+ }
-register!(NV_PFALCON_FALCON_BOOTVEC @ PFalconBase[0x00000104] {
- 31:0 value as u32;
-});
+ pub(crate) NV_PFALCON_FALCON_DMATRFMOFFS(u32) @ PFalconBase + 0x00000114 {
+ 23:0 offs;
+ }
-register!(NV_PFALCON_FALCON_DMACTL @ PFalconBase[0x0000010c] {
- 0:0 require_ctx as bool;
- 1:1 dmem_scrubbing as bool;
- 2:2 imem_scrubbing as bool;
- 6:3 dmaq_num as u8;
- 7:7 secure_stat as bool;
-});
+ pub(crate) NV_PFALCON_FALCON_DMATRFCMD(u32) @ PFalconBase + 0x00000118 {
+ 16:16 set_dmtag;
+ 14:12 ctxdma;
+ 10:8 size ?=> DmaTrfCmdSize;
+ 5:5 is_write => bool;
+ 4:4 imem => bool;
+ 3:2 sec;
+ 1:1 idle => bool;
+ 0:0 full => bool;
+ }
+
+ pub(crate) NV_PFALCON_FALCON_DMATRFFBOFFS(u32) @ PFalconBase + 0x0000011c {
+ 31:0 offs => u32;
+ }
+
+ pub(crate) NV_PFALCON_FALCON_DMATRFBASE1(u32) @ PFalconBase + 0x00000128 {
+ 8:0 base;
+ }
+
+ pub(crate) NV_PFALCON_FALCON_HWCFG1(u32) @ PFalconBase + 0x0000012c {
+ /// Core revision subversion.
+ 7:6 core_rev_subversion => FalconCoreRevSubversion;
+ /// Security model.
+ 5:4 security_model ?=> FalconSecurityModel;
+ /// Core revision.
+ 3:0 core_rev ?=> FalconCoreRev;
+ }
+
+ pub(crate) NV_PFALCON_FALCON_CPUCTL_ALIAS(u32) @ PFalconBase + 0x00000130 {
+ 1:1 startcpu => bool;
+ }
+
+ /// IMEM access control register. Up to 4 ports are available for IMEM access.
+ pub(crate) NV_PFALCON_FALCON_IMEMC(u32)[4, stride = 16] @ PFalconBase + 0x00000180 {
+ /// Access secure IMEM.
+ 28:28 secure => bool;
+ /// Auto-increment on write.
+ 24:24 aincw => bool;
+ /// IMEM block and word offset.
+ 15:0 offs;
+ }
+
+ /// IMEM data register. Reading/writing this register accesses IMEM at the address
+ /// specified by the corresponding IMEMC register.
+ pub(crate) NV_PFALCON_FALCON_IMEMD(u32)[4, stride = 16] @ PFalconBase + 0x00000184 {
+ 31:0 data;
+ }
+
+ /// IMEM tag register. Used to set the tag for the current IMEM block.
+ pub(crate) NV_PFALCON_FALCON_IMEMT(u32)[4, stride = 16] @ PFalconBase + 0x00000188 {
+ 15:0 tag;
+ }
+
+ /// DMEM access control register. Up to 8 ports are available for DMEM access.
+ pub(crate) NV_PFALCON_FALCON_DMEMC(u32)[8, stride = 8] @ PFalconBase + 0x000001c0 {
+ /// Auto-increment on write.
+ 24:24 aincw => bool;
+ /// DMEM block and word offset.
+ 15:0 offs;
+ }
+
+ /// DMEM data register. Reading/writing this register accesses DMEM at the address
+ /// specified by the corresponding DMEMC register.
+ pub(crate) NV_PFALCON_FALCON_DMEMD(u32)[8, stride = 8] @ PFalconBase + 0x000001c4 {
+ 31:0 data;
+ }
+
+ /// Actually known as `NV_PSEC_FALCON_ENGINE` and `NV_PGSP_FALCON_ENGINE` depending on the
+ /// falcon instance.
+ pub(crate) NV_PFALCON_FALCON_ENGINE(u32) @ PFalconBase + 0x000003c0 {
+ 0:0 reset => bool;
+ }
+
+ pub(crate) NV_PFALCON_FBIF_TRANSCFG(u32)[8] @ PFalconBase + 0x00000600 {
+ 2:2 mem_type => FalconFbifMemType;
+ 1:0 target ?=> FalconFbifTarget;
+ }
+
+ pub(crate) NV_PFALCON_FBIF_CTL(u32) @ PFalconBase + 0x00000624 {
+ 7:7 allow_phys_no_ctx => bool;
+ }
+}
impl NV_PFALCON_FALCON_DMACTL {
/// Returns `true` if memory scrubbing is completed.
@@ -319,133 +435,106 @@ impl NV_PFALCON_FALCON_DMACTL {
}
}
-register!(NV_PFALCON_FALCON_DMATRFBASE @ PFalconBase[0x00000110] {
- 31:0 base as u32;
-});
-
-register!(NV_PFALCON_FALCON_DMATRFMOFFS @ PFalconBase[0x00000114] {
- 23:0 offs as u32;
-});
-
-register!(NV_PFALCON_FALCON_DMATRFCMD @ PFalconBase[0x00000118] {
- 0:0 full as bool;
- 1:1 idle as bool;
- 3:2 sec as u8;
- 4:4 imem as bool;
- 5:5 is_write as bool;
- 10:8 size as u8 ?=> DmaTrfCmdSize;
- 14:12 ctxdma as u8;
- 16:16 set_dmtag as u8;
-});
-
impl NV_PFALCON_FALCON_DMATRFCMD {
/// Programs the `imem` and `sec` fields for the given FalconMem
pub(crate) fn with_falcon_mem(self, mem: FalconMem) -> Self {
- self.set_imem(mem != FalconMem::Dmem)
- .set_sec(if mem == FalconMem::ImemSecure { 1 } else { 0 })
+ let this = self.with_imem(mem != FalconMem::Dmem);
+
+ match mem {
+ FalconMem::ImemSecure => this.with_const_sec::<1>(),
+ _ => this.with_const_sec::<0>(),
+ }
}
}
-register!(NV_PFALCON_FALCON_DMATRFFBOFFS @ PFalconBase[0x0000011c] {
- 31:0 offs as u32;
-});
-
-register!(NV_PFALCON_FALCON_DMATRFBASE1 @ PFalconBase[0x00000128] {
- 8:0 base as u16;
-});
-
-register!(NV_PFALCON_FALCON_HWCFG1 @ PFalconBase[0x0000012c] {
- 3:0 core_rev as u8 ?=> FalconCoreRev, "Core revision";
- 5:4 security_model as u8 ?=> FalconSecurityModel, "Security model";
- 7:6 core_rev_subversion as u8 ?=> FalconCoreRevSubversion, "Core revision subversion";
-});
-
-register!(NV_PFALCON_FALCON_CPUCTL_ALIAS @ PFalconBase[0x00000130] {
- 1:1 startcpu as bool;
-});
-
-// Actually known as `NV_PSEC_FALCON_ENGINE` and `NV_PGSP_FALCON_ENGINE` depending on the falcon
-// instance.
-register!(NV_PFALCON_FALCON_ENGINE @ PFalconBase[0x000003c0] {
- 0:0 reset as bool;
-});
-
impl NV_PFALCON_FALCON_ENGINE {
/// Resets the falcon
pub(crate) fn reset_engine<E: FalconEngine>(bar: &Bar0) {
- Self::read(bar, &E::ID).set_reset(true).write(bar, &E::ID);
+ bar.update(Self::of::<E>(), |r| r.with_reset(true));
// TIMEOUT: falcon engine should not take more than 10us to reset.
time::delay::fsleep(time::Delta::from_micros(10));
- Self::read(bar, &E::ID).set_reset(false).write(bar, &E::ID);
+ bar.update(Self::of::<E>(), |r| r.with_reset(false));
}
}
-register!(NV_PFALCON_FBIF_TRANSCFG @ PFalconBase[0x00000600[8]] {
- 1:0 target as u8 ?=> FalconFbifTarget;
- 2:2 mem_type as bool => FalconFbifMemType;
-});
-
-register!(NV_PFALCON_FBIF_CTL @ PFalconBase[0x00000624] {
- 7:7 allow_phys_no_ctx as bool;
-});
+impl NV_PFALCON_FALCON_HWCFG2 {
+ /// Returns `true` if memory scrubbing is completed.
+ pub(crate) fn mem_scrubbing_done(self) -> bool {
+ !self.mem_scrubbing()
+ }
+}
/* PFALCON2 */
-register!(NV_PFALCON2_FALCON_MOD_SEL @ PFalcon2Base[0x00000180] {
- 7:0 algo as u8 ?=> FalconModSelAlgo;
-});
+register! {
+ pub(crate) NV_PFALCON2_FALCON_MOD_SEL(u32) @ PFalcon2Base + 0x00000180 {
+ 7:0 algo ?=> FalconModSelAlgo;
+ }
-register!(NV_PFALCON2_FALCON_BROM_CURR_UCODE_ID @ PFalcon2Base[0x00000198] {
- 7:0 ucode_id as u8;
-});
+ pub(crate) NV_PFALCON2_FALCON_BROM_CURR_UCODE_ID(u32) @ PFalcon2Base + 0x00000198 {
+ 7:0 ucode_id => u8;
+ }
-register!(NV_PFALCON2_FALCON_BROM_ENGIDMASK @ PFalcon2Base[0x0000019c] {
- 31:0 value as u32;
-});
+ pub(crate) NV_PFALCON2_FALCON_BROM_ENGIDMASK(u32) @ PFalcon2Base + 0x0000019c {
+ 31:0 value => u32;
+ }
-// OpenRM defines this as a register array, but doesn't specify its size and only uses its first
-// element. Be conservative until we know the actual size or need to use more registers.
-register!(NV_PFALCON2_FALCON_BROM_PARAADDR @ PFalcon2Base[0x00000210[1]] {
- 31:0 value as u32;
-});
+ /// OpenRM defines this as a register array, but doesn't specify its size and only uses its
+ /// first element. Be conservative until we know the actual size or need to use more registers.
+ pub(crate) NV_PFALCON2_FALCON_BROM_PARAADDR(u32)[1] @ PFalcon2Base + 0x00000210 {
+ 31:0 value => u32;
+ }
+}
// PRISCV
-// RISC-V status register for debug (Turing and GA100 only).
-// Reflects current RISC-V core status.
-register!(NV_PRISCV_RISCV_CORE_SWITCH_RISCV_STATUS @ PFalcon2Base[0x00000240] {
- 0:0 active_stat as bool, "RISC-V core active/inactive status";
-});
+register! {
+ /// RISC-V status register for debug (Turing and GA100 only).
+ /// Reflects current RISC-V core status.
+ pub(crate) NV_PRISCV_RISCV_CORE_SWITCH_RISCV_STATUS(u32) @ PFalcon2Base + 0x00000240 {
+ /// RISC-V core active/inactive status.
+ 0:0 active_stat => bool;
+ }
-// GA102 and later
-register!(NV_PRISCV_RISCV_CPUCTL @ PFalcon2Base[0x00000388] {
- 0:0 halted as bool;
- 7:7 active_stat as bool;
-});
+ /// GA102 and later.
+ pub(crate) NV_PRISCV_RISCV_CPUCTL(u32) @ PFalcon2Base + 0x00000388 {
+ 7:7 active_stat => bool;
+ 0:0 halted => bool;
+ }
-register!(NV_PRISCV_RISCV_BCR_CTRL @ PFalcon2Base[0x00000668] {
- 0:0 valid as bool;
- 4:4 core_select as bool => PeregrineCoreSelect;
- 8:8 br_fetch as bool;
-});
+ /// GA102 and later.
+ pub(crate) NV_PRISCV_RISCV_BCR_CTRL(u32) @ PFalcon2Base + 0x00000668 {
+ 8:8 br_fetch => bool;
+ 4:4 core_select => PeregrineCoreSelect;
+ 0:0 valid => bool;
+ }
+}
// The modules below provide registers that are not identical on all supported chips. They should
// only be used in HAL modules.
pub(crate) mod gm107 {
+ use kernel::io::register;
+
// FUSE
- register!(NV_FUSE_STATUS_OPT_DISPLAY @ 0x00021c04 {
- 0:0 display_disabled as bool;
- });
+ register! {
+ pub(crate) NV_FUSE_STATUS_OPT_DISPLAY(u32) @ 0x00021c04 {
+ 0:0 display_disabled => bool;
+ }
+ }
}
pub(crate) mod ga100 {
+ use kernel::io::register;
+
// FUSE
- register!(NV_FUSE_STATUS_OPT_DISPLAY @ 0x00820c04 {
- 0:0 display_disabled as bool;
- });
+ register! {
+ pub(crate) NV_FUSE_STATUS_OPT_DISPLAY(u32) @ 0x00820c04 {
+ 0:0 display_disabled => bool;
+ }
+ }
}
diff --git a/drivers/gpu/nova-core/regs/macros.rs b/drivers/gpu/nova-core/regs/macros.rs
deleted file mode 100644
index ed624be1f39b..000000000000
--- a/drivers/gpu/nova-core/regs/macros.rs
+++ /dev/null
@@ -1,739 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-
-//! `register!` macro to define register layout and accessors.
-//!
-//! A single register typically includes several fields, which are accessed through a combination
-//! of bit-shift and mask operations that introduce a class of potential mistakes, notably because
-//! not all possible field values are necessarily valid.
-//!
-//! The `register!` macro in this module provides an intuitive and readable syntax for defining a
-//! dedicated type for each register. Each such type comes with its own field accessors that can
-//! return an error if a field's value is invalid. Please look at the [`bitfield`] macro for the
-//! complete syntax of fields definitions.
-
-/// Trait providing a base address to be added to the offset of a relative register to obtain
-/// its actual offset.
-///
-/// The `T` generic argument is used to distinguish which base to use, in case a type provides
-/// several bases. It is given to the `register!` macro to restrict the use of the register to
-/// implementors of this particular variant.
-pub(crate) trait RegisterBase<T> {
- const BASE: usize;
-}
-
-/// Defines a dedicated type for a register with an absolute offset, including getter and setter
-/// methods for its fields and methods to read and write it from an `Io` region.
-///
-/// Example:
-///
-/// ```no_run
-/// register!(BOOT_0 @ 0x00000100, "Basic revision information about the GPU" {
-/// 3:0 minor_revision as u8, "Minor revision of the chip";
-/// 7:4 major_revision as u8, "Major revision of the chip";
-/// 28:20 chipset as u32 ?=> Chipset, "Chipset model";
-/// });
-/// ```
-///
-/// This defines a `BOOT_0` type which can be read or written from offset `0x100` of an `Io`
-/// region. It is composed of 3 fields, for instance `minor_revision` is made of the 4 least
-/// significant bits of the register. Each field can be accessed and modified using accessor
-/// methods:
-///
-/// ```no_run
-/// // Read from the register's defined offset (0x100).
-/// let boot0 = BOOT_0::read(&bar);
-/// pr_info!("chip revision: {}.{}", boot0.major_revision(), boot0.minor_revision());
-///
-/// // `Chipset::try_from` is called with the value of the `chipset` field and returns an
-/// // error if it is invalid.
-/// let chipset = boot0.chipset()?;
-///
-/// // Update some fields and write the value back.
-/// boot0.set_major_revision(3).set_minor_revision(10).write(&bar);
-///
-/// // Or, just read and update the register in a single step:
-/// BOOT_0::update(&bar, |r| r.set_major_revision(3).set_minor_revision(10));
-/// ```
-///
-/// The documentation strings are optional. If present, they will be added to the type's
-/// definition, or the field getter and setter methods they are attached to.
-///
-/// It is also possible to create a alias register by using the `=> ALIAS` syntax. This is useful
-/// for cases where a register's interpretation depends on the context:
-///
-/// ```no_run
-/// register!(SCRATCH @ 0x00000200, "Scratch register" {
-/// 31:0 value as u32, "Raw value";
-/// });
-///
-/// register!(SCRATCH_BOOT_STATUS => SCRATCH, "Boot status of the firmware" {
-/// 0:0 completed as bool, "Whether the firmware has completed booting";
-/// });
-/// ```
-///
-/// In this example, `SCRATCH_0_BOOT_STATUS` uses the same I/O address as `SCRATCH`, while also
-/// providing its own `completed` field.
-///
-/// ## Relative registers
-///
-/// A register can be defined as being accessible from a fixed offset of a provided base. For
-/// instance, imagine the following I/O space:
-///
-/// ```text
-/// +-----------------------------+
-/// | ... |
-/// | |
-/// 0x100--->+------------CPU0-------------+
-/// | |
-/// 0x110--->+-----------------------------+
-/// | CPU_CTL |
-/// +-----------------------------+
-/// | ... |
-/// | |
-/// | |
-/// 0x200--->+------------CPU1-------------+
-/// | |
-/// 0x210--->+-----------------------------+
-/// | CPU_CTL |
-/// +-----------------------------+
-/// | ... |
-/// +-----------------------------+
-/// ```
-///
-/// `CPU0` and `CPU1` both have a `CPU_CTL` register that starts at offset `0x10` of their I/O
-/// space segment. Since both instances of `CPU_CTL` share the same layout, we don't want to define
-/// them twice and would prefer a way to select which one to use from a single definition
-///
-/// This can be done using the `Base[Offset]` syntax when specifying the register's address.
-///
-/// `Base` is an arbitrary type (typically a ZST) to be used as a generic parameter of the
-/// [`RegisterBase`] trait to provide the base as a constant, i.e. each type providing a base for
-/// this register needs to implement `RegisterBase<Base>`. Here is the above example translated
-/// into code:
-///
-/// ```no_run
-/// // Type used to identify the base.
-/// pub(crate) struct CpuCtlBase;
-///
-/// // ZST describing `CPU0`.
-/// struct Cpu0;
-/// impl RegisterBase<CpuCtlBase> for Cpu0 {
-/// const BASE: usize = 0x100;
-/// }
-/// // Singleton of `CPU0` used to identify it.
-/// const CPU0: Cpu0 = Cpu0;
-///
-/// // ZST describing `CPU1`.
-/// struct Cpu1;
-/// impl RegisterBase<CpuCtlBase> for Cpu1 {
-/// const BASE: usize = 0x200;
-/// }
-/// // Singleton of `CPU1` used to identify it.
-/// const CPU1: Cpu1 = Cpu1;
-///
-/// // This makes `CPU_CTL` accessible from all implementors of `RegisterBase<CpuCtlBase>`.
-/// register!(CPU_CTL @ CpuCtlBase[0x10], "CPU core control" {
-/// 0:0 start as bool, "Start the CPU core";
-/// });
-///
-/// // The `read`, `write` and `update` methods of relative registers take an extra `base` argument
-/// // that is used to resolve its final address by adding its `BASE` to the offset of the
-/// // register.
-///
-/// // Start `CPU0`.
-/// CPU_CTL::update(bar, &CPU0, |r| r.set_start(true));
-///
-/// // Start `CPU1`.
-/// CPU_CTL::update(bar, &CPU1, |r| r.set_start(true));
-///
-/// // Aliases can also be defined for relative register.
-/// register!(CPU_CTL_ALIAS => CpuCtlBase[CPU_CTL], "Alias to CPU core control" {
-/// 1:1 alias_start as bool, "Start the aliased CPU core";
-/// });
-///
-/// // Start the aliased `CPU0`.
-/// CPU_CTL_ALIAS::update(bar, &CPU0, |r| r.set_alias_start(true));
-/// ```
-///
-/// ## Arrays of registers
-///
-/// Some I/O areas contain consecutive values that can be interpreted in the same way. These areas
-/// can be defined as an array of identical registers, allowing them to be accessed by index with
-/// compile-time or runtime bound checking. Simply define their address as `Address[Size]`, and add
-/// an `idx` parameter to their `read`, `write` and `update` methods:
-///
-/// ```no_run
-/// # fn no_run() -> Result<(), Error> {
-/// # fn get_scratch_idx() -> usize {
-/// # 0x15
-/// # }
-/// // Array of 64 consecutive registers with the same layout starting at offset `0x80`.
-/// register!(SCRATCH @ 0x00000080[64], "Scratch registers" {
-/// 31:0 value as u32;
-/// });
-///
-/// // Read scratch register 0, i.e. I/O address `0x80`.
-/// let scratch_0 = SCRATCH::read(bar, 0).value();
-/// // Read scratch register 15, i.e. I/O address `0x80 + (15 * 4)`.
-/// let scratch_15 = SCRATCH::read(bar, 15).value();
-///
-/// // This is out of bounds and won't build.
-/// // let scratch_128 = SCRATCH::read(bar, 128).value();
-///
-/// // Runtime-obtained array index.
-/// let scratch_idx = get_scratch_idx();
-/// // Access on a runtime index returns an error if it is out-of-bounds.
-/// let some_scratch = SCRATCH::try_read(bar, scratch_idx)?.value();
-///
-/// // Alias to a particular register in an array.
-/// // Here `SCRATCH[8]` is used to convey the firmware exit code.
-/// register!(FIRMWARE_STATUS => SCRATCH[8], "Firmware exit status code" {
-/// 7:0 status as u8;
-/// });
-///
-/// let status = FIRMWARE_STATUS::read(bar).status();
-///
-/// // Non-contiguous register arrays can be defined by adding a stride parameter.
-/// // Here, each of the 16 registers of the array are separated by 8 bytes, meaning that the
-/// // registers of the two declarations below are interleaved.
-/// register!(SCRATCH_INTERLEAVED_0 @ 0x000000c0[16 ; 8], "Scratch registers bank 0" {
-/// 31:0 value as u32;
-/// });
-/// register!(SCRATCH_INTERLEAVED_1 @ 0x000000c4[16 ; 8], "Scratch registers bank 1" {
-/// 31:0 value as u32;
-/// });
-/// # Ok(())
-/// # }
-/// ```
-///
-/// ## Relative arrays of registers
-///
-/// Combining the two features described in the sections above, arrays of registers accessible from
-/// a base can also be defined:
-///
-/// ```no_run
-/// # fn no_run() -> Result<(), Error> {
-/// # fn get_scratch_idx() -> usize {
-/// # 0x15
-/// # }
-/// // Type used as parameter of `RegisterBase` to specify the base.
-/// pub(crate) struct CpuCtlBase;
-///
-/// // ZST describing `CPU0`.
-/// struct Cpu0;
-/// impl RegisterBase<CpuCtlBase> for Cpu0 {
-/// const BASE: usize = 0x100;
-/// }
-/// // Singleton of `CPU0` used to identify it.
-/// const CPU0: Cpu0 = Cpu0;
-///
-/// // ZST describing `CPU1`.
-/// struct Cpu1;
-/// impl RegisterBase<CpuCtlBase> for Cpu1 {
-/// const BASE: usize = 0x200;
-/// }
-/// // Singleton of `CPU1` used to identify it.
-/// const CPU1: Cpu1 = Cpu1;
-///
-/// // 64 per-cpu scratch registers, arranged as an contiguous array.
-/// register!(CPU_SCRATCH @ CpuCtlBase[0x00000080[64]], "Per-CPU scratch registers" {
-/// 31:0 value as u32;
-/// });
-///
-/// let cpu0_scratch_0 = CPU_SCRATCH::read(bar, &Cpu0, 0).value();
-/// let cpu1_scratch_15 = CPU_SCRATCH::read(bar, &Cpu1, 15).value();
-///
-/// // This won't build.
-/// // let cpu0_scratch_128 = CPU_SCRATCH::read(bar, &Cpu0, 128).value();
-///
-/// // Runtime-obtained array index.
-/// let scratch_idx = get_scratch_idx();
-/// // Access on a runtime value returns an error if it is out-of-bounds.
-/// let cpu0_some_scratch = CPU_SCRATCH::try_read(bar, &Cpu0, scratch_idx)?.value();
-///
-/// // `SCRATCH[8]` is used to convey the firmware exit code.
-/// register!(CPU_FIRMWARE_STATUS => CpuCtlBase[CPU_SCRATCH[8]],
-/// "Per-CPU firmware exit status code" {
-/// 7:0 status as u8;
-/// });
-///
-/// let cpu0_status = CPU_FIRMWARE_STATUS::read(bar, &Cpu0).status();
-///
-/// // Non-contiguous register arrays can be defined by adding a stride parameter.
-/// // Here, each of the 16 registers of the array are separated by 8 bytes, meaning that the
-/// // registers of the two declarations below are interleaved.
-/// register!(CPU_SCRATCH_INTERLEAVED_0 @ CpuCtlBase[0x00000d00[16 ; 8]],
-/// "Scratch registers bank 0" {
-/// 31:0 value as u32;
-/// });
-/// register!(CPU_SCRATCH_INTERLEAVED_1 @ CpuCtlBase[0x00000d04[16 ; 8]],
-/// "Scratch registers bank 1" {
-/// 31:0 value as u32;
-/// });
-/// # Ok(())
-/// # }
-/// ```
-macro_rules! register {
- // Creates a register at a fixed offset of the MMIO space.
- ($name:ident @ $offset:literal $(, $comment:literal)? { $($fields:tt)* } ) => {
- bitfield!(pub(crate) struct $name(u32) $(, $comment)? { $($fields)* } );
- register!(@io_fixed $name @ $offset);
- };
-
- // Creates an alias register of fixed offset register `alias` with its own fields.
- ($name:ident => $alias:ident $(, $comment:literal)? { $($fields:tt)* } ) => {
- bitfield!(pub(crate) struct $name(u32) $(, $comment)? { $($fields)* } );
- register!(@io_fixed $name @ $alias::OFFSET);
- };
-
- // Creates a register at a relative offset from a base address provider.
- ($name:ident @ $base:ty [ $offset:literal ] $(, $comment:literal)? { $($fields:tt)* } ) => {
- bitfield!(pub(crate) struct $name(u32) $(, $comment)? { $($fields)* } );
- register!(@io_relative $name @ $base [ $offset ]);
- };
-
- // Creates an alias register of relative offset register `alias` with its own fields.
- ($name:ident => $base:ty [ $alias:ident ] $(, $comment:literal)? { $($fields:tt)* }) => {
- bitfield!(pub(crate) struct $name(u32) $(, $comment)? { $($fields)* } );
- register!(@io_relative $name @ $base [ $alias::OFFSET ]);
- };
-
- // Creates an array of registers at a fixed offset of the MMIO space.
- (
- $name:ident @ $offset:literal [ $size:expr ; $stride:expr ] $(, $comment:literal)? {
- $($fields:tt)*
- }
- ) => {
- static_assert!(::core::mem::size_of::<u32>() <= $stride);
- bitfield!(pub(crate) struct $name(u32) $(, $comment)? { $($fields)* } );
- register!(@io_array $name @ $offset [ $size ; $stride ]);
- };
-
- // Shortcut for contiguous array of registers (stride == size of element).
- (
- $name:ident @ $offset:literal [ $size:expr ] $(, $comment:literal)? {
- $($fields:tt)*
- }
- ) => {
- register!($name @ $offset [ $size ; ::core::mem::size_of::<u32>() ] $(, $comment)? {
- $($fields)*
- } );
- };
-
- // Creates an array of registers at a relative offset from a base address provider.
- (
- $name:ident @ $base:ty [ $offset:literal [ $size:expr ; $stride:expr ] ]
- $(, $comment:literal)? { $($fields:tt)* }
- ) => {
- static_assert!(::core::mem::size_of::<u32>() <= $stride);
- bitfield!(pub(crate) struct $name(u32) $(, $comment)? { $($fields)* } );
- register!(@io_relative_array $name @ $base [ $offset [ $size ; $stride ] ]);
- };
-
- // Shortcut for contiguous array of relative registers (stride == size of element).
- (
- $name:ident @ $base:ty [ $offset:literal [ $size:expr ] ] $(, $comment:literal)? {
- $($fields:tt)*
- }
- ) => {
- register!($name @ $base [ $offset [ $size ; ::core::mem::size_of::<u32>() ] ]
- $(, $comment)? { $($fields)* } );
- };
-
- // Creates an alias of register `idx` of relative array of registers `alias` with its own
- // fields.
- (
- $name:ident => $base:ty [ $alias:ident [ $idx:expr ] ] $(, $comment:literal)? {
- $($fields:tt)*
- }
- ) => {
- static_assert!($idx < $alias::SIZE);
- bitfield!(pub(crate) struct $name(u32) $(, $comment)? { $($fields)* } );
- register!(@io_relative $name @ $base [ $alias::OFFSET + $idx * $alias::STRIDE ] );
- };
-
- // Creates an alias of register `idx` of array of registers `alias` with its own fields.
- // This rule belongs to the (non-relative) register arrays set, but needs to be put last
- // to avoid it being interpreted in place of the relative register array alias rule.
- ($name:ident => $alias:ident [ $idx:expr ] $(, $comment:literal)? { $($fields:tt)* }) => {
- static_assert!($idx < $alias::SIZE);
- bitfield!(pub(crate) struct $name(u32) $(, $comment)? { $($fields)* } );
- register!(@io_fixed $name @ $alias::OFFSET + $idx * $alias::STRIDE );
- };
-
- // Generates the IO accessors for a fixed offset register.
- (@io_fixed $name:ident @ $offset:expr) => {
- #[allow(dead_code)]
- impl $name {
- pub(crate) const OFFSET: usize = $offset;
-
- /// Read the register from its address in `io`.
- #[inline(always)]
- pub(crate) fn read<T, I>(io: &T) -> Self where
- T: ::core::ops::Deref<Target = I>,
- I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<u32>,
- {
- Self(io.read32($offset))
- }
-
- /// Write the value contained in `self` to the register address in `io`.
- #[inline(always)]
- pub(crate) fn write<T, I>(self, io: &T) where
- T: ::core::ops::Deref<Target = I>,
- I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<u32>,
- {
- io.write32(self.0, $offset)
- }
-
- /// Read the register from its address in `io` and run `f` on its value to obtain a new
- /// value to write back.
- #[inline(always)]
- pub(crate) fn update<T, I, F>(
- io: &T,
- f: F,
- ) where
- T: ::core::ops::Deref<Target = I>,
- I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<u32>,
- F: ::core::ops::FnOnce(Self) -> Self,
- {
- let reg = f(Self::read(io));
- reg.write(io);
- }
- }
- };
-
- // Generates the IO accessors for a relative offset register.
- (@io_relative $name:ident @ $base:ty [ $offset:expr ]) => {
- #[allow(dead_code)]
- impl $name {
- pub(crate) const OFFSET: usize = $offset;
-
- /// Read the register from `io`, using the base address provided by `base` and adding
- /// the register's offset to it.
- #[inline(always)]
- pub(crate) fn read<T, I, B>(
- io: &T,
- #[allow(unused_variables)]
- base: &B,
- ) -> Self where
- T: ::core::ops::Deref<Target = I>,
- I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<u32>,
- B: crate::regs::macros::RegisterBase<$base>,
- {
- const OFFSET: usize = $name::OFFSET;
-
- let value = io.read32(
- <B as crate::regs::macros::RegisterBase<$base>>::BASE + OFFSET
- );
-
- Self(value)
- }
-
- /// Write the value contained in `self` to `io`, using the base address provided by
- /// `base` and adding the register's offset to it.
- #[inline(always)]
- pub(crate) fn write<T, I, B>(
- self,
- io: &T,
- #[allow(unused_variables)]
- base: &B,
- ) where
- T: ::core::ops::Deref<Target = I>,
- I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<u32>,
- B: crate::regs::macros::RegisterBase<$base>,
- {
- const OFFSET: usize = $name::OFFSET;
-
- io.write32(
- self.0,
- <B as crate::regs::macros::RegisterBase<$base>>::BASE + OFFSET
- );
- }
-
- /// Read the register from `io`, using the base address provided by `base` and adding
- /// the register's offset to it, then run `f` on its value to obtain a new value to
- /// write back.
- #[inline(always)]
- pub(crate) fn update<T, I, B, F>(
- io: &T,
- base: &B,
- f: F,
- ) where
- T: ::core::ops::Deref<Target = I>,
- I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<u32>,
- B: crate::regs::macros::RegisterBase<$base>,
- F: ::core::ops::FnOnce(Self) -> Self,
- {
- let reg = f(Self::read(io, base));
- reg.write(io, base);
- }
- }
- };
-
- // Generates the IO accessors for an array of registers.
- (@io_array $name:ident @ $offset:literal [ $size:expr ; $stride:expr ]) => {
- #[allow(dead_code)]
- impl $name {
- pub(crate) const OFFSET: usize = $offset;
- pub(crate) const SIZE: usize = $size;
- pub(crate) const STRIDE: usize = $stride;
-
- /// Read the array register at index `idx` from its address in `io`.
- #[inline(always)]
- pub(crate) fn read<T, I>(
- io: &T,
- idx: usize,
- ) -> Self where
- T: ::core::ops::Deref<Target = I>,
- I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<u32>,
- {
- build_assert!(idx < Self::SIZE);
-
- let offset = Self::OFFSET + (idx * Self::STRIDE);
- let value = io.read32(offset);
-
- Self(value)
- }
-
- /// Write the value contained in `self` to the array register with index `idx` in `io`.
- #[inline(always)]
- pub(crate) fn write<T, I>(
- self,
- io: &T,
- idx: usize
- ) where
- T: ::core::ops::Deref<Target = I>,
- I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<u32>,
- {
- build_assert!(idx < Self::SIZE);
-
- let offset = Self::OFFSET + (idx * Self::STRIDE);
-
- io.write32(self.0, offset);
- }
-
- /// Read the array register at index `idx` in `io` and run `f` on its value to obtain a
- /// new value to write back.
- #[inline(always)]
- pub(crate) fn update<T, I, F>(
- io: &T,
- idx: usize,
- f: F,
- ) where
- T: ::core::ops::Deref<Target = I>,
- I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<u32>,
- F: ::core::ops::FnOnce(Self) -> Self,
- {
- let reg = f(Self::read(io, idx));
- reg.write(io, idx);
- }
-
- /// Read the array register at index `idx` from its address in `io`.
- ///
- /// The validity of `idx` is checked at run-time, and `EINVAL` is returned is the
- /// access was out-of-bounds.
- #[inline(always)]
- pub(crate) fn try_read<T, I>(
- io: &T,
- idx: usize,
- ) -> ::kernel::error::Result<Self> where
- T: ::core::ops::Deref<Target = I>,
- I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<u32>,
- {
- if idx < Self::SIZE {
- Ok(Self::read(io, idx))
- } else {
- Err(EINVAL)
- }
- }
-
- /// Write the value contained in `self` to the array register with index `idx` in `io`.
- ///
- /// The validity of `idx` is checked at run-time, and `EINVAL` is returned is the
- /// access was out-of-bounds.
- #[inline(always)]
- pub(crate) fn try_write<T, I>(
- self,
- io: &T,
- idx: usize,
- ) -> ::kernel::error::Result where
- T: ::core::ops::Deref<Target = I>,
- I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<u32>,
- {
- if idx < Self::SIZE {
- Ok(self.write(io, idx))
- } else {
- Err(EINVAL)
- }
- }
-
- /// Read the array register at index `idx` in `io` and run `f` on its value to obtain a
- /// new value to write back.
- ///
- /// The validity of `idx` is checked at run-time, and `EINVAL` is returned is the
- /// access was out-of-bounds.
- #[inline(always)]
- pub(crate) fn try_update<T, I, F>(
- io: &T,
- idx: usize,
- f: F,
- ) -> ::kernel::error::Result where
- T: ::core::ops::Deref<Target = I>,
- I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<u32>,
- F: ::core::ops::FnOnce(Self) -> Self,
- {
- if idx < Self::SIZE {
- Ok(Self::update(io, idx, f))
- } else {
- Err(EINVAL)
- }
- }
- }
- };
-
- // Generates the IO accessors for an array of relative registers.
- (
- @io_relative_array $name:ident @ $base:ty
- [ $offset:literal [ $size:expr ; $stride:expr ] ]
- ) => {
- #[allow(dead_code)]
- impl $name {
- pub(crate) const OFFSET: usize = $offset;
- pub(crate) const SIZE: usize = $size;
- pub(crate) const STRIDE: usize = $stride;
-
- /// Read the array register at index `idx` from `io`, using the base address provided
- /// by `base` and adding the register's offset to it.
- #[inline(always)]
- pub(crate) fn read<T, I, B>(
- io: &T,
- #[allow(unused_variables)]
- base: &B,
- idx: usize,
- ) -> Self where
- T: ::core::ops::Deref<Target = I>,
- I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<u32>,
- B: crate::regs::macros::RegisterBase<$base>,
- {
- build_assert!(idx < Self::SIZE);
-
- let offset = <B as crate::regs::macros::RegisterBase<$base>>::BASE +
- Self::OFFSET + (idx * Self::STRIDE);
- let value = io.read32(offset);
-
- Self(value)
- }
-
- /// Write the value contained in `self` to `io`, using the base address provided by
- /// `base` and adding the offset of array register `idx` to it.
- #[inline(always)]
- pub(crate) fn write<T, I, B>(
- self,
- io: &T,
- #[allow(unused_variables)]
- base: &B,
- idx: usize
- ) where
- T: ::core::ops::Deref<Target = I>,
- I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<u32>,
- B: crate::regs::macros::RegisterBase<$base>,
- {
- build_assert!(idx < Self::SIZE);
-
- let offset = <B as crate::regs::macros::RegisterBase<$base>>::BASE +
- Self::OFFSET + (idx * Self::STRIDE);
-
- io.write32(self.0, offset);
- }
-
- /// Read the array register at index `idx` from `io`, using the base address provided
- /// by `base` and adding the register's offset to it, then run `f` on its value to
- /// obtain a new value to write back.
- #[inline(always)]
- pub(crate) fn update<T, I, B, F>(
- io: &T,
- base: &B,
- idx: usize,
- f: F,
- ) where
- T: ::core::ops::Deref<Target = I>,
- I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<u32>,
- B: crate::regs::macros::RegisterBase<$base>,
- F: ::core::ops::FnOnce(Self) -> Self,
- {
- let reg = f(Self::read(io, base, idx));
- reg.write(io, base, idx);
- }
-
- /// Read the array register at index `idx` from `io`, using the base address provided
- /// by `base` and adding the register's offset to it.
- ///
- /// The validity of `idx` is checked at run-time, and `EINVAL` is returned is the
- /// access was out-of-bounds.
- #[inline(always)]
- pub(crate) fn try_read<T, I, B>(
- io: &T,
- base: &B,
- idx: usize,
- ) -> ::kernel::error::Result<Self> where
- T: ::core::ops::Deref<Target = I>,
- I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<u32>,
- B: crate::regs::macros::RegisterBase<$base>,
- {
- if idx < Self::SIZE {
- Ok(Self::read(io, base, idx))
- } else {
- Err(EINVAL)
- }
- }
-
- /// Write the value contained in `self` to `io`, using the base address provided by
- /// `base` and adding the offset of array register `idx` to it.
- ///
- /// The validity of `idx` is checked at run-time, and `EINVAL` is returned is the
- /// access was out-of-bounds.
- #[inline(always)]
- pub(crate) fn try_write<T, I, B>(
- self,
- io: &T,
- base: &B,
- idx: usize,
- ) -> ::kernel::error::Result where
- T: ::core::ops::Deref<Target = I>,
- I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<u32>,
- B: crate::regs::macros::RegisterBase<$base>,
- {
- if idx < Self::SIZE {
- Ok(self.write(io, base, idx))
- } else {
- Err(EINVAL)
- }
- }
-
- /// Read the array register at index `idx` from `io`, using the base address provided
- /// by `base` and adding the register's offset to it, then run `f` on its value to
- /// obtain a new value to write back.
- ///
- /// The validity of `idx` is checked at run-time, and `EINVAL` is returned is the
- /// access was out-of-bounds.
- #[inline(always)]
- pub(crate) fn try_update<T, I, B, F>(
- io: &T,
- base: &B,
- idx: usize,
- f: F,
- ) -> ::kernel::error::Result where
- T: ::core::ops::Deref<Target = I>,
- I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<u32>,
- B: crate::regs::macros::RegisterBase<$base>,
- F: ::core::ops::FnOnce(Self) -> Self,
- {
- if idx < Self::SIZE {
- Ok(Self::update(io, base, idx, f))
- } else {
- Err(EINVAL)
- }
- }
- }
- };
-}