summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorJani Nikula <jani.nikula@intel.com>2024-08-01 13:06:09 +0300
committerJani Nikula <jani.nikula@intel.com>2024-08-01 13:06:09 +0300
commit3663e2c4bc45fcdc71931fcbfcbfbf9b71f55c83 (patch)
tree3927fa90c7faa89131fcf2e789ca9de97a65dc5f /drivers/gpu/drm
parent688c43dd6ca9e0cd0568868aefca5b041695c3f4 (diff)
parent8400291e289ee6b2bf9779ff1c83a291501f017b (diff)
downloadlinux-3663e2c4bc45fcdc71931fcbfcbfbf9b71f55c83.tar.gz
linux-3663e2c4bc45fcdc71931fcbfcbfbf9b71f55c83.zip
Merge drm/drm-next into drm-intel-next
Sync with v6.11-rc1 in general, and specifically get the new BACKLIGHT_POWER_ constants for power states. Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/Kconfig19
-rw-r--r--drivers/gpu/drm/Makefile6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/Kconfig11
-rw-r--r--drivers/gpu/drm/amd/amdgpu/Makefile11
-rw-r--r--drivers/gpu/drm/amd/amdgpu/aldebaran.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu.h13
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c34
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_aca.h4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c16
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c15
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_device.c62
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_df.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c77
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_display.c94
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c34
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c13
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c11
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c14
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c75
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c51
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c210
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_isp.h60
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_job.c22
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h31
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c34
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_mca.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c18
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_object.c65
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c176
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c554
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h38
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h15
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c21
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h14
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c35
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c19
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c67
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c52
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c26
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c9
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c7
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c12
-rw-r--r--drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c50
-rw-r--r--drivers/gpu/drm/amd/amdgpu/atom.c8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/cik_sdma.c11
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_v10_0.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_v11_0.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_v6_0.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_v8_0.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/df_v4_15.c45
-rw-r--r--drivers/gpu/drm/amd/amdgpu/df_v4_15.h30
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c37
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c68
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v11_0_3.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c374
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c19
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c27
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c69
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c45
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c99
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfxhub_v12_0.c22
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfxhub_v1_2.c8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c7
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c14
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c7
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/ih_v6_0.c28
-rw-r--r--drivers/gpu/drm/amd/amdgpu/ih_v6_1.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/ih_v7_0.c26
-rw-r--r--drivers/gpu/drm/amd/amdgpu/imu_v11_0.c11
-rw-r--r--drivers/gpu/drm/amd/amdgpu/imu_v12_0.c17
-rw-r--r--drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.c137
-rw-r--r--drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.h39
-rw-r--r--drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.c137
-rw-r--r--drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.h39
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c29
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c165
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.h6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mes_v11_0.c81
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mes_v12_0.c77
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmhub_v3_3.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c64
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mxgpu_ai.h4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c68
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mxgpu_nv.h5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mxgpu_vi.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/nbif_v6_3_1.c14
-rw-r--r--drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/psp_gfx_if.h5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/psp_v13_0.c3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/psp_v14_0.c5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c11
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c11
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c20
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c12
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v6_0_0_pkt_open.h8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c18
-rw-r--r--drivers/gpu/drm/amd/amdgpu/smu_v13_0_10.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/soc21.c30
-rw-r--r--drivers/gpu/drm/amd/amdgpu/soc24.c5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/umc_v12_0.c22
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c14
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c14
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c11
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c16
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c20
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c64
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c16
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vpe_v6_1.c1
-rw-r--r--drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h16
-rw-r--r--drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm38
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_crat.c1
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_device.c8
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c80
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h1
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c3
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c27
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c32
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c8
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c3
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c67
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_priv.h4
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_process.c24
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c13
-rw-r--r--drivers/gpu/drm/amd/display/Kconfig2
-rw-r--r--drivers/gpu/drm/amd/display/Makefile7
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c729
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h37
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c49
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c10
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c12
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c248
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c158
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/Makefile6
-rw-r--r--drivers/gpu/drm/amd/display/dc/basics/dce_calcs.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/bios/bios_parser.c14
-rw-r--r--drivers/gpu/drm/amd/display/dc/bios/command_table2.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn201/dcn201_clk_mgr.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c10
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c10
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c16
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr_smu_msg.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/smu13_driver_if.h108
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c61
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.c21
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c103
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc.c43
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c13
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_resource.c111
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_state.c104
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_stream.c39
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_surface.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc.h21
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c36
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_spl_translate.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_types.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c61
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_audio.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c20
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dmub_abm_lcd.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c161
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dmub_replay.h33
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/Makefile1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn20/Makefile1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dwb_scl.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/Makefile2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn301/Makefile11
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn31/Makefile12
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn314/Makefile11
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn32/Makefile19
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn321/Makefile17
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn35/Makefile19
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn401/Makefile5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/Makefile99
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.c (renamed from drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c)8
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.h (renamed from drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c (renamed from drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.h (renamed from drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_link_encoder.c (renamed from drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.c)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_link_encoder.h (renamed from drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_stream_encoder.c (renamed from drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_stream_encoder.h (renamed from drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.h)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_link_encoder.c (renamed from drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.c)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_link_encoder.h (renamed from drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_stream_encoder.c (renamed from drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_stream_encoder.h (renamed from drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.h)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn31/dcn31_dio_link_encoder.c (renamed from drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.c)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn31/dcn31_dio_link_encoder.h (renamed from drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.h)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_link_encoder.c (renamed from drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.c)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_link_encoder.h (renamed from drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.h)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_stream_encoder.c (renamed from drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.c)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_stream_encoder.h (renamed from drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.h)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn321/dcn321_dio_link_encoder.c (renamed from drivers/gpu/drm/amd/display/dc/dcn321/dcn321_dio_link_encoder.c)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn321/dcn321_dio_link_encoder.h (renamed from drivers/gpu/drm/amd/display/dc/dcn321/dcn321_dio_link_encoder.h)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_link_encoder.c (renamed from drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_link_encoder.c)10
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_link_encoder.h (renamed from drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_link_encoder.h)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_stream_encoder.c (renamed from drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_stream_encoder.c)4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_stream_encoder.h (renamed from drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_stream_encoder.h)6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.c (renamed from drivers/gpu/drm/amd/display/dc/dcn401/dcn401_dio_link_encoder.c)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.h (renamed from drivers/gpu/drm/amd/display/dc/dcn401/dcn401_dio_link_encoder.h)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c (renamed from drivers/gpu/drm/amd/display/dc/dcn401/dcn401_dio_stream_encoder.c)4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.h (renamed from drivers/gpu/drm/amd/display/dc/dcn401/dcn401_dio_stream_encoder.h)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calcs.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c22
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20.c16
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c19
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c19
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c22
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c19
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c19
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c11
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn314/display_rq_dlg_calc_314.c19
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c15
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/display_mode_core.c57
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/display_mode_core_structs.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_utils.c35
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_utils.h4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c38
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c75
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_factory.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_shared.c74
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_dpmm/dml2_dpmm_factory.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_mcg/dml2_mcg_factory.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c21
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_pmo/dml2_pmo_factory.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_standalone_libraries/lib_float_math.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_top/dml_top.c21
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml21/src/inc/dml2_internal_shared_types.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c15
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml2_mall_phantom.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.c14
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c27
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c34
-rw-r--r--drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_cm.c50
-rw-r--r--drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.c24
-rw-r--r--drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.h13
-rw-r--r--drivers/gpu/drm/amd/display/dc/dsc/dcn35/dcn35_dsc.c58
-rw-r--r--drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dwb/Makefile37
-rw-r--r--drivers/gpu/drm/amd/display/dc/dwb/dcn35/dcn35_dwb.c (renamed from drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dwb.c)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/dwb/dcn35/dcn35_dwb.h (renamed from drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dwb.h)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c11
-rw-r--r--drivers/gpu/drm/amd/display/dc/gpio/hw_generic.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/hpo/Makefile35
-rw-r--r--drivers/gpu/drm/amd/display/dc/hpo/dcn32/dcn32_hpo_dp_link_encoder.c (renamed from drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hpo_dp_link_encoder.c)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/hpo/dcn32/dcn32_hpo_dp_link_encoder.h (renamed from drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hpo_dp_link_encoder.h)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubbub/dcn20/dcn20_hubbub.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubbub/dcn30/dcn30_hubbub.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubbub/dcn31/dcn31_hubbub.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c286
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.h5
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.h14
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c82
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.h14
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c70
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c70
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c48
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_hwseq.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn21/dcn21_hwseq.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c19
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c113
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c159
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c328
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h5
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h9
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/core_types.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h4
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h22
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/hubp.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/mpc.h14
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/opp.h15
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/link.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/irq_service.c2
-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_dio.c29
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.h9
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/link_dpms.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/link_factory.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c71
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c24
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c11
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c9
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/mmhubbub/Makefile45
-rw-r--r--drivers/gpu/drm/amd/display/dc/mmhubbub/dcn32/dcn32_mmhubbub.c (renamed from drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mmhubbub.c)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/mmhubbub/dcn32/dcn32_mmhubbub.h (renamed from drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mmhubbub.h)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/mmhubbub/dcn35/dcn35_mmhubbub.c (renamed from drivers/gpu/drm/amd/display/dc/dcn35/dcn35_mmhubbub.c)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/mmhubbub/dcn35/dcn35_mmhubbub.h (renamed from drivers/gpu/drm/amd/display/dc/dcn35/dcn35_mmhubbub.h)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/mpc/Makefile45
-rw-r--r--drivers/gpu/drm/amd/display/dc/mpc/dcn32/dcn32_mpc.c (renamed from drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/mpc/dcn32/dcn32_mpc.h (renamed from drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.h)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/mpc/dcn401/dcn401_mpc.c (renamed from drivers/gpu/drm/amd/display/dc/dcn401/dcn401_mpc.c)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/mpc/dcn401/dcn401_mpc.h (renamed from drivers/gpu/drm/amd/display/dc/dcn401/dcn401_mpc.h)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/opp/Makefile35
-rw-r--r--drivers/gpu/drm/amd/display/dc/opp/dcn35/dcn35_opp.c (renamed from drivers/gpu/drm/amd/display/dc/dcn35/dcn35_opp.c)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/opp/dcn35/dcn35_opp.h (renamed from drivers/gpu/drm/amd/display/dc/dcn35/dcn35_opp.h)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.c15
-rw-r--r--drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.c10
-rw-r--r--drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.c11
-rw-r--r--drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c13
-rw-r--r--drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/optc/dcn401/dcn401_optc.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/optc/dcn401/dcn401_optc.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/pg/Makefile35
-rw-r--r--drivers/gpu/drm/amd/display/dc/pg/dcn35/dcn35_pg_cntl.c (renamed from drivers/gpu/drm/amd/display/dc/dcn35/dcn35_pg_cntl.c)6
-rw-r--r--drivers/gpu/drm/amd/display/dc/pg/dcn35/dcn35_pg_cntl.h (renamed from drivers/gpu/drm/amd/display/dc/dcn35/dcn35_pg_cntl.h)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/Makefile2
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c15
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c22
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c10
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource_helpers.c (renamed from drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c10
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c22
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/spl/dc_spl.c40
-rw-r--r--drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h4
-rw-r--r--drivers/gpu/drm/amd/display/dmub/dmub_srv.h3
-rw-r--r--drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h187
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c6
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_srv_stat.c6
-rw-r--r--drivers/gpu/drm/amd/display/include/dpcd_defs.h5
-rw-r--r--drivers/gpu/drm/amd/display/modules/freesync/freesync.c2
-rw-r--r--drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c24
-rw-r--r--drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c12
-rw-r--r--drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c3
-rw-r--r--drivers/gpu/drm/amd/display/modules/power/power_helpers.c14
-rw-r--r--drivers/gpu/drm/amd/display/modules/power/power_helpers.h5
-rw-r--r--drivers/gpu/drm/amd/include/amd_shared.h2
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_4_1_0_offset.h18
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_4_1_0_sh_mask.h110
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/df/df_4_15_offset.h28
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/df/df_4_15_sh_mask.h28
-rw-r--r--drivers/gpu/drm/amd/include/atomfirmware.h2
-rw-r--r--drivers/gpu/drm/amd/include/ivsrcid/isp/irqsrcs_isp_4_1.h62
-rw-r--r--drivers/gpu/drm/amd/pm/amdgpu_dpm.c2
-rw-r--r--drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c2
-rw-r--r--drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c8
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/pptable_v1_0.h36
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h38
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c35
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h12
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v14_0_0_ppsmc.h4
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h6
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c4
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c6
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c5
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c6
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c3
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c18
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c26
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c261
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c30
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c36
-rw-r--r--drivers/gpu/drm/arm/display/komeda/komeda_crtc.c49
-rw-r--r--drivers/gpu/drm/arm/display/komeda/komeda_dev.c8
-rw-r--r--drivers/gpu/drm/arm/display/komeda/komeda_drv.c8
-rw-r--r--drivers/gpu/drm/arm/display/komeda/komeda_kms.h1
-rw-r--r--drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c4
-rw-r--r--drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c2
-rw-r--r--drivers/gpu/drm/ast/ast_drv.c4
-rw-r--r--drivers/gpu/drm/ast/ast_mode.c249
-rw-r--r--drivers/gpu/drm/ast/ast_reg.h10
-rw-r--r--drivers/gpu/drm/atmel-hlcdc/Kconfig2
-rw-r--r--drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c172
-rw-r--r--drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c105
-rw-r--r--drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h132
-rw-r--r--drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c369
-rw-r--r--drivers/gpu/drm/bridge/adv7511/adv7511.h2
-rw-r--r--drivers/gpu/drm/bridge/adv7511/adv7511_cec.c13
-rw-r--r--drivers/gpu/drm/bridge/adv7511/adv7511_drv.c27
-rw-r--r--drivers/gpu/drm/bridge/analogix/analogix-anx6345.c20
-rw-r--r--drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c28
-rw-r--r--drivers/gpu/drm/bridge/analogix/analogix_dp_core.c365
-rw-r--r--drivers/gpu/drm/bridge/analogix/analogix_dp_core.h29
-rw-r--r--drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c157
-rw-r--r--drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h9
-rw-r--r--drivers/gpu/drm/bridge/analogix/anx7625.c36
-rw-r--r--drivers/gpu/drm/bridge/analogix/anx7625.h10
-rw-r--r--drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c5
-rw-r--r--drivers/gpu/drm/bridge/imx/imx-ldb-helper.c5
-rw-r--r--drivers/gpu/drm/bridge/imx/imx8qxp-pixel-combiner.c5
-rw-r--r--drivers/gpu/drm/bridge/imx/imx8qxp-pixel-link.c5
-rw-r--r--drivers/gpu/drm/bridge/imx/imx8qxp-pxl2dpi.c5
-rw-r--r--drivers/gpu/drm/bridge/ite-it6505.c80
-rw-r--r--drivers/gpu/drm/bridge/lontium-lt9611.c1
-rw-r--r--drivers/gpu/drm/bridge/lontium-lt9611uxc.c6
-rw-r--r--drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c5
-rw-r--r--drivers/gpu/drm/bridge/nxp-ptn3460.c5
-rw-r--r--drivers/gpu/drm/bridge/panel.c12
-rw-r--r--drivers/gpu/drm/bridge/samsung-dsim.c25
-rw-r--r--drivers/gpu/drm/bridge/sii902x.c46
-rw-r--r--drivers/gpu/drm/bridge/sii9234.c1
-rw-r--r--drivers/gpu/drm/bridge/sil-sii8620.c1
-rw-r--r--drivers/gpu/drm/bridge/simple-bridge.c18
-rw-r--r--drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c5
-rw-r--r--drivers/gpu/drm/bridge/tc358767.c101
-rw-r--r--drivers/gpu/drm/bridge/ti-tfp410.c5
-rw-r--r--drivers/gpu/drm/ci/build-igt.sh41
-rw-r--r--drivers/gpu/drm/ci/build.sh10
-rw-r--r--drivers/gpu/drm/ci/build.yml1
-rw-r--r--drivers/gpu/drm/ci/container.yml12
-rw-r--r--drivers/gpu/drm/ci/gitlab-ci.yml47
-rwxr-xr-xdrivers/gpu/drm/ci/igt_runner.sh15
-rw-r--r--drivers/gpu/drm/ci/image-tags.yml4
-rwxr-xr-xdrivers/gpu/drm/ci/lava-submit.sh4
-rw-r--r--drivers/gpu/drm/ci/test.yml41
-rw-r--r--drivers/gpu/drm/ci/testlist.txt2761
-rw-r--r--drivers/gpu/drm/ci/x86_64.config1
-rw-r--r--drivers/gpu/drm/ci/xfails/amdgpu-stoney-fails.txt41
-rw-r--r--drivers/gpu/drm/ci/xfails/amdgpu-stoney-flakes.txt7
-rw-r--r--drivers/gpu/drm/ci/xfails/amdgpu-stoney-skips.txt33
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-amly-fails.txt31
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-amly-flakes.txt9
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-amly-skips.txt22
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-apl-fails.txt46
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-apl-flakes.txt6
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-apl-skips.txt26
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-cml-fails.txt38
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-cml-flakes.txt6
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-cml-skips.txt23
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-glk-fails.txt41
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-glk-flakes.txt7
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-glk-skips.txt26
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-kbl-fails.txt42
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-kbl-flakes.txt7
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-kbl-skips.txt36
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-tgl-fails.txt77
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-tgl-skips.txt28
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-whl-fails.txt63
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-whl-flakes.txt6
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-whl-skips.txt22
-rw-r--r--drivers/gpu/drm/ci/xfails/mediatek-mt8173-fails.txt30
-rw-r--r--drivers/gpu/drm/ci/xfails/mediatek-mt8173-flakes.txt11
-rw-r--r--drivers/gpu/drm/ci/xfails/mediatek-mt8173-skips.txt16
-rw-r--r--drivers/gpu/drm/ci/xfails/mediatek-mt8183-fails.txt21
-rw-r--r--drivers/gpu/drm/ci/xfails/mediatek-mt8183-skips.txt18
-rw-r--r--drivers/gpu/drm/ci/xfails/meson-g12b-fails.txt24
-rw-r--r--drivers/gpu/drm/ci/xfails/meson-g12b-skips.txt18
-rw-r--r--drivers/gpu/drm/ci/xfails/msm-apq8016-fails.txt26
-rw-r--r--drivers/gpu/drm/ci/xfails/msm-apq8016-skips.txt15
-rw-r--r--drivers/gpu/drm/ci/xfails/msm-apq8096-fails.txt8
-rw-r--r--drivers/gpu/drm/ci/xfails/msm-apq8096-flakes.txt6
-rw-r--r--drivers/gpu/drm/ci/xfails/msm-apq8096-skips.txt26
-rw-r--r--drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-fails.txt175
-rw-r--r--drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-flakes.txt8
-rw-r--r--drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-skips.txt19
-rw-r--r--drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-fails.txt175
-rw-r--r--drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-flakes.txt6
-rw-r--r--drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-skips.txt16
-rw-r--r--drivers/gpu/drm/ci/xfails/msm-sdm845-fails.txt38
-rw-r--r--drivers/gpu/drm/ci/xfails/msm-sdm845-flakes.txt25
-rw-r--r--drivers/gpu/drm/ci/xfails/msm-sdm845-skips.txt19
-rw-r--r--drivers/gpu/drm/ci/xfails/rockchip-rk3288-fails.txt62
-rw-r--r--drivers/gpu/drm/ci/xfails/rockchip-rk3288-skips.txt21
-rw-r--r--drivers/gpu/drm/ci/xfails/rockchip-rk3399-fails.txt83
-rw-r--r--drivers/gpu/drm/ci/xfails/rockchip-rk3399-flakes.txt13
-rw-r--r--drivers/gpu/drm/ci/xfails/rockchip-rk3399-skips.txt19
-rwxr-xr-xdrivers/gpu/drm/ci/xfails/update-xfails.py4
-rw-r--r--drivers/gpu/drm/ci/xfails/virtio_gpu-none-fails.txt94
-rw-r--r--drivers/gpu/drm/ci/xfails/virtio_gpu-none-skips.txt20
-rw-r--r--drivers/gpu/drm/ci/xfails/vkms-none-fails.txt57
-rw-r--r--drivers/gpu/drm/ci/xfails/vkms-none-flakes.txt69
-rw-r--r--drivers/gpu/drm/ci/xfails/vkms-none-skips.txt119
-rw-r--r--drivers/gpu/drm/display/Kconfig7
-rw-r--r--drivers/gpu/drm/display/Makefile2
-rw-r--r--drivers/gpu/drm/display/drm_dp_aux_bus.c2
-rw-r--r--drivers/gpu/drm/display/drm_dp_helper.c5
-rw-r--r--drivers/gpu/drm/display/drm_dp_mst_topology.c15
-rw-r--r--drivers/gpu/drm/display/drm_dsc_helper.c91
-rw-r--r--drivers/gpu/drm/display/drm_hdmi_helper.c61
-rw-r--r--drivers/gpu/drm/display/drm_hdmi_state_helper.c752
-rw-r--r--drivers/gpu/drm/drm_atomic.c11
-rw-r--r--drivers/gpu/drm/drm_atomic_uapi.c4
-rw-r--r--drivers/gpu/drm/drm_bridge.c42
-rw-r--r--drivers/gpu/drm/drm_bridge_connector.c107
-rw-r--r--drivers/gpu/drm/drm_color_mgmt.c2
-rw-r--r--drivers/gpu/drm/drm_connector.c201
-rw-r--r--drivers/gpu/drm/drm_crtc_internal.h2
-rw-r--r--drivers/gpu/drm/drm_debugfs.c158
-rw-r--r--drivers/gpu/drm/drm_drv.c6
-rw-r--r--drivers/gpu/drm/drm_edid.c61
-rw-r--r--drivers/gpu/drm/drm_fb_helper.c17
-rw-r--r--drivers/gpu/drm/drm_fbdev_dma.c74
-rw-r--r--drivers/gpu/drm/drm_fbdev_shmem.c317
-rw-r--r--drivers/gpu/drm/drm_fbdev_ttm.c (renamed from drivers/gpu/drm/drm_fbdev_generic.c)83
-rw-r--r--drivers/gpu/drm/drm_file.c8
-rw-r--r--drivers/gpu/drm/drm_ioctl.c5
-rw-r--r--drivers/gpu/drm/drm_managed.c2
-rw-r--r--drivers/gpu/drm/drm_mipi_dbi.c77
-rw-r--r--drivers/gpu/drm/drm_mipi_dsi.c324
-rw-r--r--drivers/gpu/drm/drm_mm.c35
-rw-r--r--drivers/gpu/drm/drm_mode_object.c1
-rw-r--r--drivers/gpu/drm/drm_modes.c5
-rw-r--r--drivers/gpu/drm/drm_panel_orientation_quirks.c16
-rw-r--r--drivers/gpu/drm/drm_panic.c353
-rw-r--r--drivers/gpu/drm/drm_print.c72
-rw-r--r--drivers/gpu/drm/drm_probe_helper.c13
-rw-r--r--drivers/gpu/drm/drm_simple_kms_helper.c1
-rw-r--r--drivers/gpu/drm/drm_sysfs.c24
-rw-r--r--drivers/gpu/drm/etnaviv/cmdstream.xml.h52
-rw-r--r--drivers/gpu/drm/etnaviv/common.xml.h12
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_dump.c5
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_gem.c6
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_gpu.c83
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_gpu.h8
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_sched.c9
-rw-r--r--drivers/gpu/drm/etnaviv/state.xml.h103
-rw-r--r--drivers/gpu/drm/etnaviv/state_blt.xml.h22
-rw-r--r--drivers/gpu/drm/etnaviv/state_hi.xml.h30
-rw-r--r--drivers/gpu/drm/exynos/exynos_dp.c6
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_vidi.c83
-rw-r--r--drivers/gpu/drm/exynos/exynos_hdmi.c7
-rw-r--r--drivers/gpu/drm/gma500/cdv_intel_dp.c2
-rw-r--r--drivers/gpu/drm/gma500/cdv_intel_lvds.c3
-rw-r--r--drivers/gpu/drm/gma500/psb_intel_lvds.c3
-rw-r--r--drivers/gpu/drm/gud/gud_drv.c5
-rw-r--r--drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c4
-rw-r--r--drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c17
-rw-r--r--drivers/gpu/drm/hisilicon/kirin/Kconfig2
-rw-r--r--drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c11
-rw-r--r--drivers/gpu/drm/hisilicon/kirin/dw_dsi_reg.h2
-rw-r--r--drivers/gpu/drm/hisilicon/kirin/kirin_ade_reg.h2
-rw-r--r--drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c4
-rw-r--r--drivers/gpu/drm/hyperv/hyperv_drm_drv.c4
-rw-r--r--drivers/gpu/drm/i2c/tda998x_drv.c19
-rw-r--r--drivers/gpu/drm/i915/Kconfig.debug17
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_context.c113
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c2
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_stolen.c8
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c2
-rw-r--r--drivers/gpu/drm/i915/gt/intel_context.c2
-rw-r--r--drivers/gpu/drm/i915/gt/intel_context.h22
-rw-r--r--drivers/gpu/drm/i915/gt/intel_context_types.h3
-rw-r--r--drivers/gpu/drm/i915/gt/intel_execlists_submission.c6
-rw-r--r--drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c1
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c4
-rw-r--r--drivers/gpu/drm/i915/gt/intel_lrc.c8
-rw-r--r--drivers/gpu/drm/i915/gt/intel_reset.c2
-rw-r--r--drivers/gpu/drm/i915/gt/intel_ring_submission.c8
-rw-r--r--drivers/gpu/drm/i915/gt/intel_workarounds.c8
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_context.c2
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c110
-rw-r--r--drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h1
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c32
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h2
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c27
-rw-r--r--drivers/gpu/drm/i915/gvt/kvmgt.c1
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h4
-rw-r--r--drivers/gpu/drm/i915/i915_params.c5
-rw-r--r--drivers/gpu/drm/i915/i915_params.h3
-rw-r--r--drivers/gpu/drm/i915/i915_pci.c6
-rw-r--r--drivers/gpu/drm/i915/i915_scatterlist.c8
-rw-r--r--drivers/gpu/drm/i915/intel_memory_region.c8
-rw-r--r--drivers/gpu/drm/i915/intel_memory_region.h5
-rw-r--r--drivers/gpu/drm/i915/intel_uncore.c9
-rw-r--r--drivers/gpu/drm/i915/selftests/mock_gem_device.c2
-rw-r--r--drivers/gpu/drm/imagination/pvr_drv.c7
-rw-r--r--drivers/gpu/drm/imx/ipuv3/imx-ldb.c24
-rw-r--r--drivers/gpu/drm/imx/ipuv3/imx-tve.c14
-rw-r--r--drivers/gpu/drm/imx/lcdc/imx-lcdc.c4
-rw-r--r--drivers/gpu/drm/ingenic/ingenic-drm-drv.c4
-rw-r--r--drivers/gpu/drm/lima/lima_drv.c1
-rw-r--r--drivers/gpu/drm/loongson/Kconfig1
-rw-r--r--drivers/gpu/drm/loongson/lsdc_drv.c4
-rw-r--r--drivers/gpu/drm/loongson/lsdc_output_7a1000.c15
-rw-r--r--drivers/gpu/drm/loongson/lsdc_output_7a2000.c15
-rw-r--r--drivers/gpu/drm/mediatek/Kconfig1
-rw-r--r--drivers/gpu/drm/mediatek/mtk_cec.c28
-rw-r--r--drivers/gpu/drm/mediatek/mtk_ddp_comp.c109
-rw-r--r--drivers/gpu/drm/mediatek/mtk_ddp_comp.h8
-rw-r--r--drivers/gpu/drm/mediatek/mtk_disp_aal.c18
-rw-r--r--drivers/gpu/drm/mediatek/mtk_disp_ccorr.c18
-rw-r--r--drivers/gpu/drm/mediatek/mtk_disp_color.c18
-rw-r--r--drivers/gpu/drm/mediatek/mtk_disp_gamma.c18
-rw-r--r--drivers/gpu/drm/mediatek/mtk_disp_merge.c25
-rw-r--r--drivers/gpu/drm/mediatek/mtk_disp_ovl.c140
-rw-r--r--drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c6
-rw-r--r--drivers/gpu/drm/mediatek/mtk_disp_rdma.c31
-rw-r--r--drivers/gpu/drm/mediatek/mtk_dp.c18
-rw-r--r--drivers/gpu/drm/mediatek/mtk_dpi.c5
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_drv.c36
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_drv.h4
-rw-r--r--drivers/gpu/drm/mediatek/mtk_dsi.c5
-rw-r--r--drivers/gpu/drm/mediatek/mtk_ethdr.c46
-rw-r--r--drivers/gpu/drm/mediatek/mtk_hdmi.c42
-rw-r--r--drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c21
-rw-r--r--drivers/gpu/drm/mediatek/mtk_mdp_rdma.c18
-rw-r--r--drivers/gpu/drm/mediatek/mtk_padding.c25
-rw-r--r--drivers/gpu/drm/mediatek/mtk_plane.c4
-rw-r--r--drivers/gpu/drm/meson/meson_drv.c37
-rw-r--r--drivers/gpu/drm/meson/meson_plane.c17
-rw-r--r--drivers/gpu/drm/mgag200/Kconfig18
-rw-r--r--drivers/gpu/drm/mgag200/Makefile5
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_bmc.c107
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_ddc.c179
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_ddc.h11
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_drv.c27
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_drv.h46
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_g200.c46
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_g200eh.c46
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_g200eh3.c46
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_g200er.c46
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_g200ev.c46
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_g200ew3.c46
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_g200se.c46
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_g200wb.c46
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_i2c.c129
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_mode.c41
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_reg.h2
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_vga.c72
-rw-r--r--drivers/gpu/drm/msm/Kconfig1
-rw-r--r--drivers/gpu/drm/msm/Makefile5
-rw-r--r--drivers/gpu/drm/msm/adreno/a2xx_catalog.c52
-rw-r--r--drivers/gpu/drm/msm/adreno/a3xx_catalog.c81
-rw-r--r--drivers/gpu/drm/msm/adreno/a4xx_catalog.c50
-rw-r--r--drivers/gpu/drm/msm/adreno/a5xx_catalog.c161
-rw-r--r--drivers/gpu/drm/msm/adreno/a5xx_gpu.c29
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_catalog.c1259
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gmu.c38
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gpu.c995
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gpu.h12
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c13
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_device.c624
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.c6
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.h44
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_2_sm7150.h335
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c25
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h2
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c61
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h15
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h13
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c36
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c34
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c14
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c7
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h1
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h3
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c19
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h5
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h26
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c14
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h2
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c45
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c7
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h4
-rw-r--r--drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c91
-rw-r--r--drivers/gpu/drm/msm/dp/dp_aux.c5
-rw-r--r--drivers/gpu/drm/msm/dp/dp_display.c11
-rw-r--r--drivers/gpu/drm/msm/dp/dp_panel.c47
-rw-r--r--drivers/gpu/drm/msm/dp/dp_panel.h2
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi.h1
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_host.c59
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_manager.c5
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy.c2
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy.h6
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c273
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c218
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c109
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c323
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c205
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c320
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h11
-rw-r--r--drivers/gpu/drm/msm/msm_gem.c37
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.c6
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.h9
-rw-r--r--drivers/gpu/drm/msm/msm_iommu.c7
-rw-r--r--drivers/gpu/drm/msm/msm_mdss.c8
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/disp.c2
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/tvnv17.c6
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/disp.c10
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/head.c8
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h6
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bios.c5
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bo.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_chan.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.c5
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.c6
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_dmem.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drm.c6
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.h1
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_exec.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fence.c30
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fence.h2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_gem.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_sched.h4
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_uvmm.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c362
-rw-r--r--drivers/gpu/drm/omapdrm/Kconfig2
-rw-r--r--drivers/gpu/drm/omapdrm/omap_gem.c4
-rw-r--r--drivers/gpu/drm/panel/Kconfig29
-rw-r--r--drivers/gpu/drm/panel/Makefile3
-rw-r--r--drivers/gpu/drm/panel/panel-abt-y030xx067a.c1
-rw-r--r--drivers/gpu/drm/panel/panel-asus-z00t-tm5p5-n35596.c140
-rw-r--r--drivers/gpu/drm/panel/panel-auo-a030jtn01.c1
-rw-r--r--drivers/gpu/drm/panel/panel-boe-himax8279d.c40
-rw-r--r--drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c2757
-rw-r--r--drivers/gpu/drm/panel/panel-edp.c260
-rw-r--r--drivers/gpu/drm/panel/panel-himax-hx83102.c706
-rw-r--r--drivers/gpu/drm/panel/panel-himax-hx8394.c3
-rw-r--r--drivers/gpu/drm/panel/panel-ilitek-ili9341.c7
-rw-r--r--drivers/gpu/drm/panel/panel-ilitek-ili9806e.c402
-rw-r--r--drivers/gpu/drm/panel/panel-ilitek-ili9882t.c830
-rw-r--r--drivers/gpu/drm/panel/panel-innolux-ej030na.c1
-rw-r--r--drivers/gpu/drm/panel/panel-innolux-p079zca.c332
-rw-r--r--drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c1088
-rw-r--r--drivers/gpu/drm/panel/panel-jdi-lt070me05000.c35
-rw-r--r--drivers/gpu/drm/panel/panel-khadas-ts050.c39
-rw-r--r--drivers/gpu/drm/panel/panel-kingdisplay-kd097d04.c48
-rw-r--r--drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c28
-rw-r--r--drivers/gpu/drm/panel/panel-leadtek-ltk500hd1829.c28
-rw-r--r--drivers/gpu/drm/panel/panel-lg-sw43408.c74
-rw-r--r--drivers/gpu/drm/panel/panel-lincolntech-lcd197.c262
-rw-r--r--drivers/gpu/drm/panel/panel-newvision-nv3052c.c226
-rw-r--r--drivers/gpu/drm/panel/panel-novatek-nt36672a.c29
-rw-r--r--drivers/gpu/drm/panel/panel-novatek-nt36672e.c647
-rw-r--r--drivers/gpu/drm/panel/panel-novatek-nt39016.c1
-rw-r--r--drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c44
-rw-r--r--drivers/gpu/drm/panel/panel-orisetech-ota5601a.c1
-rw-r--r--drivers/gpu/drm/panel/panel-osd-osd101t2587-53ts.c41
-rw-r--r--drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c47
-rw-r--r--drivers/gpu/drm/panel/panel-raydium-rm67191.c26
-rw-r--r--drivers/gpu/drm/panel/panel-raydium-rm692e5.c246
-rw-r--r--drivers/gpu/drm/panel/panel-samsung-atna33xc20.c36
-rw-r--r--drivers/gpu/drm/panel/panel-seiko-43wvf1g.c49
-rw-r--r--drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c65
-rw-r--r--drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c24
-rw-r--r--drivers/gpu/drm/panel/panel-simple.c213
-rw-r--r--drivers/gpu/drm/panel/panel-sitronix-st7703.c871
-rw-r--r--drivers/gpu/drm/panel/panel-sony-acx565akm.c6
-rw-r--r--drivers/gpu/drm/panel/panel-sony-tulip-truly-nt35521.c433
-rw-r--r--drivers/gpu/drm/panel/panel-tdo-tl070wsh30.c23
-rw-r--r--drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c28
-rw-r--r--drivers/gpu/drm/panfrost/panfrost_drv.c11
-rw-r--r--drivers/gpu/drm/panthor/panthor_drv.c6
-rw-r--r--drivers/gpu/drm/panthor/panthor_sched.c45
-rw-r--r--drivers/gpu/drm/qxl/qxl_display.c17
-rw-r--r--drivers/gpu/drm/qxl/qxl_drv.c4
-rw-r--r--drivers/gpu/drm/qxl/qxl_object.c13
-rw-r--r--drivers/gpu/drm/qxl/qxl_object.h4
-rw-r--r--drivers/gpu/drm/radeon/atombios_encoders.c10
-rw-r--r--drivers/gpu/drm/radeon/evergreen_hdmi.c5
-rw-r--r--drivers/gpu/drm/radeon/radeon_audio.c13
-rw-r--r--drivers/gpu/drm/radeon/radeon_connectors.c27
-rw-r--r--drivers/gpu/drm/radeon/radeon_display.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_encoders.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_gem.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_mode.h2
-rw-r--r--drivers/gpu/drm/radeon/sumo_dpm.c2
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/Kconfig2
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rcar_du_drv.c4
-rw-r--r--drivers/gpu/drm/renesas/rz-du/rzg2l_du_drv.c4
-rw-r--r--drivers/gpu/drm/renesas/shmobile/shmob_drm_drv.c12
-rw-r--r--drivers/gpu/drm/rockchip/Kconfig3
-rw-r--r--drivers/gpu/drm/rockchip/analogix_dp-rockchip.c26
-rw-r--r--drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c20
-rw-r--r--drivers/gpu/drm/rockchip/inno_hdmi.c152
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_drv.c4
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_vop2.c2
-rw-r--r--drivers/gpu/drm/solomon/ssd130x.c4
-rw-r--r--drivers/gpu/drm/sti/Kconfig2
-rw-r--r--drivers/gpu/drm/sti/sti_dvo.c1
-rw-r--r--drivers/gpu/drm/stm/Kconfig13
-rw-r--r--drivers/gpu/drm/stm/Makefile2
-rw-r--r--drivers/gpu/drm/stm/dw_mipi_dsi-stm.c279
-rw-r--r--drivers/gpu/drm/stm/lvds.c1224
-rw-r--r--drivers/gpu/drm/sun4i/Kconfig3
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_backend.c4
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_crtc.c2
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c83
-rw-r--r--drivers/gpu/drm/sun4i/sun8i_mixer.c70
-rw-r--r--drivers/gpu/drm/sun4i/sun8i_mixer.h20
-rw-r--r--drivers/gpu/drm/sun4i/sun8i_ui_layer.c85
-rw-r--r--drivers/gpu/drm/sun4i/sun8i_ui_layer.h20
-rw-r--r--drivers/gpu/drm/sun4i/sun8i_vi_layer.c86
-rw-r--r--drivers/gpu/drm/sun4i/sun8i_vi_layer.h20
-rw-r--r--drivers/gpu/drm/sun4i/sunxi_engine.h13
-rw-r--r--drivers/gpu/drm/tests/Makefile1
-rw-r--r--drivers/gpu/drm/tests/drm_buddy_test.c1
-rw-r--r--drivers/gpu/drm/tests/drm_cmdline_parser_test.c12
-rw-r--r--drivers/gpu/drm/tests/drm_connector_test.c1053
-rw-r--r--drivers/gpu/drm/tests/drm_damage_helper_test.c1
-rw-r--r--drivers/gpu/drm/tests/drm_dp_mst_helper_test.c1
-rw-r--r--drivers/gpu/drm/tests/drm_exec_test.c1
-rw-r--r--drivers/gpu/drm/tests/drm_format_test.c1
-rw-r--r--drivers/gpu/drm/tests/drm_framebuffer_test.c1
-rw-r--r--drivers/gpu/drm/tests/drm_gem_shmem_test.c1
-rw-r--r--drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c1744
-rw-r--r--drivers/gpu/drm/tests/drm_kunit_edid.h484
-rw-r--r--drivers/gpu/drm/tests/drm_kunit_helpers.c1
-rw-r--r--drivers/gpu/drm/tests/drm_managed_test.c1
-rw-r--r--drivers/gpu/drm/tests/drm_mm_test.c1
-rw-r--r--drivers/gpu/drm/tests/drm_modes_test.c32
-rw-r--r--drivers/gpu/drm/tests/drm_plane_helper_test.c1
-rw-r--r--drivers/gpu/drm/tests/drm_probe_helper_test.c1
-rw-r--r--drivers/gpu/drm/tests/drm_rect_test.c1
-rw-r--r--drivers/gpu/drm/tidss/tidss_plane.c14
-rw-r--r--drivers/gpu/drm/tiny/bochs.c28
-rw-r--r--drivers/gpu/drm/tiny/cirrus.c5
-rw-r--r--drivers/gpu/drm/tiny/gm12u320.c5
-rw-r--r--drivers/gpu/drm/tiny/hx8357d.c4
-rw-r--r--drivers/gpu/drm/tiny/ili9163.c4
-rw-r--r--drivers/gpu/drm/tiny/ili9225.c5
-rw-r--r--drivers/gpu/drm/tiny/ili9341.c4
-rw-r--r--drivers/gpu/drm/tiny/ili9486.c4
-rw-r--r--drivers/gpu/drm/tiny/mi0283qt.c5
-rw-r--r--drivers/gpu/drm/tiny/ofdrm.c4
-rw-r--r--drivers/gpu/drm/tiny/panel-mipi-dbi.c60
-rw-r--r--drivers/gpu/drm/tiny/repaper.c4
-rw-r--r--drivers/gpu/drm/tiny/simpledrm.c4
-rw-r--r--drivers/gpu/drm/tiny/st7586.c5
-rw-r--r--drivers/gpu/drm/tiny/st7735r.c4
-rw-r--r--drivers/gpu/drm/ttm/tests/.kunitconfig1
-rw-r--r--drivers/gpu/drm/ttm/tests/Makefile2
-rw-r--r--drivers/gpu/drm/ttm/tests/TODO27
-rw-r--r--drivers/gpu/drm/ttm/tests/ttm_bo_test.c63
-rw-r--r--drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c1225
-rw-r--r--drivers/gpu/drm/ttm/tests/ttm_device_test.c3
-rw-r--r--drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.c176
-rw-r--r--drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.h17
-rw-r--r--drivers/gpu/drm/ttm/tests/ttm_mock_manager.c234
-rw-r--r--drivers/gpu/drm/ttm/tests/ttm_mock_manager.h30
-rw-r--r--drivers/gpu/drm/ttm/tests/ttm_pool_test.c9
-rw-r--r--drivers/gpu/drm/ttm/tests/ttm_resource_test.c21
-rw-r--r--drivers/gpu/drm/ttm/tests/ttm_tt_test.c169
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo.c1
-rw-r--r--drivers/gpu/drm/ttm/ttm_tt.c3
-rw-r--r--drivers/gpu/drm/udl/Makefile8
-rw-r--r--drivers/gpu/drm/udl/udl_drv.c5
-rw-r--r--drivers/gpu/drm/udl/udl_drv.h12
-rw-r--r--drivers/gpu/drm/udl/udl_edid.c80
-rw-r--r--drivers/gpu/drm/udl/udl_edid.h15
-rw-r--r--drivers/gpu/drm/udl/udl_modeset.c138
-rw-r--r--drivers/gpu/drm/v3d/v3d_drv.c16
-rw-r--r--drivers/gpu/drm/v3d/v3d_drv.h19
-rw-r--r--drivers/gpu/drm/v3d/v3d_perfmon.c228
-rw-r--r--drivers/gpu/drm/v3d/v3d_performance_counters.h29
-rw-r--r--drivers/gpu/drm/v3d/v3d_sched.c18
-rw-r--r--drivers/gpu/drm/vboxvideo/vbox_drv.c4
-rw-r--r--drivers/gpu/drm/vboxvideo/vbox_main.c20
-rw-r--r--drivers/gpu/drm/vc4/Kconfig1
-rw-r--r--drivers/gpu/drm/vc4/tests/vc4_mock.c6
-rw-r--r--drivers/gpu/drm/vc4/tests/vc4_mock.h9
-rw-r--r--drivers/gpu/drm/vc4/tests/vc4_mock_plane.c44
-rw-r--r--drivers/gpu/drm/vc4/vc4_hdmi.c644
-rw-r--r--drivers/gpu/drm/vc4/vc4_hdmi.h44
-rw-r--r--drivers/gpu/drm/vc4/vc4_hdmi_phy.c6
-rw-r--r--drivers/gpu/drm/vc4/vc4_vec.c31
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_display.c10
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_drv.c4
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_drv.h2
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_kms.c9
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_vq.c12
-rw-r--r--drivers/gpu/drm/vkms/vkms_drv.c4
-rw-r--r--drivers/gpu/drm/vmwgfx/Kconfig2
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.c4
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_msg.c173
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_msg_arm64.h196
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_msg_x86.h185
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_vkms.c1
-rw-r--r--drivers/gpu/drm/xe/Kconfig1
-rw-r--r--drivers/gpu/drm/xe/Makefile7
-rw-r--r--drivers/gpu/drm/xe/abi/guc_actions_abi.h6
-rw-r--r--drivers/gpu/drm/xe/abi/guc_actions_slpc_abi.h22
-rw-r--r--drivers/gpu/drm/xe/abi/guc_errors_abi.h31
-rw-r--r--drivers/gpu/drm/xe/abi/guc_messages_abi.h41
-rw-r--r--drivers/gpu/drm/xe/display/xe_fb_pin.c4
-rw-r--r--drivers/gpu/drm/xe/display/xe_hdcp_gsc.c12
-rw-r--r--drivers/gpu/drm/xe/instructions/xe_mi_commands.h5
-rw-r--r--drivers/gpu/drm/xe/regs/xe_engine_regs.h2
-rw-r--r--drivers/gpu/drm/xe/regs/xe_gt_regs.h11
-rw-r--r--drivers/gpu/drm/xe/regs/xe_oa_regs.h100
-rw-r--r--drivers/gpu/drm/xe/tests/xe_mocs.c8
-rw-r--r--drivers/gpu/drm/xe/tests/xe_rtp_test.c64
-rw-r--r--drivers/gpu/drm/xe/xe_bo.c58
-rw-r--r--drivers/gpu/drm/xe/xe_bo_types.h3
-rw-r--r--drivers/gpu/drm/xe/xe_devcoredump.c8
-rw-r--r--drivers/gpu/drm/xe/xe_device.c65
-rw-r--r--drivers/gpu/drm/xe/xe_device_types.h4
-rw-r--r--drivers/gpu/drm/xe/xe_drm_client.c11
-rw-r--r--drivers/gpu/drm/xe/xe_exec.c22
-rw-r--r--drivers/gpu/drm/xe/xe_exec_queue.c8
-rw-r--r--drivers/gpu/drm/xe/xe_exec_queue_types.h26
-rw-r--r--drivers/gpu/drm/xe/xe_force_wake.c102
-rw-r--r--drivers/gpu/drm/xe/xe_force_wake.h13
-rw-r--r--drivers/gpu/drm/xe/xe_ggtt.c47
-rw-r--r--drivers/gpu/drm/xe/xe_ggtt.h1
-rw-r--r--drivers/gpu/drm/xe/xe_ggtt_types.h12
-rw-r--r--drivers/gpu/drm/xe/xe_gsc.c5
-rw-r--r--drivers/gpu/drm/xe/xe_gt.c41
-rw-r--r--drivers/gpu/drm/xe/xe_gt.h2
-rw-r--r--drivers/gpu/drm/xe/xe_gt_ccs_mode.c9
-rw-r--r--drivers/gpu/drm/xe/xe_gt_clock.c20
-rw-r--r--drivers/gpu/drm/xe/xe_gt_clock.h1
-rw-r--r--drivers/gpu/drm/xe/xe_gt_idle.c16
-rw-r--r--drivers/gpu/drm/xe/xe_gt_mcr.c6
-rw-r--r--drivers/gpu/drm/xe/xe_gt_pagefault.c144
-rw-r--r--drivers/gpu/drm/xe/xe_gt_sriov_pf.c12
-rw-r--r--drivers/gpu/drm/xe/xe_gt_sriov_pf.h5
-rw-r--r--drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c94
-rw-r--r--drivers/gpu/drm/xe/xe_gt_sriov_pf_config.h4
-rw-r--r--drivers/gpu/drm/xe/xe_gt_sriov_pf_control.c21
-rw-r--r--drivers/gpu/drm/xe/xe_gt_sriov_pf_control.h1
-rw-r--r--drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c61
-rw-r--r--drivers/gpu/drm/xe/xe_gt_types.h4
-rw-r--r--drivers/gpu/drm/xe/xe_guc.c49
-rw-r--r--drivers/gpu/drm/xe/xe_guc.h1
-rw-r--r--drivers/gpu/drm/xe/xe_guc_ct.c89
-rw-r--r--drivers/gpu/drm/xe/xe_guc_ct.h2
-rw-r--r--drivers/gpu/drm/xe/xe_guc_ct_types.h2
-rw-r--r--drivers/gpu/drm/xe/xe_guc_pc.c213
-rw-r--r--drivers/gpu/drm/xe/xe_guc_pc.h5
-rw-r--r--drivers/gpu/drm/xe/xe_guc_pc_types.h4
-rw-r--r--drivers/gpu/drm/xe/xe_guc_submit.c384
-rw-r--r--drivers/gpu/drm/xe/xe_guc_submit.h1
-rw-r--r--drivers/gpu/drm/xe/xe_huc.c30
-rw-r--r--drivers/gpu/drm/xe/xe_hw_engine.c9
-rw-r--r--drivers/gpu/drm/xe/xe_hw_engine.h1
-rw-r--r--drivers/gpu/drm/xe/xe_hw_engine_types.h2
-rw-r--r--drivers/gpu/drm/xe/xe_hw_fence.c1
-rw-r--r--drivers/gpu/drm/xe/xe_hwmon.c89
-rw-r--r--drivers/gpu/drm/xe/xe_irq.c8
-rw-r--r--drivers/gpu/drm/xe/xe_irq.h1
-rw-r--r--drivers/gpu/drm/xe/xe_lrc.c89
-rw-r--r--drivers/gpu/drm/xe/xe_lrc.h6
-rw-r--r--drivers/gpu/drm/xe/xe_migrate.c36
-rw-r--r--drivers/gpu/drm/xe/xe_mmio.c23
-rw-r--r--drivers/gpu/drm/xe/xe_mocs.c74
-rw-r--r--drivers/gpu/drm/xe/xe_module.c5
-rw-r--r--drivers/gpu/drm/xe/xe_oa.c2512
-rw-r--r--drivers/gpu/drm/xe/xe_oa.h27
-rw-r--r--drivers/gpu/drm/xe/xe_oa_types.h242
-rw-r--r--drivers/gpu/drm/xe/xe_observation.c93
-rw-r--r--drivers/gpu/drm/xe/xe_observation.h20
-rw-r--r--drivers/gpu/drm/xe/xe_pci.c8
-rw-r--r--drivers/gpu/drm/xe/xe_pci_sriov.c27
-rw-r--r--drivers/gpu/drm/xe/xe_pci_sriov.h7
-rw-r--r--drivers/gpu/drm/xe/xe_preempt_fence.c2
-rw-r--r--drivers/gpu/drm/xe/xe_pt.c8
-rw-r--r--drivers/gpu/drm/xe/xe_query.c77
-rw-r--r--drivers/gpu/drm/xe/xe_reg_whitelist.c24
-rw-r--r--drivers/gpu/drm/xe/xe_ring_ops.c21
-rw-r--r--drivers/gpu/drm/xe/xe_rtp.c45
-rw-r--r--drivers/gpu/drm/xe/xe_rtp.h69
-rw-r--r--drivers/gpu/drm/xe/xe_rtp_helpers.h2
-rw-r--r--drivers/gpu/drm/xe/xe_rtp_types.h3
-rw-r--r--drivers/gpu/drm/xe/xe_sched_job.c6
-rw-r--r--drivers/gpu/drm/xe/xe_sched_job.h3
-rw-r--r--drivers/gpu/drm/xe/xe_sriov.h6
-rw-r--r--drivers/gpu/drm/xe/xe_trace.h385
-rw-r--r--drivers/gpu/drm/xe/xe_trace_bo.c9
-rw-r--r--drivers/gpu/drm/xe/xe_trace_bo.h247
-rw-r--r--drivers/gpu/drm/xe/xe_trace_guc.c9
-rw-r--r--drivers/gpu/drm/xe/xe_trace_guc.h110
-rw-r--r--drivers/gpu/drm/xe/xe_uc.c14
-rw-r--r--drivers/gpu/drm/xe/xe_uc.h1
-rw-r--r--drivers/gpu/drm/xe/xe_uc_fw.h2
-rw-r--r--drivers/gpu/drm/xe/xe_vm.c101
-rw-r--r--drivers/gpu/drm/xe/xe_wa.c25
-rw-r--r--drivers/gpu/drm/xe/xe_wa.h2
-rw-r--r--drivers/gpu/drm/xe/xe_wa_oob.rules2
-rw-r--r--drivers/gpu/drm/xlnx/zynqmp_disp.c44
-rw-r--r--drivers/gpu/drm/xlnx/zynqmp_dp.c62
-rw-r--r--drivers/gpu/drm/xlnx/zynqmp_dpsub.c1
-rw-r--r--drivers/gpu/drm/xlnx/zynqmp_dpsub.h1
-rw-r--r--drivers/gpu/drm/xlnx/zynqmp_kms.c22
-rw-r--r--drivers/gpu/drm/xlnx/zynqmp_kms.h4
1043 files changed, 37407 insertions, 19079 deletions
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 026444eeb5c6..fd0749c0c630 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -79,6 +79,7 @@ config DRM_KUNIT_TEST
depends on DRM && KUNIT && MMU
select DRM_BUDDY
select DRM_DISPLAY_DP_HELPER
+ select DRM_DISPLAY_HDMI_STATE_HELPER
select DRM_DISPLAY_HELPER
select DRM_EXEC
select DRM_EXPORT_FOR_TESTS if m
@@ -106,8 +107,7 @@ config DRM_KMS_HELPER
config DRM_PANIC
bool "Display a user-friendly message when a kernel panic occurs"
- depends on DRM && !FRAMEBUFFER_CONSOLE
- select DRM_KMS_HELPER
+ depends on DRM && !(FRAMEBUFFER_CONSOLE && VT_CONSOLE)
select FONT_SUPPORT
help
Enable a drm panic handler, which will display a user-friendly message
@@ -136,6 +136,19 @@ config DRM_PANIC_DEBUG
This is unsafe and should not be enabled on a production build.
If in doubt, say "N".
+config DRM_PANIC_SCREEN
+ string "Panic screen formatter"
+ default "user"
+ depends on DRM_PANIC
+ help
+ This option enable to choose what will be displayed when a kernel
+ panic occurs. You can choose between "user", a short message telling
+ the user to reboot the system, or "kmsg" which will display the last
+ lines of kmsg.
+ This can also be overridden by drm.panic_screen=xxxx kernel parameter
+ or by writing to /sys/module/drm/parameters/panic_screen sysfs entry
+ Default is "user"
+
config DRM_DEBUG_DP_MST_TOPOLOGY_REFS
bool "Enable refcount backtrace history in the DP MST helpers"
depends on STACKTRACE_SUPPORT
@@ -234,6 +247,7 @@ config DRM_TTM_KUNIT_TEST
default n
depends on DRM && KUNIT && MMU && (UML || COMPILE_TEST)
select DRM_TTM
+ select DRM_BUDDY
select DRM_EXPORT_FOR_TESTS if m
select DRM_KUNIT_TEST_HELPERS
default KUNIT_ALL_TESTS
@@ -450,6 +464,7 @@ config DRM_PRIVACY_SCREEN
config DRM_WERROR
bool "Compile the drm subsystem with warnings as errors"
depends on DRM && EXPERT
+ depends on !WERROR
default n
help
A kernel build should not cause any compiler warnings, and this
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index f9ca4f8fa6c5..68cc9258ffc4 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -108,6 +108,7 @@ drm_dma_helper-$(CONFIG_DRM_KMS_HELPER) += drm_fb_dma_helper.o
obj-$(CONFIG_DRM_GEM_DMA_HELPER) += drm_dma_helper.o
drm_shmem_helper-y := drm_gem_shmem_helper.o
+drm_shmem_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fbdev_shmem.o
obj-$(CONFIG_DRM_GEM_SHMEM_HELPER) += drm_shmem_helper.o
drm_suballoc_helper-y := drm_suballoc.o
@@ -117,6 +118,7 @@ drm_vram_helper-y := drm_gem_vram_helper.o
obj-$(CONFIG_DRM_VRAM_HELPER) += drm_vram_helper.o
drm_ttm_helper-y := drm_gem_ttm_helper.o
+drm_ttm_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fbdev_ttm.o
obj-$(CONFIG_DRM_TTM_HELPER) += drm_ttm_helper.o
#
@@ -142,9 +144,7 @@ drm_kms_helper-y := \
drm_self_refresh_helper.o \
drm_simple_kms_helper.o
drm_kms_helper-$(CONFIG_DRM_PANEL_BRIDGE) += bridge/panel.o
-drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += \
- drm_fbdev_generic.o \
- drm_fb_helper.o
+drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o
obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o
#
diff --git a/drivers/gpu/drm/amd/amdgpu/Kconfig b/drivers/gpu/drm/amd/amdgpu/Kconfig
index 4232ab27f990..0051fb1b437f 100644
--- a/drivers/gpu/drm/amd/amdgpu/Kconfig
+++ b/drivers/gpu/drm/amd/amdgpu/Kconfig
@@ -71,6 +71,17 @@ config DRM_AMDGPU_USERPTR
This option selects CONFIG_HMM and CONFIG_HMM_MIRROR if it
isn't already selected to enabled full userptr support.
+config DRM_AMD_ISP
+ bool "Enable AMD Image Signal Processor IP support"
+ depends on DRM_AMDGPU
+ select MFD_CORE
+ select PM_GENERIC_DOMAINS if PM
+ help
+ Choose this option to enable ISP IP support for AMD SOCs.
+ This adds the ISP (Image Signal Processor) IP driver and wires
+ it up into the amdgpu driver. It is required for cameras
+ on APUs which utilize mipi cameras.
+
config DRM_AMDGPU_WERROR
bool "Force the compiler to throw an error instead of a warning when compiling"
depends on DRM_AMDGPU
diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile
index dfd2d594e143..38408e4e158e 100644
--- a/drivers/gpu/drm/amd/amdgpu/Makefile
+++ b/drivers/gpu/drm/amd/amdgpu/Makefile
@@ -106,7 +106,8 @@ amdgpu-y += \
df_v1_7.o \
df_v3_6.o \
df_v4_3.o \
- df_v4_6_2.o
+ df_v4_6_2.o \
+ df_v4_15.o
# add GMC block
amdgpu-y += \
@@ -323,4 +324,12 @@ amdgpu-y += $(AMD_DISPLAY_FILES)
endif
+# add isp block
+ifneq ($(CONFIG_DRM_AMD_ISP),)
+amdgpu-y += \
+ amdgpu_isp.o \
+ isp_v4_1_0.o \
+ isp_v4_1_1.o
+endif
+
obj-$(CONFIG_DRM_AMDGPU)+= amdgpu.o
diff --git a/drivers/gpu/drm/amd/amdgpu/aldebaran.c b/drivers/gpu/drm/amd/amdgpu/aldebaran.c
index d0a8da67dc2a..b0f95a7649bf 100644
--- a/drivers/gpu/drm/amd/amdgpu/aldebaran.c
+++ b/drivers/gpu/drm/amd/amdgpu/aldebaran.c
@@ -316,8 +316,6 @@ static int aldebaran_mode2_restore_ip(struct amdgpu_device *adev)
adev->ip_blocks[i].status.late_initialized = true;
}
- amdgpu_ras_set_error_query_ready(adev, true);
-
amdgpu_device_set_cg_state(adev, AMD_CG_STATE_GATE);
amdgpu_device_set_pg_state(adev, AMD_PG_STATE_GATE);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 35faa286bb1c..137a88b8de45 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -112,6 +112,9 @@
#include "amdgpu_xcp.h"
#include "amdgpu_seq64.h"
#include "amdgpu_reg_state.h"
+#if defined(CONFIG_DRM_AMD_ISP)
+#include "amdgpu_isp.h"
+#endif
#define MAX_GPU_INSTANCE 64
@@ -221,7 +224,6 @@ extern int amdgpu_mes;
extern int amdgpu_mes_log_enable;
extern int amdgpu_mes_kiq;
extern int amdgpu_uni_mes;
-extern int amdgpu_jpeg_test;
extern int amdgpu_noretry;
extern int amdgpu_force_asic_type;
extern int amdgpu_smartshift_bias;
@@ -721,6 +723,7 @@ enum amd_hw_ip_block_type {
XGMI_HWIP,
DCI_HWIP,
PCIE_HWIP,
+ ISP_HWIP,
MAX_HWIP
};
@@ -1018,7 +1021,6 @@ struct amdgpu_device {
/* jpeg */
struct amdgpu_jpeg jpeg;
- bool enable_jpeg_test;
/* vpe */
struct amdgpu_vpe vpe;
@@ -1048,6 +1050,11 @@ struct amdgpu_device {
/* display related functionality */
struct amdgpu_display_manager dm;
+#if defined(CONFIG_DRM_AMD_ISP)
+ /* isp */
+ struct amdgpu_isp isp;
+#endif
+
/* mes */
bool enable_mes;
bool enable_mes_kiq;
@@ -1441,6 +1448,7 @@ u32 amdgpu_device_pcie_port_rreg(struct amdgpu_device *adev,
u32 reg);
void amdgpu_device_pcie_port_wreg(struct amdgpu_device *adev,
u32 reg, u32 v);
+struct dma_fence *amdgpu_device_get_gang(struct amdgpu_device *adev);
struct dma_fence *amdgpu_device_switch_gang(struct amdgpu_device *adev,
struct dma_fence *gang);
bool amdgpu_device_has_display_hardware(struct amdgpu_device *adev);
@@ -1567,6 +1575,7 @@ static inline int amdgpu_acpi_power_shift_control(struct amdgpu_device *adev,
u8 dev_state, bool drv_state) { return 0; }
static inline int amdgpu_acpi_smart_shift_update(struct drm_device *dev,
enum amdgpu_ss ss_state) { return 0; }
+static inline void amdgpu_acpi_get_backlight_caps(struct amdgpu_dm_backlight_caps *caps) { }
#endif
#if defined(CONFIG_ACPI) && defined(CONFIG_SUSPEND)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c
index 01d50ad603d3..19158cc30f31 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c
@@ -119,7 +119,7 @@ static struct aca_regs_dump {
static void aca_smu_bank_dump(struct amdgpu_device *adev, int idx, int total, struct aca_bank *bank,
struct ras_query_context *qctx)
{
- u64 event_id = qctx ? qctx->event_id : 0ULL;
+ u64 event_id = qctx ? qctx->evid.event_id : RAS_EVENT_INVALID_ID;
int i;
RAS_EVENT_LOG(adev, event_id, HW_ERR "Accelerator Check Architecture events logged\n");
@@ -222,9 +222,9 @@ static struct aca_bank_error *new_bank_error(struct aca_error *aerr, struct aca_
INIT_LIST_HEAD(&bank_error->node);
memcpy(&bank_error->info, info, sizeof(*info));
- spin_lock(&aerr->lock);
+ mutex_lock(&aerr->lock);
list_add_tail(&bank_error->node, &aerr->list);
- spin_unlock(&aerr->lock);
+ mutex_unlock(&aerr->lock);
return bank_error;
}
@@ -235,7 +235,7 @@ static struct aca_bank_error *find_bank_error(struct aca_error *aerr, struct aca
struct aca_bank_info *tmp_info;
bool found = false;
- spin_lock(&aerr->lock);
+ mutex_lock(&aerr->lock);
list_for_each_entry(bank_error, &aerr->list, node) {
tmp_info = &bank_error->info;
if (tmp_info->socket_id == info->socket_id &&
@@ -246,7 +246,7 @@ static struct aca_bank_error *find_bank_error(struct aca_error *aerr, struct aca
}
out_unlock:
- spin_unlock(&aerr->lock);
+ mutex_unlock(&aerr->lock);
return found ? bank_error : NULL;
}
@@ -474,7 +474,7 @@ static int aca_log_aca_error(struct aca_handle *handle, enum aca_error_type type
struct aca_error *aerr = &error_cache->errors[type];
struct aca_bank_error *bank_error, *tmp;
- spin_lock(&aerr->lock);
+ mutex_lock(&aerr->lock);
if (list_empty(&aerr->list))
goto out_unlock;
@@ -485,7 +485,7 @@ static int aca_log_aca_error(struct aca_handle *handle, enum aca_error_type type
}
out_unlock:
- spin_unlock(&aerr->lock);
+ mutex_unlock(&aerr->lock);
return 0;
}
@@ -542,7 +542,7 @@ int amdgpu_aca_get_error_data(struct amdgpu_device *adev, struct aca_handle *han
static void aca_error_init(struct aca_error *aerr, enum aca_error_type type)
{
- spin_lock_init(&aerr->lock);
+ mutex_init(&aerr->lock);
INIT_LIST_HEAD(&aerr->list);
aerr->type = type;
aerr->nr_errors = 0;
@@ -561,10 +561,11 @@ static void aca_error_fini(struct aca_error *aerr)
{
struct aca_bank_error *bank_error, *tmp;
- spin_lock(&aerr->lock);
+ mutex_lock(&aerr->lock);
list_for_each_entry_safe(bank_error, tmp, &aerr->list, node)
aca_bank_error_remove(aerr, bank_error);
- spin_unlock(&aerr->lock);
+
+ mutex_destroy(&aerr->lock);
}
static void aca_fini_error_cache(struct aca_handle *handle)
@@ -712,6 +713,15 @@ void amdgpu_aca_fini(struct amdgpu_device *adev)
atomic_set(&aca->ue_update_flag, 0);
}
+int amdgpu_aca_reset(struct amdgpu_device *adev)
+{
+ struct amdgpu_aca *aca = &adev->aca;
+
+ atomic_set(&aca->ue_update_flag, 0);
+
+ return 0;
+}
+
void amdgpu_aca_set_smu_funcs(struct amdgpu_device *adev, const struct aca_smu_funcs *smu_funcs)
{
struct amdgpu_aca *aca = &adev->aca;
@@ -885,9 +895,7 @@ DEFINE_DEBUGFS_ATTRIBUTE(aca_debug_mode_fops, NULL, amdgpu_aca_smu_debug_mode_se
void amdgpu_aca_smu_debugfs_init(struct amdgpu_device *adev, struct dentry *root)
{
#if defined(CONFIG_DEBUG_FS)
- if (!root ||
- (adev->ip_versions[MP1_HWIP][0] != IP_VERSION(13, 0, 6) &&
- adev->ip_versions[MP1_HWIP][0] != IP_VERSION(13, 0, 14)))
+ if (!root)
return;
debugfs_create_file("aca_debug_mode", 0200, root, adev, &aca_debug_mode_fops);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.h
index 4327ce1ceacf..5ef6b745f222 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.h
@@ -25,7 +25,6 @@
#define __AMDGPU_ACA_H__
#include <linux/list.h>
-#include <linux/spinlock.h>
struct ras_err_data;
struct ras_query_context;
@@ -134,7 +133,7 @@ struct aca_bank_error {
struct aca_error {
struct list_head list;
- spinlock_t lock;
+ struct mutex lock;
enum aca_error_type type;
int nr_errors;
};
@@ -192,6 +191,7 @@ struct aca_info {
int amdgpu_aca_init(struct amdgpu_device *adev);
void amdgpu_aca_fini(struct amdgpu_device *adev);
+int amdgpu_aca_reset(struct amdgpu_device *adev);
void amdgpu_aca_set_smu_funcs(struct amdgpu_device *adev, const struct aca_smu_funcs *smu_funcs);
bool amdgpu_aca_is_enabled(struct amdgpu_device *adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
index 7099ff9cf8c5..f85ace0384d2 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
@@ -383,6 +383,8 @@ static int amdgpu_atif_query_backlight_caps(struct amdgpu_atif *atif)
characteristics.min_input_signal;
atif->backlight_caps.max_input_signal =
characteristics.max_input_signal;
+ atif->backlight_caps.ac_level = characteristics.ac_level;
+ atif->backlight_caps.dc_level = characteristics.dc_level;
out:
kfree(info);
return err;
@@ -1268,6 +1270,8 @@ void amdgpu_acpi_get_backlight_caps(struct amdgpu_dm_backlight_caps *caps)
caps->caps_valid = atif->backlight_caps.caps_valid;
caps->min_input_signal = atif->backlight_caps.min_input_signal;
caps->max_input_signal = atif->backlight_caps.max_input_signal;
+ caps->ac_level = atif->backlight_caps.ac_level;
+ caps->dc_level = atif->backlight_caps.dc_level;
}
/**
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c
index f932bec6e534..f873dd3cae16 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c
@@ -433,7 +433,7 @@ amdgpu_atomfirmware_get_vram_info(struct amdgpu_device *adev,
mem_channel_number = vram_info->v30.channel_num;
mem_channel_width = vram_info->v30.channel_width;
if (vram_width)
- *vram_width = mem_channel_number * (1 << mem_channel_width);
+ *vram_width = mem_channel_number * 16;
break;
default:
return -EINVAL;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
index 9caba10315a8..cae7479c3ecf 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
@@ -246,22 +246,6 @@ amdgpu_connector_find_encoder(struct drm_connector *connector,
return NULL;
}
-struct edid *amdgpu_connector_edid(struct drm_connector *connector)
-{
- struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
- struct drm_property_blob *edid_blob = connector->edid_blob_ptr;
-
- if (amdgpu_connector->edid) {
- return amdgpu_connector->edid;
- } else if (edid_blob) {
- struct edid *edid = kmemdup(edid_blob->data, edid_blob->length, GFP_KERNEL);
-
- if (edid)
- amdgpu_connector->edid = edid;
- }
- return amdgpu_connector->edid;
-}
-
static struct edid *
amdgpu_connector_get_hardcoded_edid(struct amdgpu_device *adev)
{
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.h
index 61fcef15ad72..eff833b6ed31 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.h
@@ -24,7 +24,6 @@
#ifndef __AMDGPU_CONNECTORS_H__
#define __AMDGPU_CONNECTORS_H__
-struct edid *amdgpu_connector_edid(struct drm_connector *connector);
void amdgpu_connector_hotplug(struct drm_connector *connector);
int amdgpu_connector_get_monitor_bpc(struct drm_connector *connector);
u16 amdgpu_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector *connector);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
index ec888fc6ead8..916b6b8cf7d9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
@@ -1093,6 +1093,21 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p)
unsigned int i;
int r;
+ /*
+ * We can't use gang submit on with reserved VMIDs when the VM changes
+ * can't be invalidated by more than one engine at the same time.
+ */
+ if (p->gang_size > 1 && !p->adev->vm_manager.concurrent_flush) {
+ for (i = 0; i < p->gang_size; ++i) {
+ struct drm_sched_entity *entity = p->entities[i];
+ struct drm_gpu_scheduler *sched = entity->rq->sched;
+ struct amdgpu_ring *ring = to_amdgpu_ring(sched);
+
+ if (amdgpu_vmid_uses_reserved(vm, ring->vm_hub))
+ return -EINVAL;
+ }
+ }
+
r = amdgpu_vm_clear_freed(adev, vm, NULL);
if (r)
return r;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 4096cb3e937e..bcacf2e35eba 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -2350,7 +2350,6 @@ void amdgpu_device_set_sriov_virtual_display(struct amdgpu_device *adev)
static int amdgpu_device_parse_gpu_info_fw(struct amdgpu_device *adev)
{
const char *chip_name;
- char fw_name[40];
int err;
const struct gpu_info_firmware_header_v1_0 *hdr;
@@ -2384,12 +2383,12 @@ static int amdgpu_device_parse_gpu_info_fw(struct amdgpu_device *adev)
break;
}
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_gpu_info.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->firmware.gpu_info_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->firmware.gpu_info_fw,
+ "amdgpu/%s_gpu_info.bin", chip_name);
if (err) {
dev_err(adev->dev,
- "Failed to get gpu_info firmware \"%s\"\n",
- fw_name);
+ "Failed to get gpu_info firmware \"%s_gpu_info.bin\"\n",
+ chip_name);
goto out;
}
@@ -3143,7 +3142,8 @@ static int amdgpu_device_ip_late_init(struct amdgpu_device *adev)
return r;
}
- amdgpu_ras_set_error_query_ready(adev, true);
+ if (!amdgpu_in_reset(adev))
+ amdgpu_ras_set_error_query_ready(adev, true);
amdgpu_device_set_cg_state(adev, AMD_CG_STATE_GATE);
amdgpu_device_set_pg_state(adev, AMD_PG_STATE_GATE);
@@ -5070,6 +5070,9 @@ static int amdgpu_device_reset_sriov(struct amdgpu_device *adev,
struct amdgpu_hive_info *hive = NULL;
if (test_bit(AMDGPU_HOST_FLR, &reset_context->flags)) {
+ if (!amdgpu_ras_get_fed_status(adev))
+ amdgpu_virt_ready_to_reset(adev);
+ amdgpu_virt_wait_reset(adev);
clear_bit(AMDGPU_HOST_FLR, &reset_context->flags);
r = amdgpu_virt_request_full_gpu(adev, true);
} else {
@@ -5223,11 +5226,14 @@ int amdgpu_device_mode1_reset(struct amdgpu_device *adev)
dev_info(adev->dev, "GPU mode1 reset\n");
+ /* Cache the state before bus master disable. The saved config space
+ * values are used in other cases like restore after mode-2 reset.
+ */
+ amdgpu_device_cache_pci_state(adev->pdev);
+
/* disable BM */
pci_clear_master(adev->pdev);
- amdgpu_device_cache_pci_state(adev->pdev);
-
if (amdgpu_dpm_is_mode1_reset_supported(adev)) {
dev_info(adev->dev, "GPU smu mode1 reset\n");
ret = amdgpu_dpm_mode1_reset(adev);
@@ -5833,6 +5839,12 @@ retry: /* Rest of adevs pre asic reset from XGMI hive. */
/* Actual ASIC resets if needed.*/
/* Host driver will handle XGMI hive reset for SRIOV */
if (amdgpu_sriov_vf(adev)) {
+ if (amdgpu_ras_get_fed_status(adev) || amdgpu_virt_rcvd_ras_interrupt(adev)) {
+ dev_dbg(adev->dev, "Detected RAS error, wait for FLR completion\n");
+ amdgpu_ras_set_fed(adev, true);
+ set_bit(AMDGPU_HOST_FLR, &reset_context->flags);
+ }
+
r = amdgpu_device_reset_sriov(adev, reset_context);
if (AMDGPU_RETRY_SRIOV_RESET(r) && (retry_limit--) > 0) {
amdgpu_virt_release_full_gpu(adev, true);
@@ -6275,20 +6287,11 @@ pci_ers_result_t amdgpu_pci_slot_reset(struct pci_dev *pdev)
struct amdgpu_reset_context reset_context;
u32 memsize;
struct list_head device_list;
- struct amdgpu_hive_info *hive;
- int hive_ras_recovery = 0;
- struct amdgpu_ras *ras;
/* PCI error slot reset should be skipped During RAS recovery */
- hive = amdgpu_get_xgmi_hive(adev);
- if (hive) {
- hive_ras_recovery = atomic_read(&hive->ras_recovery);
- amdgpu_put_xgmi_hive(hive);
- }
- ras = amdgpu_ras_get_context(adev);
if ((amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 3) ||
- amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 4)) &&
- ras && (atomic_read(&ras->in_recovery) || hive_ras_recovery))
+ amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 4)) &&
+ amdgpu_ras_in_recovery(adev))
return PCI_ERS_RESULT_RECOVERED;
DRM_INFO("PCI error: slot reset callback!!\n");
@@ -6531,6 +6534,22 @@ void amdgpu_device_pcie_port_wreg(struct amdgpu_device *adev,
}
/**
+ * amdgpu_device_get_gang - return a reference to the current gang
+ * @adev: amdgpu_device pointer
+ *
+ * Returns: A new reference to the current gang leader.
+ */
+struct dma_fence *amdgpu_device_get_gang(struct amdgpu_device *adev)
+{
+ struct dma_fence *fence;
+
+ rcu_read_lock();
+ fence = dma_fence_get_rcu_safe(&adev->gang_submit);
+ rcu_read_unlock();
+ return fence;
+}
+
+/**
* amdgpu_device_switch_gang - switch to a new gang
* @adev: amdgpu_device pointer
* @gang: the gang to switch to
@@ -6546,10 +6565,7 @@ struct dma_fence *amdgpu_device_switch_gang(struct amdgpu_device *adev,
do {
dma_fence_put(old);
- rcu_read_lock();
- old = dma_fence_get_rcu_safe(&adev->gang_submit);
- rcu_read_unlock();
-
+ old = amdgpu_device_get_gang(adev);
if (old == gang)
break;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_df.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_df.h
index 1538b2dbfff1..eb605e79ae0e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_df.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_df.h
@@ -33,6 +33,7 @@ struct amdgpu_df_hash_status {
struct amdgpu_df_funcs {
void (*sw_init)(struct amdgpu_device *adev);
void (*sw_fini)(struct amdgpu_device *adev);
+ void (*hw_init)(struct amdgpu_device *adev);
void (*enable_broadcast_mode)(struct amdgpu_device *adev,
bool enable);
u32 (*get_fb_channel_number)(struct amdgpu_device *adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
index c71356cb393d..ac108fca64fe 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
@@ -37,6 +37,7 @@
#include "df_v3_6.h"
#include "df_v4_3.h"
#include "df_v4_6_2.h"
+#include "df_v4_15.h"
#include "nbio_v6_1.h"
#include "nbio_v7_0.h"
#include "nbio_v7_4.h"
@@ -106,6 +107,9 @@
#include "jpeg_v5_0_0.h"
#include "amdgpu_vpe.h"
+#if defined(CONFIG_DRM_AMD_ISP)
+#include "amdgpu_isp.h"
+#endif
#define FIRMWARE_IP_DISCOVERY "amdgpu/ip_discovery.bin"
MODULE_FIRMWARE(FIRMWARE_IP_DISCOVERY);
@@ -225,6 +229,7 @@ static int hw_id_map[MAX_HWIP] = {
[DCI_HWIP] = DCI_HWID,
[PCIE_HWIP] = PCIE_HWID,
[VPE_HWIP] = VPE_HWID,
+ [ISP_HWIP] = ISP_HWID,
};
static int amdgpu_discovery_read_binary_from_sysmem(struct amdgpu_device *adev, uint8_t *binary)
@@ -260,19 +265,21 @@ static int amdgpu_discovery_read_binary_from_mem(struct amdgpu_device *adev,
u32 msg;
int i, ret = 0;
- /* It can take up to a second for IFWI init to complete on some dGPUs,
- * but generally it should be in the 60-100ms range. Normally this starts
- * as soon as the device gets power so by the time the OS loads this has long
- * completed. However, when a card is hotplugged via e.g., USB4, we need to
- * wait for this to complete. Once the C2PMSG is updated, we can
- * continue.
- */
+ if (!amdgpu_sriov_vf(adev)) {
+ /* It can take up to a second for IFWI init to complete on some dGPUs,
+ * but generally it should be in the 60-100ms range. Normally this starts
+ * as soon as the device gets power so by the time the OS loads this has long
+ * completed. However, when a card is hotplugged via e.g., USB4, we need to
+ * wait for this to complete. Once the C2PMSG is updated, we can
+ * continue.
+ */
- for (i = 0; i < 1000; i++) {
- msg = RREG32(mmMP0_SMN_C2PMSG_33);
- if (msg & 0x80000000)
- break;
- usleep_range(1000, 1100);
+ for (i = 0; i < 1000; i++) {
+ msg = RREG32(mmMP0_SMN_C2PMSG_33);
+ if (msg & 0x80000000)
+ break;
+ usleep_range(1000, 1100);
+ }
}
vram_size = (uint64_t)RREG32(mmRCC_CONFIG_MEMSIZE) << 20;
@@ -709,6 +716,12 @@ static void amdgpu_discovery_read_from_harvest_table(struct amdgpu_device *adev,
adev->sdma.sdma_mask &=
~(1U << harvest_info->list[i].number_instance);
break;
+#if defined(CONFIG_DRM_AMD_ISP)
+ case ISP_HWID:
+ adev->isp.harvest_config |=
+ ~(1U << harvest_info->list[i].number_instance);
+ break;
+#endif
default:
break;
}
@@ -1796,6 +1809,7 @@ static int amdgpu_discovery_set_common_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(11, 0, 4):
case IP_VERSION(11, 5, 0):
case IP_VERSION(11, 5, 1):
+ case IP_VERSION(11, 5, 2):
amdgpu_device_ip_block_add(adev, &soc21_common_ip_block);
break;
case IP_VERSION(12, 0, 0):
@@ -1849,6 +1863,7 @@ static int amdgpu_discovery_set_gmc_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(11, 0, 4):
case IP_VERSION(11, 5, 0):
case IP_VERSION(11, 5, 1):
+ case IP_VERSION(11, 5, 2):
amdgpu_device_ip_block_add(adev, &gmc_v11_0_ip_block);
break;
case IP_VERSION(12, 0, 0):
@@ -1950,6 +1965,7 @@ static int amdgpu_discovery_set_psp_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(13, 0, 14):
case IP_VERSION(14, 0, 0):
case IP_VERSION(14, 0, 1):
+ case IP_VERSION(14, 0, 4):
amdgpu_device_ip_block_add(adev, &psp_v13_0_ip_block);
break;
case IP_VERSION(13, 0, 4):
@@ -2013,6 +2029,7 @@ static int amdgpu_discovery_set_smu_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(14, 0, 1):
case IP_VERSION(14, 0, 2):
case IP_VERSION(14, 0, 3):
+ case IP_VERSION(14, 0, 4):
amdgpu_device_ip_block_add(adev, &smu_v14_0_ip_block);
break;
default:
@@ -2140,12 +2157,11 @@ static int amdgpu_discovery_set_gc_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(11, 0, 4):
case IP_VERSION(11, 5, 0):
case IP_VERSION(11, 5, 1):
+ case IP_VERSION(11, 5, 2):
amdgpu_device_ip_block_add(adev, &gfx_v11_0_ip_block);
break;
case IP_VERSION(12, 0, 0):
case IP_VERSION(12, 0, 1):
- if (!amdgpu_exp_hw_support)
- return -EINVAL;
amdgpu_device_ip_block_add(adev, &gfx_v12_0_ip_block);
break;
default:
@@ -2195,6 +2211,7 @@ static int amdgpu_discovery_set_sdma_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(6, 0, 3):
case IP_VERSION(6, 1, 0):
case IP_VERSION(6, 1, 1):
+ case IP_VERSION(6, 1, 2):
amdgpu_device_ip_block_add(adev, &sdma_v6_0_ip_block);
break;
case IP_VERSION(7, 0, 0):
@@ -2292,8 +2309,6 @@ static int amdgpu_discovery_set_mm_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(5, 0, 0):
amdgpu_device_ip_block_add(adev, &vcn_v5_0_0_ip_block);
amdgpu_device_ip_block_add(adev, &jpeg_v5_0_0_ip_block);
- if (amdgpu_jpeg_test)
- adev->enable_jpeg_test = true;
break;
default:
dev_err(adev->dev,
@@ -2315,6 +2330,7 @@ static int amdgpu_discovery_set_mes_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(11, 0, 4):
case IP_VERSION(11, 5, 0):
case IP_VERSION(11, 5, 1):
+ case IP_VERSION(11, 5, 2):
amdgpu_device_ip_block_add(adev, &mes_v11_0_ip_block);
adev->enable_mes = true;
adev->enable_mes_kiq = true;
@@ -2350,6 +2366,7 @@ static int amdgpu_discovery_set_vpe_ip_blocks(struct amdgpu_device *adev)
switch (amdgpu_ip_version(adev, VPE_HWIP, 0)) {
case IP_VERSION(6, 1, 0):
case IP_VERSION(6, 1, 1):
+ case IP_VERSION(6, 1, 3):
amdgpu_device_ip_block_add(adev, &vpe_v6_1_ip_block);
break;
default:
@@ -2376,6 +2393,24 @@ static int amdgpu_discovery_set_umsch_mm_ip_blocks(struct amdgpu_device *adev)
return 0;
}
+static int amdgpu_discovery_set_isp_ip_blocks(struct amdgpu_device *adev)
+{
+#if defined(CONFIG_DRM_AMD_ISP)
+ switch (amdgpu_ip_version(adev, ISP_HWIP, 0)) {
+ case IP_VERSION(4, 1, 0):
+ amdgpu_device_ip_block_add(adev, &isp_v4_1_0_ip_block);
+ break;
+ case IP_VERSION(4, 1, 1):
+ amdgpu_device_ip_block_add(adev, &isp_v4_1_1_ip_block);
+ break;
+ default:
+ break;
+ }
+#endif
+
+ return 0;
+}
+
int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
{
int r;
@@ -2606,6 +2641,7 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
break;
case IP_VERSION(11, 5, 0):
case IP_VERSION(11, 5, 1):
+ case IP_VERSION(11, 5, 2):
adev->family = AMDGPU_FAMILY_GC_11_5_0;
break;
case IP_VERSION(12, 0, 0):
@@ -2630,6 +2666,7 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(11, 0, 4):
case IP_VERSION(11, 5, 0):
case IP_VERSION(11, 5, 1):
+ case IP_VERSION(11, 5, 2):
adev->flags |= AMD_IS_APU;
break;
default:
@@ -2668,6 +2705,7 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
break;
case IP_VERSION(7, 11, 0):
case IP_VERSION(7, 11, 1):
+ case IP_VERSION(7, 11, 3):
adev->nbio.funcs = &nbio_v7_11_funcs;
adev->nbio.hdp_flush_reg = &nbio_v7_11_hdp_flush_reg;
break;
@@ -2766,6 +2804,10 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(4, 6, 2):
adev->df.funcs = &df_v4_6_2_funcs;
break;
+ case IP_VERSION(4, 15, 0):
+ case IP_VERSION(4, 15, 1):
+ adev->df.funcs = &df_v4_15_funcs;
+ break;
default:
break;
}
@@ -2902,6 +2944,9 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
if (r)
return r;
+ r = amdgpu_discovery_set_isp_ip_blocks(adev);
+ if (r)
+ return r;
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
index cfec85563bc6..092ec11258cd 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
@@ -654,6 +654,10 @@ amdgpu_lookup_format_info(u32 format, uint64_t modifier)
if (!IS_AMD_FMT_MOD(modifier))
return NULL;
+ if (AMD_FMT_MOD_GET(TILE_VERSION, modifier) < AMD_FMT_MOD_TILE_VER_GFX9 ||
+ AMD_FMT_MOD_GET(TILE_VERSION, modifier) >= AMD_FMT_MOD_TILE_VER_GFX12)
+ return NULL;
+
if (AMD_FMT_MOD_GET(DCC_RETILE, modifier))
return lookup_format_info(dcc_retile_formats,
ARRAY_SIZE(dcc_retile_formats),
@@ -720,32 +724,25 @@ extract_render_dcc_offset(struct amdgpu_device *adev,
static int convert_tiling_flags_to_modifier_gfx12(struct amdgpu_framebuffer *afb)
{
- struct amdgpu_device *adev = drm_to_adev(afb->base.dev);
- const struct drm_format_info *format_info;
u64 modifier = 0;
- int tile = 0;
- int swizzle = 0;
+ int swizzle_mode = AMDGPU_TILING_GET(afb->tiling_flags, GFX12_SWIZZLE_MODE);
- if (amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(12, 0, 0)) {
- tile = AMD_FMT_MOD_TILE_VER_GFX12;
- swizzle = AMDGPU_TILING_GET(afb->tiling_flags, GFX12_SWIZZLE_MODE);
+ if (!swizzle_mode) {
+ modifier = DRM_FORMAT_MOD_LINEAR;
+ } else {
+ int max_comp_block =
+ AMDGPU_TILING_GET(afb->tiling_flags, GFX12_DCC_MAX_COMPRESSED_BLOCK);
+
+ modifier =
+ AMD_FMT_MOD |
+ AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX12) |
+ AMD_FMT_MOD_SET(TILE, swizzle_mode) |
+ AMD_FMT_MOD_SET(DCC, afb->gfx12_dcc) |
+ AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, max_comp_block);
}
- modifier =
- AMD_FMT_MOD |
- AMD_FMT_MOD_SET(TILE, swizzle) |
- AMD_FMT_MOD_SET(TILE_VERSION, tile) |
- AMD_FMT_MOD_SET(DCC, 0) |
- AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, 0);
-
- format_info = amdgpu_lookup_format_info(afb->base.format->format,
- modifier);
- if (!format_info)
- return -EINVAL;
-
afb->base.modifier = modifier;
afb->base.flags |= DRM_MODE_FB_MODIFIERS;
-
return 0;
}
@@ -773,12 +770,6 @@ static int convert_tiling_flags_to_modifier(struct amdgpu_framebuffer *afb)
int pipes = ilog2(num_pipes);
uint32_t dcc_offset = AMDGPU_TILING_GET(afb->tiling_flags, DCC_OFFSET_256B);
-
- if (amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(12, 0, 0)) {
- convert_tiling_flags_to_modifier_gfx12(afb);
- return 0;
- }
-
switch (swizzle >> 2) {
case 0: /* 256B */
block_size_bits = 8;
@@ -954,8 +945,7 @@ static int check_tiling_flags_gfx6(struct amdgpu_framebuffer *afb)
{
u64 micro_tile_mode;
- /* Zero swizzle mode means linear */
- if (AMDGPU_TILING_GET(afb->tiling_flags, SWIZZLE_MODE) == 0)
+ if (AMDGPU_TILING_GET(afb->tiling_flags, ARRAY_MODE) == 1) /* LINEAR_ALIGNED */
return 0;
micro_tile_mode = AMDGPU_TILING_GET(afb->tiling_flags, MICRO_TILE_MODE);
@@ -1079,6 +1069,30 @@ static int amdgpu_display_verify_sizes(struct amdgpu_framebuffer *rfb)
block_width = 256 / format_info->cpp[i];
block_height = 1;
block_size_log2 = 8;
+ } else if (AMD_FMT_MOD_GET(TILE_VERSION, modifier) >= AMD_FMT_MOD_TILE_VER_GFX12) {
+ int swizzle = AMD_FMT_MOD_GET(TILE, modifier);
+
+ switch (swizzle) {
+ case AMD_FMT_MOD_TILE_GFX12_256B_2D:
+ block_size_log2 = 8;
+ break;
+ case AMD_FMT_MOD_TILE_GFX12_4K_2D:
+ block_size_log2 = 12;
+ break;
+ case AMD_FMT_MOD_TILE_GFX12_64K_2D:
+ block_size_log2 = 16;
+ break;
+ case AMD_FMT_MOD_TILE_GFX12_256K_2D:
+ block_size_log2 = 18;
+ break;
+ default:
+ drm_dbg_kms(rfb->base.dev,
+ "Gfx12 swizzle mode with unknown block size: %d\n", swizzle);
+ return -EINVAL;
+ }
+
+ get_block_dimensions(block_size_log2, format_info->cpp[i],
+ &block_width, &block_height);
} else {
int swizzle = AMD_FMT_MOD_GET(TILE, modifier);
@@ -1114,7 +1128,8 @@ static int amdgpu_display_verify_sizes(struct amdgpu_framebuffer *rfb)
return ret;
}
- if (AMD_FMT_MOD_GET(DCC, modifier)) {
+ if (AMD_FMT_MOD_GET(TILE_VERSION, modifier) <= AMD_FMT_MOD_TILE_VER_GFX11 &&
+ AMD_FMT_MOD_GET(DCC, modifier)) {
if (AMD_FMT_MOD_GET(DCC_RETILE, modifier)) {
block_size_log2 = get_dcc_block_size(modifier, false, false);
get_block_dimensions(block_size_log2 + 8, format_info->cpp[0],
@@ -1144,7 +1159,8 @@ static int amdgpu_display_verify_sizes(struct amdgpu_framebuffer *rfb)
}
static int amdgpu_display_get_fb_info(const struct amdgpu_framebuffer *amdgpu_fb,
- uint64_t *tiling_flags, bool *tmz_surface)
+ uint64_t *tiling_flags, bool *tmz_surface,
+ bool *gfx12_dcc)
{
struct amdgpu_bo *rbo;
int r;
@@ -1152,6 +1168,7 @@ static int amdgpu_display_get_fb_info(const struct amdgpu_framebuffer *amdgpu_fb
if (!amdgpu_fb) {
*tiling_flags = 0;
*tmz_surface = false;
+ *gfx12_dcc = false;
return 0;
}
@@ -1165,11 +1182,9 @@ static int amdgpu_display_get_fb_info(const struct amdgpu_framebuffer *amdgpu_fb
return r;
}
- if (tiling_flags)
- amdgpu_bo_get_tiling_flags(rbo, tiling_flags);
-
- if (tmz_surface)
- *tmz_surface = amdgpu_bo_encrypted(rbo);
+ amdgpu_bo_get_tiling_flags(rbo, tiling_flags);
+ *tmz_surface = amdgpu_bo_encrypted(rbo);
+ *gfx12_dcc = rbo->flags & AMDGPU_GEM_CREATE_GFX12_DCC;
amdgpu_bo_unreserve(rbo);
@@ -1238,7 +1253,8 @@ static int amdgpu_display_framebuffer_init(struct drm_device *dev,
}
}
- ret = amdgpu_display_get_fb_info(rfb, &rfb->tiling_flags, &rfb->tmz_surface);
+ ret = amdgpu_display_get_fb_info(rfb, &rfb->tiling_flags, &rfb->tmz_surface,
+ &rfb->gfx12_dcc);
if (ret)
return ret;
@@ -1252,7 +1268,11 @@ static int amdgpu_display_framebuffer_init(struct drm_device *dev,
if (!dev->mode_config.fb_modifiers_not_supported &&
!(rfb->base.flags & DRM_MODE_FB_MODIFIERS)) {
- ret = convert_tiling_flags_to_modifier(rfb);
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(12, 0, 0))
+ ret = convert_tiling_flags_to_modifier_gfx12(rfb);
+ else
+ ret = convert_tiling_flags_to_modifier(rfb);
+
if (ret) {
drm_dbg_kms(dev, "Failed to convert tiling flags 0x%llX to a modifier",
rfb->tiling_flags);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
index 0b3b10d21952..8e81a83d37d8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
@@ -41,8 +41,6 @@
#include <linux/dma-buf.h>
#include <linux/dma-fence-array.h>
#include <linux/pci-p2pdma.h>
-#include <linux/pm_runtime.h>
-#include "amdgpu_trace.h"
/**
* amdgpu_dma_buf_attach - &dma_buf_ops.attach implementation
@@ -58,42 +56,11 @@ static int amdgpu_dma_buf_attach(struct dma_buf *dmabuf,
struct drm_gem_object *obj = dmabuf->priv;
struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
- int r;
if (pci_p2pdma_distance(adev->pdev, attach->dev, false) < 0)
attach->peer2peer = false;
- r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
- trace_amdgpu_runpm_reference_dumps(1, __func__);
- if (r < 0)
- goto out;
-
return 0;
-
-out:
- pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
- trace_amdgpu_runpm_reference_dumps(0, __func__);
- return r;
-}
-
-/**
- * amdgpu_dma_buf_detach - &dma_buf_ops.detach implementation
- *
- * @dmabuf: DMA-buf where we remove the attachment from
- * @attach: the attachment to remove
- *
- * Called when an attachment is removed from the DMA-buf.
- */
-static void amdgpu_dma_buf_detach(struct dma_buf *dmabuf,
- struct dma_buf_attachment *attach)
-{
- struct drm_gem_object *obj = dmabuf->priv;
- struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
- struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
-
- pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
- pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
- trace_amdgpu_runpm_reference_dumps(0, __func__);
}
/**
@@ -266,7 +233,6 @@ static int amdgpu_dma_buf_begin_cpu_access(struct dma_buf *dma_buf,
const struct dma_buf_ops amdgpu_dmabuf_ops = {
.attach = amdgpu_dma_buf_attach,
- .detach = amdgpu_dma_buf_detach,
.pin = amdgpu_dma_buf_pin,
.unpin = amdgpu_dma_buf_unpin,
.map_dma_buf = amdgpu_dma_buf_map,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 2da76fadf6ea..094498a0964b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -24,7 +24,7 @@
#include <drm/amdgpu_drm.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_ttm.h>
#include <drm/drm_gem.h>
#include <drm/drm_managed.h>
#include <drm/drm_pciids.h>
@@ -116,9 +116,10 @@
* - 3.55.0 - Add AMDGPU_INFO_GPUVM_FAULT query
* - 3.56.0 - Update IB start address and size alignment for decode and encode
* - 3.57.0 - Compute tunneling on GFX10+
+ * - 3.58.0 - Add GFX12 DCC support
*/
#define KMS_DRIVER_MAJOR 3
-#define KMS_DRIVER_MINOR 57
+#define KMS_DRIVER_MINOR 58
#define KMS_DRIVER_PATCHLEVEL 0
/*
@@ -204,7 +205,6 @@ int amdgpu_force_asic_type = -1;
int amdgpu_tmz = -1; /* auto */
uint amdgpu_freesync_vid_mode;
int amdgpu_reset_method = -1; /* auto */
-int amdgpu_jpeg_test;
int amdgpu_num_kcq = -1;
int amdgpu_smartshift_bias;
int amdgpu_use_xgmi_p2p = 1;
@@ -940,9 +940,6 @@ module_param_named(freesync_video, amdgpu_freesync_vid_mode, uint, 0444);
MODULE_PARM_DESC(reset_method, "GPU reset method (-1 = auto (default), 0 = legacy, 1 = mode0, 2 = mode1, 3 = mode2, 4 = baco/bamaco)");
module_param_named(reset_method, amdgpu_reset_method, int, 0644);
-MODULE_PARM_DESC(jpeg_test, "jpeg test(0 = disable (default), 1 = enable)");
-module_param_named(jpeg_test, amdgpu_jpeg_test, int, 0444);
-
/**
* DOC: bad_page_threshold (int) Bad page threshold is specifies the
* threshold value of faulty pages detected by RAS ECC, which may
@@ -2346,9 +2343,9 @@ retry_init:
!list_empty(&adev_to_drm(adev)->mode_config.connector_list)) {
/* select 8 bpp console on low vram cards */
if (adev->gmc.real_vram_size <= (32*1024*1024))
- drm_fbdev_generic_setup(adev_to_drm(adev), 8);
+ drm_fbdev_ttm_setup(adev_to_drm(adev), 8);
else
- drm_fbdev_generic_setup(adev_to_drm(adev), 32);
+ drm_fbdev_ttm_setup(adev_to_drm(adev), 32);
}
ret = amdgpu_debugfs_init(adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
index 10832b470448..2f24a6aa13bf 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
@@ -181,7 +181,6 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **f, struct amd
amdgpu_ring_emit_fence(ring, ring->fence_drv.gpu_addr,
seq, flags | AMDGPU_FENCE_FLAG_INT);
pm_runtime_get_noresume(adev_to_drm(adev)->dev);
- trace_amdgpu_runpm_reference_dumps(1, __func__);
ptr = &ring->fence_drv.fences[seq & ring->fence_drv.num_fences_mask];
if (unlikely(rcu_dereference_protected(*ptr, 1))) {
struct dma_fence *old;
@@ -309,7 +308,6 @@ bool amdgpu_fence_process(struct amdgpu_ring *ring)
dma_fence_put(fence);
pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
- trace_amdgpu_runpm_reference_dumps(0, __func__);
} while (last_seq != seq);
return true;
@@ -980,7 +978,9 @@ static void amdgpu_debugfs_reset_work(struct work_struct *work)
reset_context.method = AMD_RESET_METHOD_NONE;
reset_context.reset_req_dev = adev;
+ reset_context.src = AMDGPU_RESET_SRC_USER;
set_bit(AMDGPU_NEED_FULL_RESET, &reset_context.flags);
+ set_bit(AMDGPU_SKIP_COREDUMP, &reset_context.flags);
amdgpu_device_gpu_recover(adev, NULL, &reset_context);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c
index c623e23049d1..256b95232de5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c
@@ -34,6 +34,7 @@
#include <asm/set_memory.h>
#endif
#include "amdgpu.h"
+#include "amdgpu_reset.h"
#include <drm/drm_drv.h>
#include <drm/ttm/ttm_tt.h>
@@ -325,10 +326,7 @@ void amdgpu_gart_unbind(struct amdgpu_device *adev, uint64_t offset,
page_base += AMDGPU_GPU_PAGE_SIZE;
}
}
- mb();
- amdgpu_device_flush_hdp(adev, NULL);
- for_each_set_bit(i, adev->vmhubs_mask, AMDGPU_MAX_VMHUBS)
- amdgpu_gmc_flush_gpu_tlb(adev, 0, i, 0);
+ amdgpu_gart_invalidate_tlb(adev);
drm_dev_exit(idx);
}
@@ -408,7 +406,10 @@ void amdgpu_gart_invalidate_tlb(struct amdgpu_device *adev)
return;
mb();
- amdgpu_device_flush_hdp(adev, NULL);
+ if (down_read_trylock(&adev->reset_domain->sem)) {
+ amdgpu_device_flush_hdp(adev, NULL);
+ up_read(&adev->reset_domain->sem);
+ }
for_each_set_bit(i, adev->vmhubs_mask, AMDGPU_MAX_VMHUBS)
amdgpu_gmc_flush_gpu_tlb(adev, 0, i, 0);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
index 3b67809a59bc..aad2027e5c7c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
@@ -108,6 +108,7 @@ int amdgpu_gem_object_create(struct amdgpu_device *adev, unsigned long size,
memset(&bp, 0, sizeof(bp));
*obj = NULL;
+ flags |= AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE;
bp.size = size;
bp.byte_align = alignment;
@@ -334,6 +335,7 @@ int amdgpu_gem_create_ioctl(struct drm_device *dev, void *data,
AMDGPU_GEM_CREATE_VM_ALWAYS_VALID |
AMDGPU_GEM_CREATE_EXPLICIT_SYNC |
AMDGPU_GEM_CREATE_ENCRYPTED |
+ AMDGPU_GEM_CREATE_GFX12_DCC |
AMDGPU_GEM_CREATE_DISCARDABLE))
return -EINVAL;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
index 19b1817b55d7..82452606ae6c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
@@ -506,9 +506,6 @@ int amdgpu_gfx_disable_kcq(struct amdgpu_device *adev, int xcc_id)
{
struct amdgpu_kiq *kiq = &adev->gfx.kiq[xcc_id];
struct amdgpu_ring *kiq_ring = &kiq->ring;
- struct amdgpu_hive_info *hive;
- struct amdgpu_ras *ras;
- int hive_ras_recovery = 0;
int i, r = 0;
int j;
@@ -533,16 +530,9 @@ int amdgpu_gfx_disable_kcq(struct amdgpu_device *adev, int xcc_id)
* This is workaround: only skip kiq_ring test
* during ras recovery in suspend stage for gfx9.4.3
*/
- hive = amdgpu_get_xgmi_hive(adev);
- if (hive) {
- hive_ras_recovery = atomic_read(&hive->ras_recovery);
- amdgpu_put_xgmi_hive(hive);
- }
-
- ras = amdgpu_ras_get_context(adev);
if ((amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 3) ||
- amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 4)) &&
- ras && (atomic_read(&ras->in_recovery) || hive_ras_recovery)) {
+ amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 4)) &&
+ amdgpu_ras_in_recovery(adev)) {
spin_unlock(&kiq->ring_lock);
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
index 6b0416777c5b..ddda94e49db4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
@@ -297,6 +297,7 @@ struct amdgpu_gfx_funcs {
int (*switch_partition_mode)(struct amdgpu_device *adev,
int num_xccs_per_xcp);
int (*ih_node_to_logical_xcc)(struct amdgpu_device *adev, int ih_node);
+ int (*get_xccs_per_xcp)(struct amdgpu_device *adev);
};
struct sq_work {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
index 603c0738fd03..c02659025656 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
@@ -620,10 +620,8 @@ void amdgpu_gmc_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
int r;
if (!hub->sdma_invalidation_workaround || vmid ||
- !adev->mman.buffer_funcs_enabled ||
- !adev->ib_pool_ready || amdgpu_in_reset(adev) ||
+ !adev->mman.buffer_funcs_enabled || !adev->ib_pool_ready ||
!ring->sched.ready) {
-
/*
* A GPU reset should flush all TLBs anyway, so no need to do
* this while one is ongoing.
@@ -684,12 +682,17 @@ int amdgpu_gmc_flush_gpu_tlb_pasid(struct amdgpu_device *adev, uint16_t pasid,
struct amdgpu_ring *ring = &adev->gfx.kiq[inst].ring;
struct amdgpu_kiq *kiq = &adev->gfx.kiq[inst];
unsigned int ndw;
- signed long r;
+ int r;
uint32_t seq;
- if (!adev->gmc.flush_pasid_uses_kiq || !ring->sched.ready ||
- !down_read_trylock(&adev->reset_domain->sem)) {
+ /*
+ * A GPU reset should flush all TLBs anyway, so no need to do
+ * this while one is ongoing.
+ */
+ if (!down_read_trylock(&adev->reset_domain->sem))
+ return 0;
+ if (!adev->gmc.flush_pasid_uses_kiq || !ring->sched.ready) {
if (adev->gmc.flush_tlb_needs_extra_type_2)
adev->gmc.gmc_funcs->flush_gpu_tlb_pasid(adev, pasid,
2, all_hub,
@@ -703,43 +706,44 @@ int amdgpu_gmc_flush_gpu_tlb_pasid(struct amdgpu_device *adev, uint16_t pasid,
adev->gmc.gmc_funcs->flush_gpu_tlb_pasid(adev, pasid,
flush_type, all_hub,
inst);
- return 0;
- }
+ r = 0;
+ } else {
+ /* 2 dwords flush + 8 dwords fence */
+ ndw = kiq->pmf->invalidate_tlbs_size + 8;
- /* 2 dwords flush + 8 dwords fence */
- ndw = kiq->pmf->invalidate_tlbs_size + 8;
+ if (adev->gmc.flush_tlb_needs_extra_type_2)
+ ndw += kiq->pmf->invalidate_tlbs_size;
- if (adev->gmc.flush_tlb_needs_extra_type_2)
- ndw += kiq->pmf->invalidate_tlbs_size;
+ if (adev->gmc.flush_tlb_needs_extra_type_0)
+ ndw += kiq->pmf->invalidate_tlbs_size;
- if (adev->gmc.flush_tlb_needs_extra_type_0)
- ndw += kiq->pmf->invalidate_tlbs_size;
+ spin_lock(&adev->gfx.kiq[inst].ring_lock);
+ r = amdgpu_ring_alloc(ring, ndw);
+ if (r) {
+ spin_unlock(&adev->gfx.kiq[inst].ring_lock);
+ goto error_unlock_reset;
+ }
+ if (adev->gmc.flush_tlb_needs_extra_type_2)
+ kiq->pmf->kiq_invalidate_tlbs(ring, pasid, 2, all_hub);
- spin_lock(&adev->gfx.kiq[inst].ring_lock);
- amdgpu_ring_alloc(ring, ndw);
- if (adev->gmc.flush_tlb_needs_extra_type_2)
- kiq->pmf->kiq_invalidate_tlbs(ring, pasid, 2, all_hub);
+ if (flush_type == 2 && adev->gmc.flush_tlb_needs_extra_type_0)
+ kiq->pmf->kiq_invalidate_tlbs(ring, pasid, 0, all_hub);
- if (flush_type == 2 && adev->gmc.flush_tlb_needs_extra_type_0)
- kiq->pmf->kiq_invalidate_tlbs(ring, pasid, 0, all_hub);
+ kiq->pmf->kiq_invalidate_tlbs(ring, pasid, flush_type, all_hub);
+ r = amdgpu_fence_emit_polling(ring, &seq, MAX_KIQ_REG_WAIT);
+ if (r) {
+ amdgpu_ring_undo(ring);
+ spin_unlock(&adev->gfx.kiq[inst].ring_lock);
+ goto error_unlock_reset;
+ }
- kiq->pmf->kiq_invalidate_tlbs(ring, pasid, flush_type, all_hub);
- r = amdgpu_fence_emit_polling(ring, &seq, MAX_KIQ_REG_WAIT);
- if (r) {
- amdgpu_ring_undo(ring);
+ amdgpu_ring_commit(ring);
spin_unlock(&adev->gfx.kiq[inst].ring_lock);
- goto error_unlock_reset;
- }
-
- amdgpu_ring_commit(ring);
- spin_unlock(&adev->gfx.kiq[inst].ring_lock);
- r = amdgpu_fence_wait_polling(ring, seq, usec_timeout);
- if (r < 1) {
- dev_err(adev->dev, "wait for kiq fence error: %ld.\n", r);
- r = -ETIME;
- goto error_unlock_reset;
+ if (amdgpu_fence_wait_polling(ring, seq, usec_timeout) < 1) {
+ dev_err(adev->dev, "timeout waiting for kiq fence\n");
+ r = -ETIME;
+ }
}
- r = 0;
error_unlock_reset:
up_read(&adev->reset_domain->sem);
@@ -844,6 +848,7 @@ void amdgpu_gmc_tmz_set(struct amdgpu_device *adev)
case IP_VERSION(11, 0, 4):
case IP_VERSION(11, 5, 0):
case IP_VERSION(11, 5, 1):
+ case IP_VERSION(11, 5, 2):
/* Don't enable it by default yet.
*/
if (amdgpu_tmz < 1) {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
index 44367f03316f..0760e70402ec 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
@@ -200,8 +200,6 @@ void amdgpu_gtt_mgr_recover(struct amdgpu_gtt_mgr *mgr)
amdgpu_ttm_recover_gart(node->base.bo);
}
spin_unlock(&mgr->lock);
-
- amdgpu_gart_invalidate_tlb(adev);
}
/**
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
index 3d7fcdeaf8cf..b6a8bddada4c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
@@ -290,18 +290,36 @@ static int amdgpu_vmid_grab_reserved(struct amdgpu_vm *vm,
!dma_fence_is_signaled((*id)->last_flush))) {
struct dma_fence *tmp;
- /* Don't use per engine and per process VMID at the same time */
- if (adev->vm_manager.concurrent_flush)
- ring = NULL;
-
- /* to prevent one context starved by another context */
- (*id)->pd_gpu_addr = 0;
- tmp = amdgpu_sync_peek_fence(&(*id)->active, ring);
- if (tmp) {
+ /* Wait for the gang to be assembled before using a
+ * reserved VMID or otherwise the gang could deadlock.
+ */
+ tmp = amdgpu_device_get_gang(adev);
+ if (!dma_fence_is_signaled(tmp) && tmp != job->gang_submit) {
*id = NULL;
- *fence = dma_fence_get(tmp);
+ *fence = tmp;
return 0;
}
+ dma_fence_put(tmp);
+
+ /* Make sure the id is owned by the gang before proceeding */
+ if (!job->gang_submit ||
+ (*id)->owner != vm->immediate.fence_context) {
+
+ /* Don't use per engine and per process VMID at the
+ * same time
+ */
+ if (adev->vm_manager.concurrent_flush)
+ ring = NULL;
+
+ /* to prevent one context starved by another context */
+ (*id)->pd_gpu_addr = 0;
+ tmp = amdgpu_sync_peek_fence(&(*id)->active, ring);
+ if (tmp) {
+ *id = NULL;
+ *fence = dma_fence_get(tmp);
+ return 0;
+ }
+ }
needs_flush = true;
}
@@ -406,7 +424,7 @@ int amdgpu_vmid_grab(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
if (r || !idle)
goto error;
- if (vm->reserved_vmid[vmhub] || (enforce_isolation && (vmhub == AMDGPU_GFXHUB(0)))) {
+ if (amdgpu_vmid_uses_reserved(vm, vmhub)) {
r = amdgpu_vmid_grab_reserved(vm, ring, job, &id, fence);
if (r || !id)
goto error;
@@ -456,6 +474,19 @@ error:
return r;
}
+/*
+ * amdgpu_vmid_uses_reserved - check if a VM will use a reserved VMID
+ * @vm: the VM to check
+ * @vmhub: the VMHUB which will be used
+ *
+ * Returns: True if the VM will use a reserved VMID.
+ */
+bool amdgpu_vmid_uses_reserved(struct amdgpu_vm *vm, unsigned int vmhub)
+{
+ return vm->reserved_vmid[vmhub] ||
+ (enforce_isolation && (vmhub == AMDGPU_GFXHUB(0)));
+}
+
int amdgpu_vmid_alloc_reserved(struct amdgpu_device *adev,
unsigned vmhub)
{
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h
index fa8c42c83d5d..240fa6751260 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h
@@ -78,6 +78,7 @@ void amdgpu_pasid_free_delayed(struct dma_resv *resv,
bool amdgpu_vmid_had_gpu_reset(struct amdgpu_device *adev,
struct amdgpu_vmid *id);
+bool amdgpu_vmid_uses_reserved(struct amdgpu_vm *vm, unsigned int vmhub);
int amdgpu_vmid_alloc_reserved(struct amdgpu_device *adev,
unsigned vmhub);
void amdgpu_vmid_free_reserved(struct amdgpu_device *adev,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
index 013ff373e067..19ce4da285e8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
@@ -466,7 +466,8 @@ void amdgpu_irq_dispatch(struct amdgpu_device *adev,
} else if (src_id >= AMDGPU_MAX_IRQ_SRC_ID) {
DRM_DEBUG("Invalid src_id in IV: %d\n", src_id);
- } else if ((client_id == AMDGPU_IRQ_CLIENTID_LEGACY) &&
+ } else if (((client_id == AMDGPU_IRQ_CLIENTID_LEGACY) ||
+ (client_id == SOC15_IH_CLIENTID_ISP)) &&
adev->irq.virq[src_id]) {
generic_handle_domain_irq(adev->irq.domain, src_id);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c
new file mode 100644
index 000000000000..4766e99dd98f
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c
@@ -0,0 +1,210 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+ * 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, sub license, 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 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ */
+
+#include <linux/firmware.h>
+#include <linux/mfd/core.h>
+
+#include "amdgpu.h"
+#include "amdgpu_isp.h"
+#include "isp_v4_1_0.h"
+#include "isp_v4_1_1.h"
+
+static int isp_sw_init(void *handle)
+{
+ return 0;
+}
+
+static int isp_sw_fini(void *handle)
+{
+ return 0;
+}
+
+/**
+ * isp_hw_init - start and test isp block
+ *
+ * @handle: handle for amdgpu_device pointer
+ *
+ */
+static int isp_hw_init(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ struct amdgpu_isp *isp = &adev->isp;
+
+ const struct amdgpu_ip_block *ip_block =
+ amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_ISP);
+
+ if (!ip_block)
+ return -EINVAL;
+
+ if (isp->funcs->hw_init != NULL)
+ return isp->funcs->hw_init(isp);
+
+ return -ENODEV;
+}
+
+/**
+ * isp_hw_fini - stop the hardware block
+ *
+ * @handle: handle for amdgpu_device pointer
+ *
+ */
+static int isp_hw_fini(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ struct amdgpu_isp *isp = &adev->isp;
+
+ if (isp->funcs->hw_fini != NULL)
+ return isp->funcs->hw_fini(isp);
+
+ return -ENODEV;
+}
+
+static int isp_suspend(void *handle)
+{
+ return 0;
+}
+
+static int isp_resume(void *handle)
+{
+ return 0;
+}
+
+static int isp_load_fw_by_psp(struct amdgpu_device *adev)
+{
+ const struct common_firmware_header *hdr;
+ char ucode_prefix[10];
+ int r = 0;
+
+ /* get isp fw binary name and path */
+ amdgpu_ucode_ip_version_decode(adev, ISP_HWIP, ucode_prefix,
+ sizeof(ucode_prefix));
+
+ /* read isp fw */
+ r = amdgpu_ucode_request(adev, &adev->isp.fw, "amdgpu/%s.bin", ucode_prefix);
+ if (r) {
+ amdgpu_ucode_release(&adev->isp.fw);
+ return r;
+ }
+
+ hdr = (const struct common_firmware_header *)adev->isp.fw->data;
+
+ adev->firmware.ucode[AMDGPU_UCODE_ID_ISP].ucode_id =
+ AMDGPU_UCODE_ID_ISP;
+ adev->firmware.ucode[AMDGPU_UCODE_ID_ISP].fw = adev->isp.fw;
+
+ adev->firmware.fw_size +=
+ ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE);
+
+ return r;
+}
+
+static int isp_early_init(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ struct amdgpu_isp *isp = &adev->isp;
+
+ switch (amdgpu_ip_version(adev, ISP_HWIP, 0)) {
+ case IP_VERSION(4, 1, 0):
+ isp_v4_1_0_set_isp_funcs(isp);
+ break;
+ case IP_VERSION(4, 1, 1):
+ isp_v4_1_1_set_isp_funcs(isp);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ isp->adev = adev;
+ isp->parent = adev->dev;
+
+ if (isp_load_fw_by_psp(adev)) {
+ DRM_DEBUG_DRIVER("%s: isp fw load failed\n", __func__);
+ return -ENOENT;
+ }
+
+ return 0;
+}
+
+static bool isp_is_idle(void *handle)
+{
+ return true;
+}
+
+static int isp_wait_for_idle(void *handle)
+{
+ return 0;
+}
+
+static int isp_soft_reset(void *handle)
+{
+ return 0;
+}
+
+static int isp_set_clockgating_state(void *handle,
+ enum amd_clockgating_state state)
+{
+ return 0;
+}
+
+static int isp_set_powergating_state(void *handle,
+ enum amd_powergating_state state)
+{
+ return 0;
+}
+
+static const struct amd_ip_funcs isp_ip_funcs = {
+ .name = "isp_ip",
+ .early_init = isp_early_init,
+ .late_init = NULL,
+ .sw_init = isp_sw_init,
+ .sw_fini = isp_sw_fini,
+ .hw_init = isp_hw_init,
+ .hw_fini = isp_hw_fini,
+ .suspend = isp_suspend,
+ .resume = isp_resume,
+ .is_idle = isp_is_idle,
+ .wait_for_idle = isp_wait_for_idle,
+ .soft_reset = isp_soft_reset,
+ .set_clockgating_state = isp_set_clockgating_state,
+ .set_powergating_state = isp_set_powergating_state,
+};
+
+const struct amdgpu_ip_block_version isp_v4_1_0_ip_block = {
+ .type = AMD_IP_BLOCK_TYPE_ISP,
+ .major = 4,
+ .minor = 1,
+ .rev = 0,
+ .funcs = &isp_ip_funcs,
+};
+
+const struct amdgpu_ip_block_version isp_v4_1_1_ip_block = {
+ .type = AMD_IP_BLOCK_TYPE_ISP,
+ .major = 4,
+ .minor = 1,
+ .rev = 1,
+ .funcs = &isp_ip_funcs,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.h
new file mode 100644
index 000000000000..44e2ea8c9728
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.h
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+ * 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, sub license, 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 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ */
+
+#ifndef __AMDGPU_ISP_H__
+#define __AMDGPU_ISP_H__
+
+#define ISP_REGS_OFFSET_END 0x629A4
+
+struct amdgpu_isp;
+
+struct isp_platform_data {
+ void *adev;
+ u32 asic_type;
+ resource_size_t base_rmmio_size;
+};
+
+struct isp_funcs {
+ int (*hw_init)(struct amdgpu_isp *isp);
+ int (*hw_fini)(struct amdgpu_isp *isp);
+};
+
+struct amdgpu_isp {
+ struct device *parent;
+ struct amdgpu_device *adev;
+ const struct isp_funcs *funcs;
+ struct mfd_cell *isp_cell;
+ struct resource *isp_res;
+ struct isp_platform_data *isp_pdata;
+ unsigned int harvest_config;
+ const struct firmware *fw;
+};
+
+extern const struct amdgpu_ip_block_version isp_v4_1_0_ip_block;
+extern const struct amdgpu_ip_block_version isp_v4_1_1_ip_block;
+
+#endif /* __AMDGPU_ISP_H__ */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
index e4742b65032d..e238f2832f65 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
@@ -41,7 +41,7 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job)
int r;
if (!drm_dev_enter(adev_to_drm(adev), &idx)) {
- DRM_INFO("%s - device unplugged skipping recovery on scheduler:%s",
+ dev_info(adev->dev, "%s - device unplugged skipping recovery on scheduler:%s",
__func__, s_job->sched->name);
/* Effectively the job is aborted as the device is gone */
@@ -53,19 +53,20 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job)
if (amdgpu_gpu_recovery &&
amdgpu_ring_soft_recovery(ring, job->vmid, s_job->s_fence->parent)) {
- DRM_ERROR("ring %s timeout, but soft recovered\n",
- s_job->sched->name);
+ dev_err(adev->dev, "ring %s timeout, but soft recovered\n",
+ s_job->sched->name);
goto exit;
}
- DRM_ERROR("ring %s timeout, signaled seq=%u, emitted seq=%u\n",
- job->base.sched->name, atomic_read(&ring->fence_drv.last_seq),
- ring->fence_drv.sync_seq);
+ dev_err(adev->dev, "ring %s timeout, signaled seq=%u, emitted seq=%u\n",
+ job->base.sched->name, atomic_read(&ring->fence_drv.last_seq),
+ ring->fence_drv.sync_seq);
ti = amdgpu_vm_get_task_info_pasid(ring->adev, job->pasid);
if (ti) {
- DRM_ERROR("Process information: process %s pid %d thread %s pid %d\n",
- ti->process_name, ti->tgid, ti->task_name, ti->pid);
+ dev_err(adev->dev,
+ "Process information: process %s pid %d thread %s pid %d\n",
+ ti->process_name, ti->tgid, ti->task_name, ti->pid);
amdgpu_vm_put_task_info(ti);
}
@@ -77,11 +78,12 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job)
reset_context.method = AMD_RESET_METHOD_NONE;
reset_context.reset_req_dev = adev;
+ reset_context.src = AMDGPU_RESET_SRC_JOB;
clear_bit(AMDGPU_NEED_FULL_RESET, &reset_context.flags);
r = amdgpu_device_gpu_recover(ring->adev, job, &reset_context);
if (r)
- DRM_ERROR("GPU Recovery Failed: %d\n", r);
+ dev_err(adev->dev, "GPU Recovery Failed: %d\n", r);
} else {
drm_sched_suspend_timeout(&ring->sched);
if (amdgpu_sriov_vf(adev))
@@ -273,7 +275,7 @@ amdgpu_job_prepare_job(struct drm_sched_job *sched_job,
while (!fence && job->vm && !job->vmid) {
r = amdgpu_vmid_grab(job->vm, ring, job, &fence);
if (r) {
- DRM_ERROR("Error getting VM ID (%d)\n", r);
+ dev_err(ring->adev->dev, "Error getting VM ID (%d)\n", r);
goto error;
}
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h
index aea31d61d991..f9cdd873ac9b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h
@@ -60,6 +60,37 @@
RREG32_SOC15(JPEG, inst_idx, mmUVD_DPG_LMA_DATA); \
})
+#define WREG32_SOC24_JPEG_DPG_MODE(inst_idx, offset, value, indirect) \
+ do { \
+ WREG32_SOC15(JPEG, GET_INST(JPEG, inst_idx), \
+ regUVD_DPG_LMA_DATA, value); \
+ WREG32_SOC15(JPEG, GET_INST(JPEG, inst_idx), \
+ regUVD_DPG_LMA_MASK, 0xFFFFFFFF); \
+ WREG32_SOC15( \
+ JPEG, GET_INST(JPEG, inst_idx), \
+ regUVD_DPG_LMA_CTL, \
+ (UVD_DPG_LMA_CTL__READ_WRITE_MASK | \
+ offset << UVD_DPG_LMA_CTL__READ_WRITE_ADDR__SHIFT | \
+ indirect << UVD_DPG_LMA_CTL__SRAM_SEL__SHIFT)); \
+ } while (0)
+
+#define RREG32_SOC24_JPEG_DPG_MODE(inst_idx, offset, mask_en) \
+ do { \
+ WREG32_SOC15(JPEG, GET_INST(JPEG, inst_idx), \
+ regUVD_DPG_LMA_MASK, 0xFFFFFFFF); \
+ WREG32_SOC15(JPEG, GET_INST(JPEG, inst_idx), \
+ regUVD_DPG_LMA_CTL, \
+ (UVD_DPG_LMA_CTL__MASK_EN_MASK | \
+ offset << UVD_DPG_LMA_CTL__READ_WRITE_ADDR__SHIFT)); \
+ RREG32_SOC15(JPEG, inst_idx, regUVD_DPG_LMA_DATA); \
+ } while (0)
+
+#define ADD_SOC24_JPEG_TO_DPG_SRAM(inst_idx, offset, value, indirect) \
+ do { \
+ *adev->jpeg.inst[inst_idx].dpg_sram_curr_addr++ = offset; \
+ *adev->jpeg.inst[inst_idx].dpg_sram_curr_addr++ = value; \
+ } while (0)
+
struct amdgpu_jpeg_reg{
unsigned jpeg_pitch[AMDGPU_MAX_JPEG_RINGS];
};
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c
index da40c2d97df8..2542bd7aa7c7 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c
@@ -193,27 +193,26 @@ static int amdgpu_mca_bank_set_merge(struct mca_bank_set *mca_set, struct mca_ba
return 0;
}
-static int amdgpu_mca_bank_set_remove_node(struct mca_bank_set *mca_set, struct mca_bank_node *node)
+static void amdgpu_mca_bank_set_remove_node(struct mca_bank_set *mca_set, struct mca_bank_node *node)
{
if (!node)
- return -EINVAL;
+ return;
list_del(&node->node);
kvfree(node);
mca_set->nr_entries--;
-
- return 0;
}
static void amdgpu_mca_bank_set_release(struct mca_bank_set *mca_set)
{
struct mca_bank_node *node, *tmp;
- list_for_each_entry_safe(node, tmp, &mca_set->list, node) {
- list_del(&node->node);
- kvfree(node);
- }
+ if (list_empty(&mca_set->list))
+ return;
+
+ list_for_each_entry_safe(node, tmp, &mca_set->list, node)
+ amdgpu_mca_bank_set_remove_node(mca_set, node);
}
void amdgpu_mca_smu_init_funcs(struct amdgpu_device *adev, const struct amdgpu_mca_smu_funcs *mca_funcs)
@@ -233,7 +232,7 @@ int amdgpu_mca_init(struct amdgpu_device *adev)
for (i = 0; i < ARRAY_SIZE(mca->mca_caches); i++) {
mca_cache = &mca->mca_caches[i];
- spin_lock_init(&mca_cache->lock);
+ mutex_init(&mca_cache->lock);
amdgpu_mca_bank_set_init(&mca_cache->mca_set);
}
@@ -251,6 +250,7 @@ void amdgpu_mca_fini(struct amdgpu_device *adev)
for (i = 0; i < ARRAY_SIZE(mca->mca_caches); i++) {
mca_cache = &mca->mca_caches[i];
amdgpu_mca_bank_set_release(&mca_cache->mca_set);
+ mutex_destroy(&mca_cache->lock);
}
}
@@ -274,7 +274,7 @@ int amdgpu_mca_smu_set_debug_mode(struct amdgpu_device *adev, bool enable)
static void amdgpu_mca_smu_mca_bank_dump(struct amdgpu_device *adev, int idx, struct mca_bank_entry *entry,
struct ras_query_context *qctx)
{
- u64 event_id = qctx->event_id;
+ u64 event_id = qctx ? qctx->evid.event_id : RAS_EVENT_INVALID_ID;
RAS_EVENT_LOG(adev, event_id, HW_ERR "Accelerator Check Architecture events logged\n");
RAS_EVENT_LOG(adev, event_id, HW_ERR "aca entry[%02d].STATUS=0x%016llx\n",
@@ -455,9 +455,9 @@ static int amdgpu_mca_add_mca_set_to_cache(struct amdgpu_device *adev, enum amdg
struct mca_bank_cache *mca_cache = &adev->mca.mca_caches[type];
int ret;
- spin_lock(&mca_cache->lock);
+ mutex_lock(&mca_cache->lock);
ret = amdgpu_mca_bank_set_merge(&mca_cache->mca_set, new);
- spin_unlock(&mca_cache->lock);
+ mutex_unlock(&mca_cache->lock);
return ret;
}
@@ -487,10 +487,10 @@ int amdgpu_mca_smu_log_ras_error(struct amdgpu_device *adev, enum amdgpu_ras_blo
}
/* dispatch mca set again if mca cache has valid data */
- spin_lock(&mca_cache->lock);
+ mutex_lock(&mca_cache->lock);
if (mca_cache->mca_set.nr_entries)
ret = amdgpu_mca_dispatch_mca_set(adev, blk, type, &mca_cache->mca_set, err_data);
- spin_unlock(&mca_cache->lock);
+ mutex_unlock(&mca_cache->lock);
out_mca_release:
amdgpu_mca_bank_set_release(&mca_set);
@@ -543,7 +543,7 @@ static int mca_dump_show(struct seq_file *m, enum amdgpu_mca_error_type type)
amdgpu_mca_bank_set_init(&mca_set);
- qctx.event_id = 0ULL;
+ qctx.evid.event_id = RAS_EVENT_INVALID_ID;
ret = amdgpu_mca_smu_get_mca_set(adev, type, &mca_set, &qctx);
if (ret)
goto err_free_mca_set;
@@ -608,9 +608,7 @@ DEFINE_DEBUGFS_ATTRIBUTE(mca_debug_mode_fops, NULL, amdgpu_mca_smu_debug_mode_se
void amdgpu_mca_smu_debugfs_init(struct amdgpu_device *adev, struct dentry *root)
{
#if defined(CONFIG_DEBUG_FS)
- if (!root ||
- (amdgpu_ip_version(adev, MP1_HWIP, 0) != IP_VERSION(13, 0, 6) &&
- amdgpu_ip_version(adev, MP1_HWIP, 0) != IP_VERSION(13, 0, 14)))
+ if (!root)
return;
debugfs_create_file("mca_debug_mode", 0200, root, adev, &mca_debug_mode_fops);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.h
index c3c184c88dad..e80323ff90c1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.h
@@ -84,7 +84,7 @@ struct mca_bank_set {
struct mca_bank_cache {
struct mca_bank_set mca_set;
- spinlock_t lock;
+ struct mutex lock;
};
struct amdgpu_mca {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c
index 62edf6328566..e499d6ba306b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c
@@ -32,18 +32,6 @@
#define AMDGPU_MES_MAX_NUM_OF_QUEUES_PER_PROCESS 1024
#define AMDGPU_ONE_DOORBELL_SIZE 8
-signed long amdgpu_mes_fence_wait_polling(u64 *fence,
- u64 wait_seq,
- signed long timeout)
-{
-
- while ((s64)(wait_seq - *fence) > 0 && timeout > 0) {
- udelay(2);
- timeout -= 2;
- }
- return timeout > 0 ? timeout : 0;
-}
-
int amdgpu_mes_doorbell_process_slice(struct amdgpu_device *adev)
{
return roundup(AMDGPU_ONE_DOORBELL_SIZE *
@@ -1528,11 +1516,9 @@ int amdgpu_mes_init_microcode(struct amdgpu_device *adev, int pipe)
r = amdgpu_ucode_request(adev, &adev->mes.fw[pipe], fw_name);
if (r && need_retry && pipe == AMDGPU_MES_SCHED_PIPE) {
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mes.bin",
- ucode_prefix);
- DRM_INFO("try to fall back to %s\n", fw_name);
+ dev_info(adev->dev, "try to fall back to %s_mes.bin\n", ucode_prefix);
r = amdgpu_ucode_request(adev, &adev->mes.fw[pipe],
- fw_name);
+ "amdgpu/%s_mes.bin", ucode_prefix);
}
if (r)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h
index df9f0404d842..e11051271f71 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h
@@ -352,10 +352,6 @@ struct amdgpu_mes_funcs {
#define amdgpu_mes_kiq_hw_init(adev) (adev)->mes.kiq_hw_init((adev))
#define amdgpu_mes_kiq_hw_fini(adev) (adev)->mes.kiq_hw_fini((adev))
-signed long amdgpu_mes_fence_wait_polling(u64 *fence,
- u64 wait_seq,
- signed long timeout);
-
int amdgpu_mes_ctx_get_offs(struct amdgpu_ring *ring, unsigned int id_offs);
int amdgpu_mes_init_microcode(struct amdgpu_device *adev, int pipe);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
index 1fe21a70ddd0..d002b845d8ac 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
@@ -300,6 +300,7 @@ struct amdgpu_framebuffer {
uint64_t tiling_flags;
bool tmz_surface;
+ bool gfx12_dcc;
/* caching for later use */
uint64_t address;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
index fa5227a4aac2..e32161f6b67a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
@@ -604,8 +604,6 @@ int amdgpu_bo_create(struct amdgpu_device *adev,
if (!amdgpu_bo_support_uswc(bo->flags))
bo->flags &= ~AMDGPU_GEM_CREATE_CPU_GTT_USWC;
- bo->flags |= AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE;
-
bo->tbo.bdev = &adev->mman.bdev;
if (bp->domain & (AMDGPU_GEM_DOMAIN_GWS | AMDGPU_GEM_DOMAIN_OA |
AMDGPU_GEM_DOMAIN_GDS))
@@ -1601,36 +1599,39 @@ u64 amdgpu_bo_print_info(int id, struct amdgpu_bo *bo, struct seq_file *m)
u64 size;
if (dma_resv_trylock(bo->tbo.base.resv)) {
-
- switch (bo->tbo.resource->mem_type) {
- case TTM_PL_VRAM:
- if (amdgpu_res_cpu_visible(adev, bo->tbo.resource))
- placement = "VRAM VISIBLE";
- else
- placement = "VRAM";
- break;
- case TTM_PL_TT:
- placement = "GTT";
- break;
- case AMDGPU_PL_GDS:
- placement = "GDS";
- break;
- case AMDGPU_PL_GWS:
- placement = "GWS";
- break;
- case AMDGPU_PL_OA:
- placement = "OA";
- break;
- case AMDGPU_PL_PREEMPT:
- placement = "PREEMPTIBLE";
- break;
- case AMDGPU_PL_DOORBELL:
- placement = "DOORBELL";
- break;
- case TTM_PL_SYSTEM:
- default:
- placement = "CPU";
- break;
+ if (!bo->tbo.resource) {
+ placement = "NONE";
+ } else {
+ switch (bo->tbo.resource->mem_type) {
+ case TTM_PL_VRAM:
+ if (amdgpu_res_cpu_visible(adev, bo->tbo.resource))
+ placement = "VRAM VISIBLE";
+ else
+ placement = "VRAM";
+ break;
+ case TTM_PL_TT:
+ placement = "GTT";
+ break;
+ case AMDGPU_PL_GDS:
+ placement = "GDS";
+ break;
+ case AMDGPU_PL_GWS:
+ placement = "GWS";
+ break;
+ case AMDGPU_PL_OA:
+ placement = "OA";
+ break;
+ case AMDGPU_PL_PREEMPT:
+ placement = "PREEMPTIBLE";
+ break;
+ case AMDGPU_PL_DOORBELL:
+ placement = "DOORBELL";
+ break;
+ case TTM_PL_SYSTEM:
+ default:
+ placement = "CPU";
+ break;
+ }
}
dma_resv_unlock(bo->tbo.base.resv);
} else {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
index 5a648a657dc6..189574d53ebd 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
@@ -219,6 +219,7 @@ static int psp_early_init(void *handle)
case IP_VERSION(13, 0, 11):
case IP_VERSION(14, 0, 0):
case IP_VERSION(14, 0, 1):
+ case IP_VERSION(14, 0, 4):
psp_v13_0_set_psp_funcs(psp);
psp->boot_time_tmr = false;
break;
@@ -643,6 +644,20 @@ static const char *psp_gfx_cmd_name(enum psp_gfx_cmd_id cmd_id)
}
}
+static bool psp_err_warn(struct psp_context *psp)
+{
+ struct psp_gfx_cmd_resp *cmd = psp->cmd_buf_mem;
+
+ /* This response indicates reg list is already loaded */
+ if (amdgpu_ip_version(psp->adev, MP0_HWIP, 0) == IP_VERSION(13, 0, 2) &&
+ cmd->cmd_id == GFX_CMD_ID_LOAD_IP_FW &&
+ cmd->cmd.cmd_load_ip_fw.fw_type == GFX_FW_TYPE_REG_LIST &&
+ cmd->resp.status == TEE_ERROR_CANCEL)
+ return false;
+
+ return true;
+}
+
static int
psp_cmd_submit_buf(struct psp_context *psp,
struct amdgpu_firmware_info *ucode,
@@ -702,10 +717,13 @@ psp_cmd_submit_buf(struct psp_context *psp,
dev_warn(psp->adev->dev,
"failed to load ucode %s(0x%X) ",
amdgpu_ucode_name(ucode->ucode_id), ucode->ucode_id);
- dev_warn(psp->adev->dev,
- "psp gfx command %s(0x%X) failed and response status is (0x%X)\n",
- psp_gfx_cmd_name(psp->cmd_buf_mem->cmd_id), psp->cmd_buf_mem->cmd_id,
- psp->cmd_buf_mem->resp.status);
+ if (psp_err_warn(psp))
+ dev_warn(
+ psp->adev->dev,
+ "psp gfx command %s(0x%X) failed and response status is (0x%X)\n",
+ psp_gfx_cmd_name(psp->cmd_buf_mem->cmd_id),
+ psp->cmd_buf_mem->cmd_id,
+ psp->cmd_buf_mem->resp.status);
/* If any firmware (including CAP) load fails under SRIOV, it should
* return failure to stop the VF from initializing.
* Also return failure in case of timeout
@@ -1573,6 +1591,66 @@ static void psp_ras_ta_check_status(struct psp_context *psp)
}
}
+static int psp_ras_send_cmd(struct psp_context *psp,
+ enum ras_command cmd_id, void *in, void *out)
+{
+ struct ta_ras_shared_memory *ras_cmd;
+ uint32_t cmd = cmd_id;
+ int ret = 0;
+
+ if (!in)
+ return -EINVAL;
+
+ mutex_lock(&psp->ras_context.mutex);
+ ras_cmd = (struct ta_ras_shared_memory *)psp->ras_context.context.mem_context.shared_buf;
+ memset(ras_cmd, 0, sizeof(struct ta_ras_shared_memory));
+
+ switch (cmd) {
+ case TA_RAS_COMMAND__ENABLE_FEATURES:
+ case TA_RAS_COMMAND__DISABLE_FEATURES:
+ memcpy(&ras_cmd->ras_in_message,
+ in, sizeof(ras_cmd->ras_in_message));
+ break;
+ case TA_RAS_COMMAND__TRIGGER_ERROR:
+ memcpy(&ras_cmd->ras_in_message.trigger_error,
+ in, sizeof(ras_cmd->ras_in_message.trigger_error));
+ break;
+ case TA_RAS_COMMAND__QUERY_ADDRESS:
+ memcpy(&ras_cmd->ras_in_message.address,
+ in, sizeof(ras_cmd->ras_in_message.address));
+ break;
+ default:
+ dev_err(psp->adev->dev, "Invalid ras cmd id: %u\n", cmd);
+ ret = -EINVAL;
+ goto err_out;
+ }
+
+ ras_cmd->cmd_id = cmd;
+ ret = psp_ras_invoke(psp, ras_cmd->cmd_id);
+
+ switch (cmd) {
+ case TA_RAS_COMMAND__TRIGGER_ERROR:
+ if (!ret && out)
+ memcpy(out, &ras_cmd->ras_status, sizeof(ras_cmd->ras_status));
+ break;
+ case TA_RAS_COMMAND__QUERY_ADDRESS:
+ if (ret || ras_cmd->ras_status || psp->cmd_buf_mem->resp.status)
+ ret = -EINVAL;
+ else if (out)
+ memcpy(out,
+ &ras_cmd->ras_out_message.address,
+ sizeof(ras_cmd->ras_out_message.address));
+ break;
+ default:
+ break;
+ }
+
+err_out:
+ mutex_unlock(&psp->ras_context.mutex);
+
+ return ret;
+}
+
int psp_ras_invoke(struct psp_context *psp, uint32_t ta_cmd_id)
{
struct ta_ras_shared_memory *ras_cmd;
@@ -1614,23 +1692,15 @@ int psp_ras_invoke(struct psp_context *psp, uint32_t ta_cmd_id)
int psp_ras_enable_features(struct psp_context *psp,
union ta_ras_cmd_input *info, bool enable)
{
- struct ta_ras_shared_memory *ras_cmd;
+ enum ras_command cmd_id;
int ret;
- if (!psp->ras_context.context.initialized)
+ if (!psp->ras_context.context.initialized || !info)
return -EINVAL;
- ras_cmd = (struct ta_ras_shared_memory *)psp->ras_context.context.mem_context.shared_buf;
- memset(ras_cmd, 0, sizeof(struct ta_ras_shared_memory));
-
- if (enable)
- ras_cmd->cmd_id = TA_RAS_COMMAND__ENABLE_FEATURES;
- else
- ras_cmd->cmd_id = TA_RAS_COMMAND__DISABLE_FEATURES;
-
- ras_cmd->ras_in_message = *info;
-
- ret = psp_ras_invoke(psp, ras_cmd->cmd_id);
+ cmd_id = enable ?
+ TA_RAS_COMMAND__ENABLE_FEATURES : TA_RAS_COMMAND__DISABLE_FEATURES;
+ ret = psp_ras_send_cmd(psp, cmd_id, info, NULL);
if (ret)
return -EINVAL;
@@ -1654,6 +1724,8 @@ int psp_ras_terminate(struct psp_context *psp)
psp->ras_context.context.initialized = false;
+ mutex_destroy(&psp->ras_context.mutex);
+
return ret;
}
@@ -1738,9 +1810,10 @@ int psp_ras_initialize(struct psp_context *psp)
ret = psp_ta_load(psp, &psp->ras_context.context);
- if (!ret && !ras_cmd->ras_status)
+ if (!ret && !ras_cmd->ras_status) {
psp->ras_context.context.initialized = true;
- else {
+ mutex_init(&psp->ras_context.mutex);
+ } else {
if (ras_cmd->ras_status)
dev_warn(adev->dev, "RAS Init Status: 0x%X\n", ras_cmd->ras_status);
@@ -1754,12 +1827,12 @@ int psp_ras_initialize(struct psp_context *psp)
int psp_ras_trigger_error(struct psp_context *psp,
struct ta_ras_trigger_error_input *info, uint32_t instance_mask)
{
- struct ta_ras_shared_memory *ras_cmd;
struct amdgpu_device *adev = psp->adev;
int ret;
uint32_t dev_mask;
+ uint32_t ras_status = 0;
- if (!psp->ras_context.context.initialized)
+ if (!psp->ras_context.context.initialized || !info)
return -EINVAL;
switch (info->block_id) {
@@ -1783,13 +1856,8 @@ int psp_ras_trigger_error(struct psp_context *psp,
dev_mask &= AMDGPU_RAS_INST_MASK;
info->sub_block_index |= dev_mask;
- ras_cmd = (struct ta_ras_shared_memory *)psp->ras_context.context.mem_context.shared_buf;
- memset(ras_cmd, 0, sizeof(struct ta_ras_shared_memory));
-
- ras_cmd->cmd_id = TA_RAS_COMMAND__TRIGGER_ERROR;
- ras_cmd->ras_in_message.trigger_error = *info;
-
- ret = psp_ras_invoke(psp, ras_cmd->cmd_id);
+ ret = psp_ras_send_cmd(psp,
+ TA_RAS_COMMAND__TRIGGER_ERROR, info, &ras_status);
if (ret)
return -EINVAL;
@@ -1799,9 +1867,9 @@ int psp_ras_trigger_error(struct psp_context *psp,
if (amdgpu_ras_intr_triggered())
return 0;
- if (ras_cmd->ras_status == TA_RAS_STATUS__TEE_ERROR_ACCESS_DENIED)
+ if (ras_status == TA_RAS_STATUS__TEE_ERROR_ACCESS_DENIED)
return -EACCES;
- else if (ras_cmd->ras_status)
+ else if (ras_status)
return -EINVAL;
return 0;
@@ -1811,25 +1879,16 @@ int psp_ras_query_address(struct psp_context *psp,
struct ta_ras_query_address_input *addr_in,
struct ta_ras_query_address_output *addr_out)
{
- struct ta_ras_shared_memory *ras_cmd;
int ret;
- if (!psp->ras_context.context.initialized)
- return -EINVAL;
-
- ras_cmd = (struct ta_ras_shared_memory *)psp->ras_context.context.mem_context.shared_buf;
- memset(ras_cmd, 0, sizeof(struct ta_ras_shared_memory));
-
- ras_cmd->cmd_id = TA_RAS_COMMAND__QUERY_ADDRESS;
- ras_cmd->ras_in_message.address = *addr_in;
-
- ret = psp_ras_invoke(psp, ras_cmd->cmd_id);
- if (ret || ras_cmd->ras_status || psp->cmd_buf_mem->resp.status)
+ if (!psp->ras_context.context.initialized ||
+ !addr_in || !addr_out)
return -EINVAL;
- *addr_out = ras_cmd->ras_out_message.address;
+ ret = psp_ras_send_cmd(psp,
+ TA_RAS_COMMAND__QUERY_ADDRESS, addr_in, addr_out);
- return 0;
+ return ret;
}
// ras end
@@ -2542,6 +2601,9 @@ static int psp_get_fw_type(struct amdgpu_firmware_info *ucode,
case AMDGPU_UCODE_ID_JPEG_RAM:
*type = GFX_FW_TYPE_JPEG_RAM;
break;
+ case AMDGPU_UCODE_ID_ISP:
+ *type = GFX_FW_TYPE_ISP;
+ break;
case AMDGPU_UCODE_ID_MAXIMUM:
default:
return -EINVAL;
@@ -3181,12 +3243,10 @@ int psp_ring_cmd_submit(struct psp_context *psp,
int psp_init_asd_microcode(struct psp_context *psp, const char *chip_name)
{
struct amdgpu_device *adev = psp->adev;
- char fw_name[PSP_FW_NAME_LEN];
const struct psp_firmware_header_v1_0 *asd_hdr;
int err = 0;
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_asd.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->psp.asd_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->psp.asd_fw, "amdgpu/%s_asd.bin", chip_name);
if (err)
goto out;
@@ -3205,12 +3265,10 @@ out:
int psp_init_toc_microcode(struct psp_context *psp, const char *chip_name)
{
struct amdgpu_device *adev = psp->adev;
- char fw_name[PSP_FW_NAME_LEN];
const struct psp_firmware_header_v1_0 *toc_hdr;
int err = 0;
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_toc.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->psp.toc_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->psp.toc_fw, "amdgpu/%s_toc.bin", chip_name);
if (err)
goto out;
@@ -3362,7 +3420,6 @@ static int psp_init_sos_base_fw(struct amdgpu_device *adev)
int psp_init_sos_microcode(struct psp_context *psp, const char *chip_name)
{
struct amdgpu_device *adev = psp->adev;
- char fw_name[PSP_FW_NAME_LEN];
const struct psp_firmware_header_v1_0 *sos_hdr;
const struct psp_firmware_header_v1_1 *sos_hdr_v1_1;
const struct psp_firmware_header_v1_2 *sos_hdr_v1_2;
@@ -3372,8 +3429,7 @@ int psp_init_sos_microcode(struct psp_context *psp, const char *chip_name)
uint8_t *ucode_array_start_addr;
int fw_index = 0;
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sos.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->psp.sos_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->psp.sos_fw, "amdgpu/%s_sos.bin", chip_name);
if (err)
goto out;
@@ -3598,11 +3654,9 @@ int psp_init_ta_microcode(struct psp_context *psp, const char *chip_name)
{
const struct common_firmware_header *hdr;
struct amdgpu_device *adev = psp->adev;
- char fw_name[PSP_FW_NAME_LEN];
int err;
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->psp.ta_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->psp.ta_fw, "amdgpu/%s_ta.bin", chip_name);
if (err)
return err;
@@ -3628,7 +3682,6 @@ int psp_init_ta_microcode(struct psp_context *psp, const char *chip_name)
int psp_init_cap_microcode(struct psp_context *psp, const char *chip_name)
{
struct amdgpu_device *adev = psp->adev;
- char fw_name[PSP_FW_NAME_LEN];
const struct psp_firmware_header_v1_0 *cap_hdr_v1_0;
struct amdgpu_firmware_info *info = NULL;
int err = 0;
@@ -3638,8 +3691,7 @@ int psp_init_cap_microcode(struct psp_context *psp, const char *chip_name)
return -EINVAL;
}
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_cap.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->psp.cap_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->psp.cap_fw, "amdgpu/%s_cap.bin", chip_name);
if (err) {
if (err == -ENODEV) {
dev_warn(adev->dev, "cap microcode does not exist, skip\n");
@@ -3713,7 +3765,6 @@ static ssize_t psp_usbc_pd_fw_sysfs_write(struct device *dev,
struct drm_device *ddev = dev_get_drvdata(dev);
struct amdgpu_device *adev = drm_to_adev(ddev);
int ret, idx;
- char fw_name[100];
const struct firmware *usbc_pd_fw;
struct amdgpu_bo *fw_buf_bo = NULL;
uint64_t fw_pri_mc_addr;
@@ -3727,8 +3778,7 @@ static ssize_t psp_usbc_pd_fw_sysfs_write(struct device *dev,
if (!drm_dev_enter(ddev, &idx))
return -ENODEV;
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s", buf);
- ret = request_firmware(&usbc_pd_fw, fw_name, adev->dev);
+ ret = amdgpu_ucode_request(adev, &usbc_pd_fw, "amdgpu/%s", buf);
if (ret)
goto fail;
@@ -3750,7 +3800,7 @@ static ssize_t psp_usbc_pd_fw_sysfs_write(struct device *dev,
amdgpu_bo_free_kernel(&fw_buf_bo, &fw_pri_mc_addr, &fw_pri_cpu_addr);
rel_buf:
- release_firmware(usbc_pd_fw);
+ amdgpu_ucode_release(&usbc_pd_fw);
fail:
if (ret) {
dev_err(adev->dev, "Failed to load USBC PD FW, err = %d", ret);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
index 3635303e6548..74a96516c913 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
@@ -200,6 +200,7 @@ struct psp_xgmi_context {
struct psp_ras_context {
struct ta_context context;
struct amdgpu_ras *ras;
+ struct mutex mutex;
};
#define MEM_TRAIN_SYSTEM_SIGNATURE 0x54534942
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c
index 8e8afbd237bc..0c856005df6b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c
@@ -348,6 +348,7 @@ static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf, size
context->session_id = ta_id;
+ mutex_lock(&psp->ras_context.mutex);
ret = prep_ta_mem_context(&context->mem_context, shared_buf, shared_buf_len);
if (ret)
goto err_free_shared_buf;
@@ -366,6 +367,7 @@ static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf, size
ret = -EFAULT;
err_free_shared_buf:
+ mutex_unlock(&psp->ras_context.mutex);
kfree(shared_buf);
return ret;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
index b3d11703df04..d0307c55da50 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
@@ -120,10 +120,12 @@ const char *get_ras_block_str(struct ras_common_if *ras_block)
/* typical ECC bad page rate is 1 bad page per 100MB VRAM */
#define RAS_BAD_PAGE_COVER (100 * 1024 * 1024ULL)
-#define MAX_UMC_POISON_POLLING_TIME_ASYNC 100 //ms
+#define MAX_UMC_POISON_POLLING_TIME_ASYNC 300 //ms
#define AMDGPU_RAS_RETIRE_PAGE_INTERVAL 100 //ms
+#define MAX_FLUSH_RETIRE_DWORK_TIMES 100
+
enum amdgpu_ras_retire_page_reservation {
AMDGPU_RAS_RETIRE_PAGE_RESERVED,
AMDGPU_RAS_RETIRE_PAGE_PENDING,
@@ -1055,7 +1057,7 @@ static void amdgpu_ras_error_print_error_data(struct amdgpu_device *adev,
struct amdgpu_smuio_mcm_config_info *mcm_info;
struct ras_err_node *err_node;
struct ras_err_info *err_info;
- u64 event_id = qctx->event_id;
+ u64 event_id = qctx->evid.event_id;
if (is_ue) {
for_each_ras_error(err_node, err_data) {
@@ -1140,7 +1142,7 @@ static void amdgpu_ras_error_generate_report(struct amdgpu_device *adev,
{
struct ras_manager *ras_mgr = amdgpu_ras_find_obj(adev, &query_if->head);
const char *blk_name = get_ras_block_str(&query_if->head);
- u64 event_id = qctx->event_id;
+ u64 event_id = qctx->evid.event_id;
if (err_data->ce_count) {
if (err_data_has_source_info(err_data)) {
@@ -1295,6 +1297,9 @@ ssize_t amdgpu_ras_aca_sysfs_read(struct device *dev, struct device_attribute *a
.head = obj->head,
};
+ if (!amdgpu_ras_get_error_query_ready(obj->adev))
+ return sysfs_emit(buf, "Query currently inaccessible\n");
+
if (amdgpu_ras_query_error_status(obj->adev, &info))
return -EINVAL;
@@ -1363,7 +1368,9 @@ static int amdgpu_ras_query_error_status_helper(struct amdgpu_device *adev,
}
/* query/inject/cure begin */
-int amdgpu_ras_query_error_status(struct amdgpu_device *adev, struct ras_query_if *info)
+static int amdgpu_ras_query_error_status_with_event(struct amdgpu_device *adev,
+ struct ras_query_if *info,
+ enum ras_event_type type)
{
struct ras_manager *obj = amdgpu_ras_find_obj(adev, &info->head);
struct ras_err_data err_data;
@@ -1382,12 +1389,19 @@ int amdgpu_ras_query_error_status(struct amdgpu_device *adev, struct ras_query_i
return -EINVAL;
memset(&qctx, 0, sizeof(qctx));
- qctx.event_id = amdgpu_ras_acquire_event_id(adev, amdgpu_ras_intr_triggered() ?
- RAS_EVENT_TYPE_ISR : RAS_EVENT_TYPE_INVALID);
+ qctx.evid.type = type;
+ qctx.evid.event_id = amdgpu_ras_acquire_event_id(adev, type);
+
+ if (!down_read_trylock(&adev->reset_domain->sem)) {
+ ret = -EIO;
+ goto out_fini_err_data;
+ }
+
ret = amdgpu_ras_query_error_status_helper(adev, info,
&err_data,
&qctx,
error_query_mode);
+ up_read(&adev->reset_domain->sem);
if (ret)
goto out_fini_err_data;
@@ -1405,15 +1419,17 @@ out_fini_err_data:
return ret;
}
+int amdgpu_ras_query_error_status(struct amdgpu_device *adev, struct ras_query_if *info)
+{
+ return amdgpu_ras_query_error_status_with_event(adev, info, RAS_EVENT_TYPE_INVALID);
+}
+
int amdgpu_ras_reset_error_count(struct amdgpu_device *adev,
enum amdgpu_ras_block block)
{
struct amdgpu_ras_block_object *block_obj = amdgpu_ras_get_ras_block(adev, block, 0);
- struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
const struct amdgpu_mca_smu_funcs *mca_funcs = adev->mca.mca_funcs;
const struct aca_smu_funcs *smu_funcs = adev->aca.smu_funcs;
- struct amdgpu_hive_info *hive;
- int hive_ras_recovery = 0;
if (!block_obj || !block_obj->hw_ops) {
dev_dbg_once(adev->dev, "%s doesn't config RAS function\n",
@@ -1425,15 +1441,8 @@ int amdgpu_ras_reset_error_count(struct amdgpu_device *adev,
!amdgpu_ras_get_aca_debug_mode(adev))
return -EOPNOTSUPP;
- hive = amdgpu_get_xgmi_hive(adev);
- if (hive) {
- hive_ras_recovery = atomic_read(&hive->ras_recovery);
- amdgpu_put_xgmi_hive(hive);
- }
-
/* skip ras error reset in gpu reset */
- if ((amdgpu_in_reset(adev) || atomic_read(&ras->in_recovery) ||
- hive_ras_recovery) &&
+ if ((amdgpu_in_reset(adev) || amdgpu_ras_in_recovery(adev)) &&
((smu_funcs && smu_funcs->set_debug_mode) ||
(mca_funcs && mca_funcs->mca_set_debug_mode)))
return -EOPNOTSUPP;
@@ -1724,6 +1733,39 @@ static ssize_t amdgpu_ras_sysfs_schema_show(struct device *dev,
return sysfs_emit(buf, "schema: 0x%x\n", con->schema);
}
+static struct {
+ enum ras_event_type type;
+ const char *name;
+} dump_event[] = {
+ {RAS_EVENT_TYPE_FATAL, "Fatal Error"},
+ {RAS_EVENT_TYPE_POISON_CREATION, "Poison Creation"},
+ {RAS_EVENT_TYPE_POISON_CONSUMPTION, "Poison Consumption"},
+};
+
+static ssize_t amdgpu_ras_sysfs_event_state_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct amdgpu_ras *con =
+ container_of(attr, struct amdgpu_ras, event_state_attr);
+ struct ras_event_manager *event_mgr = con->event_mgr;
+ struct ras_event_state *event_state;
+ int i, size = 0;
+
+ if (!event_mgr)
+ return -EINVAL;
+
+ size += sysfs_emit_at(buf, size, "current seqno: %llu\n", atomic64_read(&event_mgr->seqno));
+ for (i = 0; i < ARRAY_SIZE(dump_event); i++) {
+ event_state = &event_mgr->event_state[dump_event[i].type];
+ size += sysfs_emit_at(buf, size, "%s: count:%llu, last_seqno:%llu\n",
+ dump_event[i].name,
+ atomic64_read(&event_state->count),
+ event_state->last_seqno);
+ }
+
+ return (ssize_t)size;
+}
+
static void amdgpu_ras_sysfs_remove_bad_page_node(struct amdgpu_device *adev)
{
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
@@ -1741,6 +1783,7 @@ static int amdgpu_ras_sysfs_remove_dev_attr_node(struct amdgpu_device *adev)
&con->features_attr.attr,
&con->version_attr.attr,
&con->schema_attr.attr,
+ &con->event_state_attr.attr,
NULL
};
struct attribute_group group = {
@@ -1911,6 +1954,23 @@ static void amdgpu_ras_debugfs_create(struct amdgpu_device *adev,
obj, &amdgpu_ras_debugfs_ops);
}
+static bool amdgpu_ras_aca_is_supported(struct amdgpu_device *adev)
+{
+ bool ret;
+
+ switch (amdgpu_ip_version(adev, MP0_HWIP, 0)) {
+ case IP_VERSION(13, 0, 6):
+ case IP_VERSION(13, 0, 14):
+ ret = true;
+ break;
+ default:
+ ret = false;
+ break;
+ }
+
+ return ret;
+}
+
void amdgpu_ras_debugfs_create_all(struct amdgpu_device *adev)
{
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
@@ -1937,10 +1997,12 @@ void amdgpu_ras_debugfs_create_all(struct amdgpu_device *adev)
}
}
- if (amdgpu_aca_is_enabled(adev))
- amdgpu_aca_smu_debugfs_init(adev, dir);
- else
- amdgpu_mca_smu_debugfs_init(adev, dir);
+ if (amdgpu_ras_aca_is_supported(adev)) {
+ if (amdgpu_aca_is_enabled(adev))
+ amdgpu_aca_smu_debugfs_init(adev, dir);
+ else
+ amdgpu_mca_smu_debugfs_init(adev, dir);
+ }
}
/* debugfs end */
@@ -1954,6 +2016,8 @@ static DEVICE_ATTR(version, 0444,
amdgpu_ras_sysfs_version_show, NULL);
static DEVICE_ATTR(schema, 0444,
amdgpu_ras_sysfs_schema_show, NULL);
+static DEVICE_ATTR(event_state, 0444,
+ amdgpu_ras_sysfs_event_state_show, NULL);
static int amdgpu_ras_fs_init(struct amdgpu_device *adev)
{
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
@@ -1964,6 +2028,7 @@ static int amdgpu_ras_fs_init(struct amdgpu_device *adev)
&con->features_attr.attr,
&con->version_attr.attr,
&con->schema_attr.attr,
+ &con->event_state_attr.attr,
NULL
};
struct bin_attribute *bin_attrs[] = {
@@ -1986,6 +2051,10 @@ static int amdgpu_ras_fs_init(struct amdgpu_device *adev)
con->schema_attr = dev_attr_schema;
sysfs_attr_init(attrs[2]);
+ /* add event_state entry */
+ con->event_state_attr = dev_attr_event_state;
+ sysfs_attr_init(attrs[3]);
+
if (amdgpu_bad_page_threshold != 0) {
/* add bad_page_features entry */
bin_attr_gpu_vram_bad_pages.private = NULL;
@@ -2049,8 +2118,16 @@ static void amdgpu_ras_interrupt_poison_consumption_handler(struct ras_manager *
struct amdgpu_device *adev = obj->adev;
struct amdgpu_ras_block_object *block_obj =
amdgpu_ras_get_ras_block(adev, obj->head.block, 0);
+ struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
+ enum ras_event_type type = RAS_EVENT_TYPE_POISON_CONSUMPTION;
+ u64 event_id;
+ int ret;
- if (!block_obj)
+ if (!block_obj || !con)
+ return;
+
+ ret = amdgpu_ras_mark_ras_event(adev, type);
+ if (ret)
return;
/* both query_poison_status and handle_poison_consumption are optional,
@@ -2073,29 +2150,41 @@ static void amdgpu_ras_interrupt_poison_consumption_handler(struct ras_manager *
if (block_obj->hw_ops && block_obj->hw_ops->handle_poison_consumption)
poison_stat = block_obj->hw_ops->handle_poison_consumption(adev);
- /* gpu reset is fallback for failed and default cases */
- if (poison_stat) {
- dev_info(adev->dev, "GPU reset for %s RAS poison consumption is issued!\n",
- block_obj->ras_comm.name);
+ /* gpu reset is fallback for failed and default cases.
+ * For RMA case, amdgpu_umc_poison_handler will handle gpu reset.
+ */
+ if (poison_stat && !con->is_rma) {
+ event_id = amdgpu_ras_acquire_event_id(adev, type);
+ RAS_EVENT_LOG(adev, event_id,
+ "GPU reset for %s RAS poison consumption is issued!\n",
+ block_obj->ras_comm.name);
amdgpu_ras_reset_gpu(adev);
- } else {
- amdgpu_gfx_poison_consumption_handler(adev, entry);
}
+
+ if (!poison_stat)
+ amdgpu_gfx_poison_consumption_handler(adev, entry);
}
static void amdgpu_ras_interrupt_poison_creation_handler(struct ras_manager *obj,
struct amdgpu_iv_entry *entry)
{
- dev_info(obj->adev->dev,
- "Poison is created\n");
+ struct amdgpu_device *adev = obj->adev;
+ enum ras_event_type type = RAS_EVENT_TYPE_POISON_CREATION;
+ u64 event_id;
+ int ret;
+
+ ret = amdgpu_ras_mark_ras_event(adev, type);
+ if (ret)
+ return;
+
+ event_id = amdgpu_ras_acquire_event_id(adev, type);
+ RAS_EVENT_LOG(adev, event_id, "Poison is created\n");
if (amdgpu_ip_version(obj->adev, UMC_HWIP, 0) >= IP_VERSION(12, 0, 0)) {
struct amdgpu_ras *con = amdgpu_ras_get_context(obj->adev);
- amdgpu_ras_put_poison_req(obj->adev,
- AMDGPU_RAS_BLOCK__UMC, 0, NULL, NULL, false);
-
atomic_inc(&con->page_retirement_req_cnt);
+ atomic_inc(&con->poison_creation_count);
wake_up(&con->page_retirement_wq);
}
@@ -2118,6 +2207,7 @@ static void amdgpu_ras_interrupt_umc_handler(struct ras_manager *obj,
/* Let IP handle its data, maybe we need get the output
* from the callback to update the error type/count, etc
*/
+ amdgpu_ras_set_fed(obj->adev, true);
ret = data->cb(obj->adev, &err_data, entry);
/* ue will trigger an interrupt, and in that case
* we need do a reset to recovery the whole system.
@@ -2283,7 +2373,7 @@ static int amdgpu_ras_interrupt_remove_all(struct amdgpu_device *adev)
/* ih end */
/* traversal all IPs except NBIO to query error counter */
-static void amdgpu_ras_log_on_err_counter(struct amdgpu_device *adev)
+static void amdgpu_ras_log_on_err_counter(struct amdgpu_device *adev, enum ras_event_type type)
{
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
struct ras_manager *obj;
@@ -2316,7 +2406,7 @@ static void amdgpu_ras_log_on_err_counter(struct amdgpu_device *adev)
IP_VERSION(13, 0, 2)))
continue;
- amdgpu_ras_query_error_status(adev, &info);
+ amdgpu_ras_query_error_status_with_event(adev, &info, type);
if (amdgpu_ip_version(adev, MP0_HWIP, 0) !=
IP_VERSION(11, 0, 2) &&
@@ -2438,6 +2528,31 @@ static void amdgpu_ras_set_fed_all(struct amdgpu_device *adev,
}
}
+bool amdgpu_ras_in_recovery(struct amdgpu_device *adev)
+{
+ struct amdgpu_hive_info *hive = amdgpu_get_xgmi_hive(adev);
+ struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
+ int hive_ras_recovery = 0;
+
+ if (hive) {
+ hive_ras_recovery = atomic_read(&hive->ras_recovery);
+ amdgpu_put_xgmi_hive(hive);
+ }
+
+ if (ras && (atomic_read(&ras->in_recovery) || hive_ras_recovery))
+ return true;
+
+ return false;
+}
+
+static enum ras_event_type amdgpu_ras_get_fatal_error_event(struct amdgpu_device *adev)
+{
+ if (amdgpu_ras_intr_triggered())
+ return RAS_EVENT_TYPE_FATAL;
+ else
+ return RAS_EVENT_TYPE_POISON_CONSUMPTION;
+}
+
static void amdgpu_ras_do_recovery(struct work_struct *work)
{
struct amdgpu_ras *ras =
@@ -2446,6 +2561,7 @@ static void amdgpu_ras_do_recovery(struct work_struct *work)
struct amdgpu_device *adev = ras->adev;
struct list_head device_list, *device_list_handle = NULL;
struct amdgpu_hive_info *hive = amdgpu_get_xgmi_hive(adev);
+ enum ras_event_type type;
if (hive) {
atomic_set(&hive->ras_recovery, 1);
@@ -2473,10 +2589,11 @@ static void amdgpu_ras_do_recovery(struct work_struct *work)
device_list_handle = &device_list;
}
+ type = amdgpu_ras_get_fatal_error_event(adev);
list_for_each_entry(remote_adev,
device_list_handle, gmc.xgmi.head) {
amdgpu_ras_query_err_status(remote_adev);
- amdgpu_ras_log_on_err_counter(remote_adev);
+ amdgpu_ras_log_on_err_counter(remote_adev, type);
}
}
@@ -2487,6 +2604,7 @@ static void amdgpu_ras_do_recovery(struct work_struct *work)
reset_context.method = AMD_RESET_METHOD_NONE;
reset_context.reset_req_dev = adev;
+ reset_context.src = AMDGPU_RESET_SRC_RAS;
/* Perform full reset in fatal error mode */
if (!amdgpu_ras_is_poison_mode_supported(ras->adev))
@@ -2767,7 +2885,8 @@ static void amdgpu_ras_ecc_log_init(struct ras_ecc_log_info *ecc_log)
memset(&ecc_log->ecc_key, 0xad, sizeof(ecc_log->ecc_key));
INIT_RADIX_TREE(&ecc_log->de_page_tree, GFP_KERNEL);
- ecc_log->de_updated = false;
+ ecc_log->de_queried_count = 0;
+ ecc_log->prev_de_queried_count = 0;
}
static void amdgpu_ras_ecc_log_fini(struct ras_ecc_log_info *ecc_log)
@@ -2786,7 +2905,25 @@ static void amdgpu_ras_ecc_log_fini(struct ras_ecc_log_info *ecc_log)
mutex_unlock(&ecc_log->lock);
mutex_destroy(&ecc_log->lock);
- ecc_log->de_updated = false;
+ ecc_log->de_queried_count = 0;
+ ecc_log->prev_de_queried_count = 0;
+}
+
+static bool amdgpu_ras_schedule_retirement_dwork(struct amdgpu_ras *con,
+ uint32_t delayed_ms)
+{
+ int ret;
+
+ mutex_lock(&con->umc_ecc_log.lock);
+ ret = radix_tree_tagged(&con->umc_ecc_log.de_page_tree,
+ UMC_ECC_NEW_DETECTED_TAG);
+ mutex_unlock(&con->umc_ecc_log.lock);
+
+ if (ret)
+ schedule_delayed_work(&con->page_retirement_dwork,
+ msecs_to_jiffies(delayed_ms));
+
+ return ret ? true : false;
}
static void amdgpu_ras_do_page_retirement(struct work_struct *work)
@@ -2795,77 +2932,140 @@ static void amdgpu_ras_do_page_retirement(struct work_struct *work)
page_retirement_dwork.work);
struct amdgpu_device *adev = con->adev;
struct ras_err_data err_data;
+ unsigned long err_cnt;
- if (amdgpu_in_reset(adev) || atomic_read(&con->in_recovery))
+ /* If gpu reset is ongoing, delay retiring the bad pages */
+ if (amdgpu_in_reset(adev) || amdgpu_ras_in_recovery(adev)) {
+ amdgpu_ras_schedule_retirement_dwork(con,
+ AMDGPU_RAS_RETIRE_PAGE_INTERVAL * 3);
return;
+ }
amdgpu_ras_error_data_init(&err_data);
amdgpu_umc_handle_bad_pages(adev, &err_data);
+ err_cnt = err_data.err_addr_cnt;
amdgpu_ras_error_data_fini(&err_data);
- mutex_lock(&con->umc_ecc_log.lock);
- if (radix_tree_tagged(&con->umc_ecc_log.de_page_tree,
- UMC_ECC_NEW_DETECTED_TAG))
- schedule_delayed_work(&con->page_retirement_dwork,
- msecs_to_jiffies(AMDGPU_RAS_RETIRE_PAGE_INTERVAL));
- mutex_unlock(&con->umc_ecc_log.lock);
+ if (err_cnt && con->is_rma)
+ amdgpu_ras_reset_gpu(adev);
+
+ amdgpu_ras_schedule_retirement_dwork(con,
+ AMDGPU_RAS_RETIRE_PAGE_INTERVAL);
}
-static void amdgpu_ras_poison_creation_handler(struct amdgpu_device *adev,
- uint32_t timeout_ms)
+static int amdgpu_ras_poison_creation_handler(struct amdgpu_device *adev,
+ uint32_t poison_creation_count)
{
int ret = 0;
struct ras_ecc_log_info *ecc_log;
struct ras_query_if info;
- uint32_t timeout = timeout_ms;
+ uint32_t timeout = 0;
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
+ uint64_t de_queried_count;
+ uint32_t new_detect_count, total_detect_count;
+ uint32_t need_query_count = poison_creation_count;
+ bool query_data_timeout = false;
+ enum ras_event_type type = RAS_EVENT_TYPE_POISON_CREATION;
memset(&info, 0, sizeof(info));
info.head.block = AMDGPU_RAS_BLOCK__UMC;
ecc_log = &ras->umc_ecc_log;
- ecc_log->de_updated = false;
+ total_detect_count = 0;
do {
- ret = amdgpu_ras_query_error_status(adev, &info);
- if (ret) {
- dev_err(adev->dev, "Failed to query ras error! ret:%d\n", ret);
- return;
+ ret = amdgpu_ras_query_error_status_with_event(adev, &info, type);
+ if (ret)
+ return ret;
+
+ de_queried_count = ecc_log->de_queried_count;
+ if (de_queried_count > ecc_log->prev_de_queried_count) {
+ new_detect_count = de_queried_count - ecc_log->prev_de_queried_count;
+ ecc_log->prev_de_queried_count = de_queried_count;
+ timeout = 0;
+ } else {
+ new_detect_count = 0;
}
- if (timeout && !ecc_log->de_updated) {
- msleep(1);
- timeout--;
+ if (new_detect_count) {
+ total_detect_count += new_detect_count;
+ } else {
+ if (!timeout && need_query_count)
+ timeout = MAX_UMC_POISON_POLLING_TIME_ASYNC;
+
+ if (timeout) {
+ if (!--timeout) {
+ query_data_timeout = true;
+ break;
+ }
+ msleep(1);
+ }
}
- } while (timeout && !ecc_log->de_updated);
+ } while (total_detect_count < need_query_count);
- if (timeout_ms && !timeout) {
- dev_warn(adev->dev, "Can't find deferred error\n");
- return;
+ if (query_data_timeout) {
+ dev_warn(adev->dev, "Can't find deferred error! count: %u\n",
+ (need_query_count - total_detect_count));
+ return -ENOENT;
}
- if (!ret)
+ if (total_detect_count)
schedule_delayed_work(&ras->page_retirement_dwork, 0);
+
+ return 0;
+}
+
+static void amdgpu_ras_clear_poison_fifo(struct amdgpu_device *adev)
+{
+ struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
+ struct ras_poison_msg msg;
+ int ret;
+
+ do {
+ ret = kfifo_get(&con->poison_fifo, &msg);
+ } while (ret);
}
static int amdgpu_ras_poison_consumption_handler(struct amdgpu_device *adev,
- struct ras_poison_msg *poison_msg)
+ uint32_t msg_count, uint32_t *gpu_reset)
{
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
- uint32_t reset = poison_msg->reset;
- uint16_t pasid = poison_msg->pasid;
+ uint32_t reset_flags = 0, reset = 0;
+ struct ras_poison_msg msg;
+ int ret, i;
kgd2kfd_set_sram_ecc_flag(adev->kfd.dev);
- if (poison_msg->pasid_fn)
- poison_msg->pasid_fn(adev, pasid, poison_msg->data);
+ for (i = 0; i < msg_count; i++) {
+ ret = amdgpu_ras_get_poison_req(adev, &msg);
+ if (!ret)
+ continue;
+
+ if (msg.pasid_fn)
+ msg.pasid_fn(adev, msg.pasid, msg.data);
+
+ reset_flags |= msg.reset;
+ }
+
+ /* for RMA, amdgpu_ras_poison_creation_handler will trigger gpu reset */
+ if (reset_flags && !con->is_rma) {
+ if (reset_flags & AMDGPU_RAS_GPU_RESET_MODE1_RESET)
+ reset = AMDGPU_RAS_GPU_RESET_MODE1_RESET;
+ else if (reset_flags & AMDGPU_RAS_GPU_RESET_MODE2_RESET)
+ reset = AMDGPU_RAS_GPU_RESET_MODE2_RESET;
+ else
+ reset = reset_flags;
- if (reset) {
flush_delayed_work(&con->page_retirement_dwork);
con->gpu_reset_flags |= reset;
amdgpu_ras_reset_gpu(adev);
+
+ *gpu_reset = reset;
+
+ /* Wait for gpu recovery to complete */
+ flush_work(&con->recovery_work);
}
return 0;
@@ -2875,9 +3075,9 @@ static int amdgpu_ras_page_retirement_thread(void *param)
{
struct amdgpu_device *adev = (struct amdgpu_device *)param;
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
- struct ras_poison_msg poison_msg;
- enum amdgpu_ras_block ras_block;
- bool poison_creation_is_handled = false;
+ uint32_t poison_creation_count, msg_count;
+ uint32_t gpu_reset;
+ int ret;
while (!kthread_should_stop()) {
@@ -2888,33 +3088,61 @@ static int amdgpu_ras_page_retirement_thread(void *param)
if (kthread_should_stop())
break;
- atomic_dec(&con->page_retirement_req_cnt);
+ gpu_reset = 0;
- if (!amdgpu_ras_get_poison_req(adev, &poison_msg))
- continue;
+ do {
+ poison_creation_count = atomic_read(&con->poison_creation_count);
+ ret = amdgpu_ras_poison_creation_handler(adev, poison_creation_count);
+ if (ret == -EIO)
+ break;
- ras_block = poison_msg.block;
+ if (poison_creation_count) {
+ atomic_sub(poison_creation_count, &con->poison_creation_count);
+ atomic_sub(poison_creation_count, &con->page_retirement_req_cnt);
+ }
+ } while (atomic_read(&con->poison_creation_count));
+
+ if (ret != -EIO) {
+ msg_count = kfifo_len(&con->poison_fifo);
+ if (msg_count) {
+ ret = amdgpu_ras_poison_consumption_handler(adev,
+ msg_count, &gpu_reset);
+ if ((ret != -EIO) &&
+ (gpu_reset != AMDGPU_RAS_GPU_RESET_MODE1_RESET))
+ atomic_sub(msg_count, &con->page_retirement_req_cnt);
+ }
+ }
- dev_dbg(adev->dev, "Start processing ras block %s(%d)\n",
- ras_block_str(ras_block), ras_block);
+ if ((ret == -EIO) || (gpu_reset == AMDGPU_RAS_GPU_RESET_MODE1_RESET)) {
+ /* gpu mode-1 reset is ongoing or just completed ras mode-1 reset */
+ /* Clear poison creation request */
+ atomic_set(&con->poison_creation_count, 0);
- if (ras_block == AMDGPU_RAS_BLOCK__UMC) {
- amdgpu_ras_poison_creation_handler(adev,
- MAX_UMC_POISON_POLLING_TIME_ASYNC);
- poison_creation_is_handled = true;
- } else {
- /* poison_creation_is_handled:
- * false: no poison creation interrupt, but it has poison
- * consumption interrupt.
- * true: It has poison creation interrupt at the beginning,
- * but it has no poison creation interrupt later.
- */
- amdgpu_ras_poison_creation_handler(adev,
- poison_creation_is_handled ?
- 0 : MAX_UMC_POISON_POLLING_TIME_ASYNC);
+ /* Clear poison fifo */
+ amdgpu_ras_clear_poison_fifo(adev);
- amdgpu_ras_poison_consumption_handler(adev, &poison_msg);
- poison_creation_is_handled = false;
+ /* Clear all poison requests */
+ atomic_set(&con->page_retirement_req_cnt, 0);
+
+ if (ret == -EIO) {
+ /* Wait for mode-1 reset to complete */
+ down_read(&adev->reset_domain->sem);
+ up_read(&adev->reset_domain->sem);
+ }
+
+ /* Wake up work to save bad pages to eeprom */
+ schedule_delayed_work(&con->page_retirement_dwork, 0);
+ } else if (gpu_reset) {
+ /* gpu just completed mode-2 reset or other reset */
+ /* Clear poison consumption messages cached in fifo */
+ msg_count = kfifo_len(&con->poison_fifo);
+ if (msg_count) {
+ amdgpu_ras_clear_poison_fifo(adev);
+ atomic_sub(msg_count, &con->page_retirement_req_cnt);
+ }
+
+ /* Wake up work to save bad pages to eeprom */
+ schedule_delayed_work(&con->page_retirement_dwork, 0);
}
}
@@ -2988,6 +3216,7 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev)
mutex_init(&con->page_retirement_lock);
init_waitqueue_head(&con->page_retirement_wq);
atomic_set(&con->page_retirement_req_cnt, 0);
+ atomic_set(&con->poison_creation_count, 0);
con->page_retirement_thread =
kthread_run(amdgpu_ras_page_retirement_thread, adev, "umc_page_retirement");
if (IS_ERR(con->page_retirement_thread)) {
@@ -3027,15 +3256,24 @@ static int amdgpu_ras_recovery_fini(struct amdgpu_device *adev)
{
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
struct ras_err_handler_data *data = con->eh_data;
+ int max_flush_timeout = MAX_FLUSH_RETIRE_DWORK_TIMES;
+ bool ret;
/* recovery_init failed to init it, fini is useless */
if (!data)
return 0;
+ /* Save all cached bad pages to eeprom */
+ do {
+ flush_delayed_work(&con->page_retirement_dwork);
+ ret = amdgpu_ras_schedule_retirement_dwork(con, 0);
+ } while (ret && max_flush_timeout--);
+
if (con->page_retirement_thread)
kthread_stop(con->page_retirement_thread);
atomic_set(&con->page_retirement_req_cnt, 0);
+ atomic_set(&con->poison_creation_count, 0);
mutex_destroy(&con->page_rsv_lock);
@@ -3270,10 +3508,17 @@ static int amdgpu_get_ras_schema(struct amdgpu_device *adev)
static void ras_event_mgr_init(struct ras_event_manager *mgr)
{
+ struct ras_event_state *event_state;
int i;
- for (i = 0; i < ARRAY_SIZE(mgr->seqnos); i++)
- atomic64_set(&mgr->seqnos[i], 0);
+ memset(mgr, 0, sizeof(*mgr));
+ atomic64_set(&mgr->seqno, 0);
+
+ for (i = 0; i < ARRAY_SIZE(mgr->event_state); i++) {
+ event_state = &mgr->event_state[i];
+ event_state->last_seqno = RAS_EVENT_INVALID_ID;
+ atomic64_set(&event_state->count, 0);
+ }
}
static void amdgpu_ras_event_mgr_init(struct amdgpu_device *adev)
@@ -3427,6 +3672,15 @@ int amdgpu_ras_init(struct amdgpu_device *adev)
goto release_con;
}
+ if (amdgpu_ras_aca_is_supported(adev)) {
+ if (amdgpu_aca_is_enabled(adev))
+ r = amdgpu_aca_init(adev);
+ else
+ r = amdgpu_mca_init(adev);
+ if (r)
+ goto release_con;
+ }
+
dev_info(adev->dev, "RAS INFO: ras initialized successfully, "
"hardware ability[%x] ras_mask[%x]\n",
adev->ras_hw_enabled, adev->ras_enabled);
@@ -3635,25 +3889,22 @@ int amdgpu_ras_late_init(struct amdgpu_device *adev)
amdgpu_ras_event_mgr_init(adev);
- if (amdgpu_aca_is_enabled(adev)) {
- if (!amdgpu_in_reset(adev)) {
- r = amdgpu_aca_init(adev);
+ if (amdgpu_ras_aca_is_supported(adev)) {
+ if (amdgpu_in_reset(adev)) {
+ if (amdgpu_aca_is_enabled(adev))
+ r = amdgpu_aca_reset(adev);
+ else
+ r = amdgpu_mca_reset(adev);
if (r)
return r;
}
- if (!amdgpu_sriov_vf(adev))
- amdgpu_ras_set_aca_debug_mode(adev, false);
- } else {
- if (amdgpu_in_reset(adev))
- r = amdgpu_mca_reset(adev);
- else
- r = amdgpu_mca_init(adev);
- if (r)
- return r;
-
- if (!amdgpu_sriov_vf(adev))
- amdgpu_ras_set_mca_debug_mode(adev, false);
+ if (!amdgpu_sriov_vf(adev)) {
+ if (amdgpu_aca_is_enabled(adev))
+ amdgpu_ras_set_aca_debug_mode(adev, false);
+ else
+ amdgpu_ras_set_mca_debug_mode(adev, false);
+ }
}
/* Guest side doesn't need init ras feature */
@@ -3727,10 +3978,12 @@ int amdgpu_ras_fini(struct amdgpu_device *adev)
amdgpu_ras_fs_fini(adev);
amdgpu_ras_interrupt_remove_all(adev);
- if (amdgpu_aca_is_enabled(adev))
- amdgpu_aca_fini(adev);
- else
- amdgpu_mca_fini(adev);
+ if (amdgpu_ras_aca_is_supported(adev)) {
+ if (amdgpu_aca_is_enabled(adev))
+ amdgpu_aca_fini(adev);
+ else
+ amdgpu_mca_fini(adev);
+ }
WARN(AMDGPU_RAS_GET_FEATURES(con->features), "Feature mask is not cleared");
@@ -3765,23 +4018,68 @@ void amdgpu_ras_set_fed(struct amdgpu_device *adev, bool status)
atomic_set(&ras->fed, !!status);
}
-bool amdgpu_ras_event_id_is_valid(struct amdgpu_device *adev, u64 id)
+static struct ras_event_manager *__get_ras_event_mgr(struct amdgpu_device *adev)
{
- return !(id & BIT_ULL(63));
+ struct amdgpu_ras *ras;
+
+ ras = amdgpu_ras_get_context(adev);
+ if (!ras)
+ return NULL;
+
+ return ras->event_mgr;
+}
+
+int amdgpu_ras_mark_ras_event_caller(struct amdgpu_device *adev, enum ras_event_type type,
+ const void *caller)
+{
+ struct ras_event_manager *event_mgr;
+ struct ras_event_state *event_state;
+ int ret = 0;
+
+ if (type >= RAS_EVENT_TYPE_COUNT) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ event_mgr = __get_ras_event_mgr(adev);
+ if (!event_mgr) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ event_state = &event_mgr->event_state[type];
+ event_state->last_seqno = atomic64_inc_return(&event_mgr->seqno);
+ atomic64_inc(&event_state->count);
+
+out:
+ if (ret && caller)
+ dev_warn(adev->dev, "failed mark ras event (%d) in %ps, ret:%d\n",
+ (int)type, caller, ret);
+
+ return ret;
}
u64 amdgpu_ras_acquire_event_id(struct amdgpu_device *adev, enum ras_event_type type)
{
- struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
+ struct ras_event_manager *event_mgr;
u64 id;
+ if (type >= RAS_EVENT_TYPE_COUNT)
+ return RAS_EVENT_INVALID_ID;
+
switch (type) {
- case RAS_EVENT_TYPE_ISR:
- id = (u64)atomic64_read(&ras->event_mgr->seqnos[type]);
+ case RAS_EVENT_TYPE_FATAL:
+ case RAS_EVENT_TYPE_POISON_CREATION:
+ case RAS_EVENT_TYPE_POISON_CONSUMPTION:
+ event_mgr = __get_ras_event_mgr(adev);
+ if (!event_mgr)
+ return RAS_EVENT_INVALID_ID;
+
+ id = event_mgr->event_state[type].last_seqno;
break;
case RAS_EVENT_TYPE_INVALID:
default:
- id = BIT_ULL(63) | 0ULL;
+ id = RAS_EVENT_INVALID_ID;
break;
}
@@ -3792,7 +4090,13 @@ void amdgpu_ras_global_ras_isr(struct amdgpu_device *adev)
{
if (atomic_cmpxchg(&amdgpu_ras_in_intr, 0, 1) == 0) {
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
- u64 event_id = (u64)atomic64_inc_return(&ras->event_mgr->seqnos[RAS_EVENT_TYPE_ISR]);
+ enum ras_event_type type = RAS_EVENT_TYPE_FATAL;
+ u64 event_id;
+
+ if (amdgpu_ras_mark_ras_event(adev, type))
+ return;
+
+ event_id = amdgpu_ras_acquire_event_id(adev, type);
RAS_EVENT_LOG(adev, event_id, "uncorrectable hardware error"
"(ERREVENT_ATHUB_INTERRUPT) detected!\n");
@@ -3982,6 +4286,12 @@ int amdgpu_ras_reset_gpu(struct amdgpu_device *adev)
{
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
+ /* mode1 is the only selection for RMA status */
+ if (ras->is_rma) {
+ ras->gpu_reset_flags = 0;
+ ras->gpu_reset_flags |= AMDGPU_RAS_GPU_RESET_MODE1_RESET;
+ }
+
if (atomic_cmpxchg(&ras->in_recovery, 0, 1) == 0)
amdgpu_reset_domain_schedule(ras->adev->reset_domain, &ras->recovery_work);
return 0;
@@ -4420,7 +4730,7 @@ static void amdgpu_ras_boot_time_error_reporting(struct amdgpu_device *adev,
socket_id = AMDGPU_RAS_GPU_ERR_SOCKET_ID(boot_error);
aid_id = AMDGPU_RAS_GPU_ERR_AID_ID(boot_error);
- hbm_id = AMDGPU_RAS_GPU_ERR_HBM_ID(boot_error);
+ hbm_id = ((1 == AMDGPU_RAS_GPU_ERR_HBM_ID(boot_error)) ? 0 : 1);
if (AMDGPU_RAS_GPU_ERR_MEM_TRAINING(boot_error))
dev_info(adev->dev,
@@ -4520,7 +4830,7 @@ void amdgpu_ras_event_log_print(struct amdgpu_device *adev, u64 event_id,
vaf.fmt = fmt;
vaf.va = &args;
- if (amdgpu_ras_event_id_is_valid(adev, event_id))
+ if (RAS_EVENT_ID_IS_VALID(event_id))
dev_printk(KERN_INFO, adev->dev, "{%llu}%pV", event_id, &vaf);
else
dev_printk(KERN_INFO, adev->dev, "%pV", &vaf);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h
index e70c45712ddb..dcf1f3dbb5c4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h
@@ -68,8 +68,14 @@ struct amdgpu_iv_entry;
/* The high three bits indicates socketid */
#define AMDGPU_RAS_GET_FEATURES(val) ((val) & ~AMDGPU_RAS_FEATURES_SOCKETID_MASK)
+#define RAS_EVENT_INVALID_ID (BIT_ULL(63))
+#define RAS_EVENT_ID_IS_VALID(x) (!((x) & BIT_ULL(63)))
+
#define RAS_EVENT_LOG(adev, id, fmt, ...) \
- amdgpu_ras_event_log_print((adev), (id), (fmt), ##__VA_ARGS__);
+ amdgpu_ras_event_log_print((adev), (id), (fmt), ##__VA_ARGS__)
+
+#define amdgpu_ras_mark_ras_event(adev, type) \
+ (amdgpu_ras_mark_ras_event_caller((adev), (type), __builtin_return_address(0)))
enum amdgpu_ras_block {
AMDGPU_RAS_BLOCK__UMC = 0,
@@ -427,20 +433,32 @@ struct umc_ecc_info {
};
enum ras_event_type {
- RAS_EVENT_TYPE_INVALID = -1,
- RAS_EVENT_TYPE_ISR = 0,
+ RAS_EVENT_TYPE_INVALID = 0,
+ RAS_EVENT_TYPE_FATAL,
+ RAS_EVENT_TYPE_POISON_CREATION,
+ RAS_EVENT_TYPE_POISON_CONSUMPTION,
RAS_EVENT_TYPE_COUNT,
};
+struct ras_event_state {
+ u64 last_seqno;
+ atomic64_t count;
+};
+
struct ras_event_manager {
- atomic64_t seqnos[RAS_EVENT_TYPE_COUNT];
+ atomic64_t seqno;
+ struct ras_event_state event_state[RAS_EVENT_TYPE_COUNT];
};
-struct ras_query_context {
+struct ras_event_id {
enum ras_event_type type;
u64 event_id;
};
+struct ras_query_context {
+ struct ras_event_id evid;
+};
+
typedef int (*pasid_notify)(struct amdgpu_device *adev,
uint16_t pasid, void *data);
@@ -469,7 +487,8 @@ struct ras_ecc_log_info {
struct mutex lock;
siphash_key_t ecc_key;
struct radix_tree_root de_page_tree;
- bool de_updated;
+ uint64_t de_queried_count;
+ uint64_t prev_de_queried_count;
};
struct amdgpu_ras {
@@ -482,6 +501,7 @@ struct amdgpu_ras {
struct device_attribute features_attr;
struct device_attribute version_attr;
struct device_attribute schema_attr;
+ struct device_attribute event_state_attr;
struct bin_attribute badpages_attr;
struct dentry *de_ras_eeprom_table;
/* block array */
@@ -531,6 +551,7 @@ struct amdgpu_ras {
wait_queue_head_t page_retirement_wq;
struct mutex page_retirement_lock;
atomic_t page_retirement_req_cnt;
+ atomic_t poison_creation_count;
struct mutex page_rsv_lock;
DECLARE_KFIFO(poison_fifo, struct ras_poison_msg, 128);
struct ras_ecc_log_info umc_ecc_log;
@@ -945,8 +966,9 @@ void amdgpu_ras_del_mca_err_addr(struct ras_err_info *err_info,
void amdgpu_ras_set_fed(struct amdgpu_device *adev, bool status);
bool amdgpu_ras_get_fed_status(struct amdgpu_device *adev);
-bool amdgpu_ras_event_id_is_valid(struct amdgpu_device *adev, u64 id);
u64 amdgpu_ras_acquire_event_id(struct amdgpu_device *adev, enum ras_event_type type);
+int amdgpu_ras_mark_ras_event_caller(struct amdgpu_device *adev, enum ras_event_type type,
+ const void *caller);
int amdgpu_ras_reserve_page(struct amdgpu_device *adev, uint64_t pfn);
@@ -954,6 +976,8 @@ int amdgpu_ras_put_poison_req(struct amdgpu_device *adev,
enum amdgpu_ras_block block, uint16_t pasid,
pasid_notify pasid_fn, void *data, uint32_t reset);
+bool amdgpu_ras_in_recovery(struct amdgpu_device *adev);
+
__printf(3, 4)
void amdgpu_ras_event_log_print(struct amdgpu_device *adev, u64 event_id,
const char *fmt, ...);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
index eae0a555df3c..aab8077e5098 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
@@ -1011,6 +1011,9 @@ Out:
uint32_t amdgpu_ras_eeprom_max_record_count(struct amdgpu_ras_eeprom_control *control)
{
+ /* get available eeprom table version first before eeprom table init */
+ amdgpu_ras_set_eeprom_table_version(control);
+
if (control->tbl_hdr.version == RAS_TABLE_VER_V2_1)
return RAS_MAX_RECORD_COUNT_V2_1;
else
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c
index 9deb41d61e8d..66c1a868c0e1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c
@@ -164,16 +164,14 @@ void amdgpu_device_unlock_reset_domain(struct amdgpu_reset_domain *reset_domain)
void amdgpu_reset_get_desc(struct amdgpu_reset_context *rst_ctxt, char *buf,
size_t len)
{
- struct amdgpu_ring *ring;
-
if (!buf || !len)
return;
switch (rst_ctxt->src) {
case AMDGPU_RESET_SRC_JOB:
if (rst_ctxt->job) {
- ring = amdgpu_job_ring(rst_ctxt->job);
- snprintf(buf, len, "job hang on ring:%s", ring->name);
+ snprintf(buf, len, "job hang on ring:%s",
+ rst_ctxt->job->base.sched->name);
} else {
strscpy(buf, "job hang", len);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
index 151f83ea803b..183a976ba29d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
@@ -215,14 +215,14 @@ int amdgpu_sdma_init_microcode(struct amdgpu_device *adev,
const struct sdma_firmware_header_v3_0 *sdma_hv3;
uint16_t version_major;
char ucode_prefix[30];
- char fw_name[52];
amdgpu_ucode_ip_version_decode(adev, SDMA0_HWIP, ucode_prefix, sizeof(ucode_prefix));
if (instance == 0)
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s.bin", ucode_prefix);
+ err = amdgpu_ucode_request(adev, &adev->sdma.instance[instance].fw,
+ "amdgpu/%s.bin", ucode_prefix);
else
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s%d.bin", ucode_prefix, instance);
- err = amdgpu_ucode_request(adev, &adev->sdma.instance[instance].fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->sdma.instance[instance].fw,
+ "amdgpu/%s%d.bin", ucode_prefix, instance);
if (err)
goto out;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h
index 7aafeb763e5d..383fce40d4dd 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h
@@ -554,21 +554,6 @@ TRACE_EVENT(amdgpu_reset_reg_dumps,
__entry->value)
);
-TRACE_EVENT(amdgpu_runpm_reference_dumps,
- TP_PROTO(uint32_t index, const char *func),
- TP_ARGS(index, func),
- TP_STRUCT__entry(
- __field(uint32_t, index)
- __string(func, func)
- ),
- TP_fast_assign(
- __entry->index = index;
- __assign_str(func);
- ),
- TP_printk("amdgpu runpm reference dump 0x%x: 0x%s\n",
- __entry->index,
- __get_str(func))
-);
#undef AMDGPU_JOB_GET_TIMELINE_NAME
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index 8de2d05d0735..b8bc7fa8c375 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -295,8 +295,8 @@ int amdgpu_ttm_copy_mem_to_mem(struct amdgpu_device *adev,
struct amdgpu_res_cursor src_mm, dst_mm;
struct dma_fence *fence = NULL;
int r = 0;
-
uint32_t copy_flags = 0;
+ struct amdgpu_bo *abo_src, *abo_dst;
if (!adev->mman.buffer_funcs_enabled) {
DRM_ERROR("Trying to move memory with ring turned off.\n");
@@ -308,7 +308,8 @@ int amdgpu_ttm_copy_mem_to_mem(struct amdgpu_device *adev,
mutex_lock(&adev->mman.gtt_window_lock);
while (src_mm.remaining) {
- uint64_t from, to, cur_size;
+ uint64_t from, to, cur_size, tiling_flags;
+ uint32_t num_type, data_format, max_com;
struct dma_fence *next;
/* Never copy more than 256MiB at once to avoid a timeout */
@@ -325,8 +326,24 @@ int amdgpu_ttm_copy_mem_to_mem(struct amdgpu_device *adev,
if (r)
goto error;
+ abo_src = ttm_to_amdgpu_bo(src->bo);
+ abo_dst = ttm_to_amdgpu_bo(dst->bo);
if (tmz)
copy_flags |= AMDGPU_COPY_FLAGS_TMZ;
+ if ((abo_src->flags & AMDGPU_GEM_CREATE_GFX12_DCC) &&
+ (abo_src->tbo.resource->mem_type == TTM_PL_VRAM))
+ copy_flags |= AMDGPU_COPY_FLAGS_READ_DECOMPRESSED;
+ if ((abo_dst->flags & AMDGPU_GEM_CREATE_GFX12_DCC) &&
+ (dst->mem->mem_type == TTM_PL_VRAM)) {
+ copy_flags |= AMDGPU_COPY_FLAGS_WRITE_COMPRESSED;
+ amdgpu_bo_get_tiling_flags(abo_dst, &tiling_flags);
+ max_com = AMDGPU_TILING_GET(tiling_flags, GFX12_DCC_MAX_COMPRESSED_BLOCK);
+ num_type = AMDGPU_TILING_GET(tiling_flags, GFX12_DCC_NUMBER_TYPE);
+ data_format = AMDGPU_TILING_GET(tiling_flags, GFX12_DCC_DATA_FORMAT);
+ copy_flags |= (AMDGPU_COPY_FLAGS_SET(MAX_COMPRESSED, max_com) |
+ AMDGPU_COPY_FLAGS_SET(NUMBER_TYPE, num_type) |
+ AMDGPU_COPY_FLAGS_SET(DATA_FORMAT, data_format));
+ }
r = amdgpu_copy_buffer(ring, from, to, cur_size, resv,
&next, false, true, copy_flags);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
index b6f53129dea3..138d80017f35 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
@@ -110,6 +110,19 @@ struct amdgpu_copy_mem {
};
#define AMDGPU_COPY_FLAGS_TMZ (1 << 0)
+#define AMDGPU_COPY_FLAGS_READ_DECOMPRESSED (1 << 1)
+#define AMDGPU_COPY_FLAGS_WRITE_COMPRESSED (1 << 2)
+#define AMDGPU_COPY_FLAGS_MAX_COMPRESSED_SHIFT 3
+#define AMDGPU_COPY_FLAGS_MAX_COMPRESSED_MASK 0x03
+#define AMDGPU_COPY_FLAGS_NUMBER_TYPE_SHIFT 5
+#define AMDGPU_COPY_FLAGS_NUMBER_TYPE_MASK 0x07
+#define AMDGPU_COPY_FLAGS_DATA_FORMAT_SHIFT 8
+#define AMDGPU_COPY_FLAGS_DATA_FORMAT_MASK 0x3f
+
+#define AMDGPU_COPY_FLAGS_SET(field, value) \
+ (((__u32)(value) & AMDGPU_COPY_FLAGS_##field##_MASK) << AMDGPU_COPY_FLAGS_##field##_SHIFT)
+#define AMDGPU_COPY_FLAGS_GET(value, field) \
+ (((__u32)(value) >> AMDGPU_COPY_FLAGS_##field##_SHIFT) & AMDGPU_COPY_FLAGS_##field##_MASK)
int amdgpu_gtt_mgr_init(struct amdgpu_device *adev, uint64_t gtt_size);
void amdgpu_gtt_mgr_fini(struct amdgpu_device *adev);
@@ -146,7 +159,6 @@ int amdgpu_ttm_init(struct amdgpu_device *adev);
void amdgpu_ttm_fini(struct amdgpu_device *adev);
void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev,
bool enable);
-
int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset,
uint64_t dst_offset, uint32_t byte_count,
struct dma_resv *resv,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
index 75ece8a2f96b..4c7b53648a50 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
@@ -28,6 +28,8 @@
#include "amdgpu.h"
#include "amdgpu_ucode.h"
+#define AMDGPU_UCODE_NAME_MAX (128)
+
static void amdgpu_ucode_print_common_hdr(const struct common_firmware_header *hdr)
{
DRM_DEBUG("size_bytes: %u\n", le32_to_cpu(hdr->size_bytes));
@@ -712,6 +714,8 @@ const char *amdgpu_ucode_name(enum AMDGPU_UCODE_ID ucode_id)
return "RS64_MEC_P2_STACK";
case AMDGPU_UCODE_ID_CP_RS64_MEC_P3_STACK:
return "RS64_MEC_P3_STACK";
+ case AMDGPU_UCODE_ID_ISP:
+ return "ISP";
default:
return "UNKNOWN UCODE";
}
@@ -1411,6 +1415,9 @@ void amdgpu_ucode_ip_version_decode(struct amdgpu_device *adev, int block_type,
case VPE_HWIP:
ip_name = "vpe";
break;
+ case ISP_HWIP:
+ ip_name = "isp";
+ break;
default:
BUG();
}
@@ -1427,28 +1434,40 @@ void amdgpu_ucode_ip_version_decode(struct amdgpu_device *adev, int block_type,
*
* @adev: amdgpu device
* @fw: pointer to load firmware to
- * @fw_name: firmware to load
+ * @fmt: firmware name format string
+ * @...: variable arguments
*
* This is a helper that will use request_firmware and amdgpu_ucode_validate
* to load and run basic validation on firmware. If the load fails, remap
* the error code to -ENODEV, so that early_init functions will fail to load.
*/
int amdgpu_ucode_request(struct amdgpu_device *adev, const struct firmware **fw,
- const char *fw_name)
+ const char *fmt, ...)
{
- int err = request_firmware(fw, fw_name, adev->dev);
+ char fname[AMDGPU_UCODE_NAME_MAX];
+ va_list ap;
+ int r;
+
+ va_start(ap, fmt);
+ r = vsnprintf(fname, sizeof(fname), fmt, ap);
+ va_end(ap);
+ if (r == sizeof(fname)) {
+ dev_warn(adev->dev, "amdgpu firmware name buffer overflow\n");
+ return -EOVERFLOW;
+ }
- if (err)
+ r = request_firmware(fw, fname, adev->dev);
+ if (r)
return -ENODEV;
- err = amdgpu_ucode_validate(*fw);
- if (err) {
- dev_dbg(adev->dev, "\"%s\" failed to validate\n", fw_name);
+ r = amdgpu_ucode_validate(*fw);
+ if (r) {
+ dev_dbg(adev->dev, "\"%s\" failed to validate\n", fname);
release_firmware(*fw);
*fw = NULL;
}
- return err;
+ return r;
}
/*
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
index a3c04f711099..5bc37acd3981 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
@@ -523,6 +523,7 @@ enum AMDGPU_UCODE_ID {
AMDGPU_UCODE_ID_UMSCH_MM_CMD_BUFFER,
AMDGPU_UCODE_ID_P2S_TABLE,
AMDGPU_UCODE_ID_JPEG_RAM,
+ AMDGPU_UCODE_ID_ISP,
AMDGPU_UCODE_ID_MAXIMUM,
};
@@ -593,8 +594,9 @@ void amdgpu_ucode_print_rlc_hdr(const struct common_firmware_header *hdr);
void amdgpu_ucode_print_sdma_hdr(const struct common_firmware_header *hdr);
void amdgpu_ucode_print_psp_hdr(const struct common_firmware_header *hdr);
void amdgpu_ucode_print_gpu_info_hdr(const struct common_firmware_header *hdr);
+__printf(3, 4)
int amdgpu_ucode_request(struct amdgpu_device *adev, const struct firmware **fw,
- const char *fw_name);
+ const char *fmt, ...);
void amdgpu_ucode_release(const struct firmware **fw);
bool amdgpu_ucode_hdr_version(union amdgpu_firmware_header *hdr,
uint16_t hdr_major, uint16_t hdr_minor);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c
index 540e0f066b26..2f84bdb8c594 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c
@@ -195,7 +195,8 @@ static int amdgpu_umc_do_page_retirement(struct amdgpu_device *adev,
kgd2kfd_set_sram_ecc_flag(adev->kfd.dev);
amdgpu_umc_handle_bad_pages(adev, ras_error_status);
- if (err_data->ue_count && reset) {
+ if ((err_data->ue_count || err_data->de_count) &&
+ (reset || (con && con->is_rma))) {
con->gpu_reset_flags |= reset;
amdgpu_ras_reset_gpu(adev);
}
@@ -211,6 +212,7 @@ int amdgpu_umc_bad_page_polling_timeout(struct amdgpu_device *adev,
.block = AMDGPU_RAS_BLOCK__UMC,
};
struct ras_manager *obj = amdgpu_ras_find_obj(adev, &head);
+ struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
uint32_t timeout = timeout_ms;
memset(&err_data, 0, sizeof(err_data));
@@ -243,9 +245,7 @@ int amdgpu_umc_bad_page_polling_timeout(struct amdgpu_device *adev,
kgd2kfd_set_sram_ecc_flag(adev->kfd.dev);
- if (reset) {
- struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
-
+ if (reset || (err_data.err_addr_cnt && con && con->is_rma)) {
con->gpu_reset_flags |= reset;
amdgpu_ras_reset_gpu(adev);
}
@@ -293,14 +293,15 @@ int amdgpu_umc_pasid_poison_handler(struct amdgpu_device *adev,
amdgpu_ras_error_data_fini(&err_data);
} else {
- struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
-
- amdgpu_ras_put_poison_req(adev,
- block, pasid, pasid_fn, data, reset);
+ struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
+ int ret;
+ ret = amdgpu_ras_put_poison_req(adev,
+ block, pasid, pasid_fn, data, reset);
+ if (!ret) {
atomic_inc(&con->page_retirement_req_cnt);
-
wake_up(&con->page_retirement_wq);
+ }
}
} else {
if (adev->virt.ops && adev->virt.ops->ras_poison_handler)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
index 5e2b7c340724..43f44cc201cb 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
@@ -94,18 +94,14 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work);
int amdgpu_vcn_early_init(struct amdgpu_device *adev)
{
char ucode_prefix[25];
- char fw_name[40];
int r, i;
+ amdgpu_ucode_ip_version_decode(adev, UVD_HWIP, ucode_prefix, sizeof(ucode_prefix));
for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
- amdgpu_ucode_ip_version_decode(adev, UVD_HWIP, ucode_prefix, sizeof(ucode_prefix));
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s.bin", ucode_prefix);
- if (amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(4, 0, 6) &&
- i == 1) {
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_%d.bin", ucode_prefix, i);
- }
-
- r = amdgpu_ucode_request(adev, &adev->vcn.fw[i], fw_name);
+ if (i == 1 && amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(4, 0, 6))
+ r = amdgpu_ucode_request(adev, &adev->vcn.fw[i], "amdgpu/%s_%d.bin", ucode_prefix, i);
+ else
+ r = amdgpu_ucode_request(adev, &adev->vcn.fw[i], "amdgpu/%s.bin", ucode_prefix);
if (r) {
amdgpu_ucode_release(&adev->vcn.fw[i]);
return r;
@@ -151,6 +147,10 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
}
}
+ /* from vcn4 and above, only unified queue is used */
+ adev->vcn.using_unified_queue =
+ amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0);
+
hdr = (const struct common_firmware_header *)adev->vcn.fw[0]->data;
adev->vcn.fw_version = le32_to_cpu(hdr->ucode_version);
@@ -279,18 +279,6 @@ int amdgpu_vcn_sw_fini(struct amdgpu_device *adev)
return 0;
}
-/* from vcn4 and above, only unified queue is used */
-static bool amdgpu_vcn_using_unified_queue(struct amdgpu_ring *ring)
-{
- struct amdgpu_device *adev = ring->adev;
- bool ret = false;
-
- if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0))
- ret = true;
-
- return ret;
-}
-
bool amdgpu_vcn_is_disabled_vcn(struct amdgpu_device *adev, enum vcn_ring_type type, uint32_t vcn_instance)
{
bool ret = false;
@@ -401,7 +389,9 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work)
for (i = 0; i < adev->vcn.num_enc_rings; ++i)
fence[j] += amdgpu_fence_count_emitted(&adev->vcn.inst[j].ring_enc[i]);
- if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
+ /* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */
+ if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG &&
+ !adev->vcn.using_unified_queue) {
struct dpg_pause_state new_state;
if (fence[j] ||
@@ -447,7 +437,9 @@ void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring)
amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN,
AMD_PG_STATE_UNGATE);
- if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
+ /* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */
+ if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG &&
+ !adev->vcn.using_unified_queue) {
struct dpg_pause_state new_state;
if (ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC) {
@@ -473,8 +465,12 @@ void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring)
void amdgpu_vcn_ring_end_use(struct amdgpu_ring *ring)
{
+ struct amdgpu_device *adev = ring->adev;
+
+ /* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */
if (ring->adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG &&
- ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC)
+ ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC &&
+ !adev->vcn.using_unified_queue)
atomic_dec(&ring->adev->vcn.inst[ring->me].dpg_enc_submission_cnt);
atomic_dec(&ring->adev->vcn.total_submission_cnt);
@@ -728,12 +724,11 @@ static int amdgpu_vcn_dec_sw_send_msg(struct amdgpu_ring *ring,
struct amdgpu_job *job;
struct amdgpu_ib *ib;
uint64_t addr = AMDGPU_GPU_PAGE_ALIGN(ib_msg->gpu_addr);
- bool sq = amdgpu_vcn_using_unified_queue(ring);
uint32_t *ib_checksum;
uint32_t ib_pack_in_dw;
int i, r;
- if (sq)
+ if (adev->vcn.using_unified_queue)
ib_size_dw += 8;
r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL,
@@ -746,7 +741,7 @@ static int amdgpu_vcn_dec_sw_send_msg(struct amdgpu_ring *ring,
ib->length_dw = 0;
/* single queue headers */
- if (sq) {
+ if (adev->vcn.using_unified_queue) {
ib_pack_in_dw = sizeof(struct amdgpu_vcn_decode_buffer) / sizeof(uint32_t)
+ 4 + 2; /* engine info + decoding ib in dw */
ib_checksum = amdgpu_vcn_unified_ring_ib_header(ib, ib_pack_in_dw, false);
@@ -765,7 +760,7 @@ static int amdgpu_vcn_dec_sw_send_msg(struct amdgpu_ring *ring,
for (i = ib->length_dw; i < ib_size_dw; ++i)
ib->ptr[i] = 0x0;
- if (sq)
+ if (adev->vcn.using_unified_queue)
amdgpu_vcn_unified_ring_ib_checksum(&ib_checksum, ib_pack_in_dw);
r = amdgpu_job_submit_direct(job, ring, &f);
@@ -855,15 +850,15 @@ static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t hand
struct dma_fence **fence)
{
unsigned int ib_size_dw = 16;
+ struct amdgpu_device *adev = ring->adev;
struct amdgpu_job *job;
struct amdgpu_ib *ib;
struct dma_fence *f = NULL;
uint32_t *ib_checksum = NULL;
uint64_t addr;
- bool sq = amdgpu_vcn_using_unified_queue(ring);
int i, r;
- if (sq)
+ if (adev->vcn.using_unified_queue)
ib_size_dw += 8;
r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL,
@@ -877,7 +872,7 @@ static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t hand
ib->length_dw = 0;
- if (sq)
+ if (adev->vcn.using_unified_queue)
ib_checksum = amdgpu_vcn_unified_ring_ib_header(ib, 0x11, true);
ib->ptr[ib->length_dw++] = 0x00000018;
@@ -899,7 +894,7 @@ static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t hand
for (i = ib->length_dw; i < ib_size_dw; ++i)
ib->ptr[i] = 0x0;
- if (sq)
+ if (adev->vcn.using_unified_queue)
amdgpu_vcn_unified_ring_ib_checksum(&ib_checksum, 0x11);
r = amdgpu_job_submit_direct(job, ring, &f);
@@ -922,15 +917,15 @@ static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t han
struct dma_fence **fence)
{
unsigned int ib_size_dw = 16;
+ struct amdgpu_device *adev = ring->adev;
struct amdgpu_job *job;
struct amdgpu_ib *ib;
struct dma_fence *f = NULL;
uint32_t *ib_checksum = NULL;
uint64_t addr;
- bool sq = amdgpu_vcn_using_unified_queue(ring);
int i, r;
- if (sq)
+ if (adev->vcn.using_unified_queue)
ib_size_dw += 8;
r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL,
@@ -944,7 +939,7 @@ static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t han
ib->length_dw = 0;
- if (sq)
+ if (adev->vcn.using_unified_queue)
ib_checksum = amdgpu_vcn_unified_ring_ib_header(ib, 0x11, true);
ib->ptr[ib->length_dw++] = 0x00000018;
@@ -966,7 +961,7 @@ static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t han
for (i = ib->length_dw; i < ib_size_dw; ++i)
ib->ptr[i] = 0x0;
- if (sq)
+ if (adev->vcn.using_unified_queue)
amdgpu_vcn_unified_ring_ib_checksum(&ib_checksum, 0x11);
r = amdgpu_job_submit_direct(job, ring, &f);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
index 9f06def236fd..1a5439abd1a0 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
@@ -329,6 +329,7 @@ struct amdgpu_vcn {
uint16_t inst_mask;
uint8_t num_inst_per_aid;
+ bool using_unified_queue;
};
struct amdgpu_fw_shared_rb_ptrs_struct {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
index b56d243c53ab..111c380f929b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
@@ -86,8 +86,10 @@ int amdgpu_virt_request_full_gpu(struct amdgpu_device *adev, bool init)
if (virt->ops && virt->ops->req_full_gpu) {
r = virt->ops->req_full_gpu(adev, init);
- if (r)
+ if (r) {
+ adev->no_hw_access = true;
return r;
+ }
adev->virt.caps &= ~AMDGPU_SRIOV_CAPS_RUNTIME;
}
@@ -153,6 +155,20 @@ void amdgpu_virt_request_init_data(struct amdgpu_device *adev)
}
/**
+ * amdgpu_virt_ready_to_reset() - send ready to reset to host
+ * @adev: amdgpu device.
+ * Send ready to reset message to GPU hypervisor to signal we have stopped GPU
+ * activity and is ready for host FLR
+ */
+void amdgpu_virt_ready_to_reset(struct amdgpu_device *adev)
+{
+ struct amdgpu_virt *virt = &adev->virt;
+
+ if (virt->ops && virt->ops->reset_gpu)
+ virt->ops->ready_to_reset(adev);
+}
+
+/**
* amdgpu_virt_wait_reset() - wait for reset gpu completed
* @adev: amdgpu device.
* Wait for GPU reset completed.
@@ -215,6 +231,22 @@ void amdgpu_virt_free_mm_table(struct amdgpu_device *adev)
adev->virt.mm_table.gpu_addr = 0;
}
+/**
+ * amdgpu_virt_rcvd_ras_interrupt() - receive ras interrupt
+ * @adev: amdgpu device.
+ * Check whether host sent RAS error message
+ * Return: true if found, otherwise false
+ */
+bool amdgpu_virt_rcvd_ras_interrupt(struct amdgpu_device *adev)
+{
+ struct amdgpu_virt *virt = &adev->virt;
+
+ if (!virt->ops || !virt->ops->rcvd_ras_intr)
+ return false;
+
+ return virt->ops->rcvd_ras_intr(adev);
+}
+
unsigned int amd_sriov_msg_checksum(void *obj,
unsigned long obj_size,
@@ -598,11 +630,14 @@ static void amdgpu_virt_update_vf2pf_work_item(struct work_struct *work)
ret = amdgpu_virt_read_pf2vf_data(adev);
if (ret) {
adev->virt.vf2pf_update_retry_cnt++;
- if ((adev->virt.vf2pf_update_retry_cnt >= AMDGPU_VF2PF_UPDATE_MAX_RETRY_LIMIT) &&
- amdgpu_sriov_runtime(adev)) {
+
+ if ((amdgpu_virt_rcvd_ras_interrupt(adev) ||
+ adev->virt.vf2pf_update_retry_cnt >= AMDGPU_VF2PF_UPDATE_MAX_RETRY_LIMIT) &&
+ amdgpu_sriov_runtime(adev)) {
+
amdgpu_ras_set_fed(adev, true);
if (amdgpu_reset_domain_schedule(adev->reset_domain,
- &adev->kfd.reset_work))
+ &adev->kfd.reset_work))
return;
else
dev_err(adev->dev, "Failed to queue work! at %s", __func__);
@@ -979,6 +1014,9 @@ u32 amdgpu_virt_rlcg_reg_rw(struct amdgpu_device *adev, u32 offset, u32 v, u32 f
return 0;
}
+ if (amdgpu_device_skip_hw_access(adev))
+ return 0;
+
reg_access_ctrl = &adev->gfx.rlc.reg_access_ctrl[xcc_id];
scratch_reg0 = (void __iomem *)adev->rmmio + 4 * reg_access_ctrl->scratch_reg0;
scratch_reg1 = (void __iomem *)adev->rmmio + 4 * reg_access_ctrl->scratch_reg1;
@@ -1055,6 +1093,9 @@ void amdgpu_sriov_wreg(struct amdgpu_device *adev,
{
u32 rlcg_flag;
+ if (amdgpu_device_skip_hw_access(adev))
+ return;
+
if (!amdgpu_sriov_runtime(adev) &&
amdgpu_virt_get_rlcg_reg_access_flag(adev, acc_flags, hwip, true, &rlcg_flag)) {
amdgpu_virt_rlcg_reg_rw(adev, offset, value, rlcg_flag, xcc_id);
@@ -1072,6 +1113,9 @@ u32 amdgpu_sriov_rreg(struct amdgpu_device *adev,
{
u32 rlcg_flag;
+ if (amdgpu_device_skip_hw_access(adev))
+ return 0;
+
if (!amdgpu_sriov_runtime(adev) &&
amdgpu_virt_get_rlcg_reg_access_flag(adev, acc_flags, hwip, false, &rlcg_flag))
return amdgpu_virt_rlcg_reg_rw(adev, offset, 0, rlcg_flag, xcc_id);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h
index 0ec246c74570..b42a8854dca0 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h
@@ -52,7 +52,7 @@
/* tonga/fiji use this offset */
#define mmBIF_IOV_FUNC_IDENTIFIER 0x1503
-#define AMDGPU_VF2PF_UPDATE_MAX_RETRY_LIMIT 5
+#define AMDGPU_VF2PF_UPDATE_MAX_RETRY_LIMIT 2
enum amdgpu_sriov_vf_mode {
SRIOV_VF_MODE_BARE_METAL = 0,
@@ -88,11 +88,13 @@ struct amdgpu_virt_ops {
int (*rel_full_gpu)(struct amdgpu_device *adev, bool init);
int (*req_init_data)(struct amdgpu_device *adev);
int (*reset_gpu)(struct amdgpu_device *adev);
+ void (*ready_to_reset)(struct amdgpu_device *adev);
int (*wait_reset)(struct amdgpu_device *adev);
void (*trans_msg)(struct amdgpu_device *adev, enum idh_request req,
u32 data1, u32 data2, u32 data3);
void (*ras_poison_handler)(struct amdgpu_device *adev,
enum amdgpu_ras_block block);
+ bool (*rcvd_ras_intr)(struct amdgpu_device *adev);
};
/*
@@ -347,9 +349,11 @@ int amdgpu_virt_request_full_gpu(struct amdgpu_device *adev, bool init);
int amdgpu_virt_release_full_gpu(struct amdgpu_device *adev, bool init);
int amdgpu_virt_reset_gpu(struct amdgpu_device *adev);
void amdgpu_virt_request_init_data(struct amdgpu_device *adev);
+void amdgpu_virt_ready_to_reset(struct amdgpu_device *adev);
int amdgpu_virt_wait_reset(struct amdgpu_device *adev);
int amdgpu_virt_alloc_mm_table(struct amdgpu_device *adev);
void amdgpu_virt_free_mm_table(struct amdgpu_device *adev);
+bool amdgpu_virt_rcvd_ras_interrupt(struct amdgpu_device *adev);
void amdgpu_virt_release_ras_err_handler_data(struct amdgpu_device *adev);
void amdgpu_virt_init_data_exchange(struct amdgpu_device *adev);
void amdgpu_virt_exchange_data(struct amdgpu_device *adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
index e30eecd02ae1..6415d0d039e1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
@@ -3,6 +3,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_edid.h>
#include <drm/drm_simple_kms_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_vblank.h>
#include "amdgpu.h"
@@ -65,9 +66,7 @@ static enum hrtimer_restart amdgpu_vkms_vblank_simulate(struct hrtimer *timer)
static int amdgpu_vkms_enable_vblank(struct drm_crtc *crtc)
{
- struct drm_device *dev = crtc->dev;
- unsigned int pipe = drm_crtc_index(crtc);
- struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
+ struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
struct amdgpu_vkms_output *out = drm_crtc_to_amdgpu_vkms_output(crtc);
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
@@ -91,10 +90,8 @@ static bool amdgpu_vkms_get_vblank_timestamp(struct drm_crtc *crtc,
ktime_t *vblank_time,
bool in_vblank_irq)
{
- struct drm_device *dev = crtc->dev;
- unsigned int pipe = crtc->index;
struct amdgpu_vkms_output *output = drm_crtc_to_amdgpu_vkms_output(crtc);
- struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
+ struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
if (!READ_ONCE(vblank->enabled)) {
@@ -314,7 +311,13 @@ static int amdgpu_vkms_prepare_fb(struct drm_plane *plane,
return 0;
}
afb = to_amdgpu_framebuffer(new_state->fb);
- obj = new_state->fb->obj[0];
+
+ obj = drm_gem_fb_get_obj(new_state->fb, 0);
+ if (!obj) {
+ DRM_ERROR("Failed to get obj from framebuffer\n");
+ return -EINVAL;
+ }
+
rbo = gem_to_amdgpu_bo(obj);
adev = amdgpu_ttm_adev(rbo->tbo.bdev);
@@ -368,12 +371,19 @@ static void amdgpu_vkms_cleanup_fb(struct drm_plane *plane,
struct drm_plane_state *old_state)
{
struct amdgpu_bo *rbo;
+ struct drm_gem_object *obj;
int r;
if (!old_state->fb)
return;
- rbo = gem_to_amdgpu_bo(old_state->fb->obj[0]);
+ obj = drm_gem_fb_get_obj(old_state->fb, 0);
+ if (!obj) {
+ DRM_ERROR("Failed to get obj from framebuffer\n");
+ return;
+ }
+
+ rbo = gem_to_amdgpu_bo(obj);
r = amdgpu_bo_reserve(rbo, false);
if (unlikely(r)) {
DRM_ERROR("failed to reserve rbo before unpin\n");
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index 3abfa66d72a2..a060c28f0877 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -434,7 +434,7 @@ uint64_t amdgpu_vm_generation(struct amdgpu_device *adev, struct amdgpu_vm *vm)
if (!vm)
return result;
- result += vm->generation;
+ result += lower_32_bits(vm->generation);
/* Add one if the page tables will be re-generated on next CS */
if (drm_sched_entity_error(&vm->delayed))
++result;
@@ -463,13 +463,14 @@ int amdgpu_vm_validate(struct amdgpu_device *adev, struct amdgpu_vm *vm,
int (*validate)(void *p, struct amdgpu_bo *bo),
void *param)
{
+ uint64_t new_vm_generation = amdgpu_vm_generation(adev, vm);
struct amdgpu_vm_bo_base *bo_base;
struct amdgpu_bo *shadow;
struct amdgpu_bo *bo;
int r;
- if (drm_sched_entity_error(&vm->delayed)) {
- ++vm->generation;
+ if (vm->generation != new_vm_generation) {
+ vm->generation = new_vm_generation;
amdgpu_vm_bo_reset_state_machine(vm);
amdgpu_vm_fini_entities(vm);
r = amdgpu_vm_init_entities(adev, vm);
@@ -2439,7 +2440,7 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm,
vm->last_update = dma_fence_get_stub();
vm->last_unlocked = dma_fence_get_stub();
vm->last_tlb_flush = dma_fence_get_stub();
- vm->generation = 0;
+ vm->generation = amdgpu_vm_generation(adev, NULL);
mutex_init(&vm->eviction_lock);
vm->evicting = false;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
index 8e3501e3765b..046949c4b695 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
@@ -128,6 +128,7 @@ struct amdgpu_mem_stats;
(((uint64_t)(flags) & (~AMDGPU_PTE_MTYPE_GFX12_MASK)) | \
AMDGPU_PTE_MTYPE_GFX12_SHIFT(mtype))
+#define AMDGPU_PTE_DCC (1ULL << 58)
#define AMDGPU_PTE_IS_PTE (1ULL << 63)
/* PDE Block Fragment Size for gfx v12 */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c
index 49881073ff58..5acd20ff5979 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c
@@ -232,13 +232,11 @@ int amdgpu_vpe_init_microcode(struct amdgpu_vpe *vpe)
{
struct amdgpu_device *adev = vpe->ring.adev;
const struct vpe_firmware_header_v1_0 *vpe_hdr;
- char fw_prefix[32], fw_name[64];
+ char fw_prefix[32];
int ret;
amdgpu_ucode_ip_version_decode(adev, VPE_HWIP, fw_prefix, sizeof(fw_prefix));
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s.bin", fw_prefix);
-
- ret = amdgpu_ucode_request(adev, &adev->vpe.fw, fw_name);
+ ret = amdgpu_ucode_request(adev, &adev->vpe.fw, "amdgpu/%s.bin", fw_prefix);
if (ret)
goto out;
@@ -304,6 +302,7 @@ static int vpe_early_init(void *handle)
switch (amdgpu_ip_version(adev, VPE_HWIP, 0)) {
case IP_VERSION(6, 1, 0):
+ case IP_VERSION(6, 1, 3):
vpe_v6_1_set_funcs(vpe);
break;
case IP_VERSION(6, 1, 1):
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c
index 2b99eed5ba19..a6d456ec6aeb 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c
@@ -219,7 +219,8 @@ int amdgpu_xcp_query_partition_mode(struct amdgpu_xcp_mgr *xcp_mgr, u32 flags)
{
int mode;
- if (xcp_mgr->mode == AMDGPU_XCP_MODE_NONE)
+ if (!amdgpu_sriov_vf(xcp_mgr->adev) &&
+ xcp_mgr->mode == AMDGPU_XCP_MODE_NONE)
return xcp_mgr->mode;
if (!xcp_mgr->funcs || !xcp_mgr->funcs->query_partition_mode)
@@ -228,6 +229,12 @@ int amdgpu_xcp_query_partition_mode(struct amdgpu_xcp_mgr *xcp_mgr, u32 flags)
if (!(flags & AMDGPU_XCP_FL_LOCKED))
mutex_lock(&xcp_mgr->xcp_lock);
mode = xcp_mgr->funcs->query_partition_mode(xcp_mgr);
+
+ /* First time query for VF, set the mode here */
+ if (amdgpu_sriov_vf(xcp_mgr->adev) &&
+ xcp_mgr->mode == AMDGPU_XCP_MODE_NONE)
+ xcp_mgr->mode = mode;
+
if (xcp_mgr->mode != AMDGPU_XCP_MODE_TRANS && mode != xcp_mgr->mode)
dev_WARN(
xcp_mgr->adev->dev,
@@ -282,8 +289,7 @@ int amdgpu_xcp_mgr_init(struct amdgpu_device *adev, int init_mode,
{
struct amdgpu_xcp_mgr *xcp_mgr;
- if (!xcp_funcs || !xcp_funcs->switch_partition_mode ||
- !xcp_funcs->get_ip_details)
+ if (!xcp_funcs || !xcp_funcs->get_ip_details)
return -EINVAL;
xcp_mgr = kzalloc(sizeof(*xcp_mgr), GFP_KERNEL);
diff --git a/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c b/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c
index 2c9a0aa41e2d..228fd4dd32f1 100644
--- a/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c
+++ b/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c
@@ -304,13 +304,56 @@ u64 aqua_vanjaram_encode_ext_smn_addressing(int ext_id)
return ext_offset;
}
+static enum amdgpu_gfx_partition
+__aqua_vanjaram_calc_xcp_mode(struct amdgpu_xcp_mgr *xcp_mgr)
+{
+ struct amdgpu_device *adev = xcp_mgr->adev;
+ int num_xcc, num_xcc_per_xcp = 0, mode = 0;
+
+ num_xcc = NUM_XCC(xcp_mgr->adev->gfx.xcc_mask);
+ if (adev->gfx.funcs->get_xccs_per_xcp)
+ num_xcc_per_xcp = adev->gfx.funcs->get_xccs_per_xcp(adev);
+ if ((num_xcc_per_xcp) && (num_xcc % num_xcc_per_xcp == 0))
+ mode = num_xcc / num_xcc_per_xcp;
+
+ if (num_xcc_per_xcp == 1)
+ return AMDGPU_CPX_PARTITION_MODE;
+
+ switch (mode) {
+ case 1:
+ return AMDGPU_SPX_PARTITION_MODE;
+ case 2:
+ return AMDGPU_DPX_PARTITION_MODE;
+ case 3:
+ return AMDGPU_TPX_PARTITION_MODE;
+ case 4:
+ return AMDGPU_QPX_PARTITION_MODE;
+ default:
+ return AMDGPU_UNKNOWN_COMPUTE_PARTITION_MODE;
+ }
+
+ return AMDGPU_UNKNOWN_COMPUTE_PARTITION_MODE;
+}
+
static int aqua_vanjaram_query_partition_mode(struct amdgpu_xcp_mgr *xcp_mgr)
{
- enum amdgpu_gfx_partition mode = AMDGPU_UNKNOWN_COMPUTE_PARTITION_MODE;
+ enum amdgpu_gfx_partition derv_mode,
+ mode = AMDGPU_UNKNOWN_COMPUTE_PARTITION_MODE;
struct amdgpu_device *adev = xcp_mgr->adev;
- if (adev->nbio.funcs->get_compute_partition_mode)
+ derv_mode = __aqua_vanjaram_calc_xcp_mode(xcp_mgr);
+
+ if (amdgpu_sriov_vf(adev))
+ return derv_mode;
+
+ if (adev->nbio.funcs->get_compute_partition_mode) {
mode = adev->nbio.funcs->get_compute_partition_mode(adev);
+ if (mode != derv_mode)
+ dev_warn(
+ adev->dev,
+ "Mismatch in compute partition mode - reported : %d derived : %d",
+ mode, derv_mode);
+ }
return mode;
}
@@ -624,6 +667,9 @@ static int aqua_vanjaram_xcp_mgr_init(struct amdgpu_device *adev)
{
int ret;
+ if (amdgpu_sriov_vf(adev))
+ aqua_vanjaram_xcp_funcs.switch_partition_mode = NULL;
+
ret = amdgpu_xcp_mgr_init(adev, AMDGPU_UNKNOWN_COMPUTE_PARTITION_MODE, 1,
&aqua_vanjaram_xcp_funcs);
if (ret)
diff --git a/drivers/gpu/drm/amd/amdgpu/atom.c b/drivers/gpu/drm/amd/amdgpu/atom.c
index d552e013354c..09715b506468 100644
--- a/drivers/gpu/drm/amd/amdgpu/atom.c
+++ b/drivers/gpu/drm/amd/amdgpu/atom.c
@@ -301,7 +301,7 @@ static uint32_t atom_get_src_int(atom_exec_context *ctx, uint8_t attr,
(*ptr) += 4;
if (print)
DEBUG("IMM 0x%08X\n", val);
- return val;
+ break;
case ATOM_SRC_WORD0:
case ATOM_SRC_WORD8:
case ATOM_SRC_WORD16:
@@ -309,7 +309,7 @@ static uint32_t atom_get_src_int(atom_exec_context *ctx, uint8_t attr,
(*ptr) += 2;
if (print)
DEBUG("IMM 0x%04X\n", val);
- return val;
+ break;
case ATOM_SRC_BYTE0:
case ATOM_SRC_BYTE8:
case ATOM_SRC_BYTE16:
@@ -318,9 +318,9 @@ static uint32_t atom_get_src_int(atom_exec_context *ctx, uint8_t attr,
(*ptr)++;
if (print)
DEBUG("IMM 0x%02X\n", val);
- return val;
+ break;
}
- break;
+ return val;
case ATOM_ARG_PLL:
idx = U8(*ptr);
(*ptr)++;
diff --git a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
index 6948ebda0fa2..952737de9411 100644
--- a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
+++ b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
@@ -107,7 +107,6 @@ static void cik_sdma_free_microcode(struct amdgpu_device *adev)
static int cik_sdma_init_microcode(struct amdgpu_device *adev)
{
const char *chip_name;
- char fw_name[30];
int err = 0, i;
DRM_DEBUG("\n");
@@ -133,16 +132,18 @@ static int cik_sdma_init_microcode(struct amdgpu_device *adev)
for (i = 0; i < adev->sdma.num_instances; i++) {
if (i == 0)
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sdma.bin", chip_name);
+ err = amdgpu_ucode_request(adev, &adev->sdma.instance[i].fw,
+ "amdgpu/%s_sdma.bin", chip_name);
else
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sdma1.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->sdma.instance[i].fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->sdma.instance[i].fw,
+ "amdgpu/%s_sdma1.bin", chip_name);
if (err)
goto out;
}
out:
if (err) {
- pr_err("cik_sdma: Failed to load firmware \"%s\"\n", fw_name);
+ pr_err("cik_sdma: Failed to load firmware \"%s_sdma%s.bin\"\n",
+ chip_name, i == 0 ? "" : "1");
for (i = 0; i < adev->sdma.num_instances; i++)
amdgpu_ucode_release(&adev->sdma.instance[i].fw);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
index b44fce44c066..dddb5fe16f2c 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
@@ -1299,7 +1299,7 @@ static void dce_v10_0_audio_write_speaker_allocation(struct drm_encoder *encoder
return;
}
- sad_count = drm_edid_to_speaker_allocation(amdgpu_connector_edid(connector), &sadb);
+ sad_count = drm_edid_to_speaker_allocation(amdgpu_connector->edid, &sadb);
if (sad_count < 0) {
DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
sad_count = 0;
@@ -1369,7 +1369,7 @@ static void dce_v10_0_audio_write_sad_regs(struct drm_encoder *encoder)
return;
}
- sad_count = drm_edid_to_sad(amdgpu_connector_edid(connector), &sads);
+ sad_count = drm_edid_to_sad(amdgpu_connector->edid, &sads);
if (sad_count < 0)
DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
if (sad_count <= 0)
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
index 80b2e7f79acf..11780e4d7e9f 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
@@ -1331,7 +1331,7 @@ static void dce_v11_0_audio_write_speaker_allocation(struct drm_encoder *encoder
return;
}
- sad_count = drm_edid_to_speaker_allocation(amdgpu_connector_edid(connector), &sadb);
+ sad_count = drm_edid_to_speaker_allocation(amdgpu_connector->edid, &sadb);
if (sad_count < 0) {
DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
sad_count = 0;
@@ -1401,7 +1401,7 @@ static void dce_v11_0_audio_write_sad_regs(struct drm_encoder *encoder)
return;
}
- sad_count = drm_edid_to_sad(amdgpu_connector_edid(connector), &sads);
+ sad_count = drm_edid_to_sad(amdgpu_connector->edid, &sads);
if (sad_count < 0)
DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
if (sad_count <= 0)
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
index db20012600f5..05c0df97f01d 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
@@ -1217,7 +1217,7 @@ static void dce_v6_0_audio_write_speaker_allocation(struct drm_encoder *encoder)
return;
}
- sad_count = drm_edid_to_speaker_allocation(amdgpu_connector_edid(connector), &sadb);
+ sad_count = drm_edid_to_speaker_allocation(amdgpu_connector->edid, &sadb);
if (sad_count < 0) {
DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
sad_count = 0;
@@ -1292,7 +1292,7 @@ static void dce_v6_0_audio_write_sad_regs(struct drm_encoder *encoder)
return;
}
- sad_count = drm_edid_to_sad(amdgpu_connector_edid(connector), &sads);
+ sad_count = drm_edid_to_sad(amdgpu_connector->edid, &sads);
if (sad_count < 0)
DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
if (sad_count <= 0)
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
index 5b56100ec902..dc73e301d937 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
@@ -1272,7 +1272,7 @@ static void dce_v8_0_audio_write_speaker_allocation(struct drm_encoder *encoder)
return;
}
- sad_count = drm_edid_to_speaker_allocation(amdgpu_connector_edid(connector), &sadb);
+ sad_count = drm_edid_to_speaker_allocation(amdgpu_connector->edid, &sadb);
if (sad_count < 0) {
DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
sad_count = 0;
@@ -1340,7 +1340,7 @@ static void dce_v8_0_audio_write_sad_regs(struct drm_encoder *encoder)
return;
}
- sad_count = drm_edid_to_sad(amdgpu_connector_edid(connector), &sads);
+ sad_count = drm_edid_to_sad(amdgpu_connector->edid, &sads);
if (sad_count < 0)
DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
if (sad_count <= 0)
diff --git a/drivers/gpu/drm/amd/amdgpu/df_v4_15.c b/drivers/gpu/drm/amd/amdgpu/df_v4_15.c
new file mode 100644
index 000000000000..2a573e33908b
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/df_v4_15.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2024 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.
+ *
+ */
+#include "amdgpu.h"
+#include "df_v4_15.h"
+
+#include "df/df_4_15_offset.h"
+#include "df/df_4_15_sh_mask.h"
+
+static void df_v4_15_hw_init(struct amdgpu_device *adev)
+{
+ if (adev->have_atomics_support) {
+ uint32_t tmp;
+ uint32_t dis_lcl_proc = (1 << 1 |
+ 1 << 2 |
+ 1 << 13);
+
+ tmp = RREG32_SOC15(DF, 0, regNCSConfigurationRegister1);
+ tmp |= (dis_lcl_proc << NCSConfigurationRegister1__DisIntAtomicsLclProcessing__SHIFT);
+ WREG32_SOC15(DF, 0, regNCSConfigurationRegister1, tmp);
+ }
+}
+
+const struct amdgpu_df_funcs df_v4_15_funcs = {
+ .hw_init = df_v4_15_hw_init
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/df_v4_15.h b/drivers/gpu/drm/amd/amdgpu/df_v4_15.h
new file mode 100644
index 000000000000..dddf2422112a
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/df_v4_15.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2024 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 __DF_V4_15_H__
+#define __DF_V4_15_H__
+
+extern const struct amdgpu_df_funcs df_v4_15_funcs;
+
+#endif /* __DF_V4_15_H__ */
+
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
index 3b0d8d3af58a..2957702fca0c 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
@@ -4116,7 +4116,6 @@ static void gfx_v10_0_check_gfxoff_flag(struct amdgpu_device *adev)
static int gfx_v10_0_init_microcode(struct amdgpu_device *adev)
{
- char fw_name[53];
char ucode_prefix[30];
const char *wks = "";
int err;
@@ -4131,27 +4130,27 @@ static int gfx_v10_0_init_microcode(struct amdgpu_device *adev)
wks = "_wks";
amdgpu_ucode_ip_version_decode(adev, GC_HWIP, ucode_prefix, sizeof(ucode_prefix));
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_pfp%s.bin", ucode_prefix, wks);
- err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw,
+ "amdgpu/%s_pfp%s.bin", ucode_prefix, wks);
if (err)
goto out;
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_PFP);
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_me%s.bin", ucode_prefix, wks);
- err = amdgpu_ucode_request(adev, &adev->gfx.me_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.me_fw,
+ "amdgpu/%s_me%s.bin", ucode_prefix, wks);
if (err)
goto out;
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_ME);
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ce%s.bin", ucode_prefix, wks);
- err = amdgpu_ucode_request(adev, &adev->gfx.ce_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.ce_fw,
+ "amdgpu/%s_ce%s.bin", ucode_prefix, wks);
if (err)
goto out;
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_CE);
if (!amdgpu_sriov_vf(adev)) {
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_rlc.bin", ucode_prefix);
- err = request_firmware(&adev->gfx.rlc_fw, fw_name, adev->dev);
+ err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw,
+ "amdgpu/%s_rlc.bin", ucode_prefix);
if (err)
goto out;
@@ -4166,15 +4165,15 @@ static int gfx_v10_0_init_microcode(struct amdgpu_device *adev)
goto out;
}
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec%s.bin", ucode_prefix, wks);
- err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw,
+ "amdgpu/%s_mec%s.bin", ucode_prefix, wks);
if (err)
goto out;
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC1);
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC1_JT);
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec2%s.bin", ucode_prefix, wks);
- err = amdgpu_ucode_request(adev, &adev->gfx.mec2_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.mec2_fw,
+ "amdgpu/%s_mec2%s.bin", ucode_prefix, wks);
if (!err) {
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC2);
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC2_JT);
@@ -7325,11 +7324,9 @@ static int gfx_v10_0_hw_init(void *handle)
* loaded firstly, so in direct type, it has to load smc ucode
* here before rlc.
*/
- if (!(adev->flags & AMD_IS_APU)) {
- r = amdgpu_pm_load_smu_firmware(adev, NULL);
- if (r)
- return r;
- }
+ r = amdgpu_pm_load_smu_firmware(adev, NULL);
+ if (r)
+ return r;
gfx_v10_0_disable_gpa_mode(adev);
}
@@ -9288,6 +9285,7 @@ static void gfx_v10_ip_print(void *handle, struct drm_printer *p)
if (!adev->gfx.ip_dump_gfx_queues)
return;
+ index = 0;
reg_count = ARRAY_SIZE(gc_gfx_queue_reg_list_10);
drm_printf(p, "\nnum_me: %d num_pipe: %d num_queue: %d\n",
adev->gfx.me.num_me,
@@ -9334,7 +9332,7 @@ static void gfx_v10_ip_dump(void *handle)
for (j = 0; j < adev->gfx.mec.num_pipe_per_mec; j++) {
for (k = 0; k < adev->gfx.mec.num_queue_per_pipe; k++) {
/* ME0 is for GFX so start from 1 for CP */
- nv_grbm_select(adev, 1 + i, j, k, 0);
+ nv_grbm_select(adev, adev->gfx.me.num_me + i, j, k, 0);
for (reg = 0; reg < reg_count; reg++) {
adev->gfx.ip_dump_compute_queues[index + reg] =
@@ -9353,6 +9351,7 @@ static void gfx_v10_ip_dump(void *handle)
if (!adev->gfx.ip_dump_gfx_queues)
return;
+ index = 0;
reg_count = ARRAY_SIZE(gc_gfx_queue_reg_list_10);
amdgpu_gfx_off_ctrl(adev, false);
mutex_lock(&adev->srbm_mutex);
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
index 19d95455780f..dcef39907449 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
@@ -93,6 +93,10 @@ MODULE_FIRMWARE("amdgpu/gc_11_5_1_pfp.bin");
MODULE_FIRMWARE("amdgpu/gc_11_5_1_me.bin");
MODULE_FIRMWARE("amdgpu/gc_11_5_1_mec.bin");
MODULE_FIRMWARE("amdgpu/gc_11_5_1_rlc.bin");
+MODULE_FIRMWARE("amdgpu/gc_11_5_2_pfp.bin");
+MODULE_FIRMWARE("amdgpu/gc_11_5_2_me.bin");
+MODULE_FIRMWARE("amdgpu/gc_11_5_2_mec.bin");
+MODULE_FIRMWARE("amdgpu/gc_11_5_2_rlc.bin");
static const struct amdgpu_hwip_reg_entry gc_reg_list_11_0[] = {
SOC15_REG_ENTRY_STR(GC, 0, regGRBM_STATUS),
@@ -611,10 +615,9 @@ static int gfx_v11_0_init_toc_microcode(struct amdgpu_device *adev, const char *
{
const struct psp_firmware_header_v1_0 *toc_hdr;
int err = 0;
- char fw_name[40];
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_toc.bin", ucode_prefix);
- err = amdgpu_ucode_request(adev, &adev->psp.toc_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->psp.toc_fw,
+ "amdgpu/%s_toc.bin", ucode_prefix);
if (err)
goto out;
@@ -653,7 +656,6 @@ static void gfx_v11_0_check_fw_cp_gfx_shadow(struct amdgpu_device *adev)
static int gfx_v11_0_init_microcode(struct amdgpu_device *adev)
{
- char fw_name[40];
char ucode_prefix[25];
int err;
const struct rlc_firmware_header_v2_0 *rlc_hdr;
@@ -663,9 +665,8 @@ static int gfx_v11_0_init_microcode(struct amdgpu_device *adev)
DRM_DEBUG("\n");
amdgpu_ucode_ip_version_decode(adev, GC_HWIP, ucode_prefix, sizeof(ucode_prefix));
-
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_pfp.bin", ucode_prefix);
- err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw,
+ "amdgpu/%s_pfp.bin", ucode_prefix);
if (err)
goto out;
/* check pfp fw hdr version to decide if enable rs64 for gfx11.*/
@@ -681,8 +682,8 @@ static int gfx_v11_0_init_microcode(struct amdgpu_device *adev)
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_PFP);
}
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_me.bin", ucode_prefix);
- err = amdgpu_ucode_request(adev, &adev->gfx.me_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.me_fw,
+ "amdgpu/%s_me.bin", ucode_prefix);
if (err)
goto out;
if (adev->gfx.rs64_enable) {
@@ -696,10 +697,11 @@ static int gfx_v11_0_init_microcode(struct amdgpu_device *adev)
if (!amdgpu_sriov_vf(adev)) {
if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(11, 0, 0) &&
adev->pdev->revision == 0xCE)
- snprintf(fw_name, sizeof(fw_name), "amdgpu/gc_11_0_0_rlc_1.bin");
+ err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw,
+ "amdgpu/gc_11_0_0_rlc_1.bin");
else
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_rlc.bin", ucode_prefix);
- err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw,
+ "amdgpu/%s_rlc.bin", ucode_prefix);
if (err)
goto out;
rlc_hdr = (const struct rlc_firmware_header_v2_0 *)adev->gfx.rlc_fw->data;
@@ -710,8 +712,8 @@ static int gfx_v11_0_init_microcode(struct amdgpu_device *adev)
goto out;
}
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec.bin", ucode_prefix);
- err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw,
+ "amdgpu/%s_mec.bin", ucode_prefix);
if (err)
goto out;
if (adev->gfx.rs64_enable) {
@@ -1056,6 +1058,7 @@ static int gfx_v11_0_gpu_early_init(struct amdgpu_device *adev)
case IP_VERSION(11, 0, 4):
case IP_VERSION(11, 5, 0):
case IP_VERSION(11, 5, 1):
+ case IP_VERSION(11, 5, 2):
adev->gfx.config.max_hw_contexts = 8;
adev->gfx.config.sc_prim_fifo_size_frontend = 0x20;
adev->gfx.config.sc_prim_fifo_size_backend = 0x100;
@@ -1536,6 +1539,7 @@ static int gfx_v11_0_sw_init(void *handle)
case IP_VERSION(11, 0, 4):
case IP_VERSION(11, 5, 0):
case IP_VERSION(11, 5, 1):
+ case IP_VERSION(11, 5, 2):
adev->gfx.me.num_me = 1;
adev->gfx.me.num_pipe_per_me = 1;
adev->gfx.me.num_queue_per_pipe = 1;
@@ -2784,7 +2788,8 @@ static int gfx_v11_0_wait_for_rlc_autoload_complete(struct amdgpu_device *adev)
amdgpu_ip_version(adev, GC_HWIP, 0) ==
IP_VERSION(11, 0, 4) ||
amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(11, 5, 0) ||
- amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(11, 5, 1))
+ amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(11, 5, 1) ||
+ amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(11, 5, 2))
bootload_status = RREG32_SOC15(GC, 0,
regRLC_RLCS_BOOTLOAD_STATUS_gc_11_0_1);
else
@@ -4415,7 +4420,9 @@ static int gfx_v11_0_gfxhub_enable(struct amdgpu_device *adev)
false : true;
adev->gfxhub.funcs->set_fault_enable_default(adev, value);
- amdgpu_gmc_flush_gpu_tlb(adev, 0, AMDGPU_GFXHUB(0), 0);
+ /* TODO investigate why this and the hdp flush above is needed,
+ * are we missing a flush somewhere else? */
+ adev->gmc.gmc_funcs->flush_gpu_tlb(adev, 0, AMDGPU_GFXHUB(0), 0);
return 0;
}
@@ -4498,11 +4505,11 @@ static int gfx_v11_0_hw_init(void *handle)
/* RLC autoload sequence 1: Program rlc ram */
if (adev->gfx.imu.funcs->program_rlc_ram)
adev->gfx.imu.funcs->program_rlc_ram(adev);
+ /* rlc autoload firmware */
+ r = gfx_v11_0_rlc_backdoor_autoload_enable(adev);
+ if (r)
+ return r;
}
- /* rlc autoload firmware */
- r = gfx_v11_0_rlc_backdoor_autoload_enable(adev);
- if (r)
- return r;
} else {
if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT) {
if (adev->gfx.imu.funcs && (amdgpu_dpm > 0)) {
@@ -4551,11 +4558,9 @@ static int gfx_v11_0_hw_init(void *handle)
* loaded firstly, so in direct type, it has to load smc ucode
* here before rlc.
*/
- if (!(adev->flags & AMD_IS_APU)) {
- r = amdgpu_pm_load_smu_firmware(adev, NULL);
- if (r)
- return r;
- }
+ r = amdgpu_pm_load_smu_firmware(adev, NULL);
+ if (r)
+ return r;
}
gfx_v11_0_constants_init(adev);
@@ -5296,6 +5301,7 @@ static void gfx_v11_cntl_power_gating(struct amdgpu_device *adev, bool enable)
case IP_VERSION(11, 0, 4):
case IP_VERSION(11, 5, 0):
case IP_VERSION(11, 5, 1):
+ case IP_VERSION(11, 5, 2):
WREG32_SOC15(GC, 0, regRLC_PG_DELAY_3, RLC_PG_DELAY_3_DEFAULT_GC_11_0_1);
break;
default:
@@ -5332,6 +5338,7 @@ static int gfx_v11_0_set_powergating_state(void *handle,
case IP_VERSION(11, 0, 4):
case IP_VERSION(11, 5, 0):
case IP_VERSION(11, 5, 1):
+ case IP_VERSION(11, 5, 2):
if (!enable)
amdgpu_gfx_off_ctrl(adev, false);
@@ -5364,6 +5371,7 @@ static int gfx_v11_0_set_clockgating_state(void *handle,
case IP_VERSION(11, 0, 4):
case IP_VERSION(11, 5, 0):
case IP_VERSION(11, 5, 1):
+ case IP_VERSION(11, 5, 2):
gfx_v11_0_update_gfx_clock_gating(adev,
state == AMD_CG_STATE_GATE);
break;
@@ -5604,11 +5612,7 @@ static void gfx_v11_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr,
amdgpu_ring_write(ring, PACKET3(PACKET3_RELEASE_MEM, 6));
amdgpu_ring_write(ring, (PACKET3_RELEASE_MEM_GCR_SEQ |
PACKET3_RELEASE_MEM_GCR_GL2_WB |
- PACKET3_RELEASE_MEM_GCR_GL2_INV |
- PACKET3_RELEASE_MEM_GCR_GL2_US |
- PACKET3_RELEASE_MEM_GCR_GL1_INV |
- PACKET3_RELEASE_MEM_GCR_GLV_INV |
- PACKET3_RELEASE_MEM_GCR_GLM_INV |
+ PACKET3_RELEASE_MEM_GCR_GLM_INV | /* must be set with GLM_WB */
PACKET3_RELEASE_MEM_GCR_GLM_WB |
PACKET3_RELEASE_MEM_CACHE_POLICY(3) |
PACKET3_RELEASE_MEM_EVENT_TYPE(CACHE_FLUSH_AND_INV_TS_EVENT) |
@@ -6405,6 +6409,7 @@ static void gfx_v11_ip_print(void *handle, struct drm_printer *p)
if (!adev->gfx.ip_dump_gfx_queues)
return;
+ index = 0;
reg_count = ARRAY_SIZE(gc_gfx_queue_reg_list_11);
drm_printf(p, "\nnum_me: %d num_pipe: %d num_queue: %d\n",
adev->gfx.me.num_me,
@@ -6451,7 +6456,7 @@ static void gfx_v11_ip_dump(void *handle)
for (j = 0; j < adev->gfx.mec.num_pipe_per_mec; j++) {
for (k = 0; k < adev->gfx.mec.num_queue_per_pipe; k++) {
/* ME0 is for GFX so start from 1 for CP */
- soc21_grbm_select(adev, 1+i, j, k, 0);
+ soc21_grbm_select(adev, adev->gfx.me.num_me + i, j, k, 0);
for (reg = 0; reg < reg_count; reg++) {
adev->gfx.ip_dump_compute_queues[index + reg] =
RREG32(SOC15_REG_ENTRY_OFFSET(
@@ -6469,6 +6474,7 @@ static void gfx_v11_ip_dump(void *handle)
if (!adev->gfx.ip_dump_gfx_queues)
return;
+ index = 0;
reg_count = ARRAY_SIZE(gc_gfx_queue_reg_list_11);
amdgpu_gfx_off_ctrl(adev, false);
mutex_lock(&adev->srbm_mutex);
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0_3.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0_3.c
index 9e7ce1e6bc06..9cd221ed240c 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0_3.c
@@ -85,6 +85,7 @@ static int gfx_v11_0_3_poison_consumption_handler(struct amdgpu_device *adev,
if (entry && (entry->client_id == SOC21_IH_CLIENTID_GFX) &&
(entry->src_id == GFX_11_0_0__SRCID__RLC_GC_FED_INTERRUPT) &&
!entry->vmid && !entry->pasid) {
+ struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
uint32_t rlc_status0 = 0;
rlc_status0 = RREG32_SOC15(GC, 0, regRLC_RLCS_FED_STATUS_0);
@@ -96,7 +97,8 @@ static int gfx_v11_0_3_poison_consumption_handler(struct amdgpu_device *adev,
ras->gpu_reset_flags |= AMDGPU_RAS_GPU_RESET_MODE2_RESET;
}
- amdgpu_ras_reset_gpu(adev);
+ if (con && !con->is_rma)
+ amdgpu_ras_reset_gpu(adev);
}
return 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
index 6419f98e32b6..f384be0d1800 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
@@ -63,6 +63,145 @@ MODULE_FIRMWARE("amdgpu/gc_12_0_1_mec.bin");
MODULE_FIRMWARE("amdgpu/gc_12_0_1_rlc.bin");
MODULE_FIRMWARE("amdgpu/gc_12_0_1_toc.bin");
+static const struct amdgpu_hwip_reg_entry gc_reg_list_12_0[] = {
+ SOC15_REG_ENTRY_STR(GC, 0, regGRBM_STATUS),
+ SOC15_REG_ENTRY_STR(GC, 0, regGRBM_STATUS2),
+ SOC15_REG_ENTRY_STR(GC, 0, regGRBM_STATUS3),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_STALLED_STAT1),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_STALLED_STAT2),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_STALLED_STAT3),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_CPC_STALLED_STAT1),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_CPF_STALLED_STAT1),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_BUSY_STAT),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_CPC_BUSY_STAT),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_CPF_BUSY_STAT),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_CPC_BUSY_STAT2),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_CPF_BUSY_STAT2),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_CPF_STATUS),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_GFX_ERROR),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_GFX_HPD_STATUS0),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_RB_BASE),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_RB_RPTR),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_RB_WPTR),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_RB0_BASE),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_RB0_RPTR),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_RB0_WPTR),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_IB1_CMD_BUFSZ),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_IB2_CMD_BUFSZ),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_IB1_BASE_LO),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_IB1_BASE_HI),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_IB1_BUFSZ),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_IB2_BASE_LO),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_IB2_BASE_HI),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_IB2_BUFSZ),
+ SOC15_REG_ENTRY_STR(GC, 0, regCPF_UTCL1_STATUS),
+ SOC15_REG_ENTRY_STR(GC, 0, regCPC_UTCL1_STATUS),
+ SOC15_REG_ENTRY_STR(GC, 0, regCPG_UTCL1_STATUS),
+ SOC15_REG_ENTRY_STR(GC, 0, regIA_UTCL1_STATUS),
+ SOC15_REG_ENTRY_STR(GC, 0, regIA_UTCL1_STATUS_2),
+ SOC15_REG_ENTRY_STR(GC, 0, regPA_CL_CNTL_STATUS),
+ SOC15_REG_ENTRY_STR(GC, 0, regRMI_UTCL1_STATUS),
+ SOC15_REG_ENTRY_STR(GC, 0, regSQC_CACHES),
+ SOC15_REG_ENTRY_STR(GC, 0, regSQG_STATUS),
+ SOC15_REG_ENTRY_STR(GC, 0, regWD_UTCL1_STATUS),
+ SOC15_REG_ENTRY_STR(GC, 0, regGCVM_L2_PROTECTION_FAULT_CNTL),
+ SOC15_REG_ENTRY_STR(GC, 0, regGCVM_L2_PROTECTION_FAULT_STATUS_LO32),
+ SOC15_REG_ENTRY_STR(GC, 0, regGCVM_L2_PROTECTION_FAULT_STATUS_HI32),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_DEBUG),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_MEC_CNTL),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_MES_CNTL),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_MES_INSTR_PNTR),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_ME_INSTR_PNTR),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_PFP_INSTR_PNTR),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_CPC_STATUS),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_GFX_RS64_INSTR_PNTR0),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_GFX_RS64_INSTR_PNTR1),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_MEC_RS64_INSTR_PNTR),
+
+ /* cp header registers */
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_MEC_ME1_HEADER_DUMP),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_PFP_HEADER_DUMP),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_ME_HEADER_DUMP),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_MES_HEADER_DUMP),
+ /* SE status registers */
+ SOC15_REG_ENTRY_STR(GC, 0, regGRBM_STATUS_SE0),
+ SOC15_REG_ENTRY_STR(GC, 0, regGRBM_STATUS_SE1),
+ SOC15_REG_ENTRY_STR(GC, 0, regGRBM_STATUS_SE2),
+ SOC15_REG_ENTRY_STR(GC, 0, regGRBM_STATUS_SE3)
+};
+
+static const struct amdgpu_hwip_reg_entry gc_cp_reg_list_12[] = {
+ /* compute registers */
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_VMID),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_PERSISTENT_STATE),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_PIPE_PRIORITY),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_QUEUE_PRIORITY),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_QUANTUM),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_PQ_BASE),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_PQ_BASE_HI),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_PQ_RPTR),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_PQ_WPTR_POLL_ADDR),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_PQ_WPTR_POLL_ADDR_HI),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_PQ_DOORBELL_CONTROL),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_PQ_CONTROL),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_IB_BASE_ADDR),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_IB_BASE_ADDR_HI),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_IB_RPTR),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_IB_CONTROL),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_DEQUEUE_REQUEST),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_EOP_BASE_ADDR),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_EOP_BASE_ADDR_HI),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_EOP_CONTROL),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_EOP_RPTR),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_EOP_WPTR),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_EOP_EVENTS),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_CTX_SAVE_BASE_ADDR_LO),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_CTX_SAVE_BASE_ADDR_HI),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_CTX_SAVE_CONTROL),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_CNTL_STACK_OFFSET),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_CNTL_STACK_SIZE),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_WG_STATE_OFFSET),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_CTX_SAVE_SIZE),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_GDS_RESOURCE_STATE),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_ERROR),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_EOP_WPTR_MEM),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_PQ_WPTR_LO),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_PQ_WPTR_HI),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_SUSPEND_CNTL_STACK_OFFSET),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_SUSPEND_CNTL_STACK_DW_CNT),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_SUSPEND_WG_STATE_OFFSET),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_DEQUEUE_STATUS)
+};
+
+static const struct amdgpu_hwip_reg_entry gc_gfx_queue_reg_list_12[] = {
+ /* gfx queue registers */
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_GFX_HQD_ACTIVE),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_GFX_HQD_VMID),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_GFX_HQD_QUEUE_PRIORITY),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_GFX_HQD_QUANTUM),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_GFX_HQD_BASE),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_GFX_HQD_BASE_HI),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_GFX_HQD_OFFSET),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_GFX_HQD_CNTL),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_GFX_HQD_CSMD_RPTR),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_GFX_HQD_WPTR),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_GFX_HQD_WPTR_HI),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_GFX_HQD_DEQUEUE_REQUEST),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_GFX_HQD_MAPPED),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_GFX_HQD_QUE_MGR_CONTROL),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_GFX_HQD_HQ_CONTROL0),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_GFX_HQD_HQ_STATUS0),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_GFX_MQD_BASE_ADDR),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_GFX_MQD_BASE_ADDR_HI),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_RB_WPTR_POLL_ADDR_LO),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_RB_WPTR_POLL_ADDR_HI),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_RB_RPTR),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_IB1_BASE_LO),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_IB1_BASE_HI),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_IB1_CMD_BUFSZ),
+ SOC15_REG_ENTRY_STR(GC, 0, regCP_IB1_BUFSZ)
+};
+
#define DEFAULT_SH_MEM_CONFIG \
((SH_MEM_ADDRESS_MODE_64 << SH_MEM_CONFIG__ADDRESS_MODE__SHIFT) | \
(SH_MEM_ALIGNMENT_MODE_UNALIGNED << SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT) | \
@@ -386,10 +525,9 @@ static int gfx_v12_0_init_toc_microcode(struct amdgpu_device *adev, const char *
{
const struct psp_firmware_header_v1_0 *toc_hdr;
int err = 0;
- char fw_name[40];
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_toc.bin", ucode_prefix);
- err = amdgpu_ucode_request(adev, &adev->psp.toc_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->psp.toc_fw,
+ "amdgpu/%s_toc.bin", ucode_prefix);
if (err)
goto out;
@@ -407,7 +545,6 @@ out:
static int gfx_v12_0_init_microcode(struct amdgpu_device *adev)
{
- char fw_name[40];
char ucode_prefix[15];
int err;
const struct rlc_firmware_header_v2_0 *rlc_hdr;
@@ -418,23 +555,23 @@ static int gfx_v12_0_init_microcode(struct amdgpu_device *adev)
amdgpu_ucode_ip_version_decode(adev, GC_HWIP, ucode_prefix, sizeof(ucode_prefix));
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_pfp.bin", ucode_prefix);
- err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw,
+ "amdgpu/%s_pfp.bin", ucode_prefix);
if (err)
goto out;
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_RS64_PFP);
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_RS64_PFP_P0_STACK);
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_me.bin", ucode_prefix);
- err = amdgpu_ucode_request(adev, &adev->gfx.me_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.me_fw,
+ "amdgpu/%s_me.bin", ucode_prefix);
if (err)
goto out;
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_RS64_ME);
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_RS64_ME_P0_STACK);
if (!amdgpu_sriov_vf(adev)) {
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_rlc.bin", ucode_prefix);
- err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw,
+ "amdgpu/%s_rlc.bin", ucode_prefix);
if (err)
goto out;
rlc_hdr = (const struct rlc_firmware_header_v2_0 *)adev->gfx.rlc_fw->data;
@@ -445,8 +582,8 @@ static int gfx_v12_0_init_microcode(struct amdgpu_device *adev)
goto out;
}
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec.bin", ucode_prefix);
- err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw,
+ "amdgpu/%s_mec.bin", ucode_prefix);
if (err)
goto out;
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_RS64_MEC);
@@ -1131,6 +1268,47 @@ static int gfx_v12_0_rlc_backdoor_autoload_enable(struct amdgpu_device *adev)
return 0;
}
+static void gfx_v12_0_alloc_ip_dump(struct amdgpu_device *adev)
+{
+ uint32_t reg_count = ARRAY_SIZE(gc_reg_list_12_0);
+ uint32_t *ptr;
+ uint32_t inst;
+
+ ptr = kcalloc(reg_count, sizeof(uint32_t), GFP_KERNEL);
+ if (ptr == NULL) {
+ DRM_ERROR("Failed to allocate memory for GFX IP Dump\n");
+ adev->gfx.ip_dump_core = NULL;
+ } else {
+ adev->gfx.ip_dump_core = ptr;
+ }
+
+ /* Allocate memory for compute queue registers for all the instances */
+ reg_count = ARRAY_SIZE(gc_cp_reg_list_12);
+ inst = adev->gfx.mec.num_mec * adev->gfx.mec.num_pipe_per_mec *
+ adev->gfx.mec.num_queue_per_pipe;
+
+ ptr = kcalloc(reg_count * inst, sizeof(uint32_t), GFP_KERNEL);
+ if (ptr == NULL) {
+ DRM_ERROR("Failed to allocate memory for Compute Queues IP Dump\n");
+ adev->gfx.ip_dump_compute_queues = NULL;
+ } else {
+ adev->gfx.ip_dump_compute_queues = ptr;
+ }
+
+ /* Allocate memory for gfx queue registers for all the instances */
+ reg_count = ARRAY_SIZE(gc_gfx_queue_reg_list_12);
+ inst = adev->gfx.me.num_me * adev->gfx.me.num_pipe_per_me *
+ adev->gfx.me.num_queue_per_pipe;
+
+ ptr = kcalloc(reg_count * inst, sizeof(uint32_t), GFP_KERNEL);
+ if (ptr == NULL) {
+ DRM_ERROR("Failed to allocate memory for GFX Queues IP Dump\n");
+ adev->gfx.ip_dump_gfx_queues = NULL;
+ } else {
+ adev->gfx.ip_dump_gfx_queues = ptr;
+ }
+}
+
static int gfx_v12_0_sw_init(void *handle)
{
int i, j, k, r, ring_id = 0;
@@ -1263,6 +1441,8 @@ static int gfx_v12_0_sw_init(void *handle)
if (r)
return r;
+ gfx_v12_0_alloc_ip_dump(adev);
+
return 0;
}
@@ -1322,6 +1502,10 @@ static int gfx_v12_0_sw_fini(void *handle)
gfx_v12_0_free_microcode(adev);
+ kfree(adev->gfx.ip_dump_core);
+ kfree(adev->gfx.ip_dump_compute_queues);
+ kfree(adev->gfx.ip_dump_gfx_queues);
+
return 0;
}
@@ -3192,7 +3376,9 @@ static int gfx_v12_0_gfxhub_enable(struct amdgpu_device *adev)
false : true;
adev->gfxhub.funcs->set_fault_enable_default(adev, value);
- amdgpu_gmc_flush_gpu_tlb(adev, 0, AMDGPU_GFXHUB(0), 0);
+ /* TODO investigate why this and the hdp flush above is needed,
+ * are we missing a flush somewhere else? */
+ adev->gmc.gmc_funcs->flush_gpu_tlb(adev, 0, AMDGPU_GFXHUB(0), 0);
return 0;
}
@@ -3306,11 +3492,9 @@ static int gfx_v12_0_hw_init(void *handle)
* loaded firstly, so in direct type, it has to load smc ucode
* here before rlc.
*/
- if (!(adev->flags & AMD_IS_APU)) {
- r = amdgpu_pm_load_smu_firmware(adev, NULL);
- if (r)
- return r;
- }
+ r = amdgpu_pm_load_smu_firmware(adev, NULL);
+ if (r)
+ return r;
}
gfx_v12_0_constants_init(adev);
@@ -4108,21 +4292,6 @@ static void gfx_v12_0_ring_emit_ib_compute(struct amdgpu_ring *ring,
/* inherit vmid from mqd */
control |= 0x40000000;
- /* Currently, there is a high possibility to get wave ID mismatch
- * between ME and GDS, leading to a hw deadlock, because ME generates
- * different wave IDs than the GDS expects. This situation happens
- * randomly when at least 5 compute pipes use GDS ordered append.
- * The wave IDs generated by ME are also wrong after suspend/resume.
- * Those are probably bugs somewhere else in the kernel driver.
- *
- * Writing GDS_COMPUTE_MAX_WAVE_ID resets wave ID counters in ME and
- * GDS to 0 for this ring (me/pipe).
- */
- if (ib->flags & AMDGPU_IB_FLAG_RESET_GDS_MAX_WAVE_ID) {
- amdgpu_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1));
- amdgpu_ring_write(ring, regGDS_COMPUTE_MAX_WAVE_ID);
- }
-
amdgpu_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2));
BUG_ON(ib->gpu_addr & 0x3); /* Dword align */
amdgpu_ring_write(ring,
@@ -4144,12 +4313,6 @@ static void gfx_v12_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr,
amdgpu_ring_write(ring, PACKET3(PACKET3_RELEASE_MEM, 6));
amdgpu_ring_write(ring, (PACKET3_RELEASE_MEM_GCR_SEQ |
PACKET3_RELEASE_MEM_GCR_GL2_WB |
- PACKET3_RELEASE_MEM_GCR_GL2_INV |
- PACKET3_RELEASE_MEM_GCR_GL2_US |
- PACKET3_RELEASE_MEM_GCR_GL1_INV |
- PACKET3_RELEASE_MEM_GCR_GLV_INV |
- PACKET3_RELEASE_MEM_GCR_GLM_INV |
- PACKET3_RELEASE_MEM_GCR_GLM_WB |
PACKET3_RELEASE_MEM_CACHE_POLICY(3) |
PACKET3_RELEASE_MEM_EVENT_TYPE(CACHE_FLUSH_AND_INV_TS_EVENT) |
PACKET3_RELEASE_MEM_EVENT_INDEX(5)));
@@ -4694,6 +4857,136 @@ static void gfx_v12_0_emit_mem_sync(struct amdgpu_ring *ring)
amdgpu_ring_write(ring, gcr_cntl); /* GCR_CNTL */
}
+static void gfx_v12_ip_print(void *handle, struct drm_printer *p)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ uint32_t i, j, k, reg, index = 0;
+ uint32_t reg_count = ARRAY_SIZE(gc_reg_list_12_0);
+
+ if (!adev->gfx.ip_dump_core)
+ return;
+
+ for (i = 0; i < reg_count; i++)
+ drm_printf(p, "%-50s \t 0x%08x\n",
+ gc_reg_list_12_0[i].reg_name,
+ adev->gfx.ip_dump_core[i]);
+
+ /* print compute queue registers for all instances */
+ if (!adev->gfx.ip_dump_compute_queues)
+ return;
+
+ reg_count = ARRAY_SIZE(gc_cp_reg_list_12);
+ drm_printf(p, "\nnum_mec: %d num_pipe: %d num_queue: %d\n",
+ adev->gfx.mec.num_mec,
+ adev->gfx.mec.num_pipe_per_mec,
+ adev->gfx.mec.num_queue_per_pipe);
+
+ for (i = 0; i < adev->gfx.mec.num_mec; i++) {
+ for (j = 0; j < adev->gfx.mec.num_pipe_per_mec; j++) {
+ for (k = 0; k < adev->gfx.mec.num_queue_per_pipe; k++) {
+ drm_printf(p, "\nmec %d, pipe %d, queue %d\n", i, j, k);
+ for (reg = 0; reg < reg_count; reg++) {
+ drm_printf(p, "%-50s \t 0x%08x\n",
+ gc_cp_reg_list_12[reg].reg_name,
+ adev->gfx.ip_dump_compute_queues[index + reg]);
+ }
+ index += reg_count;
+ }
+ }
+ }
+
+ /* print gfx queue registers for all instances */
+ if (!adev->gfx.ip_dump_gfx_queues)
+ return;
+
+ index = 0;
+ reg_count = ARRAY_SIZE(gc_gfx_queue_reg_list_12);
+ drm_printf(p, "\nnum_me: %d num_pipe: %d num_queue: %d\n",
+ adev->gfx.me.num_me,
+ adev->gfx.me.num_pipe_per_me,
+ adev->gfx.me.num_queue_per_pipe);
+
+ for (i = 0; i < adev->gfx.me.num_me; i++) {
+ for (j = 0; j < adev->gfx.me.num_pipe_per_me; j++) {
+ for (k = 0; k < adev->gfx.me.num_queue_per_pipe; k++) {
+ drm_printf(p, "\nme %d, pipe %d, queue %d\n", i, j, k);
+ for (reg = 0; reg < reg_count; reg++) {
+ drm_printf(p, "%-50s \t 0x%08x\n",
+ gc_gfx_queue_reg_list_12[reg].reg_name,
+ adev->gfx.ip_dump_gfx_queues[index + reg]);
+ }
+ index += reg_count;
+ }
+ }
+ }
+}
+
+static void gfx_v12_ip_dump(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ uint32_t i, j, k, reg, index = 0;
+ uint32_t reg_count = ARRAY_SIZE(gc_reg_list_12_0);
+
+ if (!adev->gfx.ip_dump_core)
+ return;
+
+ amdgpu_gfx_off_ctrl(adev, false);
+ for (i = 0; i < reg_count; i++)
+ adev->gfx.ip_dump_core[i] = RREG32(SOC15_REG_ENTRY_OFFSET(gc_reg_list_12_0[i]));
+ amdgpu_gfx_off_ctrl(adev, true);
+
+ /* dump compute queue registers for all instances */
+ if (!adev->gfx.ip_dump_compute_queues)
+ return;
+
+ reg_count = ARRAY_SIZE(gc_cp_reg_list_12);
+ amdgpu_gfx_off_ctrl(adev, false);
+ mutex_lock(&adev->srbm_mutex);
+ for (i = 0; i < adev->gfx.mec.num_mec; i++) {
+ for (j = 0; j < adev->gfx.mec.num_pipe_per_mec; j++) {
+ for (k = 0; k < adev->gfx.mec.num_queue_per_pipe; k++) {
+ /* ME0 is for GFX so start from 1 for CP */
+ soc24_grbm_select(adev, adev->gfx.me.num_me + i, j, k, 0);
+ for (reg = 0; reg < reg_count; reg++) {
+ adev->gfx.ip_dump_compute_queues[index + reg] =
+ RREG32(SOC15_REG_ENTRY_OFFSET(
+ gc_cp_reg_list_12[reg]));
+ }
+ index += reg_count;
+ }
+ }
+ }
+ soc24_grbm_select(adev, 0, 0, 0, 0);
+ mutex_unlock(&adev->srbm_mutex);
+ amdgpu_gfx_off_ctrl(adev, true);
+
+ /* dump gfx queue registers for all instances */
+ if (!adev->gfx.ip_dump_gfx_queues)
+ return;
+
+ index = 0;
+ reg_count = ARRAY_SIZE(gc_gfx_queue_reg_list_12);
+ amdgpu_gfx_off_ctrl(adev, false);
+ mutex_lock(&adev->srbm_mutex);
+ for (i = 0; i < adev->gfx.me.num_me; i++) {
+ for (j = 0; j < adev->gfx.me.num_pipe_per_me; j++) {
+ for (k = 0; k < adev->gfx.me.num_queue_per_pipe; k++) {
+ soc24_grbm_select(adev, i, j, k, 0);
+
+ for (reg = 0; reg < reg_count; reg++) {
+ adev->gfx.ip_dump_gfx_queues[index + reg] =
+ RREG32(SOC15_REG_ENTRY_OFFSET(
+ gc_gfx_queue_reg_list_12[reg]));
+ }
+ index += reg_count;
+ }
+ }
+ }
+ soc24_grbm_select(adev, 0, 0, 0, 0);
+ mutex_unlock(&adev->srbm_mutex);
+ amdgpu_gfx_off_ctrl(adev, true);
+}
+
static const struct amd_ip_funcs gfx_v12_0_ip_funcs = {
.name = "gfx_v12_0",
.early_init = gfx_v12_0_early_init,
@@ -4709,6 +5002,8 @@ static const struct amd_ip_funcs gfx_v12_0_ip_funcs = {
.set_clockgating_state = gfx_v12_0_set_clockgating_state,
.set_powergating_state = gfx_v12_0_set_powergating_state,
.get_clockgating_state = gfx_v12_0_get_clockgating_state,
+ .dump_ip_state = gfx_v12_ip_dump,
+ .print_ip_state = gfx_v12_ip_print,
};
static const struct amdgpu_ring_funcs gfx_v12_0_ring_funcs_gfx = {
@@ -4727,7 +5022,6 @@ static const struct amdgpu_ring_funcs gfx_v12_0_ring_funcs_gfx = {
SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 +
2 + /* VM_FLUSH */
8 + /* FENCE for VM_FLUSH */
- 20 + /* GDS switch */
5 + /* COND_EXEC */
7 + /* HDP_flush */
4 + /* VGT_flush */
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
index d0992ce9fb47..564f0b9336b6 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
@@ -311,7 +311,6 @@ static const u32 verde_rlc_save_restore_register_list[] =
static int gfx_v6_0_init_microcode(struct amdgpu_device *adev)
{
const char *chip_name;
- char fw_name[30];
int err;
const struct gfx_firmware_header_v1_0 *cp_hdr;
const struct rlc_firmware_header_v1_0 *rlc_hdr;
@@ -337,32 +336,32 @@ static int gfx_v6_0_init_microcode(struct amdgpu_device *adev)
default: BUG();
}
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_pfp.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw,
+ "amdgpu/%s_pfp.bin", chip_name);
if (err)
goto out;
cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.pfp_fw->data;
adev->gfx.pfp_fw_version = le32_to_cpu(cp_hdr->header.ucode_version);
adev->gfx.pfp_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version);
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_me.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->gfx.me_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.me_fw,
+ "amdgpu/%s_me.bin", chip_name);
if (err)
goto out;
cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.me_fw->data;
adev->gfx.me_fw_version = le32_to_cpu(cp_hdr->header.ucode_version);
adev->gfx.me_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version);
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ce.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->gfx.ce_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.ce_fw,
+ "amdgpu/%s_ce.bin", chip_name);
if (err)
goto out;
cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.ce_fw->data;
adev->gfx.ce_fw_version = le32_to_cpu(cp_hdr->header.ucode_version);
adev->gfx.ce_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version);
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_rlc.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw,
+ "amdgpu/%s_rlc.bin", chip_name);
if (err)
goto out;
rlc_hdr = (const struct rlc_firmware_header_v1_0 *)adev->gfx.rlc_fw->data;
@@ -371,7 +370,7 @@ static int gfx_v6_0_init_microcode(struct amdgpu_device *adev)
out:
if (err) {
- pr_err("gfx6: Failed to load firmware \"%s\"\n", fw_name);
+ pr_err("gfx6: Failed to load firmware %s gfx firmware\n", chip_name);
amdgpu_ucode_release(&adev->gfx.pfp_fw);
amdgpu_ucode_release(&adev->gfx.me_fw);
amdgpu_ucode_release(&adev->gfx.ce_fw);
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
index 8f19b6ae8d5b..d84589137df9 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
@@ -909,7 +909,6 @@ static void gfx_v7_0_free_microcode(struct amdgpu_device *adev)
static int gfx_v7_0_init_microcode(struct amdgpu_device *adev)
{
const char *chip_name;
- char fw_name[30];
int err;
DRM_DEBUG("\n");
@@ -934,38 +933,38 @@ static int gfx_v7_0_init_microcode(struct amdgpu_device *adev)
BUG();
}
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_pfp.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw,
+ "amdgpu/%s_pfp.bin", chip_name);
if (err)
goto out;
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_me.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->gfx.me_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.me_fw,
+ "amdgpu/%s_me.bin", chip_name);
if (err)
goto out;
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ce.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->gfx.ce_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.ce_fw,
+ "amdgpu/%s_ce.bin", chip_name);
if (err)
goto out;
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw,
+ "amdgpu/%s_mec.bin", chip_name);
if (err)
goto out;
if (adev->asic_type == CHIP_KAVERI) {
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec2.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->gfx.mec2_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.mec2_fw,
+ "amdgpu/%s_mec2.bin", chip_name);
if (err)
goto out;
}
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_rlc.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw,
+ "amdgpu/%s_rlc.bin", chip_name);
out:
if (err) {
- pr_err("gfx7: Failed to load firmware \"%s\"\n", fw_name);
+ pr_err("gfx7: Failed to load firmware %s gfx firmware\n", chip_name);
gfx_v7_0_free_microcode(adev);
}
return err;
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
index 2f0e72caee1a..b4658c7db0e1 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
@@ -939,7 +939,6 @@ static void gfx_v8_0_free_microcode(struct amdgpu_device *adev)
static int gfx_v8_0_init_microcode(struct amdgpu_device *adev)
{
const char *chip_name;
- char fw_name[30];
int err;
struct amdgpu_firmware_info *info = NULL;
const struct common_firmware_header *header = NULL;
@@ -982,15 +981,15 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev)
}
if (adev->asic_type >= CHIP_POLARIS10 && adev->asic_type <= CHIP_POLARIS12) {
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_pfp_2.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw,
+ "amdgpu/%s_pfp_2.bin", chip_name);
if (err == -ENODEV) {
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_pfp.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw,
+ "amdgpu/%s_pfp.bin", chip_name);
}
} else {
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_pfp.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw,
+ "amdgpu/%s_pfp.bin", chip_name);
}
if (err)
goto out;
@@ -999,15 +998,15 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev)
adev->gfx.pfp_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version);
if (adev->asic_type >= CHIP_POLARIS10 && adev->asic_type <= CHIP_POLARIS12) {
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_me_2.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->gfx.me_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.me_fw,
+ "amdgpu/%s_me_2.bin", chip_name);
if (err == -ENODEV) {
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_me.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->gfx.me_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.me_fw,
+ "amdgpu/%s_me.bin", chip_name);
}
} else {
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_me.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->gfx.me_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.me_fw,
+ "amdgpu/%s_me.bin", chip_name);
}
if (err)
goto out;
@@ -1017,15 +1016,15 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev)
adev->gfx.me_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version);
if (adev->asic_type >= CHIP_POLARIS10 && adev->asic_type <= CHIP_POLARIS12) {
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ce_2.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->gfx.ce_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.ce_fw,
+ "amdgpu/%s_ce_2.bin", chip_name);
if (err == -ENODEV) {
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ce.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->gfx.ce_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.ce_fw,
+ "amdgpu/%s_ce.bin", chip_name);
}
} else {
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ce.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->gfx.ce_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.ce_fw,
+ "amdgpu/%s_ce.bin", chip_name);
}
if (err)
goto out;
@@ -1044,8 +1043,8 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev)
} else
adev->virt.chained_ib_support = false;
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_rlc.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw,
+ "amdgpu/%s_rlc.bin", chip_name);
if (err)
goto out;
rlc_hdr = (const struct rlc_firmware_header_v2_0 *)adev->gfx.rlc_fw->data;
@@ -1093,15 +1092,15 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev)
adev->gfx.rlc.register_restore[i] = le32_to_cpu(tmp[i]);
if (adev->asic_type >= CHIP_POLARIS10 && adev->asic_type <= CHIP_POLARIS12) {
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec_2.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw,
+ "amdgpu/%s_mec_2.bin", chip_name);
if (err == -ENODEV) {
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw,
+ "amdgpu/%s_mec.bin", chip_name);
}
} else {
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw,
+ "amdgpu/%s_mec.bin", chip_name);
}
if (err)
goto out;
@@ -1112,15 +1111,15 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev)
if ((adev->asic_type != CHIP_STONEY) &&
(adev->asic_type != CHIP_TOPAZ)) {
if (adev->asic_type >= CHIP_POLARIS10 && adev->asic_type <= CHIP_POLARIS12) {
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec2_2.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->gfx.mec2_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.mec2_fw,
+ "amdgpu/%s_mec2_2.bin", chip_name);
if (err == -ENODEV) {
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec2.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->gfx.mec2_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.mec2_fw,
+ "amdgpu/%s_mec2.bin", chip_name);
}
} else {
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec2.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->gfx.mec2_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.mec2_fw,
+ "amdgpu/%s_mec2.bin", chip_name);
}
if (!err) {
cp_hdr = (const struct gfx_firmware_header_v1_0 *)
@@ -1194,9 +1193,7 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev)
out:
if (err) {
- dev_err(adev->dev,
- "gfx8: Failed to load firmware \"%s\"\n",
- fw_name);
+ dev_err(adev->dev, "gfx8: Failed to load firmware %s gfx firmware\n", chip_name);
amdgpu_ucode_release(&adev->gfx.pfp_fw);
amdgpu_ucode_release(&adev->gfx.me_fw);
amdgpu_ucode_release(&adev->gfx.ce_fw);
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
index ad99ee10fd4a..2929c8972ea7 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
@@ -1378,23 +1378,22 @@ static void gfx_v9_0_check_if_need_gfxoff(struct amdgpu_device *adev)
static int gfx_v9_0_init_cp_gfx_microcode(struct amdgpu_device *adev,
char *chip_name)
{
- char fw_name[50];
int err;
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_pfp.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw,
+ "amdgpu/%s_pfp.bin", chip_name);
if (err)
goto out;
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_PFP);
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_me.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->gfx.me_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.me_fw,
+ "amdgpu/%s_me.bin", chip_name);
if (err)
goto out;
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_ME);
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ce.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->gfx.ce_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.ce_fw,
+ "amdgpu/%s_ce.bin", chip_name);
if (err)
goto out;
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_CE);
@@ -1411,7 +1410,6 @@ out:
static int gfx_v9_0_init_rlc_microcode(struct amdgpu_device *adev,
char *chip_name)
{
- char fw_name[53];
int err;
const struct rlc_firmware_header_v2_0 *rlc_hdr;
uint16_t version_major;
@@ -1429,20 +1427,22 @@ static int gfx_v9_0_init_rlc_microcode(struct amdgpu_device *adev,
if (!strcmp(chip_name, "picasso") &&
(((adev->pdev->revision >= 0xC8) && (adev->pdev->revision <= 0xCF)) ||
((adev->pdev->revision >= 0xD8) && (adev->pdev->revision <= 0xDF))))
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_rlc_am4.bin", chip_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw,
+ "amdgpu/%s_rlc_am4.bin", chip_name);
else if (!strcmp(chip_name, "raven") && (amdgpu_pm_load_smu_firmware(adev, &smu_version) == 0) &&
(smu_version >= 0x41e2b))
/**
*SMC is loaded by SBIOS on APU and it's able to get the SMU version directly.
*/
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_kicker_rlc.bin", chip_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw,
+ "amdgpu/%s_kicker_rlc.bin", chip_name);
else
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_rlc.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw,
+ "amdgpu/%s_rlc.bin", chip_name);
if (err)
goto out;
- rlc_hdr = (const struct rlc_firmware_header_v2_0 *)adev->gfx.rlc_fw->data;
+ rlc_hdr = (const struct rlc_firmware_header_v2_0 *)adev->gfx.rlc_fw->data;
version_major = le16_to_cpu(rlc_hdr->header.header_version_major);
version_minor = le16_to_cpu(rlc_hdr->header.header_version_minor);
err = amdgpu_gfx_rlc_init_microcode(adev, version_major, version_minor);
@@ -1466,28 +1466,27 @@ static bool gfx_v9_0_load_mec2_fw_bin_support(struct amdgpu_device *adev)
static int gfx_v9_0_init_cp_compute_microcode(struct amdgpu_device *adev,
char *chip_name)
{
- char fw_name[50];
int err;
if (amdgpu_sriov_vf(adev) && (adev->asic_type == CHIP_ALDEBARAN))
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sjt_mec.bin", chip_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw,
+ "amdgpu/%s_sjt_mec.bin", chip_name);
else
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec.bin", chip_name);
-
- err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw,
+ "amdgpu/%s_mec.bin", chip_name);
if (err)
goto out;
+
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC1);
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC1_JT);
if (gfx_v9_0_load_mec2_fw_bin_support(adev)) {
if (amdgpu_sriov_vf(adev) && (adev->asic_type == CHIP_ALDEBARAN))
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sjt_mec2.bin", chip_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.mec2_fw,
+ "amdgpu/%s_sjt_mec2.bin", chip_name);
else
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec2.bin", chip_name);
-
- /* ignore failures to load */
- err = amdgpu_ucode_request(adev, &adev->gfx.mec2_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.mec2_fw,
+ "amdgpu/%s_mec2.bin", chip_name);
if (!err) {
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC2);
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC2_JT);
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
index aecc2bcea145..20ea6cb01edf 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
@@ -55,6 +55,14 @@ MODULE_FIRMWARE("amdgpu/gc_9_4_4_rlc.bin");
#define mmSMNAID_XCD1_MCA_SMU 0x38430400 /* SMN AID XCD1 */
#define mmSMNXCD_XCD0_MCA_SMU 0x40430400 /* SMN XCD XCD0 */
+#define XCC_REG_RANGE_0_LOW 0x2000 /* XCC gfxdec0 lower Bound */
+#define XCC_REG_RANGE_0_HIGH 0x3400 /* XCC gfxdec0 upper Bound */
+#define XCC_REG_RANGE_1_LOW 0xA000 /* XCC gfxdec1 lower Bound */
+#define XCC_REG_RANGE_1_HIGH 0x10000 /* XCC gfxdec1 upper Bound */
+
+#define NORMALIZE_XCC_REG_OFFSET(offset) \
+ (offset & 0xFFFF)
+
struct amdgpu_gfx_ras gfx_v9_4_3_ras;
static void gfx_v9_4_3_set_ring_funcs(struct amdgpu_device *adev);
@@ -217,9 +225,24 @@ static void gfx_v9_4_3_init_golden_registers(struct amdgpu_device *adev)
}
}
+static uint32_t gfx_v9_4_3_normalize_xcc_reg_offset(uint32_t reg)
+{
+ uint32_t normalized_reg = NORMALIZE_XCC_REG_OFFSET(reg);
+
+ /* If it is an XCC reg, normalize the reg to keep
+ lower 16 bits in local xcc */
+
+ if (((normalized_reg >= XCC_REG_RANGE_0_LOW) && (normalized_reg < XCC_REG_RANGE_0_HIGH)) ||
+ ((normalized_reg >= XCC_REG_RANGE_1_LOW) && (normalized_reg < XCC_REG_RANGE_1_HIGH)))
+ return normalized_reg;
+ else
+ return reg;
+}
+
static void gfx_v9_4_3_write_data_to_reg(struct amdgpu_ring *ring, int eng_sel,
bool wc, uint32_t reg, uint32_t val)
{
+ reg = gfx_v9_4_3_normalize_xcc_reg_offset(reg);
amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
amdgpu_ring_write(ring, WRITE_DATA_ENGINE_SEL(eng_sel) |
WRITE_DATA_DST_SEL(0) |
@@ -234,6 +257,12 @@ static void gfx_v9_4_3_wait_reg_mem(struct amdgpu_ring *ring, int eng_sel,
uint32_t addr1, uint32_t ref, uint32_t mask,
uint32_t inv)
{
+ /* Only do the normalization on regspace */
+ if (mem_space == 0) {
+ addr0 = gfx_v9_4_3_normalize_xcc_reg_offset(addr0);
+ addr1 = gfx_v9_4_3_normalize_xcc_reg_offset(addr1);
+ }
+
amdgpu_ring_write(ring, PACKET3(PACKET3_WAIT_REG_MEM, 5));
amdgpu_ring_write(ring,
/* memory (1) or register (0) */
@@ -372,15 +401,14 @@ static void gfx_v9_4_3_free_microcode(struct amdgpu_device *adev)
static int gfx_v9_4_3_init_rlc_microcode(struct amdgpu_device *adev,
const char *chip_name)
{
- char fw_name[30];
int err;
const struct rlc_firmware_header_v2_0 *rlc_hdr;
uint16_t version_major;
uint16_t version_minor;
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_rlc.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw,
+ "amdgpu/%s_rlc.bin", chip_name);
if (err)
goto out;
rlc_hdr = (const struct rlc_firmware_header_v2_0 *)adev->gfx.rlc_fw->data;
@@ -409,12 +437,10 @@ static void gfx_v9_4_3_check_if_need_gfxoff(struct amdgpu_device *adev)
static int gfx_v9_4_3_init_cp_compute_microcode(struct amdgpu_device *adev,
const char *chip_name)
{
- char fw_name[30];
int err;
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec.bin", chip_name);
-
- err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw,
+ "amdgpu/%s_mec.bin", chip_name);
if (err)
goto out;
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC1);
@@ -626,6 +652,15 @@ static void gfx_v9_4_3_select_me_pipe_q(struct amdgpu_device *adev,
soc15_grbm_select(adev, me, pipe, q, vm, GET_INST(GC, xcc_id));
}
+static int gfx_v9_4_3_get_xccs_per_xcp(struct amdgpu_device *adev)
+{
+ u32 xcp_ctl;
+
+ /* Value is expected to be the same on all, fetch from first instance */
+ xcp_ctl = RREG32_SOC15(GC, GET_INST(GC, 0), regCP_HYP_XCP_CTL);
+
+ return REG_GET_FIELD(xcp_ctl, CP_HYP_XCP_CTL, NUM_XCC_IN_XCP);
+}
static int gfx_v9_4_3_switch_compute_partition(struct amdgpu_device *adev,
int num_xccs_per_xcp)
@@ -680,6 +715,7 @@ static const struct amdgpu_gfx_funcs gfx_v9_4_3_gfx_funcs = {
.select_me_pipe_q = &gfx_v9_4_3_select_me_pipe_q,
.switch_partition_mode = &gfx_v9_4_3_switch_compute_partition,
.ih_node_to_logical_xcc = &gfx_v9_4_3_ih_to_xcc_inst,
+ .get_xccs_per_xcp = &gfx_v9_4_3_get_xccs_per_xcp,
};
static int gfx_v9_4_3_aca_bank_parser(struct aca_handle *handle,
@@ -1587,6 +1623,9 @@ static int gfx_v9_4_3_xcc_mqd_init(struct amdgpu_ring *ring, int xcc_id)
DOORBELL_SOURCE, 0);
tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL,
DOORBELL_HIT, 0);
+ if (amdgpu_sriov_vf(adev))
+ tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL,
+ DOORBELL_MODE, 1);
} else {
tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL,
DOORBELL_EN, 0);
@@ -2021,18 +2060,31 @@ static int gfx_v9_4_3_xcc_cp_resume(struct amdgpu_device *adev, int xcc_id)
static int gfx_v9_4_3_cp_resume(struct amdgpu_device *adev)
{
- int r = 0, i, num_xcc;
+ int r = 0, i, num_xcc, num_xcp, num_xcc_per_xcp;
+
+ num_xcc = NUM_XCC(adev->gfx.xcc_mask);
+ if (amdgpu_sriov_vf(adev)) {
+ enum amdgpu_gfx_partition mode;
- if (amdgpu_xcp_query_partition_mode(adev->xcp_mgr,
- AMDGPU_XCP_FL_NONE) ==
- AMDGPU_UNKNOWN_COMPUTE_PARTITION_MODE)
- r = amdgpu_xcp_switch_partition_mode(adev->xcp_mgr,
- amdgpu_user_partt_mode);
+ mode = amdgpu_xcp_query_partition_mode(adev->xcp_mgr,
+ AMDGPU_XCP_FL_NONE);
+ if (mode == AMDGPU_UNKNOWN_COMPUTE_PARTITION_MODE)
+ return -EINVAL;
+ num_xcc_per_xcp = gfx_v9_4_3_get_xccs_per_xcp(adev);
+ adev->gfx.num_xcc_per_xcp = num_xcc_per_xcp;
+ num_xcp = num_xcc / num_xcc_per_xcp;
+ r = amdgpu_xcp_init(adev->xcp_mgr, num_xcp, mode);
+ } else {
+ if (amdgpu_xcp_query_partition_mode(adev->xcp_mgr,
+ AMDGPU_XCP_FL_NONE) ==
+ AMDGPU_UNKNOWN_COMPUTE_PARTITION_MODE)
+ r = amdgpu_xcp_switch_partition_mode(
+ adev->xcp_mgr, amdgpu_user_partt_mode);
+ }
if (r)
return r;
- num_xcc = NUM_XCC(adev->gfx.xcc_mask);
for (i = 0; i < num_xcc; i++) {
r = gfx_v9_4_3_xcc_cp_resume(adev, i);
if (r)
@@ -2728,6 +2780,8 @@ static void gfx_v9_4_3_ring_emit_rreg(struct amdgpu_ring *ring, uint32_t reg,
{
struct amdgpu_device *adev = ring->adev;
+ reg = gfx_v9_4_3_normalize_xcc_reg_offset(reg);
+
amdgpu_ring_write(ring, PACKET3(PACKET3_COPY_DATA, 4));
amdgpu_ring_write(ring, 0 | /* src: register*/
(5 << 8) | /* dst: memory */
@@ -2745,6 +2799,8 @@ static void gfx_v9_4_3_ring_emit_wreg(struct amdgpu_ring *ring, uint32_t reg,
{
uint32_t cmd = 0;
+ reg = gfx_v9_4_3_normalize_xcc_reg_offset(reg);
+
switch (ring->funcs->type) {
case AMDGPU_RING_TYPE_GFX:
cmd = WRITE_DATA_ENGINE_SEL(1) | WR_CONFIRM;
@@ -4203,9 +4259,10 @@ static u32 gfx_v9_4_3_get_cu_active_bitmap(struct amdgpu_device *adev, int xcc_i
static int gfx_v9_4_3_get_cu_info(struct amdgpu_device *adev,
struct amdgpu_cu_info *cu_info)
{
- int i, j, k, counter, xcc_id, active_cu_number = 0;
- u32 mask, bitmap, ao_bitmap, ao_cu_mask = 0;
+ int i, j, k, prev_counter, counter, xcc_id, active_cu_number = 0;
+ u32 mask, bitmap, ao_bitmap, ao_cu_mask = 0, tmp;
unsigned disable_masks[4 * 4];
+ bool is_symmetric_cus;
if (!adev || !cu_info)
return -EINVAL;
@@ -4223,6 +4280,7 @@ static int gfx_v9_4_3_get_cu_info(struct amdgpu_device *adev,
mutex_lock(&adev->grbm_idx_mutex);
for (xcc_id = 0; xcc_id < NUM_XCC(adev->gfx.xcc_mask); xcc_id++) {
+ is_symmetric_cus = true;
for (i = 0; i < adev->gfx.config.max_shader_engines; i++) {
for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) {
mask = 1;
@@ -4250,6 +4308,15 @@ static int gfx_v9_4_3_get_cu_info(struct amdgpu_device *adev,
ao_cu_mask |= (ao_bitmap << (i * 16 + j * 8));
cu_info->ao_cu_bitmap[i][j] = ao_bitmap;
}
+ if (i && is_symmetric_cus && prev_counter != counter)
+ is_symmetric_cus = false;
+ prev_counter = counter;
+ }
+ if (is_symmetric_cus) {
+ tmp = RREG32_SOC15(GC, GET_INST(GC, xcc_id), regCP_CPC_DEBUG);
+ tmp = REG_SET_FIELD(tmp, CP_CPC_DEBUG, CPC_HARVESTING_RELAUNCH_DISABLE, 1);
+ tmp = REG_SET_FIELD(tmp, CP_CPC_DEBUG, CPC_HARVESTING_DISPATCH_DISABLE, 1);
+ WREG32_SOC15(GC, GET_INST(GC, xcc_id), regCP_CPC_DEBUG, tmp);
}
gfx_v9_4_3_xcc_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff,
xcc_id);
diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v12_0.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v12_0.c
index 7ea64f1e1e48..7609b9cecae8 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v12_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v12_0.c
@@ -35,7 +35,27 @@
#define regGRBM_GFX_INDEX_DEFAULT 0xe0000000
static const char *gfxhub_client_ids[] = {
- /* TODO */
+ "CB",
+ "DB",
+ "GE1",
+ "GE2",
+ "CPF",
+ "CPC",
+ "CPG",
+ "RLC",
+ "TCP",
+ "SQC (inst)",
+ "SQC (data)",
+ "SQG/PC/SC",
+ "Reserved",
+ "SDMA0",
+ "SDMA1",
+ "GCR",
+ "Reserved",
+ "Reserved",
+ "WGS",
+ "DSM",
+ "PA"
};
static uint32_t gfxhub_v12_0_get_invalidate_req(unsigned int vmid,
diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_2.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_2.c
index e14acab5cceb..72109abe7c86 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_2.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_2.c
@@ -629,9 +629,11 @@ static bool gfxhub_v1_2_query_utcl2_poison_status(struct amdgpu_device *adev,
status = RREG32_SOC15(GC, GET_INST(GC, xcc_id), regVM_L2_PROTECTION_FAULT_STATUS);
fed = REG_GET_FIELD(status, VM_L2_PROTECTION_FAULT_STATUS, FED);
- /* reset page fault status */
- WREG32_P(SOC15_REG_OFFSET(GC, GET_INST(GC, xcc_id),
- regVM_L2_PROTECTION_FAULT_STATUS), 1, ~1);
+ if (!amdgpu_sriov_vf(adev)) {
+ /* clear page fault status and address */
+ WREG32_P(SOC15_REG_OFFSET(GC, GET_INST(GC, xcc_id),
+ regVM_L2_PROTECTION_FAULT_CNTL), 1, ~1);
+ }
return fed;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
index cad883783834..b88a6fa173b3 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
@@ -592,6 +592,7 @@ static void gmc_v11_0_set_gfxhub_funcs(struct amdgpu_device *adev)
break;
case IP_VERSION(11, 5, 0):
case IP_VERSION(11, 5, 1):
+ case IP_VERSION(11, 5, 2):
adev->gfxhub.funcs = &gfxhub_v11_5_0_funcs;
break;
default:
@@ -754,6 +755,7 @@ static int gmc_v11_0_sw_init(void *handle)
case IP_VERSION(11, 0, 4):
case IP_VERSION(11, 5, 0):
case IP_VERSION(11, 5, 1):
+ case IP_VERSION(11, 5, 2):
set_bit(AMDGPU_GFXHUB(0), adev->vmhubs_mask);
set_bit(AMDGPU_MMHUB0(0), adev->vmhubs_mask);
/*
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c
index 16d3443f8a82..fd3ac483760e 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c
@@ -464,10 +464,6 @@ static uint64_t gmc_v12_0_map_mtype(struct amdgpu_device *adev, uint32_t flags)
return AMDGPU_PTE_MTYPE_GFX12(0ULL, MTYPE_NC);
case AMDGPU_VM_MTYPE_NC:
return AMDGPU_PTE_MTYPE_GFX12(0ULL, MTYPE_NC);
- case AMDGPU_VM_MTYPE_WC:
- return AMDGPU_PTE_MTYPE_GFX12(0ULL, MTYPE_WC);
- case AMDGPU_VM_MTYPE_CC:
- return AMDGPU_PTE_MTYPE_GFX12(0ULL, MTYPE_CC);
case AMDGPU_VM_MTYPE_UC:
return AMDGPU_PTE_MTYPE_GFX12(0ULL, MTYPE_UC);
default:
@@ -532,6 +528,9 @@ static void gmc_v12_0_get_vm_pte(struct amdgpu_device *adev,
is_system = (bo->tbo.resource->mem_type == TTM_PL_TT) ||
(bo->tbo.resource->mem_type == AMDGPU_PL_PREEMPT);
+ if (bo && bo->flags & AMDGPU_GEM_CREATE_GFX12_DCC)
+ *flags |= AMDGPU_PTE_DCC;
+
/* WA for HW bug */
if (is_system || ((bo_adev != adev) && coherent))
*flags = AMDGPU_PTE_MTYPE_GFX12(*flags, MTYPE_NC);
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c
index 3e38d8bfcb69..d36725666b54 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c
@@ -98,9 +98,7 @@ static void gmc_v6_0_mc_resume(struct amdgpu_device *adev)
static int gmc_v6_0_init_microcode(struct amdgpu_device *adev)
{
const char *chip_name;
- char fw_name[30];
int err;
- bool is_58_fw = false;
DRM_DEBUG("\n");
@@ -126,17 +124,13 @@ static int gmc_v6_0_init_microcode(struct amdgpu_device *adev)
/* this memory configuration requires special firmware */
if (((RREG32(mmMC_SEQ_MISC0) & 0xff000000) >> 24) == 0x58)
- is_58_fw = true;
+ chip_name = "si58";
- if (is_58_fw)
- snprintf(fw_name, sizeof(fw_name), "amdgpu/si58_mc.bin");
- else
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mc.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->gmc.fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gmc.fw, "amdgpu/%s_mc.bin", chip_name);
if (err) {
dev_err(adev->dev,
- "si_mc: Failed to load firmware \"%s\"\n",
- fw_name);
+ "si_mc: Failed to load firmware \"%s_mc.bin\"\n",
+ chip_name);
amdgpu_ucode_release(&adev->gmc.fw);
}
return err;
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
index 85df8fc81065..994432fb57ea 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
@@ -130,7 +130,6 @@ static void gmc_v7_0_mc_resume(struct amdgpu_device *adev)
static int gmc_v7_0_init_microcode(struct amdgpu_device *adev)
{
const char *chip_name;
- char fw_name[30];
int err;
DRM_DEBUG("\n");
@@ -153,11 +152,9 @@ static int gmc_v7_0_init_microcode(struct amdgpu_device *adev)
return -EINVAL;
}
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mc.bin", chip_name);
-
- err = amdgpu_ucode_request(adev, &adev->gmc.fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gmc.fw, "amdgpu/%s_mc.bin", chip_name);
if (err) {
- pr_err("cik_mc: Failed to load firmware \"%s\"\n", fw_name);
+ pr_err("cik_mc: Failed to load firmware \"%s_mc.bin\"\n", chip_name);
amdgpu_ucode_release(&adev->gmc.fw);
}
return err;
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
index fc97757e33d9..86488c052f82 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
@@ -212,7 +212,6 @@ static void gmc_v8_0_mc_resume(struct amdgpu_device *adev)
static int gmc_v8_0_init_microcode(struct amdgpu_device *adev)
{
const char *chip_name;
- char fw_name[30];
int err;
DRM_DEBUG("\n");
@@ -255,10 +254,9 @@ static int gmc_v8_0_init_microcode(struct amdgpu_device *adev)
return -EINVAL;
}
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mc.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->gmc.fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gmc.fw, "amdgpu/%s_mc.bin", chip_name);
if (err) {
- pr_err("mc: Failed to load firmware \"%s\"\n", fw_name);
+ pr_err("mc: Failed to load firmware \"%s_mc.bin\"\n", chip_name);
amdgpu_ucode_release(&adev->gmc.fw);
}
return err;
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
index 88b4644f8e96..b73136d390cc 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
@@ -672,7 +672,8 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev,
(amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(9, 4, 2)))
return 0;
- WREG32_P(hub->vm_l2_pro_fault_cntl, 1, ~1);
+ if (!amdgpu_sriov_vf(adev))
+ WREG32_P(hub->vm_l2_pro_fault_cntl, 1, ~1);
amdgpu_vm_update_fault_cache(adev, entry->pasid, addr, status, vmhub);
diff --git a/drivers/gpu/drm/amd/amdgpu/ih_v6_0.c b/drivers/gpu/drm/amd/amdgpu/ih_v6_0.c
index 3cb64c8f7175..18a761d6ef33 100644
--- a/drivers/gpu/drm/amd/amdgpu/ih_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/ih_v6_0.c
@@ -135,6 +135,34 @@ static int ih_v6_0_toggle_ring_interrupts(struct amdgpu_device *adev,
tmp = RREG32(ih_regs->ih_rb_cntl);
tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, RB_ENABLE, (enable ? 1 : 0));
+
+ if (enable) {
+ /* Unset the CLEAR_OVERFLOW bit to make sure the next step
+ * is switching the bit from 0 to 1
+ */
+ tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 0);
+ if (amdgpu_sriov_vf(adev) && amdgpu_sriov_reg_indirect_ih(adev)) {
+ if (psp_reg_program(&adev->psp, ih_regs->psp_reg_id, tmp))
+ return -ETIMEDOUT;
+ } else {
+ WREG32_NO_KIQ(ih_regs->ih_rb_cntl, tmp);
+ }
+
+ /* Clear RB_OVERFLOW bit */
+ tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
+ if (amdgpu_sriov_vf(adev) && amdgpu_sriov_reg_indirect_ih(adev)) {
+ if (psp_reg_program(&adev->psp, ih_regs->psp_reg_id, tmp))
+ return -ETIMEDOUT;
+ } else {
+ WREG32_NO_KIQ(ih_regs->ih_rb_cntl, tmp);
+ }
+
+ /* Unset the CLEAR_OVERFLOW bit immediately so new overflows
+ * can be detected.
+ */
+ tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 0);
+ }
+
/* enable_intr field is only valid in ring0 */
if (ih == &adev->irq.ih)
tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, ENABLE_INTR, (enable ? 1 : 0));
diff --git a/drivers/gpu/drm/amd/amdgpu/ih_v6_1.c b/drivers/gpu/drm/amd/amdgpu/ih_v6_1.c
index 0fbf5fa7b0f8..2e0469feca1e 100644
--- a/drivers/gpu/drm/amd/amdgpu/ih_v6_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/ih_v6_1.c
@@ -535,6 +535,12 @@ static void ih_v6_1_set_self_irq_funcs(struct amdgpu_device *adev)
static int ih_v6_1_early_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int ret;
+
+ ret = amdgpu_irq_add_domain(adev);
+ if (ret) {
+ return ret;
+ }
ih_v6_1_set_interrupt_funcs(adev);
ih_v6_1_set_self_irq_funcs(adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/ih_v7_0.c b/drivers/gpu/drm/amd/amdgpu/ih_v7_0.c
index aa6235dd4f2b..6852081fcff2 100644
--- a/drivers/gpu/drm/amd/amdgpu/ih_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/ih_v7_0.c
@@ -346,6 +346,21 @@ static int ih_v7_0_irq_init(struct amdgpu_device *adev)
DELAY, 3);
WREG32_SOC15(OSSSYS, 0, regIH_MSI_STORM_CTRL, tmp);
+ /* Redirect the interrupts to IH RB1 for dGPU */
+ if (adev->irq.ih1.ring_size) {
+ tmp = RREG32_SOC15(OSSSYS, 0, regIH_RING1_CLIENT_CFG_INDEX);
+ tmp = REG_SET_FIELD(tmp, IH_RING1_CLIENT_CFG_INDEX, INDEX, 0);
+ WREG32_SOC15(OSSSYS, 0, regIH_RING1_CLIENT_CFG_INDEX, tmp);
+
+ tmp = RREG32_SOC15(OSSSYS, 0, regIH_RING1_CLIENT_CFG_DATA);
+ tmp = REG_SET_FIELD(tmp, IH_RING1_CLIENT_CFG_DATA, CLIENT_ID, 0xa);
+ tmp = REG_SET_FIELD(tmp, IH_RING1_CLIENT_CFG_DATA, SOURCE_ID, 0x0);
+ tmp = REG_SET_FIELD(tmp, IH_RING1_CLIENT_CFG_DATA,
+ SOURCE_ID_MATCH_ENABLE, 0x1);
+
+ WREG32_SOC15(OSSSYS, 0, regIH_RING1_CLIENT_CFG_DATA, tmp);
+ }
+
pci_set_master(adev->pdev);
/* enable interrupts */
@@ -546,8 +561,15 @@ static int ih_v7_0_sw_init(void *handle)
adev->irq.ih.use_doorbell = true;
adev->irq.ih.doorbell_index = adev->doorbell_index.ih << 1;
- adev->irq.ih1.ring_size = 0;
- adev->irq.ih2.ring_size = 0;
+ if (!(adev->flags & AMD_IS_APU)) {
+ r = amdgpu_ih_ring_init(adev, &adev->irq.ih1, IH_RING_SIZE,
+ use_bus_addr);
+ if (r)
+ return r;
+
+ adev->irq.ih1.use_doorbell = true;
+ adev->irq.ih1.doorbell_index = (adev->doorbell_index.ih + 1) << 1;
+ }
/* initialize ih control register offset */
ih_v7_0_init_register_offset(adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/imu_v11_0.c b/drivers/gpu/drm/amd/amdgpu/imu_v11_0.c
index 3e91a8e42c21..6c1891889c4d 100644
--- a/drivers/gpu/drm/amd/amdgpu/imu_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/imu_v11_0.c
@@ -38,10 +38,10 @@ MODULE_FIRMWARE("amdgpu/gc_11_0_3_imu.bin");
MODULE_FIRMWARE("amdgpu/gc_11_0_4_imu.bin");
MODULE_FIRMWARE("amdgpu/gc_11_5_0_imu.bin");
MODULE_FIRMWARE("amdgpu/gc_11_5_1_imu.bin");
+MODULE_FIRMWARE("amdgpu/gc_11_5_2_imu.bin");
static int imu_v11_0_init_microcode(struct amdgpu_device *adev)
{
- char fw_name[45];
char ucode_prefix[30];
int err;
const struct imu_firmware_header_v1_0 *imu_hdr;
@@ -50,11 +50,10 @@ static int imu_v11_0_init_microcode(struct amdgpu_device *adev)
DRM_DEBUG("\n");
amdgpu_ucode_ip_version_decode(adev, GC_HWIP, ucode_prefix, sizeof(ucode_prefix));
-
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_imu.bin", ucode_prefix);
- err = amdgpu_ucode_request(adev, &adev->gfx.imu_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.imu_fw, "amdgpu/%s_imu.bin", ucode_prefix);
if (err)
goto out;
+
imu_hdr = (const struct imu_firmware_header_v1_0 *)adev->gfx.imu_fw->data;
//adev->gfx.imu_feature_version = le32_to_cpu(imu_hdr->ucode_feature_version);
@@ -75,8 +74,8 @@ static int imu_v11_0_init_microcode(struct amdgpu_device *adev)
out:
if (err) {
dev_err(adev->dev,
- "gfx11: Failed to load firmware \"%s\"\n",
- fw_name);
+ "gfx11: Failed to load firmware \"%s_imu.bin\"\n",
+ ucode_prefix);
amdgpu_ucode_release(&adev->gfx.imu_fw);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/imu_v12_0.c b/drivers/gpu/drm/amd/amdgpu/imu_v12_0.c
index 0c8ef908d112..1341f0292031 100644
--- a/drivers/gpu/drm/amd/amdgpu/imu_v12_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/imu_v12_0.c
@@ -39,7 +39,6 @@ MODULE_FIRMWARE("amdgpu/gc_12_0_1_imu.bin");
static int imu_v12_0_init_microcode(struct amdgpu_device *adev)
{
- char fw_name[40];
char ucode_prefix[15];
int err;
const struct imu_firmware_header_v1_0 *imu_hdr;
@@ -48,11 +47,10 @@ static int imu_v12_0_init_microcode(struct amdgpu_device *adev)
DRM_DEBUG("\n");
amdgpu_ucode_ip_version_decode(adev, GC_HWIP, ucode_prefix, sizeof(ucode_prefix));
-
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_imu.bin", ucode_prefix);
- err = amdgpu_ucode_request(adev, &adev->gfx.imu_fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->gfx.imu_fw, "amdgpu/%s_imu.bin", ucode_prefix);
if (err)
goto out;
+
imu_hdr = (const struct imu_firmware_header_v1_0 *)adev->gfx.imu_fw->data;
adev->gfx.imu_fw_version = le32_to_cpu(imu_hdr->header.ucode_version);
@@ -72,8 +70,8 @@ static int imu_v12_0_init_microcode(struct amdgpu_device *adev)
out:
if (err) {
dev_err(adev->dev,
- "gfx12: Failed to load firmware \"%s\"\n",
- fw_name);
+ "gfx12: Failed to load firmware \"%s_imu.bin\"\n",
+ ucode_prefix);
amdgpu_ucode_release(&adev->gfx.imu_fw);
}
@@ -119,7 +117,8 @@ static int imu_v12_0_load_microcode(struct amdgpu_device *adev)
static int imu_v12_0_wait_for_reset_status(struct amdgpu_device *adev)
{
- int i, imu_reg_val = 0;
+ u32 imu_reg_val = 0;
+ int i;
for (i = 0; i < adev->usec_timeout; i++) {
imu_reg_val = RREG32_SOC15(GC, 0, regGFX_IMU_GFX_RESET_CTRL);
@@ -138,7 +137,7 @@ static int imu_v12_0_wait_for_reset_status(struct amdgpu_device *adev)
static void imu_v12_0_setup(struct amdgpu_device *adev)
{
- int imu_reg_val;
+ u32 imu_reg_val;
WREG32_SOC15(GC, 0, regGFX_IMU_C2PMSG_ACCESS_CTRL0, 0xffffff);
WREG32_SOC15(GC, 0, regGFX_IMU_C2PMSG_ACCESS_CTRL1, 0xffff);
@@ -157,7 +156,7 @@ static void imu_v12_0_setup(struct amdgpu_device *adev)
static int imu_v12_0_start(struct amdgpu_device *adev)
{
- int imu_reg_val;
+ u32 imu_reg_val;
imu_reg_val = RREG32_SOC15(GC, 0, regGFX_IMU_CORE_CTRL);
imu_reg_val &= 0xfffffffe;
diff --git a/drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.c b/drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.c
new file mode 100644
index 000000000000..aac107898bae
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.c
@@ -0,0 +1,137 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+ * 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, sub license, 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 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ */
+
+#include "amdgpu.h"
+#include "isp_v4_1_0.h"
+
+static const unsigned int isp_4_1_0_int_srcid[MAX_ISP410_INT_SRC] = {
+ ISP_4_1__SRCID__ISP_RINGBUFFER_WPT9,
+ ISP_4_1__SRCID__ISP_RINGBUFFER_WPT10,
+ ISP_4_1__SRCID__ISP_RINGBUFFER_WPT11,
+ ISP_4_1__SRCID__ISP_RINGBUFFER_WPT12,
+ ISP_4_1__SRCID__ISP_RINGBUFFER_WPT13,
+ ISP_4_1__SRCID__ISP_RINGBUFFER_WPT14,
+ ISP_4_1__SRCID__ISP_RINGBUFFER_WPT15,
+ ISP_4_1__SRCID__ISP_RINGBUFFER_WPT16
+};
+
+static int isp_v4_1_0_hw_init(struct amdgpu_isp *isp)
+{
+ struct amdgpu_device *adev = isp->adev;
+ u64 isp_base;
+ int int_idx;
+ int r;
+
+ if (adev->rmmio_size == 0 || adev->rmmio_size < 0x5289)
+ return -EINVAL;
+
+ isp_base = adev->rmmio_base;
+
+ isp->isp_cell = kcalloc(1, sizeof(struct mfd_cell), GFP_KERNEL);
+ if (!isp->isp_cell) {
+ r = -ENOMEM;
+ DRM_ERROR("%s: isp mfd cell alloc failed\n", __func__);
+ goto failure;
+ }
+
+ isp->isp_res = kcalloc(MAX_ISP410_INT_SRC + 1, sizeof(struct resource),
+ GFP_KERNEL);
+ if (!isp->isp_res) {
+ r = -ENOMEM;
+ DRM_ERROR("%s: isp mfd res alloc failed\n", __func__);
+ goto failure;
+ }
+
+ isp->isp_pdata = kzalloc(sizeof(*isp->isp_pdata), GFP_KERNEL);
+ if (!isp->isp_pdata) {
+ r = -ENOMEM;
+ DRM_ERROR("%s: isp platform data alloc failed\n", __func__);
+ goto failure;
+ }
+
+ /* initialize isp platform data */
+ isp->isp_pdata->adev = (void *)adev;
+ isp->isp_pdata->asic_type = adev->asic_type;
+ isp->isp_pdata->base_rmmio_size = adev->rmmio_size;
+
+ isp->isp_res[0].name = "isp_4_1_0_reg";
+ isp->isp_res[0].flags = IORESOURCE_MEM;
+ isp->isp_res[0].start = isp_base;
+ isp->isp_res[0].end = isp_base + ISP_REGS_OFFSET_END;
+
+ for (int_idx = 0; int_idx < MAX_ISP410_INT_SRC; int_idx++) {
+ isp->isp_res[int_idx + 1].name = "isp_4_1_0_irq";
+ isp->isp_res[int_idx + 1].flags = IORESOURCE_IRQ;
+ isp->isp_res[int_idx + 1].start =
+ amdgpu_irq_create_mapping(adev, isp_4_1_0_int_srcid[int_idx]);
+ isp->isp_res[int_idx + 1].end =
+ isp->isp_res[int_idx + 1].start;
+ }
+
+ isp->isp_cell[0].name = "amd_isp_capture";
+ isp->isp_cell[0].num_resources = MAX_ISP410_INT_SRC + 1;
+ isp->isp_cell[0].resources = &isp->isp_res[0];
+ isp->isp_cell[0].platform_data = isp->isp_pdata;
+ isp->isp_cell[0].pdata_size = sizeof(struct isp_platform_data);
+
+ r = mfd_add_hotplug_devices(isp->parent, isp->isp_cell, 1);
+ if (r) {
+ DRM_ERROR("%s: add mfd hotplug device failed\n", __func__);
+ goto failure;
+ }
+
+ return 0;
+
+failure:
+
+ kfree(isp->isp_pdata);
+ kfree(isp->isp_res);
+ kfree(isp->isp_cell);
+
+ return r;
+}
+
+static int isp_v4_1_0_hw_fini(struct amdgpu_isp *isp)
+{
+ mfd_remove_devices(isp->parent);
+
+ kfree(isp->isp_res);
+ kfree(isp->isp_cell);
+ kfree(isp->isp_pdata);
+
+ return 0;
+}
+
+static const struct isp_funcs isp_v4_1_0_funcs = {
+ .hw_init = isp_v4_1_0_hw_init,
+ .hw_fini = isp_v4_1_0_hw_fini,
+};
+
+void isp_v4_1_0_set_isp_funcs(struct amdgpu_isp *isp)
+{
+ isp->funcs = &isp_v4_1_0_funcs;
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.h b/drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.h
new file mode 100644
index 000000000000..315f2822410c
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+ * 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, sub license, 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 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ */
+
+#ifndef __ISP_V4_1_0_H__
+#define __ISP_V4_1_0_H__
+
+#include "amdgpu_isp.h"
+
+#include "ivsrcid/isp/irqsrcs_isp_4_1.h"
+
+#define MAX_ISP410_INT_SRC 8
+
+void isp_v4_1_0_set_isp_funcs(struct amdgpu_isp *isp);
+
+#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.c b/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.c
new file mode 100644
index 000000000000..4e17fa03f7b5
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.c
@@ -0,0 +1,137 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+ * 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, sub license, 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 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ */
+
+#include "amdgpu.h"
+#include "isp_v4_1_1.h"
+
+static const unsigned int isp_4_1_1_int_srcid[MAX_ISP411_INT_SRC] = {
+ ISP_4_1__SRCID__ISP_RINGBUFFER_WPT9,
+ ISP_4_1__SRCID__ISP_RINGBUFFER_WPT10,
+ ISP_4_1__SRCID__ISP_RINGBUFFER_WPT11,
+ ISP_4_1__SRCID__ISP_RINGBUFFER_WPT12,
+ ISP_4_1__SRCID__ISP_RINGBUFFER_WPT13,
+ ISP_4_1__SRCID__ISP_RINGBUFFER_WPT14,
+ ISP_4_1__SRCID__ISP_RINGBUFFER_WPT15,
+ ISP_4_1__SRCID__ISP_RINGBUFFER_WPT16
+};
+
+static int isp_v4_1_1_hw_init(struct amdgpu_isp *isp)
+{
+ struct amdgpu_device *adev = isp->adev;
+ u64 isp_base;
+ int int_idx;
+ int r;
+
+ if (adev->rmmio_size == 0 || adev->rmmio_size < 0x5289)
+ return -EINVAL;
+
+ isp_base = adev->rmmio_base;
+
+ isp->isp_cell = kcalloc(1, sizeof(struct mfd_cell), GFP_KERNEL);
+ if (!isp->isp_cell) {
+ r = -ENOMEM;
+ DRM_ERROR("%s: isp mfd cell alloc failed\n", __func__);
+ goto failure;
+ }
+
+ isp->isp_res = kcalloc(MAX_ISP411_INT_SRC + 1, sizeof(struct resource),
+ GFP_KERNEL);
+ if (!isp->isp_res) {
+ r = -ENOMEM;
+ DRM_ERROR("%s: isp mfd res alloc failed\n", __func__);
+ goto failure;
+ }
+
+ isp->isp_pdata = kzalloc(sizeof(*isp->isp_pdata), GFP_KERNEL);
+ if (!isp->isp_pdata) {
+ r = -ENOMEM;
+ DRM_ERROR("%s: isp platform data alloc failed\n", __func__);
+ goto failure;
+ }
+
+ /* initialize isp platform data */
+ isp->isp_pdata->adev = (void *)adev;
+ isp->isp_pdata->asic_type = adev->asic_type;
+ isp->isp_pdata->base_rmmio_size = adev->rmmio_size;
+
+ isp->isp_res[0].name = "isp_4_1_1_reg";
+ isp->isp_res[0].flags = IORESOURCE_MEM;
+ isp->isp_res[0].start = isp_base;
+ isp->isp_res[0].end = isp_base + ISP_REGS_OFFSET_END;
+
+ for (int_idx = 0; int_idx < MAX_ISP411_INT_SRC; int_idx++) {
+ isp->isp_res[int_idx + 1].name = "isp_4_1_1_irq";
+ isp->isp_res[int_idx + 1].flags = IORESOURCE_IRQ;
+ isp->isp_res[int_idx + 1].start =
+ amdgpu_irq_create_mapping(adev, isp_4_1_1_int_srcid[int_idx]);
+ isp->isp_res[int_idx + 1].end =
+ isp->isp_res[int_idx + 1].start;
+ }
+
+ isp->isp_cell[0].name = "amd_isp_capture";
+ isp->isp_cell[0].num_resources = MAX_ISP411_INT_SRC + 1;
+ isp->isp_cell[0].resources = &isp->isp_res[0];
+ isp->isp_cell[0].platform_data = isp->isp_pdata;
+ isp->isp_cell[0].pdata_size = sizeof(struct isp_platform_data);
+
+ r = mfd_add_hotplug_devices(isp->parent, isp->isp_cell, 1);
+ if (r) {
+ DRM_ERROR("%s: add mfd hotplug device failed\n", __func__);
+ goto failure;
+ }
+
+ return 0;
+
+failure:
+
+ kfree(isp->isp_pdata);
+ kfree(isp->isp_res);
+ kfree(isp->isp_cell);
+
+ return r;
+}
+
+static int isp_v4_1_1_hw_fini(struct amdgpu_isp *isp)
+{
+ mfd_remove_devices(isp->parent);
+
+ kfree(isp->isp_res);
+ kfree(isp->isp_cell);
+ kfree(isp->isp_pdata);
+
+ return 0;
+}
+
+static const struct isp_funcs isp_v4_1_1_funcs = {
+ .hw_init = isp_v4_1_1_hw_init,
+ .hw_fini = isp_v4_1_1_hw_fini,
+};
+
+void isp_v4_1_1_set_isp_funcs(struct amdgpu_isp *isp)
+{
+ isp->funcs = &isp_v4_1_1_funcs;
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.h b/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.h
new file mode 100644
index 000000000000..dfb9522c9d6a
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+ * 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, sub license, 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 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ */
+
+#ifndef __ISP_V4_1_1_H__
+#define __ISP_V4_1_1_H__
+
+#include "amdgpu_isp.h"
+
+#include "ivsrcid/isp/irqsrcs_isp_4_1.h"
+
+#define MAX_ISP411_INT_SRC 8
+
+void isp_v4_1_1_set_isp_funcs(struct amdgpu_isp *isp);
+
+#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c
index 77595e9622da..71f43a5c7f72 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c
@@ -581,7 +581,6 @@ static const struct amdgpu_ring_funcs jpeg_v1_0_decode_ring_vm_funcs = {
static void jpeg_v1_0_set_dec_ring_funcs(struct amdgpu_device *adev)
{
adev->jpeg.inst->ring_dec->funcs = &jpeg_v1_0_decode_ring_vm_funcs;
- DRM_INFO("JPEG decode is enabled in VM mode\n");
}
static const struct amdgpu_irq_src_funcs jpeg_v1_0_irq_funcs = {
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c
index ef3e42f6b841..99adf3625657 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c
@@ -131,16 +131,11 @@ static int jpeg_v2_0_hw_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
struct amdgpu_ring *ring = adev->jpeg.inst->ring_dec;
- int r;
adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell,
(adev->doorbell_index.vcn.vcn_ring0_1 << 1), 0);
- r = amdgpu_ring_test_helper(ring);
- if (!r)
- DRM_INFO("JPEG decode initialized successfully.\n");
-
- return r;
+ return amdgpu_ring_test_helper(ring);
}
/**
@@ -795,7 +790,6 @@ static const struct amdgpu_ring_funcs jpeg_v2_0_dec_ring_vm_funcs = {
static void jpeg_v2_0_set_dec_ring_funcs(struct amdgpu_device *adev)
{
adev->jpeg.inst->ring_dec->funcs = &jpeg_v2_0_dec_ring_vm_funcs;
- DRM_INFO("JPEG decode is enabled in VM mode\n");
}
static const struct amdgpu_irq_src_funcs jpeg_v2_0_irq_funcs = {
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
index afeaf3c64e27..d8ef95c847c2 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
@@ -196,8 +196,6 @@ static int jpeg_v2_5_hw_init(void *handle)
return r;
}
- DRM_INFO("JPEG decode initialized successfully.\n");
-
return 0;
}
@@ -728,7 +726,6 @@ static void jpeg_v2_5_set_dec_ring_funcs(struct amdgpu_device *adev)
else /* CHIP_ALDEBARAN */
adev->jpeg.inst[i].ring_dec->funcs = &jpeg_v2_6_dec_ring_vm_funcs;
adev->jpeg.inst[i].ring_dec->me = i;
- DRM_INFO("JPEG(%d) JPEG decode is enabled in VM mode\n", i);
}
}
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c
index 1c7cf4800bf7..31cfa3ce6528 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c
@@ -146,18 +146,11 @@ static int jpeg_v3_0_hw_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
struct amdgpu_ring *ring = adev->jpeg.inst->ring_dec;
- int r;
adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell,
(adev->doorbell_index.vcn.vcn_ring0_1 << 1), 0);
- r = amdgpu_ring_test_helper(ring);
- if (r)
- return r;
-
- DRM_INFO("JPEG decode initialized successfully.\n");
-
- return 0;
+ return amdgpu_ring_test_helper(ring);
}
/**
@@ -593,7 +586,6 @@ static const struct amdgpu_ring_funcs jpeg_v3_0_dec_ring_vm_funcs = {
static void jpeg_v3_0_set_dec_ring_funcs(struct amdgpu_device *adev)
{
adev->jpeg.inst->ring_dec->funcs = &jpeg_v3_0_dec_ring_vm_funcs;
- DRM_INFO("JPEG decode is enabled in VM mode\n");
}
static const struct amdgpu_irq_src_funcs jpeg_v3_0_irq_funcs = {
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
index 237fe5df5a8f..3dac8f259d7f 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
@@ -181,8 +181,6 @@ static int jpeg_v4_0_hw_init(void *handle)
return r;
}
- DRM_DEV_INFO(adev->dev, "JPEG decode initialized successfully.\n");
-
return 0;
}
@@ -755,7 +753,6 @@ static const struct amdgpu_ring_funcs jpeg_v4_0_dec_ring_vm_funcs = {
static void jpeg_v4_0_set_dec_ring_funcs(struct amdgpu_device *adev)
{
adev->jpeg.inst->ring_dec->funcs = &jpeg_v4_0_dec_ring_vm_funcs;
- DRM_DEV_INFO(adev->dev, "JPEG decode is enabled in VM mode\n");
}
static const struct amdgpu_irq_src_funcs jpeg_v4_0_irq_funcs = {
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c
index d66af11aa66c..ad524ddc9760 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c
@@ -32,6 +32,9 @@
#include "vcn/vcn_4_0_3_sh_mask.h"
#include "ivsrcid/vcn/irqsrcs_vcn_4_0.h"
+#define NORMALIZE_JPEG_REG_OFFSET(offset) \
+ (offset & 0x1FFFF)
+
enum jpeg_engin_status {
UVD_PGFSM_STATUS__UVDJ_PWR_ON = 0,
UVD_PGFSM_STATUS__UVDJ_PWR_OFF = 2,
@@ -341,7 +344,6 @@ static int jpeg_v4_0_3_hw_init(void *handle)
}
}
}
- DRM_DEV_INFO(adev->dev, "JPEG decode initialized successfully.\n");
return 0;
}
@@ -622,6 +624,13 @@ static uint64_t jpeg_v4_0_3_dec_ring_get_wptr(struct amdgpu_ring *ring)
ring->pipe ? (0x40 * ring->pipe - 0xc80) : 0);
}
+static void jpeg_v4_0_3_ring_emit_hdp_flush(struct amdgpu_ring *ring)
+{
+ /* JPEG engine access for HDP flush doesn't work when RRMT is enabled.
+ * This is a workaround to avoid any HDP flush through JPEG ring.
+ */
+}
+
/**
* jpeg_v4_0_3_dec_ring_set_wptr - set write pointer
*
@@ -818,7 +827,13 @@ void jpeg_v4_0_3_dec_ring_emit_ib(struct amdgpu_ring *ring,
void jpeg_v4_0_3_dec_ring_emit_reg_wait(struct amdgpu_ring *ring, uint32_t reg,
uint32_t val, uint32_t mask)
{
- uint32_t reg_offset = (reg << 2);
+ uint32_t reg_offset;
+
+ /* For VF, only local offsets should be used */
+ if (amdgpu_sriov_vf(ring->adev))
+ reg = NORMALIZE_JPEG_REG_OFFSET(reg);
+
+ reg_offset = (reg << 2);
amdgpu_ring_write(ring, PACKETJ(regUVD_JRBC_RB_COND_RD_TIMER_INTERNAL_OFFSET,
0, 0, PACKETJ_TYPE0));
@@ -859,7 +874,13 @@ void jpeg_v4_0_3_dec_ring_emit_vm_flush(struct amdgpu_ring *ring,
void jpeg_v4_0_3_dec_ring_emit_wreg(struct amdgpu_ring *ring, uint32_t reg, uint32_t val)
{
- uint32_t reg_offset = (reg << 2);
+ uint32_t reg_offset;
+
+ /* For VF, only local offsets should be used */
+ if (amdgpu_sriov_vf(ring->adev))
+ reg = NORMALIZE_JPEG_REG_OFFSET(reg);
+
+ reg_offset = (reg << 2);
amdgpu_ring_write(ring, PACKETJ(regUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET,
0, 0, PACKETJ_TYPE0));
@@ -1073,6 +1094,7 @@ static const struct amdgpu_ring_funcs jpeg_v4_0_3_dec_ring_vm_funcs = {
.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,
@@ -1100,7 +1122,6 @@ static void jpeg_v4_0_3_set_dec_ring_funcs(struct amdgpu_device *adev)
adev->jpeg.inst[i].aid_id =
jpeg_inst / adev->jpeg.num_inst_per_aid;
}
- DRM_DEV_INFO(adev->dev, "JPEG decode is enabled in VM mode\n");
}
static const struct amdgpu_irq_src_funcs jpeg_v4_0_3_irq_funcs = {
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c
index 4c8f9772437b..f96ac6bce526 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c
@@ -191,7 +191,6 @@ static int jpeg_v4_0_5_hw_init(void *handle)
// TODO: Enable ring test with DPG support
if (adev->pg_flags & AMD_PG_SUPPORT_JPEG_DPG) {
- DRM_DEV_INFO(adev->dev, "JPEG decode initialized successfully under DPG Mode");
return 0;
}
@@ -205,9 +204,6 @@ static int jpeg_v4_0_5_hw_init(void *handle)
return r;
}
- if (!r)
- DRM_INFO("JPEG decode initialized successfully under SPG Mode\n");
-
return 0;
}
@@ -805,7 +801,6 @@ static void jpeg_v4_0_5_set_dec_ring_funcs(struct amdgpu_device *adev)
adev->jpeg.inst[i].ring_dec->funcs = &jpeg_v4_0_5_dec_ring_vm_funcs;
adev->jpeg.inst[i].ring_dec->me = i;
- DRM_DEV_INFO(adev->dev, "JPEG%d decode is enabled in VM mode\n", i);
}
}
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c
index 68ef29bc70e2..d694a276498a 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c
@@ -31,6 +31,7 @@
#include "vcn/vcn_5_0_0_offset.h"
#include "vcn/vcn_5_0_0_sh_mask.h"
#include "ivsrcid/vcn/irqsrcs_vcn_4_0.h"
+#include "jpeg_v5_0_0.h"
static void jpeg_v5_0_0_set_dec_ring_funcs(struct amdgpu_device *adev);
static void jpeg_v5_0_0_set_irq_funcs(struct amdgpu_device *adev);
@@ -137,9 +138,9 @@ static int jpeg_v5_0_0_hw_init(void *handle)
adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell,
(adev->doorbell_index.vcn.vcn_ring0_1 << 1), 0);
- WREG32_SOC15(VCN, 0, regVCN_JPEG_DB_CTRL,
- ring->doorbell_index << VCN_JPEG_DB_CTRL__OFFSET__SHIFT |
- VCN_JPEG_DB_CTRL__EN_MASK);
+ /* Skip ring test because pause DPG is not implemented. */
+ if (adev->pg_flags & AMD_PG_SUPPORT_JPEG_DPG)
+ return 0;
r = amdgpu_ring_test_helper(ring);
if (r)
@@ -239,7 +240,7 @@ static void jpeg_v5_0_0_enable_clock_gating(struct amdgpu_device *adev)
WREG32_SOC15(JPEG, 0, regJPEG_CGC_GATE, data);
}
-static int jpeg_v5_0_0_disable_static_power_gating(struct amdgpu_device *adev)
+static int jpeg_v5_0_0_disable_power_gating(struct amdgpu_device *adev)
{
uint32_t data = 0;
@@ -252,14 +253,10 @@ static int jpeg_v5_0_0_disable_static_power_gating(struct amdgpu_device *adev)
WREG32_P(SOC15_REG_OFFSET(JPEG, 0, 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, 0, regUVD_JPEG_POWER_STATUS), 0,
- ~UVD_JPEG_POWER_STATUS__JPEG_PG_MODE_MASK);
-
return 0;
}
-static int jpeg_v5_0_0_enable_static_power_gating(struct amdgpu_device *adev)
+static int jpeg_v5_0_0_enable_power_gating(struct amdgpu_device *adev)
{
/* enable anti hang mechanism */
WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regUVD_JPEG_POWER_STATUS),
@@ -277,6 +274,121 @@ static int jpeg_v5_0_0_enable_static_power_gating(struct amdgpu_device *adev)
return 0;
}
+static void jpeg_engine_5_0_0_dpg_clock_gating_mode(struct amdgpu_device *adev,
+ int inst_idx, uint8_t indirect)
+{
+ uint32_t data = 0;
+
+ // JPEG disable CGC
+ if (adev->cg_flags & AMD_CG_SUPPORT_JPEG_MGCG)
+ data = 1 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
+ else
+ data = 0 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
+
+ data |= 1 << JPEG_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
+ data |= 4 << JPEG_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
+
+ if (indirect) {
+ ADD_SOC24_JPEG_TO_DPG_SRAM(inst_idx, vcnipJPEG_CGC_CTRL, data, indirect);
+
+ // Turn on All JPEG clocks
+ data = 0;
+ ADD_SOC24_JPEG_TO_DPG_SRAM(inst_idx, vcnipJPEG_CGC_GATE, data, indirect);
+ } else {
+ WREG32_SOC24_JPEG_DPG_MODE(inst_idx, vcnipJPEG_CGC_CTRL, data, indirect);
+
+ // Turn on All JPEG clocks
+ data = 0;
+ WREG32_SOC24_JPEG_DPG_MODE(inst_idx, vcnipJPEG_CGC_GATE, data, indirect);
+ }
+}
+
+/**
+ * jpeg_v5_0_0_start_dpg_mode - Jpeg start with dpg mode
+ *
+ * @adev: amdgpu_device pointer
+ * @inst_idx: instance number index
+ * @indirect: indirectly write sram
+ *
+ * Start JPEG block with dpg mode
+ */
+static int jpeg_v5_0_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)
+{
+ struct amdgpu_ring *ring = adev->jpeg.inst[inst_idx].ring_dec;
+ uint32_t reg_data = 0;
+
+ jpeg_v5_0_0_enable_power_gating(adev);
+
+ // enable dynamic power gating mode
+ reg_data = RREG32_SOC15(JPEG, inst_idx, regUVD_JPEG_POWER_STATUS);
+ reg_data |= UVD_JPEG_POWER_STATUS__JPEG_PG_MODE_MASK;
+ WREG32_SOC15(JPEG, inst_idx, regUVD_JPEG_POWER_STATUS, reg_data);
+
+ if (indirect)
+ adev->jpeg.inst[inst_idx].dpg_sram_curr_addr =
+ (uint32_t *)adev->jpeg.inst[inst_idx].dpg_sram_cpu_addr;
+
+ jpeg_engine_5_0_0_dpg_clock_gating_mode(adev, inst_idx, indirect);
+
+ /* MJPEG global tiling registers */
+ if (indirect)
+ ADD_SOC24_JPEG_TO_DPG_SRAM(inst_idx, vcnipJPEG_DEC_GFX10_ADDR_CONFIG,
+ adev->gfx.config.gb_addr_config, indirect);
+ else
+ WREG32_SOC24_JPEG_DPG_MODE(inst_idx, vcnipJPEG_DEC_GFX10_ADDR_CONFIG,
+ adev->gfx.config.gb_addr_config, 1);
+
+ /* enable System Interrupt for JRBC */
+ if (indirect)
+ ADD_SOC24_JPEG_TO_DPG_SRAM(inst_idx, vcnipJPEG_SYS_INT_EN,
+ JPEG_SYS_INT_EN__DJRBC0_MASK, indirect);
+ else
+ WREG32_SOC24_JPEG_DPG_MODE(inst_idx, vcnipJPEG_SYS_INT_EN,
+ JPEG_SYS_INT_EN__DJRBC0_MASK, 1);
+
+ if (indirect) {
+ /* add nop to workaround PSP size check */
+ ADD_SOC24_JPEG_TO_DPG_SRAM(inst_idx, vcnipUVD_NO_OP, 0, indirect);
+
+ amdgpu_jpeg_psp_update_sram(adev, inst_idx, 0);
+ }
+
+ WREG32_SOC15(VCN, 0, regVCN_JPEG_DB_CTRL,
+ ring->doorbell_index << VCN_JPEG_DB_CTRL__OFFSET__SHIFT |
+ VCN_JPEG_DB_CTRL__EN_MASK);
+
+ WREG32_SOC15(JPEG, inst_idx, regUVD_LMI_JRBC_RB_VMID, 0);
+ WREG32_SOC15(JPEG, inst_idx, regUVD_JRBC_RB_CNTL, (0x00000001L | 0x00000002L));
+ WREG32_SOC15(JPEG, inst_idx, regUVD_LMI_JRBC_RB_64BIT_BAR_LOW,
+ lower_32_bits(ring->gpu_addr));
+ WREG32_SOC15(JPEG, inst_idx, regUVD_LMI_JRBC_RB_64BIT_BAR_HIGH,
+ upper_32_bits(ring->gpu_addr));
+ WREG32_SOC15(JPEG, inst_idx, regUVD_JRBC_RB_RPTR, 0);
+ WREG32_SOC15(JPEG, inst_idx, regUVD_JRBC_RB_WPTR, 0);
+ WREG32_SOC15(JPEG, inst_idx, regUVD_JRBC_RB_CNTL, 0x00000002L);
+ WREG32_SOC15(JPEG, inst_idx, regUVD_JRBC_RB_SIZE, ring->ring_size / 4);
+ ring->wptr = RREG32_SOC15(JPEG, inst_idx, regUVD_JRBC_RB_WPTR);
+
+ return 0;
+}
+
+/**
+ * jpeg_v5_0_0_stop_dpg_mode - Jpeg stop with dpg mode
+ *
+ * @adev: amdgpu_device pointer
+ * @inst_idx: instance number index
+ *
+ * Stop JPEG block with dpg mode
+ */
+static void jpeg_v5_0_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
+{
+ uint32_t reg_data = 0;
+
+ reg_data = RREG32_SOC15(JPEG, inst_idx, regUVD_JPEG_POWER_STATUS);
+ reg_data &= ~UVD_JPEG_POWER_STATUS__JPEG_PG_MODE_MASK;
+ WREG32_SOC15(JPEG, inst_idx, regUVD_JPEG_POWER_STATUS, reg_data);
+}
+
/**
* jpeg_v5_0_0_start - start JPEG block
*
@@ -292,8 +404,13 @@ static int jpeg_v5_0_0_start(struct amdgpu_device *adev)
if (adev->pm.dpm_enabled)
amdgpu_dpm_enable_jpeg(adev, true);
+ if (adev->pg_flags & AMD_PG_SUPPORT_JPEG_DPG) {
+ r = jpeg_v5_0_0_start_dpg_mode(adev, 0, adev->jpeg.indirect_sram);
+ return r;
+ }
+
/* disable power gating */
- r = jpeg_v5_0_0_disable_static_power_gating(adev);
+ r = jpeg_v5_0_0_disable_power_gating(adev);
if (r)
return r;
@@ -304,7 +421,6 @@ static int jpeg_v5_0_0_start(struct amdgpu_device *adev)
WREG32_SOC15(JPEG, 0, regJPEG_DEC_GFX10_ADDR_CONFIG,
adev->gfx.config.gb_addr_config);
-
/* enable JMI channel */
WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regUVD_JMI_CNTL), 0,
~UVD_JMI_CNTL__SOFT_RESET_MASK);
@@ -314,6 +430,10 @@ static int jpeg_v5_0_0_start(struct amdgpu_device *adev)
JPEG_SYS_INT_EN__DJRBC0_MASK,
~JPEG_SYS_INT_EN__DJRBC0_MASK);
+ WREG32_SOC15(VCN, 0, regVCN_JPEG_DB_CTRL,
+ ring->doorbell_index << VCN_JPEG_DB_CTRL__OFFSET__SHIFT |
+ VCN_JPEG_DB_CTRL__EN_MASK);
+
WREG32_SOC15(JPEG, 0, regUVD_LMI_JRBC_RB_VMID, 0);
WREG32_SOC15(JPEG, 0, regUVD_JRBC_RB_CNTL, (0x00000001L | 0x00000002L));
WREG32_SOC15(JPEG, 0, regUVD_LMI_JRBC_RB_64BIT_BAR_LOW,
@@ -340,17 +460,22 @@ static int jpeg_v5_0_0_stop(struct amdgpu_device *adev)
{
int r;
- /* reset JMI */
- WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regUVD_JMI_CNTL),
- UVD_JMI_CNTL__SOFT_RESET_MASK,
- ~UVD_JMI_CNTL__SOFT_RESET_MASK);
+ if (adev->pg_flags & AMD_PG_SUPPORT_JPEG_DPG) {
+ jpeg_v5_0_0_stop_dpg_mode(adev, 0);
+ } else {
- jpeg_v5_0_0_enable_clock_gating(adev);
+ /* reset JMI */
+ WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regUVD_JMI_CNTL),
+ UVD_JMI_CNTL__SOFT_RESET_MASK,
+ ~UVD_JMI_CNTL__SOFT_RESET_MASK);
- /* enable power gating */
- r = jpeg_v5_0_0_enable_static_power_gating(adev);
- if (r)
- return r;
+ jpeg_v5_0_0_enable_clock_gating(adev);
+
+ /* enable power gating */
+ r = jpeg_v5_0_0_enable_power_gating(adev);
+ if (r)
+ return r;
+ }
if (adev->pm.dpm_enabled)
amdgpu_dpm_enable_jpeg(adev, false);
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.h b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.h
index bd348336b215..5abb96159814 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.h
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.h
@@ -24,6 +24,12 @@
#ifndef __JPEG_V5_0_0_H__
#define __JPEG_V5_0_0_H__
+#define vcnipJPEG_CGC_GATE 0x4160
+#define vcnipJPEG_CGC_CTRL 0x4161
+#define vcnipJPEG_SYS_INT_EN 0x4141
+#define vcnipUVD_NO_OP 0x0029
+#define vcnipJPEG_DEC_GFX10_ADDR_CONFIG 0x404A
+
extern const struct amdgpu_ip_block_version jpeg_v5_0_0_ip_block;
#endif /* __JPEG_V5_0_0_H__ */
diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
index 8263b97c4466..8ce51b9236c1 100644
--- a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
@@ -51,6 +51,8 @@ MODULE_FIRMWARE("amdgpu/gc_11_5_0_mes_2.bin");
MODULE_FIRMWARE("amdgpu/gc_11_5_0_mes1.bin");
MODULE_FIRMWARE("amdgpu/gc_11_5_1_mes_2.bin");
MODULE_FIRMWARE("amdgpu/gc_11_5_1_mes1.bin");
+MODULE_FIRMWARE("amdgpu/gc_11_5_2_mes_2.bin");
+MODULE_FIRMWARE("amdgpu/gc_11_5_2_mes1.bin");
static int mes_v11_0_hw_init(void *handle);
static int mes_v11_0_hw_fini(void *handle);
@@ -118,6 +120,9 @@ static const char *mes_v11_0_opcodes[] = {
"MISC",
"UPDATE_ROOT_PAGE_TABLE",
"AMD_LOG",
+ "unused",
+ "unused",
+ "SET_HW_RSRC_1",
};
static const char *mes_v11_0_misc_opcodes[] = {
@@ -154,18 +159,18 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes,
void *pkt, int size,
int api_status_off)
{
- int ndw = size / 4;
- signed long r;
- union MESAPI__MISC *x_pkt = pkt;
- struct MES_API_STATUS *api_status;
+ union MESAPI__QUERY_MES_STATUS mes_status_pkt;
+ signed long timeout = 3000000; /* 3000 ms */
struct amdgpu_device *adev = mes->adev;
struct amdgpu_ring *ring = &mes->ring;
- unsigned long flags;
- signed long timeout = 3000000; /* 3000 ms */
+ struct MES_API_STATUS *api_status;
+ union MESAPI__MISC *x_pkt = pkt;
const char *op_str, *misc_op_str;
- u32 fence_offset;
- u64 fence_gpu_addr;
- u64 *fence_ptr;
+ unsigned long flags;
+ u64 status_gpu_addr;
+ u32 status_offset;
+ u64 *status_ptr;
+ signed long r;
int ret;
if (x_pkt->header.opcode >= MES_SCH_API_MAX)
@@ -177,28 +182,38 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes,
/* Worst case in sriov where all other 15 VF timeout, each VF needs about 600ms */
timeout = 15 * 600 * 1000;
}
- BUG_ON(size % 4 != 0);
- ret = amdgpu_device_wb_get(adev, &fence_offset);
+ ret = amdgpu_device_wb_get(adev, &status_offset);
if (ret)
return ret;
- fence_gpu_addr =
- adev->wb.gpu_addr + (fence_offset * 4);
- fence_ptr = (u64 *)&adev->wb.wb[fence_offset];
- *fence_ptr = 0;
+
+ status_gpu_addr = adev->wb.gpu_addr + (status_offset * 4);
+ status_ptr = (u64 *)&adev->wb.wb[status_offset];
+ *status_ptr = 0;
spin_lock_irqsave(&mes->ring_lock, flags);
- if (amdgpu_ring_alloc(ring, ndw)) {
- spin_unlock_irqrestore(&mes->ring_lock, flags);
- amdgpu_device_wb_free(adev, fence_offset);
- return -ENOMEM;
- }
+ r = amdgpu_ring_alloc(ring, (size + sizeof(mes_status_pkt)) / 4);
+ if (r)
+ goto error_unlock_free;
api_status = (struct MES_API_STATUS *)((char *)pkt + api_status_off);
- api_status->api_completion_fence_addr = fence_gpu_addr;
+ api_status->api_completion_fence_addr = status_gpu_addr;
api_status->api_completion_fence_value = 1;
- amdgpu_ring_write_multiple(ring, pkt, ndw);
+ amdgpu_ring_write_multiple(ring, pkt, size / 4);
+
+ memset(&mes_status_pkt, 0, sizeof(mes_status_pkt));
+ mes_status_pkt.header.type = MES_API_TYPE_SCHEDULER;
+ mes_status_pkt.header.opcode = MES_SCH_API_QUERY_SCHEDULER_STATUS;
+ mes_status_pkt.header.dwsize = API_FRAME_SIZE_IN_DWORDS;
+ mes_status_pkt.api_status.api_completion_fence_addr =
+ ring->fence_drv.gpu_addr;
+ mes_status_pkt.api_status.api_completion_fence_value =
+ ++ring->fence_drv.sync_seq;
+
+ amdgpu_ring_write_multiple(ring, &mes_status_pkt,
+ sizeof(mes_status_pkt) / 4);
+
amdgpu_ring_commit(ring);
spin_unlock_irqrestore(&mes->ring_lock, flags);
@@ -206,15 +221,16 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes,
misc_op_str = mes_v11_0_get_misc_op_string(x_pkt);
if (misc_op_str)
- dev_dbg(adev->dev, "MES msg=%s (%s) was emitted\n", op_str, misc_op_str);
+ dev_dbg(adev->dev, "MES msg=%s (%s) was emitted\n", op_str,
+ misc_op_str);
else if (op_str)
dev_dbg(adev->dev, "MES msg=%s was emitted\n", op_str);
else
- dev_dbg(adev->dev, "MES msg=%d was emitted\n", x_pkt->header.opcode);
+ dev_dbg(adev->dev, "MES msg=%d was emitted\n",
+ x_pkt->header.opcode);
- r = amdgpu_mes_fence_wait_polling(fence_ptr, (u64)1, timeout);
- amdgpu_device_wb_free(adev, fence_offset);
- if (r < 1) {
+ r = amdgpu_fence_wait_polling(ring, ring->fence_drv.sync_seq, timeout);
+ if (r < 1 || !*status_ptr) {
if (misc_op_str)
dev_err(adev->dev, "MES failed to respond to msg=%s (%s)\n",
@@ -229,10 +245,19 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes,
while (halt_if_hws_hang)
schedule();
- return -ETIMEDOUT;
+ r = -ETIMEDOUT;
+ goto error_wb_free;
}
+ amdgpu_device_wb_free(adev, status_offset);
return 0;
+
+error_unlock_free:
+ spin_unlock_irqrestore(&mes->ring_lock, flags);
+
+error_wb_free:
+ amdgpu_device_wb_free(adev, status_offset);
+ return r;
}
static int convert_to_mes_queue_type(int queue_type)
diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c
index f18fdda023c9..c9f74231ad59 100644
--- a/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c
@@ -99,6 +99,7 @@ static const char *mes_v12_0_opcodes[] = {
"SET_LOG_BUFFER",
"CHANGE_GANG_PRORITY",
"QUERY_SCHEDULER_STATUS",
+ "unused",
"SET_DEBUG_VMID",
"MISC",
"UPDATE_ROOT_PAGE_TABLE",
@@ -144,18 +145,18 @@ static int mes_v12_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes,
void *pkt, int size,
int api_status_off)
{
- int ndw = size / 4;
- signed long r;
- union MESAPI__MISC *x_pkt = pkt;
- struct MES_API_STATUS *api_status;
+ union MESAPI__QUERY_MES_STATUS mes_status_pkt;
+ signed long timeout = 3000000; /* 3000 ms */
struct amdgpu_device *adev = mes->adev;
struct amdgpu_ring *ring = &mes->ring;
- unsigned long flags;
+ struct MES_API_STATUS *api_status;
+ union MESAPI__MISC *x_pkt = pkt;
const char *op_str, *misc_op_str;
- signed long timeout = 3000000; /* 3000 ms */
- u32 fence_offset;
- u64 fence_gpu_addr;
- u64 *fence_ptr;
+ unsigned long flags;
+ u64 status_gpu_addr;
+ u32 status_offset;
+ u64 *status_ptr;
+ signed long r;
int ret;
if (x_pkt->header.opcode >= MES_SCH_API_MAX)
@@ -167,28 +168,38 @@ static int mes_v12_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes,
/* Worst case in sriov where all other 15 VF timeout, each VF needs about 600ms */
timeout = 15 * 600 * 1000;
}
- BUG_ON(size % 4 != 0);
- ret = amdgpu_device_wb_get(adev, &fence_offset);
+ ret = amdgpu_device_wb_get(adev, &status_offset);
if (ret)
return ret;
- fence_gpu_addr =
- adev->wb.gpu_addr + (fence_offset * 4);
- fence_ptr = (u64 *)&adev->wb.wb[fence_offset];
- *fence_ptr = 0;
+
+ status_gpu_addr = adev->wb.gpu_addr + (status_offset * 4);
+ status_ptr = (u64 *)&adev->wb.wb[status_offset];
+ *status_ptr = 0;
spin_lock_irqsave(&mes->ring_lock, flags);
- if (amdgpu_ring_alloc(ring, ndw)) {
- spin_unlock_irqrestore(&mes->ring_lock, flags);
- amdgpu_device_wb_free(adev, fence_offset);
- return -ENOMEM;
- }
+ r = amdgpu_ring_alloc(ring, (size + sizeof(mes_status_pkt)) / 4);
+ if (r)
+ goto error_unlock_free;
api_status = (struct MES_API_STATUS *)((char *)pkt + api_status_off);
- api_status->api_completion_fence_addr = fence_gpu_addr;
+ api_status->api_completion_fence_addr = status_gpu_addr;
api_status->api_completion_fence_value = 1;
- amdgpu_ring_write_multiple(ring, pkt, ndw);
+ amdgpu_ring_write_multiple(ring, pkt, size / 4);
+
+ memset(&mes_status_pkt, 0, sizeof(mes_status_pkt));
+ mes_status_pkt.header.type = MES_API_TYPE_SCHEDULER;
+ mes_status_pkt.header.opcode = MES_SCH_API_QUERY_SCHEDULER_STATUS;
+ mes_status_pkt.header.dwsize = API_FRAME_SIZE_IN_DWORDS;
+ mes_status_pkt.api_status.api_completion_fence_addr =
+ ring->fence_drv.gpu_addr;
+ mes_status_pkt.api_status.api_completion_fence_value =
+ ++ring->fence_drv.sync_seq;
+
+ amdgpu_ring_write_multiple(ring, &mes_status_pkt,
+ sizeof(mes_status_pkt) / 4);
+
amdgpu_ring_commit(ring);
spin_unlock_irqrestore(&mes->ring_lock, flags);
@@ -196,16 +207,17 @@ static int mes_v12_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes,
misc_op_str = mes_v12_0_get_misc_op_string(x_pkt);
if (misc_op_str)
- dev_dbg(adev->dev, "MES msg=%s (%s) was emitted\n", op_str, misc_op_str);
+ dev_dbg(adev->dev, "MES msg=%s (%s) was emitted\n", op_str,
+ misc_op_str);
else if (op_str)
dev_dbg(adev->dev, "MES msg=%s was emitted\n", op_str);
else
- dev_dbg(adev->dev, "MES msg=%d was emitted\n", x_pkt->header.opcode);
+ dev_dbg(adev->dev, "MES msg=%d was emitted\n",
+ x_pkt->header.opcode);
- r = amdgpu_mes_fence_wait_polling(fence_ptr, (u64)1, timeout);
- amdgpu_device_wb_free(adev, fence_offset);
+ r = amdgpu_fence_wait_polling(ring, ring->fence_drv.sync_seq, timeout);
+ if (r < 1 || !*status_ptr) {
- if (r < 1) {
if (misc_op_str)
dev_err(adev->dev, "MES failed to respond to msg=%s (%s)\n",
op_str, misc_op_str);
@@ -219,10 +231,19 @@ static int mes_v12_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes,
while (halt_if_hws_hang)
schedule();
- return -ETIMEDOUT;
+ r = -ETIMEDOUT;
+ goto error_wb_free;
}
+ amdgpu_device_wb_free(adev, status_offset);
return 0;
+
+error_unlock_free:
+ spin_unlock_irqrestore(&mes->ring_lock, flags);
+
+error_wb_free:
+ amdgpu_device_wb_free(adev, status_offset);
+ return r;
}
static int convert_to_mes_queue_type(int queue_type)
diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c
index 92432cd2c0c7..9689e2b5d4e5 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c
+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c
@@ -544,7 +544,7 @@ static int mmhub_v1_7_set_clockgating(struct amdgpu_device *adev,
static void mmhub_v1_7_get_clockgating(struct amdgpu_device *adev, u64 *flags)
{
- int data, data1;
+ u32 data, data1;
if (amdgpu_sriov_vf(adev))
*flags = 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c
index 7a1ff298417a..621761a17ac7 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c
+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c
@@ -566,9 +566,11 @@ static bool mmhub_v1_8_query_utcl2_poison_status(struct amdgpu_device *adev,
status = RREG32_SOC15(MMHUB, hub_inst, regVM_L2_PROTECTION_FAULT_STATUS);
fed = REG_GET_FIELD(status, VM_L2_PROTECTION_FAULT_STATUS, FED);
- /* reset page fault status */
- WREG32_P(SOC15_REG_OFFSET(MMHUB, hub_inst,
- regVM_L2_PROTECTION_FAULT_STATUS), 1, ~1);
+ if (!amdgpu_sriov_vf(adev)) {
+ /* clear page fault status and address */
+ WREG32_P(SOC15_REG_OFFSET(MMHUB, hub_inst,
+ regVM_L2_PROTECTION_FAULT_CNTL), 1, ~1);
+ }
return fed;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c
index 02fd45261399..a0cc8e218ca1 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c
@@ -671,7 +671,7 @@ static int mmhub_v2_0_set_clockgating(struct amdgpu_device *adev,
static void mmhub_v2_0_get_clockgating(struct amdgpu_device *adev, u64 *flags)
{
- int data, data1;
+ u32 data, data1;
if (amdgpu_sriov_vf(adev))
*flags = 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v3_3.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v3_3.c
index 8928f9160822..b4ce3375d3fd 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v3_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v3_3.c
@@ -613,7 +613,7 @@ static int mmhub_v3_3_set_clockgating(struct amdgpu_device *adev,
static void mmhub_v3_3_get_clockgating(struct amdgpu_device *adev, u64 *flags)
{
- int data;
+ u32 data;
if (amdgpu_sriov_vf(adev))
*flags = 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c
index 1b7da4aff2b8..ff1b58e44689 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c
+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c
@@ -657,7 +657,7 @@ static int mmhub_v9_4_set_clockgating(struct amdgpu_device *adev,
static void mmhub_v9_4_get_clockgating(struct amdgpu_device *adev, u64 *flags)
{
- int data, data1;
+ u32 data, data1;
if (amdgpu_sriov_vf(adev))
*flags = 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c
index f4c47492e0cd..f5411b798e11 100644
--- a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c
+++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c
@@ -93,7 +93,7 @@ static int xgpu_ai_poll_ack(struct amdgpu_device *adev)
timeout -= 5;
} while (timeout > 1);
- pr_err("Doesn't get TRN_MSG_ACK from pf in %d msec\n", AI_MAILBOX_POLL_ACK_TIMEDOUT);
+ dev_err(adev->dev, "Doesn't get TRN_MSG_ACK from pf in %d msec\n", AI_MAILBOX_POLL_ACK_TIMEDOUT);
return -ETIME;
}
@@ -111,7 +111,7 @@ static int xgpu_ai_poll_msg(struct amdgpu_device *adev, enum idh_event event)
timeout -= 10;
} while (timeout > 1);
- pr_err("Doesn't get msg:%d from pf, error=%d\n", event, r);
+ dev_err(adev->dev, "Doesn't get msg:%d from pf, error=%d\n", event, r);
return -ETIME;
}
@@ -132,7 +132,7 @@ static void xgpu_ai_mailbox_trans_msg (struct amdgpu_device *adev,
xgpu_ai_mailbox_set_valid(adev, false);
trn = xgpu_ai_peek_ack(adev);
if (trn) {
- pr_err("trn=%x ACK should not assert! wait again !\n", trn);
+ dev_err_ratelimited(adev->dev, "trn=%x ACK should not assert! wait again !\n", trn);
msleep(1);
}
} while(trn);
@@ -155,7 +155,7 @@ static void xgpu_ai_mailbox_trans_msg (struct amdgpu_device *adev,
/* start to poll ack */
r = xgpu_ai_poll_ack(adev);
if (r)
- pr_err("Doesn't get ack from pf, continue\n");
+ dev_err(adev->dev, "Doesn't get ack from pf, continue\n");
xgpu_ai_mailbox_set_valid(adev, false);
}
@@ -173,7 +173,7 @@ static int xgpu_ai_send_access_requests(struct amdgpu_device *adev,
req == IDH_REQ_GPU_RESET_ACCESS) {
r = xgpu_ai_poll_msg(adev, IDH_READY_TO_ACCESS_GPU);
if (r) {
- pr_err("Doesn't get READY_TO_ACCESS_GPU from pf, give up\n");
+ dev_err(adev->dev, "Doesn't get READY_TO_ACCESS_GPU from pf, give up\n");
return r;
}
/* Retrieve checksum from mailbox2 */
@@ -231,7 +231,7 @@ static int xgpu_ai_mailbox_ack_irq(struct amdgpu_device *adev,
struct amdgpu_irq_src *source,
struct amdgpu_iv_entry *entry)
{
- DRM_DEBUG("get ack intr and do nothing.\n");
+ dev_dbg(adev->dev, "get ack intr and do nothing.\n");
return 0;
}
@@ -249,38 +249,33 @@ static int xgpu_ai_set_mailbox_ack_irq(struct amdgpu_device *adev,
return 0;
}
-static void xgpu_ai_mailbox_flr_work(struct work_struct *work)
+static void xgpu_ai_ready_to_reset(struct amdgpu_device *adev)
{
- struct amdgpu_virt *virt = container_of(work, struct amdgpu_virt, flr_work);
- struct amdgpu_device *adev = container_of(virt, struct amdgpu_device, virt);
- int timeout = AI_MAILBOX_POLL_FLR_TIMEDOUT;
-
- /* block amdgpu_gpu_recover till msg FLR COMPLETE received,
- * otherwise the mailbox msg will be ruined/reseted by
- * the VF FLR.
- */
- if (atomic_cmpxchg(&adev->reset_domain->in_gpu_reset, 0, 1) != 0)
- return;
-
- down_write(&adev->reset_domain->sem);
-
- amdgpu_virt_fini_data_exchange(adev);
-
xgpu_ai_mailbox_trans_msg(adev, IDH_READY_TO_RESET, 0, 0, 0);
+}
+static int xgpu_ai_wait_reset(struct amdgpu_device *adev)
+{
+ int timeout = AI_MAILBOX_POLL_FLR_TIMEDOUT;
do {
- if (xgpu_ai_mailbox_peek_msg(adev) == IDH_FLR_NOTIFICATION_CMPL)
- goto flr_done;
-
+ if (xgpu_ai_mailbox_peek_msg(adev) == IDH_FLR_NOTIFICATION_CMPL) {
+ dev_dbg(adev->dev, "Got AI IDH_FLR_NOTIFICATION_CMPL after %d ms\n", AI_MAILBOX_POLL_FLR_TIMEDOUT - timeout);
+ return 0;
+ }
msleep(10);
timeout -= 10;
} while (timeout > 1);
- dev_warn(adev->dev, "waiting IDH_FLR_NOTIFICATION_CMPL timeout\n");
+ dev_dbg(adev->dev, "waiting AI IDH_FLR_NOTIFICATION_CMPL timeout\n");
+ return -ETIME;
+}
+
+static void xgpu_ai_mailbox_flr_work(struct work_struct *work)
+{
+ struct amdgpu_virt *virt = container_of(work, struct amdgpu_virt, flr_work);
+ struct amdgpu_device *adev = container_of(virt, struct amdgpu_device, virt);
-flr_done:
- atomic_set(&adev->reset_domain->in_gpu_reset, 0);
- up_write(&adev->reset_domain->sem);
+ amdgpu_virt_fini_data_exchange(adev);
/* Trigger recovery for world switch failure if no TDR */
if (amdgpu_device_should_recover_gpu(adev)
@@ -413,12 +408,21 @@ static void xgpu_ai_ras_poison_handler(struct amdgpu_device *adev,
xgpu_ai_send_access_requests(adev, IDH_RAS_POISON);
}
+static bool xgpu_ai_rcvd_ras_intr(struct amdgpu_device *adev)
+{
+ enum idh_event msg = xgpu_ai_mailbox_peek_msg(adev);
+
+ return (msg == IDH_RAS_ERROR_DETECTED || msg == 0xFFFFFFFF);
+}
+
const struct amdgpu_virt_ops xgpu_ai_virt_ops = {
.req_full_gpu = xgpu_ai_request_full_gpu_access,
.rel_full_gpu = xgpu_ai_release_full_gpu_access,
.reset_gpu = xgpu_ai_request_reset,
- .wait_reset = NULL,
+ .ready_to_reset = xgpu_ai_ready_to_reset,
+ .wait_reset = xgpu_ai_wait_reset,
.trans_msg = xgpu_ai_mailbox_trans_msg,
.req_init_data = xgpu_ai_request_init_data,
.ras_poison_handler = xgpu_ai_ras_poison_handler,
+ .rcvd_ras_intr = xgpu_ai_rcvd_ras_intr,
};
diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.h b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.h
index c520b2fabfb9..ed57cbc150af 100644
--- a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.h
+++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.h
@@ -51,7 +51,9 @@ enum idh_event {
IDH_FAIL,
IDH_QUERY_ALIVE,
IDH_REQ_GPU_INIT_DATA_READY,
-
+ IDH_RAS_POISON_READY,
+ IDH_PF_SOFT_FLR_NOTIFICATION,
+ IDH_RAS_ERROR_DETECTED,
IDH_TEXT_MESSAGE = 255,
};
diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c
index 37b49a5ed2a1..f47bd7ada4d7 100644
--- a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c
+++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c
@@ -91,7 +91,7 @@ static int xgpu_nv_poll_ack(struct amdgpu_device *adev)
timeout -= 5;
} while (timeout > 1);
- pr_err("Doesn't get TRN_MSG_ACK from pf in %d msec\n", NV_MAILBOX_POLL_ACK_TIMEDOUT);
+ dev_err(adev->dev, "Doesn't get TRN_MSG_ACK from pf in %d msec \n", NV_MAILBOX_POLL_ACK_TIMEDOUT);
return -ETIME;
}
@@ -106,13 +106,16 @@ static int xgpu_nv_poll_msg(struct amdgpu_device *adev, enum idh_event event)
do {
r = xgpu_nv_mailbox_rcv_msg(adev, event);
- if (!r)
+ if (!r) {
+ dev_dbg(adev->dev, "rcv_msg 0x%x after %llu ms\n", event, NV_MAILBOX_POLL_MSG_TIMEDOUT - timeout + now);
return 0;
+ }
msleep(10);
now = (uint64_t)ktime_to_ms(ktime_get());
} while (timeout > now);
+ dev_dbg(adev->dev, "nv_poll_msg timed out\n");
return -ETIME;
}
@@ -133,11 +136,12 @@ static void xgpu_nv_mailbox_trans_msg (struct amdgpu_device *adev,
xgpu_nv_mailbox_set_valid(adev, false);
trn = xgpu_nv_peek_ack(adev);
if (trn) {
- pr_err("trn=%x ACK should not assert! wait again !\n", trn);
+ dev_err_ratelimited(adev->dev, "trn=%x ACK should not assert! wait again !\n", trn);
msleep(1);
}
} while (trn);
+ dev_dbg(adev->dev, "trans_msg req = 0x%x, data1 = 0x%x\n", req, data1);
WREG32_NO_KIQ(mmMAILBOX_MSGBUF_TRN_DW0, req);
WREG32_NO_KIQ(mmMAILBOX_MSGBUF_TRN_DW1, data1);
WREG32_NO_KIQ(mmMAILBOX_MSGBUF_TRN_DW2, data2);
@@ -147,7 +151,7 @@ static void xgpu_nv_mailbox_trans_msg (struct amdgpu_device *adev,
/* start to poll ack */
r = xgpu_nv_poll_ack(adev);
if (r)
- pr_err("Doesn't get ack from pf, continue\n");
+ dev_err(adev->dev, "Doesn't get ack from pf, continue\n");
xgpu_nv_mailbox_set_valid(adev, false);
}
@@ -185,7 +189,7 @@ send_request:
goto send_request;
if (req != IDH_REQ_GPU_INIT_DATA) {
- pr_err("Doesn't get msg:%d from pf, error=%d\n", event, r);
+ dev_err(adev->dev, "Doesn't get msg:%d from pf, error=%d\n", event, r);
return r;
} else /* host doesn't support REQ_GPU_INIT_DATA handshake */
adev->virt.req_init_data_ver = 0;
@@ -261,7 +265,7 @@ static int xgpu_nv_mailbox_ack_irq(struct amdgpu_device *adev,
struct amdgpu_irq_src *source,
struct amdgpu_iv_entry *entry)
{
- DRM_DEBUG("get ack intr and do nothing.\n");
+ dev_dbg(adev->dev, "get ack intr and do nothing.\n");
return 0;
}
@@ -282,38 +286,33 @@ static int xgpu_nv_set_mailbox_ack_irq(struct amdgpu_device *adev,
return 0;
}
-static void xgpu_nv_mailbox_flr_work(struct work_struct *work)
+static void xgpu_nv_ready_to_reset(struct amdgpu_device *adev)
{
- struct amdgpu_virt *virt = container_of(work, struct amdgpu_virt, flr_work);
- struct amdgpu_device *adev = container_of(virt, struct amdgpu_device, virt);
- int timeout = NV_MAILBOX_POLL_FLR_TIMEDOUT;
-
- /* block amdgpu_gpu_recover till msg FLR COMPLETE received,
- * otherwise the mailbox msg will be ruined/reseted by
- * the VF FLR.
- */
- if (atomic_cmpxchg(&adev->reset_domain->in_gpu_reset, 0, 1) != 0)
- return;
-
- down_write(&adev->reset_domain->sem);
-
- amdgpu_virt_fini_data_exchange(adev);
-
xgpu_nv_mailbox_trans_msg(adev, IDH_READY_TO_RESET, 0, 0, 0);
+}
+static int xgpu_nv_wait_reset(struct amdgpu_device *adev)
+{
+ int timeout = NV_MAILBOX_POLL_FLR_TIMEDOUT;
do {
- if (xgpu_nv_mailbox_peek_msg(adev) == IDH_FLR_NOTIFICATION_CMPL)
- goto flr_done;
-
+ if (xgpu_nv_mailbox_peek_msg(adev) == IDH_FLR_NOTIFICATION_CMPL) {
+ dev_dbg(adev->dev, "Got NV IDH_FLR_NOTIFICATION_CMPL after %d ms\n", NV_MAILBOX_POLL_FLR_TIMEDOUT - timeout);
+ return 0;
+ }
msleep(10);
timeout -= 10;
} while (timeout > 1);
- dev_warn(adev->dev, "waiting IDH_FLR_NOTIFICATION_CMPL timeout\n");
+ dev_dbg(adev->dev, "waiting NV IDH_FLR_NOTIFICATION_CMPL timeout\n");
+ return -ETIME;
+}
+
+static void xgpu_nv_mailbox_flr_work(struct work_struct *work)
+{
+ struct amdgpu_virt *virt = container_of(work, struct amdgpu_virt, flr_work);
+ struct amdgpu_device *adev = container_of(virt, struct amdgpu_device, virt);
-flr_done:
- atomic_set(&adev->reset_domain->in_gpu_reset, 0);
- up_write(&adev->reset_domain->sem);
+ amdgpu_virt_fini_data_exchange(adev);
/* Trigger recovery for world switch failure if no TDR */
if (amdgpu_device_should_recover_gpu(adev)
@@ -450,12 +449,21 @@ static void xgpu_nv_ras_poison_handler(struct amdgpu_device *adev,
}
}
+static bool xgpu_nv_rcvd_ras_intr(struct amdgpu_device *adev)
+{
+ enum idh_event msg = xgpu_nv_mailbox_peek_msg(adev);
+
+ return (msg == IDH_RAS_ERROR_DETECTED || msg == 0xFFFFFFFF);
+}
+
const struct amdgpu_virt_ops xgpu_nv_virt_ops = {
.req_full_gpu = xgpu_nv_request_full_gpu_access,
.rel_full_gpu = xgpu_nv_release_full_gpu_access,
.req_init_data = xgpu_nv_request_init_data,
.reset_gpu = xgpu_nv_request_reset,
- .wait_reset = NULL,
+ .ready_to_reset = xgpu_nv_ready_to_reset,
+ .wait_reset = xgpu_nv_wait_reset,
.trans_msg = xgpu_nv_mailbox_trans_msg,
.ras_poison_handler = xgpu_nv_ras_poison_handler,
+ .rcvd_ras_intr = xgpu_nv_rcvd_ras_intr,
};
diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.h b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.h
index 1e8fd90cab43..caf616a2c8a6 100644
--- a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.h
+++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.h
@@ -26,7 +26,7 @@
#define NV_MAILBOX_POLL_ACK_TIMEDOUT 500
#define NV_MAILBOX_POLL_MSG_TIMEDOUT 6000
-#define NV_MAILBOX_POLL_FLR_TIMEDOUT 5000
+#define NV_MAILBOX_POLL_FLR_TIMEDOUT 10000
#define NV_MAILBOX_POLL_MSG_REP_MAX 11
enum idh_request {
@@ -52,7 +52,8 @@ enum idh_event {
IDH_QUERY_ALIVE,
IDH_REQ_GPU_INIT_DATA_READY,
IDH_RAS_POISON_READY,
-
+ IDH_PF_SOFT_FLR_NOTIFICATION,
+ IDH_RAS_ERROR_DETECTED,
IDH_TEXT_MESSAGE = 255,
};
diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_vi.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_vi.c
index 78cd07744ebe..e1d63bed84bf 100644
--- a/drivers/gpu/drm/amd/amdgpu/mxgpu_vi.c
+++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_vi.c
@@ -515,12 +515,6 @@ static void xgpu_vi_mailbox_flr_work(struct work_struct *work)
struct amdgpu_virt *virt = container_of(work, struct amdgpu_virt, flr_work);
struct amdgpu_device *adev = container_of(virt, struct amdgpu_device, virt);
- /* wait until RCV_MSG become 3 */
- if (xgpu_vi_poll_msg(adev, IDH_FLR_NOTIFICATION_CMPL)) {
- pr_err("failed to receive FLR_CMPL\n");
- return;
- }
-
/* Trigger recovery due to world switch failure */
if (amdgpu_device_should_recover_gpu(adev)) {
struct amdgpu_reset_context reset_context;
diff --git a/drivers/gpu/drm/amd/amdgpu/nbif_v6_3_1.c b/drivers/gpu/drm/amd/amdgpu/nbif_v6_3_1.c
index 5a20bb229788..39919e0892c1 100644
--- a/drivers/gpu/drm/amd/amdgpu/nbif_v6_3_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/nbif_v6_3_1.c
@@ -345,6 +345,7 @@ static void nbif_v6_3_1_program_aspm(struct amdgpu_device *adev)
{
#ifdef CONFIG_PCIEASPM
uint32_t def, data;
+ u16 devctl2, ltr;
def = data = RREG32_SOC15(PCIE, 0, regPCIE_LC_CNTL);
data &= ~PCIE_LC_CNTL__LC_L1_INACTIVITY_MASK;
@@ -374,12 +375,17 @@ static void nbif_v6_3_1_program_aspm(struct amdgpu_device *adev)
if (def != data)
WREG32_SOC15(NBIO, 0, regRCC_STRAP0_RCC_BIF_STRAP5, data);
- def = data = RREG32_SOC15(NBIO, 0, regBIF_CFG_DEV0_EPF0_DEVICE_CNTL2);
- data &= ~BIF_CFG_DEV0_EPF0_DEVICE_CNTL2__LTR_EN_MASK;
+ pcie_capability_read_word(adev->pdev, PCI_EXP_DEVCTL2, &devctl2);
+ data = def = devctl2;
+ data &= ~PCI_EXP_DEVCTL2_LTR_EN;
if (def != data)
- WREG32_SOC15(NBIO, 0, regBIF_CFG_DEV0_EPF0_DEVICE_CNTL2, data);
+ pcie_capability_set_word(adev->pdev, PCI_EXP_DEVCTL2, (u16)data);
+
+ ltr = pci_find_ext_capability(adev->pdev, PCI_EXT_CAP_ID_LTR);
- WREG32_SOC15(NBIO, 0, regBIF_CFG_DEV0_EPF0_PCIE_LTR_CAP, 0x10011001);
+ if (ltr) {
+ pci_write_config_dword(adev->pdev, ltr + PCI_LTR_MAX_SNOOP_LAT, 0x10011001);
+ }
#if 0
/* regPSWUSP0_PCIE_LC_CNTL2 should be replace by PCIE_LC_CNTL2 or someone else ? */
diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c b/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c
index 32cc60ce5521..8d80df94bd8b 100644
--- a/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c
+++ b/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c
@@ -414,6 +414,7 @@ static void nbio_v7_4_handle_ras_controller_intr_no_bifring(struct amdgpu_device
/* ras_controller_int is dedicated for nbif ras error,
* not the global interrupt for sync flood
*/
+ amdgpu_ras_set_fed(adev, true);
amdgpu_ras_reset_gpu(adev);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_gfx_if.h b/drivers/gpu/drm/amd/amdgpu/psp_gfx_if.h
index 7566973ed8f5..37b5ddd6f13b 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_gfx_if.h
+++ b/drivers/gpu/drm/amd/amdgpu/psp_gfx_if.h
@@ -464,8 +464,9 @@ struct psp_gfx_rb_frame
#define PSP_ERR_UNKNOWN_COMMAND 0x00000100
enum tee_error_code {
- TEE_SUCCESS = 0x00000000,
- TEE_ERROR_NOT_SUPPORTED = 0xFFFF000A,
+ TEE_SUCCESS = 0x00000000,
+ TEE_ERROR_CANCEL = 0xFFFF0002,
+ TEE_ERROR_NOT_SUPPORTED = 0xFFFF000A,
};
#endif /* _PSP_TEE_GFX_IF_H_ */
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c
index b52e15e2dcc7..1251ee38a676 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c
@@ -57,6 +57,8 @@ MODULE_FIRMWARE("amdgpu/psp_14_0_0_toc.bin");
MODULE_FIRMWARE("amdgpu/psp_14_0_0_ta.bin");
MODULE_FIRMWARE("amdgpu/psp_14_0_1_toc.bin");
MODULE_FIRMWARE("amdgpu/psp_14_0_1_ta.bin");
+MODULE_FIRMWARE("amdgpu/psp_14_0_4_toc.bin");
+MODULE_FIRMWARE("amdgpu/psp_14_0_4_ta.bin");
/* For large FW files the time to complete can be very long */
#define USBC_PD_POLLING_LIMIT_S 240
@@ -106,6 +108,7 @@ static int psp_v13_0_init_microcode(struct psp_context *psp)
case IP_VERSION(13, 0, 11):
case IP_VERSION(14, 0, 0):
case IP_VERSION(14, 0, 1):
+ case IP_VERSION(14, 0, 4):
err = psp_init_toc_microcode(psp, ucode_prefix);
if (err)
return err;
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v14_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v14_0.c
index cc0248efa6b6..4d33c95a5116 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v14_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v14_0.c
@@ -32,7 +32,9 @@
#include "mp/mp_14_0_2_sh_mask.h"
MODULE_FIRMWARE("amdgpu/psp_14_0_2_sos.bin");
+MODULE_FIRMWARE("amdgpu/psp_14_0_2_ta.bin");
MODULE_FIRMWARE("amdgpu/psp_14_0_3_sos.bin");
+MODULE_FIRMWARE("amdgpu/psp_14_0_3_ta.bin");
/* For large FW files the time to complete can be very long */
#define USBC_PD_POLLING_LIMIT_S 240
@@ -66,6 +68,9 @@ static int psp_v14_0_init_microcode(struct psp_context *psp)
err = psp_init_sos_microcode(psp, ucode_prefix);
if (err)
return err;
+ err = psp_init_ta_microcode(psp, ucode_prefix);
+ if (err)
+ return err;
break;
default:
BUG();
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
index ac8a9b9b3e52..725392522267 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
@@ -127,7 +127,6 @@ static void sdma_v2_4_free_microcode(struct amdgpu_device *adev)
static int sdma_v2_4_init_microcode(struct amdgpu_device *adev)
{
const char *chip_name;
- char fw_name[30];
int err = 0, i;
struct amdgpu_firmware_info *info = NULL;
const struct common_firmware_header *header = NULL;
@@ -145,10 +144,11 @@ static int sdma_v2_4_init_microcode(struct amdgpu_device *adev)
for (i = 0; i < adev->sdma.num_instances; i++) {
if (i == 0)
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sdma.bin", chip_name);
+ err = amdgpu_ucode_request(adev, &adev->sdma.instance[i].fw,
+ "amdgpu/%s_sdma.bin", chip_name);
else
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sdma1.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->sdma.instance[i].fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->sdma.instance[i].fw,
+ "amdgpu/%s_sdma1.bin", chip_name);
if (err)
goto out;
hdr = (const struct sdma_firmware_header_v1_0 *)adev->sdma.instance[i].fw->data;
@@ -169,7 +169,8 @@ static int sdma_v2_4_init_microcode(struct amdgpu_device *adev)
out:
if (err) {
- pr_err("sdma_v2_4: Failed to load firmware \"%s\"\n", fw_name);
+ pr_err("sdma_v2_4: Failed to load firmware \"%s_sdma%s.bin\"\n",
+ chip_name, i == 0 ? "" : "1");
for (i = 0; i < adev->sdma.num_instances; i++)
amdgpu_ucode_release(&adev->sdma.instance[i].fw);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
index b8ebdc4ae6f6..aa637541da58 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
@@ -267,7 +267,6 @@ static void sdma_v3_0_free_microcode(struct amdgpu_device *adev)
static int sdma_v3_0_init_microcode(struct amdgpu_device *adev)
{
const char *chip_name;
- char fw_name[30];
int err = 0, i;
struct amdgpu_firmware_info *info = NULL;
const struct common_firmware_header *header = NULL;
@@ -305,10 +304,11 @@ static int sdma_v3_0_init_microcode(struct amdgpu_device *adev)
for (i = 0; i < adev->sdma.num_instances; i++) {
if (i == 0)
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sdma.bin", chip_name);
+ err = amdgpu_ucode_request(adev, &adev->sdma.instance[i].fw,
+ "amdgpu/%s_sdma.bin", chip_name);
else
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sdma1.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->sdma.instance[i].fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->sdma.instance[i].fw,
+ "amdgpu/%s_sdma1.bin", chip_name);
if (err)
goto out;
hdr = (const struct sdma_firmware_header_v1_0 *)adev->sdma.instance[i].fw->data;
@@ -327,7 +327,8 @@ static int sdma_v3_0_init_microcode(struct amdgpu_device *adev)
}
out:
if (err) {
- pr_err("sdma_v3_0: Failed to load firmware \"%s\"\n", fw_name);
+ pr_err("sdma_v3_0: Failed to load firmware \"%s_sdma%s.bin\"\n",
+ chip_name, i == 0 ? "" : "1");
for (i = 0; i < adev->sdma.num_instances; i++)
amdgpu_ucode_release(&adev->sdma.instance[i].fw);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c
index 01644a869738..2c55bfd935bb 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c
@@ -83,7 +83,7 @@ static unsigned sdma_v4_4_2_seq_to_irq_id(int seq_num)
}
}
-static int sdma_v4_4_2_irq_id_to_seq(unsigned client_id)
+static int sdma_v4_4_2_irq_id_to_seq(struct amdgpu_device *adev, unsigned client_id)
{
switch (client_id) {
case SOC15_IH_CLIENTID_SDMA0:
@@ -91,9 +91,15 @@ static int sdma_v4_4_2_irq_id_to_seq(unsigned client_id)
case SOC15_IH_CLIENTID_SDMA1:
return 1;
case SOC15_IH_CLIENTID_SDMA2:
- return 2;
+ if (amdgpu_sriov_vf(adev) && (adev->gfx.xcc_mask == 0x1))
+ return 0;
+ else
+ return 2;
case SOC15_IH_CLIENTID_SDMA3:
- return 3;
+ if (amdgpu_sriov_vf(adev) && (adev->gfx.xcc_mask == 0x1))
+ return 1;
+ else
+ return 3;
default:
return -EINVAL;
}
@@ -1524,7 +1530,7 @@ static int sdma_v4_4_2_process_trap_irq(struct amdgpu_device *adev,
uint32_t instance, i;
DRM_DEBUG("IH: SDMA trap\n");
- instance = sdma_v4_4_2_irq_id_to_seq(entry->client_id);
+ instance = sdma_v4_4_2_irq_id_to_seq(adev, entry->client_id);
/* Client id gives the SDMA instance in AID. To know the exact SDMA
* instance, interrupt entry gives the node id which corresponds to the AID instance.
@@ -1567,7 +1573,7 @@ static int sdma_v4_4_2_process_ras_data_cb(struct amdgpu_device *adev,
if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__SDMA))
goto out;
- instance = sdma_v4_4_2_irq_id_to_seq(entry->client_id);
+ instance = sdma_v4_4_2_irq_id_to_seq(adev, entry->client_id);
if (instance < 0)
goto out;
@@ -1586,7 +1592,7 @@ static int sdma_v4_4_2_process_illegal_inst_irq(struct amdgpu_device *adev,
DRM_ERROR("Illegal instruction in SDMA command stream\n");
- instance = sdma_v4_4_2_irq_id_to_seq(entry->client_id);
+ instance = sdma_v4_4_2_irq_id_to_seq(adev, entry->client_id);
if (instance < 0)
return 0;
@@ -1620,7 +1626,7 @@ static int sdma_v4_4_2_print_iv_entry(struct amdgpu_device *adev,
struct amdgpu_task_info *task_info;
u64 addr;
- instance = sdma_v4_4_2_irq_id_to_seq(entry->client_id);
+ instance = sdma_v4_4_2_irq_id_to_seq(adev, entry->client_id);
if (instance < 0 || instance >= adev->sdma.num_instances) {
dev_err(adev->dev, "sdma instance invalid %d\n", instance);
return -EINVAL;
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c
index cc9e961f0078..af1e90159ce3 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c
@@ -176,6 +176,14 @@ static void sdma_v5_2_ring_set_wptr(struct amdgpu_ring *ring)
DRM_DEBUG("calling WDOORBELL64(0x%08x, 0x%016llx)\n",
ring->doorbell_index, ring->wptr << 2);
WDOORBELL64(ring->doorbell_index, ring->wptr << 2);
+ /* SDMA seems to miss doorbells sometimes when powergating kicks in.
+ * Updating the wptr directly will wake it. This is only safe because
+ * we disallow gfxoff in begin_use() and then allow it again in end_use().
+ */
+ WREG32(sdma_v5_2_get_reg_offset(adev, ring->me, mmSDMA0_GFX_RB_WPTR),
+ lower_32_bits(ring->wptr << 2));
+ WREG32(sdma_v5_2_get_reg_offset(adev, ring->me, mmSDMA0_GFX_RB_WPTR_HI),
+ upper_32_bits(ring->wptr << 2));
} else {
DRM_DEBUG("Not using doorbell -- "
"mmSDMA%i_GFX_RB_WPTR == 0x%08x "
@@ -1647,6 +1655,10 @@ static void sdma_v5_2_ring_begin_use(struct amdgpu_ring *ring)
* but it shouldn't hurt for other parts since
* this GFXOFF will be disallowed anyway when SDMA is
* active, this just makes it explicit.
+ * sdma_v5_2_ring_set_wptr() takes advantage of this
+ * to update the wptr because sometimes SDMA seems to miss
+ * doorbells when entering PG. If you remove this, update
+ * sdma_v5_2_ring_set_wptr() as well!
*/
amdgpu_gfx_off_ctrl(adev, false);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
index c833b6b8373b..dab4c2db8c9d 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
@@ -50,6 +50,7 @@ MODULE_FIRMWARE("amdgpu/sdma_6_0_2.bin");
MODULE_FIRMWARE("amdgpu/sdma_6_0_3.bin");
MODULE_FIRMWARE("amdgpu/sdma_6_1_0.bin");
MODULE_FIRMWARE("amdgpu/sdma_6_1_1.bin");
+MODULE_FIRMWARE("amdgpu/sdma_6_1_2.bin");
#define SDMA1_REG_OFFSET 0x600
#define SDMA0_HYP_DEC_REG_START 0x5880
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v6_0_0_pkt_open.h b/drivers/gpu/drm/amd/amdgpu/sdma_v6_0_0_pkt_open.h
index 6af23e7888ca..d8cf830916b9 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v6_0_0_pkt_open.h
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v6_0_0_pkt_open.h
@@ -91,6 +91,14 @@
#define SDMA_GCR_GLM_WB (1 << 4)
#define SDMA_GCR_GL1_RANGE(x) (((x) & 0x3) << 2)
#define SDMA_GCR_GLI_INV(x) (((x) & 0x3) << 0)
+
+#define SDMA_DCC_DATA_FORMAT(x) ((x) & 0x3f)
+#define SDMA_DCC_NUM_TYPE(x) (((x) & 0x7) << 9)
+#define SDMA_DCC_READ_CM(x) (((x) & 0x3) << 16)
+#define SDMA_DCC_WRITE_CM(x) (((x) & 0x3) << 18)
+#define SDMA_DCC_MAX_COM(x) (((x) & 0x3) << 24)
+#define SDMA_DCC_MAX_UCOM(x) (((x) & 0x1) << 26)
+
/*
** Definitions for SDMA_PKT_COPY_LINEAR packet
*/
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c
index ab1dea77be6e..41b5e45697dc 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c
@@ -1566,15 +1566,30 @@ static void sdma_v7_0_emit_copy_buffer(struct amdgpu_ib *ib,
uint32_t byte_count,
uint32_t copy_flags)
{
+ uint32_t num_type, data_format, max_com;
+
+ max_com = AMDGPU_COPY_FLAGS_GET(copy_flags, MAX_COMPRESSED);
+ data_format = AMDGPU_COPY_FLAGS_GET(copy_flags, DATA_FORMAT);
+ num_type = AMDGPU_COPY_FLAGS_GET(copy_flags, NUMBER_TYPE);
+
ib->ptr[ib->length_dw++] = SDMA_PKT_COPY_LINEAR_HEADER_OP(SDMA_OP_COPY) |
SDMA_PKT_COPY_LINEAR_HEADER_SUB_OP(SDMA_SUBOP_COPY_LINEAR) |
- SDMA_PKT_COPY_LINEAR_HEADER_TMZ((copy_flags & AMDGPU_COPY_FLAGS_TMZ) ? 1 : 0);
+ SDMA_PKT_COPY_LINEAR_HEADER_TMZ((copy_flags & AMDGPU_COPY_FLAGS_TMZ) ? 1 : 0) |
+ SDMA_PKT_COPY_LINEAR_HEADER_CPV((copy_flags &
+ (AMDGPU_COPY_FLAGS_READ_DECOMPRESSED | AMDGPU_COPY_FLAGS_WRITE_COMPRESSED)) ? 1 : 0);
+
ib->ptr[ib->length_dw++] = byte_count - 1;
ib->ptr[ib->length_dw++] = 0; /* src/dst endian swap */
ib->ptr[ib->length_dw++] = lower_32_bits(src_offset);
ib->ptr[ib->length_dw++] = upper_32_bits(src_offset);
ib->ptr[ib->length_dw++] = lower_32_bits(dst_offset);
ib->ptr[ib->length_dw++] = upper_32_bits(dst_offset);
+
+ if ((copy_flags & (AMDGPU_COPY_FLAGS_READ_DECOMPRESSED | AMDGPU_COPY_FLAGS_WRITE_COMPRESSED)))
+ ib->ptr[ib->length_dw++] = SDMA_DCC_DATA_FORMAT(data_format) | SDMA_DCC_NUM_TYPE(num_type) |
+ ((copy_flags & AMDGPU_COPY_FLAGS_READ_DECOMPRESSED) ? SDMA_DCC_READ_CM(2) : 0) |
+ ((copy_flags & AMDGPU_COPY_FLAGS_WRITE_COMPRESSED) ? SDMA_DCC_WRITE_CM(1) : 0) |
+ SDMA_DCC_MAX_COM(max_com) | SDMA_DCC_MAX_UCOM(1);
}
/**
@@ -1603,7 +1618,6 @@ static const struct amdgpu_buffer_funcs sdma_v7_0_buffer_funcs = {
.copy_max_bytes = 0x400000,
.copy_num_dw = 7,
.emit_copy_buffer = sdma_v7_0_emit_copy_buffer,
-
.fill_max_bytes = 0x400000,
.fill_num_dw = 5,
.emit_fill_buffer = sdma_v7_0_emit_fill_buffer,
diff --git a/drivers/gpu/drm/amd/amdgpu/smu_v13_0_10.c b/drivers/gpu/drm/amd/amdgpu/smu_v13_0_10.c
index 04c797d54511..0af648931df5 100644
--- a/drivers/gpu/drm/amd/amdgpu/smu_v13_0_10.c
+++ b/drivers/gpu/drm/amd/amdgpu/smu_v13_0_10.c
@@ -91,7 +91,7 @@ static int smu_v13_0_10_mode2_suspend_ip(struct amdgpu_device *adev)
adev->ip_blocks[i].status.hw = false;
}
- return r;
+ return 0;
}
static int
diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c
index 15845ecca7c7..d30ad7d56def 100644
--- a/drivers/gpu/drm/amd/amdgpu/soc21.c
+++ b/drivers/gpu/drm/amd/amdgpu/soc21.c
@@ -389,6 +389,7 @@ soc21_asic_reset_method(struct amdgpu_device *adev)
case IP_VERSION(13, 0, 11):
case IP_VERSION(14, 0, 0):
case IP_VERSION(14, 0, 1):
+ case IP_VERSION(14, 0, 4):
return AMD_RESET_METHOD_MODE2;
default:
if (amdgpu_dpm_is_baco_supported(adev))
@@ -752,6 +753,34 @@ static int soc21_common_early_init(void *handle)
AMD_PG_SUPPORT_JPEG;
adev->external_rev_id = adev->rev_id + 0xc1;
break;
+ case IP_VERSION(11, 5, 2):
+ adev->cg_flags = AMD_CG_SUPPORT_VCN_MGCG |
+ AMD_CG_SUPPORT_JPEG_MGCG |
+ AMD_CG_SUPPORT_GFX_CGCG |
+ AMD_CG_SUPPORT_GFX_CGLS |
+ AMD_CG_SUPPORT_GFX_MGCG |
+ AMD_CG_SUPPORT_GFX_FGCG |
+ AMD_CG_SUPPORT_REPEATER_FGCG |
+ AMD_CG_SUPPORT_GFX_PERF_CLK |
+ AMD_CG_SUPPORT_GFX_3D_CGCG |
+ AMD_CG_SUPPORT_GFX_3D_CGLS |
+ AMD_CG_SUPPORT_MC_MGCG |
+ AMD_CG_SUPPORT_MC_LS |
+ AMD_CG_SUPPORT_HDP_LS |
+ AMD_CG_SUPPORT_HDP_DS |
+ AMD_CG_SUPPORT_HDP_SD |
+ AMD_CG_SUPPORT_ATHUB_MGCG |
+ AMD_CG_SUPPORT_ATHUB_LS |
+ AMD_CG_SUPPORT_IH_CG |
+ AMD_CG_SUPPORT_BIF_MGCG |
+ AMD_CG_SUPPORT_BIF_LS;
+ adev->pg_flags = AMD_PG_SUPPORT_VCN_DPG |
+ AMD_PG_SUPPORT_VCN |
+ AMD_PG_SUPPORT_JPEG_DPG |
+ AMD_PG_SUPPORT_JPEG |
+ AMD_PG_SUPPORT_GFX_PG;
+ adev->external_rev_id = adev->rev_id + 0x40;
+ break;
default:
/* FIXME: not supported yet */
return -EINVAL;
@@ -927,6 +956,7 @@ static int soc21_common_set_clockgating_state(void *handle,
case IP_VERSION(7, 7, 1):
case IP_VERSION(7, 11, 0):
case IP_VERSION(7, 11, 1):
+ case IP_VERSION(7, 11, 3):
adev->nbio.funcs->update_medium_grain_clock_gating(adev,
state == AMD_CG_STATE_GATE);
adev->nbio.funcs->update_medium_grain_light_sleep(adev,
diff --git a/drivers/gpu/drm/amd/amdgpu/soc24.c b/drivers/gpu/drm/amd/amdgpu/soc24.c
index a15673e2dc99..7d641d0dadba 100644
--- a/drivers/gpu/drm/amd/amdgpu/soc24.c
+++ b/drivers/gpu/drm/amd/amdgpu/soc24.c
@@ -428,6 +428,7 @@ static int soc24_common_early_init(void *handle)
adev->pg_flags = AMD_PG_SUPPORT_VCN |
AMD_PG_SUPPORT_JPEG |
+ AMD_PG_SUPPORT_JPEG_DPG |
AMD_PG_SUPPORT_VCN_DPG;
adev->external_rev_id = adev->rev_id + 0x50;
break;
@@ -483,6 +484,10 @@ static int soc24_common_hw_init(void *handle)
*/
if (adev->nbio.funcs->remap_hdp_registers)
adev->nbio.funcs->remap_hdp_registers(adev);
+
+ if (adev->df.funcs->hw_init)
+ adev->df.funcs->hw_init(adev);
+
/* enable the doorbell aperture */
soc24_enable_doorbell_aperture(adev, true);
diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v12_0.c b/drivers/gpu/drm/amd/amdgpu/umc_v12_0.c
index 6d6350f220b0..9dbb13adb661 100644
--- a/drivers/gpu/drm/amd/amdgpu/umc_v12_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/umc_v12_0.c
@@ -29,6 +29,7 @@
#include "mp/mp_13_0_6_sh_mask.h"
#define MAX_ECC_NUM_PER_RETIREMENT 32
+#define DELAYED_TIME_FOR_GPU_RESET 1000 //ms
static inline uint64_t get_umc_v12_0_reg_offset(struct amdgpu_device *adev,
uint32_t node_inst,
@@ -557,7 +558,7 @@ static int umc_v12_0_update_ecc_status(struct amdgpu_device *adev,
ret = amdgpu_umc_logs_ecc_err(adev, &con->umc_ecc_log.de_page_tree, ecc_err);
if (ret) {
if (ret == -EEXIST)
- con->umc_ecc_log.de_updated = true;
+ con->umc_ecc_log.de_queried_count++;
else
dev_err(adev->dev, "Fail to log ecc error! ret:%d\n", ret);
@@ -566,7 +567,24 @@ static int umc_v12_0_update_ecc_status(struct amdgpu_device *adev,
return ret;
}
- con->umc_ecc_log.de_updated = true;
+ con->umc_ecc_log.de_queried_count++;
+
+ /* The problem case is as follows:
+ * 1. GPU A triggers a gpu ras reset, and GPU A drives
+ * GPU B to also perform a gpu ras reset.
+ * 2. After gpu B ras reset started, gpu B queried a DE
+ * data. Since the DE data was queried in the ras reset
+ * thread instead of the page retirement thread, bad
+ * page retirement work would not be triggered. Then
+ * even if all gpu resets are completed, the bad pages
+ * will be cached in RAM until GPU B's bad page retirement
+ * work is triggered again and then saved to eeprom.
+ * Trigger delayed work to save the bad pages to eeprom in time
+ * after gpu ras reset is completed.
+ */
+ if (amdgpu_ras_in_recovery(adev))
+ schedule_delayed_work(&con->page_retirement_dwork,
+ msecs_to_jiffies(DELAYED_TIME_FOR_GPU_RESET));
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
index cb253bd3a2a2..a280b9fecb77 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
@@ -202,24 +202,17 @@ static int vcn_v1_0_hw_init(void *handle)
r = amdgpu_ring_test_helper(ring);
if (r)
- goto done;
+ return r;
for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
ring = &adev->vcn.inst->ring_enc[i];
r = amdgpu_ring_test_helper(ring);
if (r)
- goto done;
+ return r;
}
ring = adev->jpeg.inst->ring_dec;
r = amdgpu_ring_test_helper(ring);
- if (r)
- goto done;
-
-done:
- if (!r)
- DRM_INFO("VCN decode and encode initialized successfully(under %s).\n",
- (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)?"DPG Mode":"SPG Mode");
return r;
}
@@ -2043,7 +2036,6 @@ static const struct amdgpu_ring_funcs vcn_v1_0_enc_ring_vm_funcs = {
static void vcn_v1_0_set_dec_ring_funcs(struct amdgpu_device *adev)
{
adev->vcn.inst->ring_dec.funcs = &vcn_v1_0_dec_ring_vm_funcs;
- DRM_INFO("VCN decode is enabled in VM mode\n");
}
static void vcn_v1_0_set_enc_ring_funcs(struct amdgpu_device *adev)
@@ -2052,8 +2044,6 @@ static void vcn_v1_0_set_enc_ring_funcs(struct amdgpu_device *adev)
for (i = 0; i < adev->vcn.num_enc_rings; ++i)
adev->vcn.inst->ring_enc[i].funcs = &vcn_v1_0_enc_ring_vm_funcs;
-
- DRM_INFO("VCN encode is enabled in VM mode\n");
}
static const struct amdgpu_irq_src_funcs vcn_v1_0_irq_funcs = {
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
index f18fd61c435e..d3d096909a7f 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
@@ -237,7 +237,7 @@ static int vcn_v2_0_hw_init(void *handle)
r = amdgpu_ring_test_helper(ring);
if (r)
- goto done;
+ return r;
//Disable vcn decode for sriov
if (amdgpu_sriov_vf(adev))
@@ -247,15 +247,10 @@ static int vcn_v2_0_hw_init(void *handle)
ring = &adev->vcn.inst->ring_enc[i];
r = amdgpu_ring_test_helper(ring);
if (r)
- goto done;
+ return r;
}
-done:
- if (!r)
- DRM_INFO("VCN decode and encode initialized successfully(under %s).\n",
- (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)?"DPG Mode":"SPG Mode");
-
- return r;
+ return 0;
}
/**
@@ -2074,7 +2069,6 @@ static const struct amdgpu_ring_funcs vcn_v2_0_enc_ring_vm_funcs = {
static void vcn_v2_0_set_dec_ring_funcs(struct amdgpu_device *adev)
{
adev->vcn.inst->ring_dec.funcs = &vcn_v2_0_dec_ring_vm_funcs;
- DRM_INFO("VCN decode is enabled in VM mode\n");
}
static void vcn_v2_0_set_enc_ring_funcs(struct amdgpu_device *adev)
@@ -2083,8 +2077,6 @@ static void vcn_v2_0_set_enc_ring_funcs(struct amdgpu_device *adev)
for (i = 0; i < adev->vcn.num_enc_rings; ++i)
adev->vcn.inst->ring_enc[i].funcs = &vcn_v2_0_enc_ring_vm_funcs;
-
- DRM_INFO("VCN encode is enabled in VM mode\n");
}
static const struct amdgpu_irq_src_funcs vcn_v2_0_irq_funcs = {
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
index baec14bde2a2..96f60c303161 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
@@ -314,22 +314,17 @@ static int vcn_v2_5_hw_init(void *handle)
r = amdgpu_ring_test_helper(ring);
if (r)
- goto done;
+ return r;
for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
ring = &adev->vcn.inst[j].ring_enc[i];
r = amdgpu_ring_test_helper(ring);
if (r)
- goto done;
+ return r;
}
}
}
-done:
- if (!r)
- DRM_INFO("VCN decode and encode initialized successfully(under %s).\n",
- (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)?"DPG Mode":"SPG Mode");
-
return r;
}
@@ -1710,7 +1705,6 @@ static void vcn_v2_5_set_dec_ring_funcs(struct amdgpu_device *adev)
continue;
adev->vcn.inst[i].ring_dec.funcs = &vcn_v2_5_dec_ring_vm_funcs;
adev->vcn.inst[i].ring_dec.me = i;
- DRM_INFO("VCN(%d) decode is enabled in VM mode\n", i);
}
}
@@ -1725,7 +1719,6 @@ static void vcn_v2_5_set_enc_ring_funcs(struct amdgpu_device *adev)
adev->vcn.inst[j].ring_enc[i].funcs = &vcn_v2_5_enc_ring_vm_funcs;
adev->vcn.inst[j].ring_enc[i].me = j;
}
- DRM_INFO("VCN(%d) encode is enabled in VM mode\n", j);
}
}
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
index 6b31cf4b8aac..24f947751c46 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
@@ -303,7 +303,7 @@ static int vcn_v3_0_hw_init(void *handle)
if (amdgpu_sriov_vf(adev)) {
r = vcn_v3_0_start_sriov(adev);
if (r)
- goto done;
+ return r;
/* initialize VCN dec and enc ring buffers */
for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
@@ -348,24 +348,18 @@ static int vcn_v3_0_hw_init(void *handle)
r = amdgpu_ring_test_helper(ring);
if (r)
- goto done;
+ return r;
for (j = 0; j < adev->vcn.num_enc_rings; ++j) {
ring = &adev->vcn.inst[i].ring_enc[j];
r = amdgpu_ring_test_helper(ring);
if (r)
- goto done;
+ return r;
}
}
}
return 0;
-done:
- if (!r)
- DRM_INFO("VCN decode and encode initialized successfully(under %s).\n",
- (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)?"DPG Mode":"SPG Mode");
-
- return r;
}
/**
@@ -2041,8 +2035,6 @@ static void vcn_v3_0_set_dec_ring_funcs(struct amdgpu_device *adev)
else
adev->vcn.inst[i].ring_dec.funcs = &vcn_v3_0_dec_sw_ring_vm_funcs;
adev->vcn.inst[i].ring_dec.me = i;
- DRM_INFO("VCN(%d) decode%s is enabled in VM mode\n", i,
- DEC_SW_RING_ENABLED?"(Software Ring)":"");
}
}
@@ -2058,8 +2050,6 @@ static void vcn_v3_0_set_enc_ring_funcs(struct amdgpu_device *adev)
adev->vcn.inst[i].ring_enc[j].funcs = &vcn_v3_0_enc_ring_vm_funcs;
adev->vcn.inst[i].ring_enc[j].me = i;
}
- if (adev->vcn.num_enc_rings > 0)
- DRM_INFO("VCN(%d) encode is enabled in VM mode\n", i);
}
}
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
index ac1b8ead03b3..776c539bfdda 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
@@ -258,7 +258,7 @@ static int vcn_v4_0_hw_init(void *handle)
if (amdgpu_sriov_vf(adev)) {
r = vcn_v4_0_start_sriov(adev);
if (r)
- goto done;
+ return r;
for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
if (adev->vcn.harvest_config & (1 << i))
@@ -269,7 +269,6 @@ static int vcn_v4_0_hw_init(void *handle)
ring->wptr_old = 0;
vcn_v4_0_unified_ring_set_wptr(ring);
ring->sched.ready = true;
-
}
} else {
for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
@@ -283,18 +282,11 @@ static int vcn_v4_0_hw_init(void *handle)
r = amdgpu_ring_test_helper(ring);
if (r)
- goto done;
-
+ return r;
}
}
return 0;
-done:
- if (!r)
- DRM_INFO("VCN decode and encode initialized successfully(under %s).\n",
- (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)?"DPG Mode":"SPG Mode");
-
- return r;
}
/**
@@ -1053,6 +1045,9 @@ static int vcn_v4_0_start(struct amdgpu_device *adev)
amdgpu_dpm_enable_uvd(adev, true);
for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+ if (adev->vcn.harvest_config & (1 << i))
+ continue;
+
fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
@@ -1506,6 +1501,9 @@ static int vcn_v4_0_stop(struct amdgpu_device *adev)
int i, r = 0;
for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+ if (adev->vcn.harvest_config & (1 << i))
+ continue;
+
fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;
@@ -1900,8 +1898,6 @@ static void vcn_v4_0_set_unified_ring_funcs(struct amdgpu_device *adev)
adev->vcn.inst[i].ring_enc[0].funcs =
(const struct amdgpu_ring_funcs *)&vcn_v4_0_unified_ring_vm_funcs;
adev->vcn.inst[i].ring_enc[0].me = i;
-
- DRM_INFO("VCN(%d) encode/decode are enabled in VM mode\n", i);
}
}
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 2279d8fce03d..9bae95538b62 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
@@ -45,6 +45,9 @@
#define VCN_VID_SOC_ADDRESS_2_0 0x1fb00
#define VCN1_VID_SOC_ADDRESS_3_0 0x48300
+#define NORMALIZE_VCN_REG_OFFSET(offset) \
+ (offset & 0x1FFFF)
+
static int vcn_v4_0_3_start_sriov(struct amdgpu_device *adev);
static void vcn_v4_0_3_set_unified_ring_funcs(struct amdgpu_device *adev);
static void vcn_v4_0_3_set_irq_funcs(struct amdgpu_device *adev);
@@ -210,7 +213,7 @@ static int vcn_v4_0_3_hw_init(void *handle)
if (amdgpu_sriov_vf(adev)) {
r = vcn_v4_0_3_start_sriov(adev);
if (r)
- goto done;
+ return r;
for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
ring = &adev->vcn.inst[i].ring_enc[0];
@@ -246,15 +249,10 @@ static int vcn_v4_0_3_hw_init(void *handle)
r = amdgpu_ring_test_helper(ring);
if (r)
- goto done;
+ return r;
}
}
-done:
- if (!r)
- DRM_DEV_INFO(adev->dev, "VCN decode initialized successfully(under %s).\n",
- (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)?"DPG Mode":"SPG Mode");
-
return r;
}
@@ -1380,6 +1378,50 @@ static uint64_t vcn_v4_0_3_unified_ring_get_wptr(struct amdgpu_ring *ring)
regUVD_RB_WPTR);
}
+static void vcn_v4_0_3_enc_ring_emit_reg_wait(struct amdgpu_ring *ring, uint32_t reg,
+ uint32_t val, uint32_t mask)
+{
+ /* For VF, only local offsets should be used */
+ if (amdgpu_sriov_vf(ring->adev))
+ reg = NORMALIZE_VCN_REG_OFFSET(reg);
+
+ amdgpu_ring_write(ring, VCN_ENC_CMD_REG_WAIT);
+ amdgpu_ring_write(ring, reg << 2);
+ amdgpu_ring_write(ring, mask);
+ amdgpu_ring_write(ring, val);
+}
+
+static void vcn_v4_0_3_enc_ring_emit_wreg(struct amdgpu_ring *ring, uint32_t reg, uint32_t val)
+{
+ /* For VF, only local offsets should be used */
+ if (amdgpu_sriov_vf(ring->adev))
+ reg = NORMALIZE_VCN_REG_OFFSET(reg);
+
+ amdgpu_ring_write(ring, VCN_ENC_CMD_REG_WRITE);
+ amdgpu_ring_write(ring, reg << 2);
+ amdgpu_ring_write(ring, val);
+}
+
+static void vcn_v4_0_3_enc_ring_emit_vm_flush(struct amdgpu_ring *ring,
+ unsigned int vmid, uint64_t pd_addr)
+{
+ struct amdgpu_vmhub *hub = &ring->adev->vmhub[ring->vm_hub];
+
+ pd_addr = amdgpu_gmc_emit_flush_gpu_tlb(ring, vmid, pd_addr);
+
+ /* wait for reg writes */
+ vcn_v4_0_3_enc_ring_emit_reg_wait(ring, hub->ctx0_ptb_addr_lo32 +
+ vmid * hub->ctx_addr_distance,
+ lower_32_bits(pd_addr), 0xffffffff);
+}
+
+static void vcn_v4_0_3_ring_emit_hdp_flush(struct amdgpu_ring *ring)
+{
+ /* VCN engine access for HDP flush doesn't work when RRMT is enabled.
+ * This is a workaround to avoid any HDP flush through VCN ring.
+ */
+}
+
/**
* vcn_v4_0_3_unified_ring_set_wptr - set enc write pointer
*
@@ -1419,7 +1461,8 @@ static const struct amdgpu_ring_funcs vcn_v4_0_3_unified_ring_vm_funcs = {
.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_v2_0_enc_ring_emit_vm_flush,
+ .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,
@@ -1427,8 +1470,8 @@ static const struct amdgpu_ring_funcs vcn_v4_0_3_unified_ring_vm_funcs = {
.pad_ib = amdgpu_ring_generic_pad_ib,
.begin_use = amdgpu_vcn_ring_begin_use,
.end_use = amdgpu_vcn_ring_end_use,
- .emit_wreg = vcn_v2_0_enc_ring_emit_wreg,
- .emit_reg_wait = vcn_v2_0_enc_ring_emit_reg_wait,
+ .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,
};
@@ -1450,7 +1493,6 @@ static void vcn_v4_0_3_set_unified_ring_funcs(struct amdgpu_device *adev)
adev->vcn.inst[i].aid_id =
vcn_inst / adev->vcn.num_inst_per_aid;
}
- DRM_DEV_INFO(adev->dev, "VCN decode is enabled in VM mode\n");
}
/**
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
index 81fb99729f37..8d75061f9f38 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
@@ -234,16 +234,10 @@ static int vcn_v4_0_5_hw_init(void *handle)
r = amdgpu_ring_test_helper(ring);
if (r)
- goto done;
+ return r;
}
return 0;
-done:
- if (!r)
- DRM_INFO("VCN decode and encode initialized successfully(under %s).\n",
- (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)?"DPG Mode":"SPG Mode");
-
- return r;
}
/**
@@ -964,6 +958,9 @@ static int vcn_v4_0_5_start(struct amdgpu_device *adev)
amdgpu_dpm_enable_uvd(adev, true);
for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+ if (adev->vcn.harvest_config & (1 << i))
+ continue;
+
fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
@@ -1168,6 +1165,9 @@ static int vcn_v4_0_5_stop(struct amdgpu_device *adev)
int i, r = 0;
for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+ if (adev->vcn.harvest_config & (1 << i))
+ continue;
+
fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;
@@ -1558,8 +1558,6 @@ static void vcn_v4_0_5_set_unified_ring_funcs(struct amdgpu_device *adev)
adev->vcn.inst[i].ring_enc[0].funcs = &vcn_v4_0_5_unified_ring_vm_funcs;
adev->vcn.inst[i].ring_enc[0].me = i;
-
- DRM_INFO("VCN(%d) encode/decode are enabled in VM mode\n", i);
}
}
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
index 070b56610c7d..68c97fcd539b 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
@@ -721,6 +721,9 @@ static int vcn_v5_0_0_start(struct amdgpu_device *adev)
amdgpu_dpm_enable_uvd(adev, true);
for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+ if (adev->vcn.harvest_config & (1 << i))
+ continue;
+
fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
@@ -898,6 +901,9 @@ static int vcn_v5_0_0_stop(struct amdgpu_device *adev)
int i, r = 0;
for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+ if (adev->vcn.harvest_config & (1 << i))
+ continue;
+
fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;
diff --git a/drivers/gpu/drm/amd/amdgpu/vpe_v6_1.c b/drivers/gpu/drm/amd/amdgpu/vpe_v6_1.c
index 09315dd5a1ec..45876883bbf3 100644
--- a/drivers/gpu/drm/amd/amdgpu/vpe_v6_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/vpe_v6_1.c
@@ -34,6 +34,7 @@
MODULE_FIRMWARE("amdgpu/vpe_6_1_0.bin");
MODULE_FIRMWARE("amdgpu/vpe_6_1_1.bin");
+MODULE_FIRMWARE("amdgpu/vpe_6_1_3.bin");
#define VPE_THREAD1_UCODE_OFFSET 0x8000
diff --git a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h
index 665122d1bbbd..02f7ba8c93cd 100644
--- a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h
+++ b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h
@@ -1136,7 +1136,7 @@ static const uint32_t cwsr_trap_nv1x_hex[] = {
0x705d0000, 0x807c817c,
0x8070ff70, 0x00000080,
0xbf0a7b7c, 0xbf85fff8,
- 0xbf82013d, 0xbef4037e,
+ 0xbf82013f, 0xbef4037e,
0x8775ff7f, 0x0000ffff,
0x8875ff75, 0x00040000,
0xbef60380, 0xbef703ff,
@@ -1275,7 +1275,8 @@ static const uint32_t cwsr_trap_nv1x_hex[] = {
0x80788478, 0xbf8c0000,
0xb9eef815, 0xbefc036f,
0xbefe0370, 0xbeff0371,
- 0xb9f9f816, 0xb9fbf803,
+ 0xb9f9f816, 0xb9fb4803,
+ 0x907b8b7b, 0xb9fba2c3,
0xb9f3f801, 0xb96e3a05,
0x806e816e, 0xbf0d9972,
0xbf850002, 0x8f6e896e,
@@ -2544,7 +2545,7 @@ static const uint32_t cwsr_trap_gfx10_hex[] = {
0xe0704000, 0x705d0000,
0x807c817c, 0x8070ff70,
0x00000080, 0xbf0a7b7c,
- 0xbf85fff8, 0xbf820134,
+ 0xbf85fff8, 0xbf820136,
0xbef4037e, 0x8775ff7f,
0x0000ffff, 0x8875ff75,
0x00040000, 0xbef60380,
@@ -2683,7 +2684,8 @@ static const uint32_t cwsr_trap_gfx10_hex[] = {
0xf0000000, 0x80788478,
0xbf8c0000, 0xb9eef815,
0xbefc036f, 0xbefe0370,
- 0xbeff0371, 0xb9fbf803,
+ 0xbeff0371, 0xb9fb4803,
+ 0x907b8b7b, 0xb9fba2c3,
0xb9f3f801, 0xb96e3a05,
0x806e816e, 0xbf0d9972,
0xbf850002, 0x8f6e896e,
@@ -2981,7 +2983,7 @@ static const uint32_t cwsr_trap_gfx11_hex[] = {
0x701d0000, 0x807d817d,
0x8070ff70, 0x00000080,
0xbf0a7b7d, 0xbfa2fff8,
- 0xbfa0013f, 0xbef4007e,
+ 0xbfa00143, 0xbef4007e,
0x8b75ff7f, 0x0000ffff,
0x8c75ff75, 0x00040000,
0xbef60080, 0xbef700ff,
@@ -3123,7 +3125,9 @@ static const uint32_t cwsr_trap_gfx11_hex[] = {
0x80788478, 0xbf890000,
0xb96ef815, 0xbefd006f,
0xbefe0070, 0xbeff0071,
- 0xb97bf803, 0xb973f801,
+ 0xb97b4803, 0x857b8b7b,
+ 0xb97b22c3, 0x857b867b,
+ 0xb97b7443, 0xb973f801,
0xb8ee3b05, 0x806e816e,
0xbf0d9972, 0xbfa20002,
0x846e896e, 0xbfa00001,
diff --git a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm
index ac3702b8e3c4..44772eec9ef4 100644
--- a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm
+++ b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm
@@ -119,9 +119,12 @@ var SQ_WAVE_TRAPSTS_ADDR_WATCH_SHIFT = 7
var SQ_WAVE_TRAPSTS_MEM_VIOL_MASK = 0x100
var SQ_WAVE_TRAPSTS_MEM_VIOL_SHIFT = 8
var SQ_WAVE_TRAPSTS_ILLEGAL_INST_MASK = 0x800
+var SQ_WAVE_TRAPSTS_ILLEGAL_INST_SHIFT = 11
var SQ_WAVE_TRAPSTS_EXCP_HI_MASK = 0x7000
#if ASIC_FAMILY >= CHIP_PLUM_BONITO
+var SQ_WAVE_TRAPSTS_HOST_TRAP_SHIFT = 16
var SQ_WAVE_TRAPSTS_WAVE_START_MASK = 0x20000
+var SQ_WAVE_TRAPSTS_WAVE_START_SHIFT = 17
var SQ_WAVE_TRAPSTS_WAVE_END_MASK = 0x40000
var SQ_WAVE_TRAPSTS_TRAP_AFTER_INST_MASK = 0x100000
#endif
@@ -137,14 +140,23 @@ var SQ_WAVE_IB_STS_RCNT_FIRST_REPLAY_MASK = 0x003F8000
var SQ_WAVE_MODE_DEBUG_EN_MASK = 0x800
+var S_TRAPSTS_RESTORE_PART_1_SIZE = SQ_WAVE_TRAPSTS_SAVECTX_SHIFT
+var S_TRAPSTS_RESTORE_PART_2_SHIFT = SQ_WAVE_TRAPSTS_ILLEGAL_INST_SHIFT
+
#if ASIC_FAMILY < CHIP_PLUM_BONITO
var S_TRAPSTS_NON_MASKABLE_EXCP_MASK = SQ_WAVE_TRAPSTS_MEM_VIOL_MASK|SQ_WAVE_TRAPSTS_ILLEGAL_INST_MASK
+var S_TRAPSTS_RESTORE_PART_2_SIZE = 32 - S_TRAPSTS_RESTORE_PART_2_SHIFT
+var S_TRAPSTS_RESTORE_PART_3_SHIFT = 0
+var S_TRAPSTS_RESTORE_PART_3_SIZE = 0
#else
var S_TRAPSTS_NON_MASKABLE_EXCP_MASK = SQ_WAVE_TRAPSTS_MEM_VIOL_MASK |\
SQ_WAVE_TRAPSTS_ILLEGAL_INST_MASK |\
SQ_WAVE_TRAPSTS_WAVE_START_MASK |\
SQ_WAVE_TRAPSTS_WAVE_END_MASK |\
SQ_WAVE_TRAPSTS_TRAP_AFTER_INST_MASK
+var S_TRAPSTS_RESTORE_PART_2_SIZE = SQ_WAVE_TRAPSTS_HOST_TRAP_SHIFT - SQ_WAVE_TRAPSTS_ILLEGAL_INST_SHIFT
+var S_TRAPSTS_RESTORE_PART_3_SHIFT = SQ_WAVE_TRAPSTS_WAVE_START_SHIFT
+var S_TRAPSTS_RESTORE_PART_3_SIZE = 32 - S_TRAPSTS_RESTORE_PART_3_SHIFT
#endif
var S_TRAPSTS_HWREG = HW_REG_TRAPSTS
var S_TRAPSTS_SAVE_CONTEXT_MASK = SQ_WAVE_TRAPSTS_SAVECTX_MASK
@@ -157,6 +169,7 @@ var SQ_WAVE_EXCP_FLAG_PRIV_SAVE_CONTEXT_MASK = 0x20
var SQ_WAVE_EXCP_FLAG_PRIV_ILLEGAL_INST_MASK = 0x40
var SQ_WAVE_EXCP_FLAG_PRIV_ILLEGAL_INST_SHIFT = 6
var SQ_WAVE_EXCP_FLAG_PRIV_HOST_TRAP_MASK = 0x80
+var SQ_WAVE_EXCP_FLAG_PRIV_HOST_TRAP_SHIFT = 7
var SQ_WAVE_EXCP_FLAG_PRIV_WAVE_START_MASK = 0x100
var SQ_WAVE_EXCP_FLAG_PRIV_WAVE_START_SHIFT = 8
var SQ_WAVE_EXCP_FLAG_PRIV_WAVE_END_MASK = 0x200
@@ -173,6 +186,11 @@ var S_TRAPSTS_NON_MASKABLE_EXCP_MASK = SQ_WAVE_EXCP_FLAG_PRIV_MEM_VIOL_MASK |\
SQ_WAVE_EXCP_FLAG_PRIV_WAVE_START_MASK |\
SQ_WAVE_EXCP_FLAG_PRIV_WAVE_END_MASK |\
SQ_WAVE_EXCP_FLAG_PRIV_TRAP_AFTER_INST_MASK
+var S_TRAPSTS_RESTORE_PART_1_SIZE = SQ_WAVE_EXCP_FLAG_PRIV_SAVE_CONTEXT_SHIFT
+var S_TRAPSTS_RESTORE_PART_2_SHIFT = SQ_WAVE_EXCP_FLAG_PRIV_ILLEGAL_INST_SHIFT
+var S_TRAPSTS_RESTORE_PART_2_SIZE = SQ_WAVE_EXCP_FLAG_PRIV_HOST_TRAP_SHIFT - SQ_WAVE_EXCP_FLAG_PRIV_ILLEGAL_INST_SHIFT
+var S_TRAPSTS_RESTORE_PART_3_SHIFT = SQ_WAVE_EXCP_FLAG_PRIV_WAVE_START_SHIFT
+var S_TRAPSTS_RESTORE_PART_3_SIZE = 32 - S_TRAPSTS_RESTORE_PART_3_SHIFT
var BARRIER_STATE_SIGNAL_OFFSET = 16
var BARRIER_STATE_VALID_OFFSET = 0
#endif
@@ -1386,17 +1404,17 @@ L_SKIP_BARRIER_RESTORE:
s_setreg_b32 hwreg(HW_REG_SHADER_XNACK_MASK), s_restore_xnack_mask
#endif
-#if ASIC_FAMILY < CHIP_GFX12
- s_setreg_b32 hwreg(S_TRAPSTS_HWREG), s_restore_trapsts
-#else
- // EXCP_FLAG_PRIV.SAVE_CONTEXT and HOST_TRAP may have changed.
+ // {TRAPSTS/EXCP_FLAG_PRIV}.SAVE_CONTEXT and HOST_TRAP may have changed.
// Only restore the other fields to avoid clobbering them.
- s_setreg_b32 hwreg(S_TRAPSTS_HWREG, 0, SQ_WAVE_EXCP_FLAG_PRIV_SAVE_CONTEXT_SHIFT), s_restore_trapsts
- s_lshr_b32 s_restore_trapsts, s_restore_trapsts, SQ_WAVE_EXCP_FLAG_PRIV_ILLEGAL_INST_SHIFT
- s_setreg_b32 hwreg(S_TRAPSTS_HWREG, SQ_WAVE_EXCP_FLAG_PRIV_ILLEGAL_INST_SHIFT, 1), s_restore_trapsts
- s_lshr_b32 s_restore_trapsts, s_restore_trapsts, SQ_WAVE_EXCP_FLAG_PRIV_WAVE_START_SHIFT - SQ_WAVE_EXCP_FLAG_PRIV_ILLEGAL_INST_SHIFT
- s_setreg_b32 hwreg(S_TRAPSTS_HWREG, SQ_WAVE_EXCP_FLAG_PRIV_WAVE_START_SHIFT, 32 - SQ_WAVE_EXCP_FLAG_PRIV_WAVE_START_SHIFT), s_restore_trapsts
-#endif
+ s_setreg_b32 hwreg(S_TRAPSTS_HWREG, 0, S_TRAPSTS_RESTORE_PART_1_SIZE), s_restore_trapsts
+ s_lshr_b32 s_restore_trapsts, s_restore_trapsts, S_TRAPSTS_RESTORE_PART_2_SHIFT
+ s_setreg_b32 hwreg(S_TRAPSTS_HWREG, S_TRAPSTS_RESTORE_PART_2_SHIFT, S_TRAPSTS_RESTORE_PART_2_SIZE), s_restore_trapsts
+
+if S_TRAPSTS_RESTORE_PART_3_SIZE > 0
+ s_lshr_b32 s_restore_trapsts, s_restore_trapsts, S_TRAPSTS_RESTORE_PART_3_SHIFT - S_TRAPSTS_RESTORE_PART_2_SHIFT
+ s_setreg_b32 hwreg(S_TRAPSTS_HWREG, S_TRAPSTS_RESTORE_PART_3_SHIFT, S_TRAPSTS_RESTORE_PART_3_SIZE), s_restore_trapsts
+end
+
s_setreg_b32 hwreg(HW_REG_MODE), s_restore_mode
// Restore trap temporaries 4-11, 13 initialized by SPI debug dispatch logic
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
index ead43386a7ef..cd7b81b7b939 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
@@ -1678,6 +1678,7 @@ int kfd_get_gpu_cache_info(struct kfd_node *kdev, struct kfd_gpu_cache_info **pc
case IP_VERSION(11, 0, 4):
case IP_VERSION(11, 5, 0):
case IP_VERSION(11, 5, 1):
+ case IP_VERSION(11, 5, 2):
case IP_VERSION(12, 0, 0):
case IP_VERSION(12, 0, 1):
num_of_cache_types =
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c
index 52be4e340fb1..f4d20adaa068 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c
@@ -99,6 +99,7 @@ static void kfd_device_info_set_sdma_info(struct kfd_dev *kfd)
case IP_VERSION(6, 0, 3):
case IP_VERSION(6, 1, 0):
case IP_VERSION(6, 1, 1):
+ case IP_VERSION(6, 1, 2):
case IP_VERSION(7, 0, 0):
case IP_VERSION(7, 0, 1):
kfd->device_info.num_sdma_queues_per_engine = 8;
@@ -119,6 +120,7 @@ static void kfd_device_info_set_sdma_info(struct kfd_dev *kfd)
case IP_VERSION(6, 0, 3):
case IP_VERSION(6, 1, 0):
case IP_VERSION(6, 1, 1):
+ case IP_VERSION(6, 1, 2):
case IP_VERSION(7, 0, 0):
case IP_VERSION(7, 0, 1):
/* Reserve 1 for paging and 1 for gfx */
@@ -175,6 +177,7 @@ static void kfd_device_info_set_event_interrupt_class(struct kfd_dev *kfd)
case IP_VERSION(11, 0, 4):
case IP_VERSION(11, 5, 0):
case IP_VERSION(11, 5, 1):
+ case IP_VERSION(11, 5, 2):
kfd->device_info.event_interrupt_class = &event_interrupt_class_v11;
break;
case IP_VERSION(12, 0, 0):
@@ -438,6 +441,10 @@ struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf)
gfx_target_version = 110501;
f2g = &gfx_v11_kfd2kgd;
break;
+ case IP_VERSION(11, 5, 2):
+ gfx_target_version = 110502;
+ f2g = &gfx_v11_kfd2kgd;
+ break;
case IP_VERSION(12, 0, 0):
gfx_target_version = 120000;
f2g = &gfx_v12_kfd2kgd;
@@ -936,7 +943,6 @@ int kgd2kfd_pre_reset(struct kfd_dev *kfd,
for (i = 0; i < kfd->num_nodes; i++) {
node = kfd->nodes[i];
kfd_smi_event_update_gpu_reset(node, false, reset_context);
- node->dqm->ops.pre_reset(node->dqm);
}
kgd2kfd_suspend(kfd, false);
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
index 485e26abc619..4f48507418d2 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
@@ -35,6 +35,7 @@
#include "cik_regs.h"
#include "kfd_kernel_queue.h"
#include "amdgpu_amdkfd.h"
+#include "amdgpu_reset.h"
#include "mes_v11_api_def.h"
#include "kfd_debug.h"
@@ -155,14 +156,7 @@ static void kfd_hws_hang(struct device_queue_manager *dqm)
/*
* Issue a GPU reset if HWS is unresponsive
*/
- dqm->is_hws_hang = true;
-
- /* It's possible we're detecting a HWS hang in the
- * middle of a GPU reset. No need to schedule another
- * reset in this case.
- */
- if (!dqm->is_resetting)
- schedule_work(&dqm->hw_exception_work);
+ schedule_work(&dqm->hw_exception_work);
}
static int convert_to_mes_queue_type(int queue_type)
@@ -194,7 +188,7 @@ static int add_queue_mes(struct device_queue_manager *dqm, struct queue *q,
int r, queue_type;
uint64_t wptr_addr_off;
- if (dqm->is_hws_hang)
+ if (!down_read_trylock(&adev->reset_domain->sem))
return -EIO;
memset(&queue_input, 0x0, sizeof(struct mes_add_queue_input));
@@ -236,6 +230,7 @@ static int add_queue_mes(struct device_queue_manager *dqm, struct queue *q,
if (queue_type < 0) {
dev_err(adev->dev, "Queue type not supported with MES, queue:%d\n",
q->properties.type);
+ up_read(&adev->reset_domain->sem);
return -EINVAL;
}
queue_input.queue_type = (uint32_t)queue_type;
@@ -245,6 +240,7 @@ static int add_queue_mes(struct device_queue_manager *dqm, struct queue *q,
amdgpu_mes_lock(&adev->mes);
r = adev->mes.funcs->add_hw_queue(&adev->mes, &queue_input);
amdgpu_mes_unlock(&adev->mes);
+ up_read(&adev->reset_domain->sem);
if (r) {
dev_err(adev->dev, "failed to add hardware queue to MES, doorbell=0x%x\n",
q->properties.doorbell_off);
@@ -262,7 +258,7 @@ static int remove_queue_mes(struct device_queue_manager *dqm, struct queue *q,
int r;
struct mes_remove_queue_input queue_input;
- if (dqm->is_hws_hang)
+ if (!down_read_trylock(&adev->reset_domain->sem))
return -EIO;
memset(&queue_input, 0x0, sizeof(struct mes_remove_queue_input));
@@ -272,6 +268,7 @@ static int remove_queue_mes(struct device_queue_manager *dqm, struct queue *q,
amdgpu_mes_lock(&adev->mes);
r = adev->mes.funcs->remove_hw_queue(&adev->mes, &queue_input);
amdgpu_mes_unlock(&adev->mes);
+ up_read(&adev->reset_domain->sem);
if (r) {
dev_err(adev->dev, "failed to remove hardware queue from MES, doorbell=0x%x\n",
@@ -1468,20 +1465,13 @@ static int stop_nocpsch(struct device_queue_manager *dqm)
}
if (dqm->dev->adev->asic_type == CHIP_HAWAII)
- pm_uninit(&dqm->packet_mgr, false);
+ pm_uninit(&dqm->packet_mgr);
dqm->sched_running = false;
dqm_unlock(dqm);
return 0;
}
-static void pre_reset(struct device_queue_manager *dqm)
-{
- dqm_lock(dqm);
- dqm->is_resetting = true;
- dqm_unlock(dqm);
-}
-
static int allocate_sdma_queue(struct device_queue_manager *dqm,
struct queue *q, const uint32_t *restore_sdma_id)
{
@@ -1669,8 +1659,6 @@ static int start_cpsch(struct device_queue_manager *dqm)
init_interrupts(dqm);
/* clear hang status when driver try to start the hw scheduler */
- dqm->is_hws_hang = false;
- dqm->is_resetting = false;
dqm->sched_running = true;
if (!dqm->dev->kfd->shared_resources.enable_mes)
@@ -1700,7 +1688,7 @@ static int start_cpsch(struct device_queue_manager *dqm)
fail_allocate_vidmem:
fail_set_sched_resources:
if (!dqm->dev->kfd->shared_resources.enable_mes)
- pm_uninit(&dqm->packet_mgr, false);
+ pm_uninit(&dqm->packet_mgr);
fail_packet_manager_init:
dqm_unlock(dqm);
return retval;
@@ -1708,22 +1696,17 @@ fail_packet_manager_init:
static int stop_cpsch(struct device_queue_manager *dqm)
{
- bool hanging;
-
dqm_lock(dqm);
if (!dqm->sched_running) {
dqm_unlock(dqm);
return 0;
}
- if (!dqm->is_hws_hang) {
- if (!dqm->dev->kfd->shared_resources.enable_mes)
- unmap_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES, 0, USE_DEFAULT_GRACE_PERIOD, false);
- else
- remove_all_queues_mes(dqm);
- }
+ if (!dqm->dev->kfd->shared_resources.enable_mes)
+ unmap_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES, 0, USE_DEFAULT_GRACE_PERIOD, false);
+ else
+ remove_all_queues_mes(dqm);
- hanging = dqm->is_hws_hang || dqm->is_resetting;
dqm->sched_running = false;
if (!dqm->dev->kfd->shared_resources.enable_mes)
@@ -1731,7 +1714,7 @@ static int stop_cpsch(struct device_queue_manager *dqm)
kfd_gtt_sa_free(dqm->dev, dqm->fence_mem);
if (!dqm->dev->kfd->shared_resources.enable_mes)
- pm_uninit(&dqm->packet_mgr, hanging);
+ pm_uninit(&dqm->packet_mgr);
dqm_unlock(dqm);
return 0;
@@ -1957,24 +1940,24 @@ static int unmap_queues_cpsch(struct device_queue_manager *dqm,
{
struct device *dev = dqm->dev->adev->dev;
struct mqd_manager *mqd_mgr;
- int retval = 0;
+ int retval;
if (!dqm->sched_running)
return 0;
- if (dqm->is_hws_hang || dqm->is_resetting)
- return -EIO;
if (!dqm->active_runlist)
- return retval;
+ return 0;
+ if (!down_read_trylock(&dqm->dev->adev->reset_domain->sem))
+ return -EIO;
if (grace_period != USE_DEFAULT_GRACE_PERIOD) {
retval = pm_update_grace_period(&dqm->packet_mgr, grace_period);
if (retval)
- return retval;
+ goto out;
}
retval = pm_send_unmap_queue(&dqm->packet_mgr, filter, filter_param, reset);
if (retval)
- return retval;
+ goto out;
*dqm->fence_addr = KFD_FENCE_INIT;
pm_send_query_status(&dqm->packet_mgr, dqm->fence_gpu_addr,
@@ -1985,7 +1968,7 @@ static int unmap_queues_cpsch(struct device_queue_manager *dqm,
if (retval) {
dev_err(dev, "The cp might be in an unrecoverable state due to an unsuccessful queues preemption\n");
kfd_hws_hang(dqm);
- return retval;
+ goto out;
}
/* In the current MEC firmware implementation, if compute queue
@@ -2001,7 +1984,8 @@ static int unmap_queues_cpsch(struct device_queue_manager *dqm,
while (halt_if_hws_hang)
schedule();
kfd_hws_hang(dqm);
- return -ETIME;
+ retval = -ETIME;
+ goto out;
}
/* We need to reset the grace period value for this device */
@@ -2014,6 +1998,8 @@ static int unmap_queues_cpsch(struct device_queue_manager *dqm,
pm_release_ib(&dqm->packet_mgr);
dqm->active_runlist = false;
+out:
+ up_read(&dqm->dev->adev->reset_domain->sem);
return retval;
}
@@ -2040,13 +2026,13 @@ static int execute_queues_cpsch(struct device_queue_manager *dqm,
{
int retval;
- if (dqm->is_hws_hang)
+ if (!down_read_trylock(&dqm->dev->adev->reset_domain->sem))
return -EIO;
retval = unmap_queues_cpsch(dqm, filter, filter_param, grace_period, false);
- if (retval)
- return retval;
-
- return map_queues_cpsch(dqm);
+ if (!retval)
+ retval = map_queues_cpsch(dqm);
+ up_read(&dqm->dev->adev->reset_domain->sem);
+ return retval;
}
static int wait_on_destroy_queue(struct device_queue_manager *dqm,
@@ -2427,10 +2413,12 @@ static int process_termination_cpsch(struct device_queue_manager *dqm,
if (!dqm->dev->kfd->shared_resources.enable_mes)
retval = execute_queues_cpsch(dqm, filter, 0, USE_DEFAULT_GRACE_PERIOD);
- if ((!dqm->is_hws_hang) && (retval || qpd->reset_wavefronts)) {
+ if ((retval || qpd->reset_wavefronts) &&
+ down_read_trylock(&dqm->dev->adev->reset_domain->sem)) {
pr_warn("Resetting wave fronts (cpsch) on dev %p\n", dqm->dev);
dbgdev_wave_reset_wavefronts(dqm->dev, qpd->pqm->process);
qpd->reset_wavefronts = false;
+ up_read(&dqm->dev->adev->reset_domain->sem);
}
/* Lastly, free mqd resources.
@@ -2537,7 +2525,6 @@ struct device_queue_manager *device_queue_manager_init(struct kfd_node *dev)
dqm->ops.initialize = initialize_cpsch;
dqm->ops.start = start_cpsch;
dqm->ops.stop = stop_cpsch;
- dqm->ops.pre_reset = pre_reset;
dqm->ops.destroy_queue = destroy_queue_cpsch;
dqm->ops.update_queue = update_queue;
dqm->ops.register_process = register_process;
@@ -2558,7 +2545,6 @@ struct device_queue_manager *device_queue_manager_init(struct kfd_node *dev)
/* initialize dqm for no cp scheduling */
dqm->ops.start = start_nocpsch;
dqm->ops.stop = stop_nocpsch;
- dqm->ops.pre_reset = pre_reset;
dqm->ops.create_queue = create_queue_nocpsch;
dqm->ops.destroy_queue = destroy_queue_nocpsch;
dqm->ops.update_queue = update_queue;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h
index fcc0ee67f544..3b9b8eabaacc 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h
@@ -152,7 +152,6 @@ struct device_queue_manager_ops {
int (*initialize)(struct device_queue_manager *dqm);
int (*start)(struct device_queue_manager *dqm);
int (*stop)(struct device_queue_manager *dqm);
- void (*pre_reset)(struct device_queue_manager *dqm);
void (*uninitialize)(struct device_queue_manager *dqm);
int (*create_kernel_queue)(struct device_queue_manager *dqm,
struct kernel_queue *kq,
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c b/drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c
index 4a64307bc438..dbcb60eb54b2 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c
@@ -380,7 +380,8 @@ int kfd_init_apertures(struct kfd_process *process)
pdd = kfd_create_process_device_data(dev, process);
if (!pdd) {
- pr_err("Failed to create process device data\n");
+ dev_err(dev->adev->dev,
+ "Failed to create process device data\n");
return -ENOMEM;
}
/*
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 e1c21d250611..a9c3580be8c9 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c
@@ -27,6 +27,7 @@
#include "soc15_int.h"
#include "kfd_device_queue_manager.h"
#include "kfd_smi_events.h"
+#include "amdgpu_ras.h"
/*
* GFX9 SQ Interrupts
@@ -144,9 +145,11 @@ static void event_interrupt_poison_consumption_v9(struct kfd_node *dev,
uint16_t pasid, uint16_t client_id)
{
enum amdgpu_ras_block block = 0;
- int old_poison;
uint32_t reset = 0;
struct kfd_process *p = kfd_lookup_process_by_pasid(pasid);
+ enum ras_event_type type = RAS_EVENT_TYPE_POISON_CONSUMPTION;
+ u64 event_id;
+ int old_poison, ret;
if (!p)
return;
@@ -164,7 +167,11 @@ static void event_interrupt_poison_consumption_v9(struct kfd_node *dev,
case SOC15_IH_CLIENTID_SE3SH:
case SOC15_IH_CLIENTID_UTCL2:
block = AMDGPU_RAS_BLOCK__GFX;
- reset = AMDGPU_RAS_GPU_RESET_MODE2_RESET;
+ if (amdgpu_ip_version(dev->adev, GC_HWIP, 0) == IP_VERSION(9, 4, 3) ||
+ amdgpu_ip_version(dev->adev, GC_HWIP, 0) == IP_VERSION(9, 4, 4))
+ reset = AMDGPU_RAS_GPU_RESET_MODE1_RESET;
+ else
+ reset = AMDGPU_RAS_GPU_RESET_MODE2_RESET;
break;
case SOC15_IH_CLIENTID_VMC:
case SOC15_IH_CLIENTID_VMC1:
@@ -177,7 +184,11 @@ static void event_interrupt_poison_consumption_v9(struct kfd_node *dev,
case SOC15_IH_CLIENTID_SDMA3:
case SOC15_IH_CLIENTID_SDMA4:
block = AMDGPU_RAS_BLOCK__SDMA;
- reset = AMDGPU_RAS_GPU_RESET_MODE2_RESET;
+ if (amdgpu_ip_version(dev->adev, GC_HWIP, 0) == IP_VERSION(9, 4, 3) ||
+ amdgpu_ip_version(dev->adev, GC_HWIP, 0) == IP_VERSION(9, 4, 4))
+ reset = AMDGPU_RAS_GPU_RESET_MODE1_RESET;
+ else
+ reset = AMDGPU_RAS_GPU_RESET_MODE2_RESET;
break;
default:
dev_warn(dev->adev->dev,
@@ -185,10 +196,16 @@ static void event_interrupt_poison_consumption_v9(struct kfd_node *dev,
return;
}
+ ret = amdgpu_ras_mark_ras_event(dev->adev, type);
+ if (ret)
+ return;
+
kfd_signal_poison_consumed_event(dev, pasid);
- dev_warn(dev->adev->dev,
- "poison is consumed by client %d, kick off gpu reset flow\n", client_id);
+ event_id = amdgpu_ras_acquire_event_id(dev->adev, type);
+
+ RAS_EVENT_LOG(dev->adev, event_id,
+ "poison is consumed by client %d, kick off gpu reset flow\n", client_id);
amdgpu_amdkfd_ras_pasid_poison_consumption_handler(dev->adev,
block, pasid, NULL, NULL, reset);
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c b/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c
index 32c926986dbb..4843dcb9a5f7 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c
@@ -32,6 +32,7 @@
#include "kfd_device_queue_manager.h"
#include "kfd_pm4_headers.h"
#include "kfd_pm4_opcodes.h"
+#include "amdgpu_reset.h"
#define PM4_COUNT_ZERO (((1 << 15) - 1) << 16)
@@ -68,7 +69,7 @@ static bool kq_initialize(struct kernel_queue *kq, struct kfd_node *dev,
kq->mqd_mgr = dev->dqm->mqd_mgrs[KFD_MQD_TYPE_HIQ];
break;
default:
- pr_err("Invalid queue type %d\n", type);
+ dev_err(dev->adev->dev, "Invalid queue type %d\n", type);
return false;
}
@@ -78,13 +79,14 @@ static bool kq_initialize(struct kernel_queue *kq, struct kfd_node *dev,
prop.doorbell_ptr = kfd_get_kernel_doorbell(dev->kfd, &prop.doorbell_off);
if (!prop.doorbell_ptr) {
- pr_err("Failed to initialize doorbell");
+ dev_err(dev->adev->dev, "Failed to initialize doorbell");
goto err_get_kernel_doorbell;
}
retval = kfd_gtt_sa_allocate(dev, queue_size, &kq->pq);
if (retval != 0) {
- pr_err("Failed to init pq queues size %d\n", queue_size);
+ dev_err(dev->adev->dev, "Failed to init pq queues size %d\n",
+ queue_size);
goto err_pq_allocate_vidmem;
}
@@ -196,15 +198,17 @@ err_get_kernel_doorbell:
}
/* Uninitialize a kernel queue and free all its memory usages. */
-static void kq_uninitialize(struct kernel_queue *kq, bool hanging)
+static void kq_uninitialize(struct kernel_queue *kq)
{
- if (kq->queue->properties.type == KFD_QUEUE_TYPE_HIQ && !hanging)
+ if (kq->queue->properties.type == KFD_QUEUE_TYPE_HIQ && down_read_trylock(&kq->dev->adev->reset_domain->sem)) {
kq->mqd_mgr->destroy_mqd(kq->mqd_mgr,
kq->queue->mqd,
KFD_PREEMPT_TYPE_WAVEFRONT_RESET,
KFD_UNMAP_LATENCY_MS,
kq->queue->pipe,
kq->queue->queue);
+ up_read(&kq->dev->adev->reset_domain->sem);
+ }
else if (kq->queue->properties.type == KFD_QUEUE_TYPE_DIQ)
kfd_gtt_sa_free(kq->dev, kq->fence_mem_obj);
@@ -338,15 +342,15 @@ struct kernel_queue *kernel_queue_init(struct kfd_node *dev,
if (kq_initialize(kq, dev, type, KFD_KERNEL_QUEUE_SIZE))
return kq;
- pr_err("Failed to init kernel queue\n");
+ dev_err(dev->adev->dev, "Failed to init kernel queue\n");
kfree(kq);
return NULL;
}
-void kernel_queue_uninit(struct kernel_queue *kq, bool hanging)
+void kernel_queue_uninit(struct kernel_queue *kq)
{
- kq_uninitialize(kq, hanging);
+ kq_uninitialize(kq);
kfree(kq);
}
@@ -357,26 +361,26 @@ static __attribute__((unused)) void test_kq(struct kfd_node *dev)
uint32_t *buffer, i;
int retval;
- pr_err("Starting kernel queue test\n");
+ dev_err(dev->adev->dev, "Starting kernel queue test\n");
kq = kernel_queue_init(dev, KFD_QUEUE_TYPE_HIQ);
if (unlikely(!kq)) {
- pr_err(" Failed to initialize HIQ\n");
- pr_err("Kernel queue test failed\n");
+ dev_err(dev->adev->dev, " Failed to initialize HIQ\n");
+ dev_err(dev->adev->dev, "Kernel queue test failed\n");
return;
}
retval = kq_acquire_packet_buffer(kq, 5, &buffer);
if (unlikely(retval != 0)) {
- pr_err(" Failed to acquire packet buffer\n");
- pr_err("Kernel queue test failed\n");
+ dev_err(dev->adev->dev, " Failed to acquire packet buffer\n");
+ dev_err(dev->adev->dev, "Kernel queue test failed\n");
return;
}
for (i = 0; i < 5; i++)
buffer[i] = kq->nop_packet;
kq_submit_packet(kq);
- pr_err("Ending kernel queue test\n");
+ dev_err(dev->adev->dev, "Ending kernel queue test\n");
}
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c
index ccfa5a0a8f6b..50a81da43ce1 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c
@@ -118,12 +118,14 @@ void mqd_symmetrically_map_cu_mask(struct mqd_manager *mm,
* attention grabbing.
*/
if (gfx_info->max_shader_engines > KFD_MAX_NUM_SE) {
- pr_err("Exceeded KFD_MAX_NUM_SE, chip reports %d\n",
- gfx_info->max_shader_engines);
+ dev_err(mm->dev->adev->dev,
+ "Exceeded KFD_MAX_NUM_SE, chip reports %d\n",
+ gfx_info->max_shader_engines);
return;
}
if (gfx_info->max_sh_per_se > KFD_MAX_NUM_SH_PER_SE) {
- pr_err("Exceeded KFD_MAX_NUM_SH, chip reports %d\n",
+ dev_err(mm->dev->adev->dev,
+ "Exceeded KFD_MAX_NUM_SH, chip reports %d\n",
gfx_info->max_sh_per_se * gfx_info->max_shader_engines);
return;
}
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 399fa2106631..66c73825c0a0 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c
@@ -546,6 +546,9 @@ static void init_mqd_hiq_v9_4_3(struct mqd_manager *mm, void **mqd,
m->cp_hqd_pq_control |= CP_HQD_PQ_CONTROL__NO_UPDATE_RPTR_MASK |
1 << CP_HQD_PQ_CONTROL__PRIV_STATE__SHIFT |
1 << CP_HQD_PQ_CONTROL__KMD_QUEUE__SHIFT;
+ if (amdgpu_sriov_vf(mm->dev->adev))
+ m->cp_hqd_pq_doorbell_control |= 1 <<
+ CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_MODE__SHIFT;
m->cp_mqd_stride_size = kfd_hiq_mqd_stride(mm->dev);
if (xcc == 0) {
/* Set no_update_rptr = 0 in Master XCC */
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c
index 7332ad94eab8..37930629edc5 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c
@@ -45,7 +45,8 @@ static void pm_calc_rlib_size(struct packet_manager *pm,
unsigned int process_count, queue_count, compute_queue_count, gws_queue_count;
unsigned int map_queue_size;
unsigned int max_proc_per_quantum = 1;
- struct kfd_node *dev = pm->dqm->dev;
+ struct kfd_node *node = pm->dqm->dev;
+ struct device *dev = node->adev->dev;
process_count = pm->dqm->processes_count;
queue_count = pm->dqm->active_queue_count;
@@ -59,14 +60,14 @@ static void pm_calc_rlib_size(struct packet_manager *pm,
*/
*over_subscription = false;
- if (dev->max_proc_per_quantum > 1)
- max_proc_per_quantum = dev->max_proc_per_quantum;
+ if (node->max_proc_per_quantum > 1)
+ max_proc_per_quantum = node->max_proc_per_quantum;
if ((process_count > max_proc_per_quantum) ||
compute_queue_count > get_cp_queues_num(pm->dqm) ||
gws_queue_count > 1) {
*over_subscription = true;
- pr_debug("Over subscribed runlist\n");
+ dev_dbg(dev, "Over subscribed runlist\n");
}
map_queue_size = pm->pmf->map_queues_size;
@@ -81,7 +82,7 @@ static void pm_calc_rlib_size(struct packet_manager *pm,
if (*over_subscription)
*rlib_size += pm->pmf->runlist_size;
- pr_debug("runlist ib size %d\n", *rlib_size);
+ dev_dbg(dev, "runlist ib size %d\n", *rlib_size);
}
static int pm_allocate_runlist_ib(struct packet_manager *pm,
@@ -90,6 +91,8 @@ static int pm_allocate_runlist_ib(struct packet_manager *pm,
unsigned int *rl_buffer_size,
bool *is_over_subscription)
{
+ struct kfd_node *node = pm->dqm->dev;
+ struct device *dev = node->adev->dev;
int retval;
if (WARN_ON(pm->allocated))
@@ -99,11 +102,10 @@ static int pm_allocate_runlist_ib(struct packet_manager *pm,
mutex_lock(&pm->lock);
- retval = kfd_gtt_sa_allocate(pm->dqm->dev, *rl_buffer_size,
- &pm->ib_buffer_obj);
+ retval = kfd_gtt_sa_allocate(node, *rl_buffer_size, &pm->ib_buffer_obj);
if (retval) {
- pr_err("Failed to allocate runlist IB\n");
+ dev_err(dev, "Failed to allocate runlist IB\n");
goto out;
}
@@ -125,6 +127,8 @@ static int pm_create_runlist_ib(struct packet_manager *pm,
{
unsigned int alloc_size_bytes;
unsigned int *rl_buffer, rl_wptr, i;
+ struct kfd_node *node = pm->dqm->dev;
+ struct device *dev = node->adev->dev;
int retval, processes_mapped;
struct device_process_node *cur;
struct qcm_process_device *qpd;
@@ -142,7 +146,7 @@ static int pm_create_runlist_ib(struct packet_manager *pm,
*rl_size_bytes = alloc_size_bytes;
pm->ib_size_bytes = alloc_size_bytes;
- pr_debug("Building runlist ib process count: %d queues count %d\n",
+ dev_dbg(dev, "Building runlist ib process count: %d queues count %d\n",
pm->dqm->processes_count, pm->dqm->active_queue_count);
/* build the run list ib packet */
@@ -150,7 +154,7 @@ static int pm_create_runlist_ib(struct packet_manager *pm,
qpd = cur->qpd;
/* build map process packet */
if (processes_mapped >= pm->dqm->processes_count) {
- pr_debug("Not enough space left in runlist IB\n");
+ dev_dbg(dev, "Not enough space left in runlist IB\n");
pm_release_ib(pm);
return -ENOMEM;
}
@@ -167,7 +171,8 @@ static int pm_create_runlist_ib(struct packet_manager *pm,
if (!kq->queue->properties.is_active)
continue;
- pr_debug("static_queue, mapping kernel q %d, is debug status %d\n",
+ dev_dbg(dev,
+ "static_queue, mapping kernel q %d, is debug status %d\n",
kq->queue->queue, qpd->is_debug);
retval = pm->pmf->map_queues(pm,
@@ -186,7 +191,8 @@ static int pm_create_runlist_ib(struct packet_manager *pm,
if (!q->properties.is_active)
continue;
- pr_debug("static_queue, mapping user queue %d, is debug status %d\n",
+ dev_dbg(dev,
+ "static_queue, mapping user queue %d, is debug status %d\n",
q->queue, qpd->is_debug);
retval = pm->pmf->map_queues(pm,
@@ -203,11 +209,13 @@ static int pm_create_runlist_ib(struct packet_manager *pm,
}
}
- pr_debug("Finished map process and queues to runlist\n");
+ dev_dbg(dev, "Finished map process and queues to runlist\n");
if (is_over_subscription) {
if (!pm->is_over_subscription)
- pr_warn("Runlist is getting oversubscribed. Expect reduced ROCm performance.\n");
+ dev_warn(
+ dev,
+ "Runlist is getting oversubscribed. Expect reduced ROCm performance.\n");
retval = pm->pmf->runlist(pm, &rl_buffer[rl_wptr],
*rl_gpu_addr,
alloc_size_bytes / sizeof(uint32_t),
@@ -263,16 +271,18 @@ int pm_init(struct packet_manager *pm, struct device_queue_manager *dqm)
return 0;
}
-void pm_uninit(struct packet_manager *pm, bool hanging)
+void pm_uninit(struct packet_manager *pm)
{
mutex_destroy(&pm->lock);
- kernel_queue_uninit(pm->priv_queue, hanging);
+ kernel_queue_uninit(pm->priv_queue);
pm->priv_queue = NULL;
}
int pm_send_set_resources(struct packet_manager *pm,
struct scheduling_resources *res)
{
+ struct kfd_node *node = pm->dqm->dev;
+ struct device *dev = node->adev->dev;
uint32_t *buffer, size;
int retval = 0;
@@ -282,7 +292,7 @@ int pm_send_set_resources(struct packet_manager *pm,
size / sizeof(uint32_t),
(unsigned int **)&buffer);
if (!buffer) {
- pr_err("Failed to allocate buffer on kernel queue\n");
+ dev_err(dev, "Failed to allocate buffer on kernel queue\n");
retval = -ENOMEM;
goto out;
}
@@ -344,6 +354,8 @@ fail_create_runlist_ib:
int pm_send_query_status(struct packet_manager *pm, uint64_t fence_address,
uint64_t fence_value)
{
+ struct kfd_node *node = pm->dqm->dev;
+ struct device *dev = node->adev->dev;
uint32_t *buffer, size;
int retval = 0;
@@ -355,7 +367,7 @@ int pm_send_query_status(struct packet_manager *pm, uint64_t fence_address,
kq_acquire_packet_buffer(pm->priv_queue,
size / sizeof(uint32_t), (unsigned int **)&buffer);
if (!buffer) {
- pr_err("Failed to allocate buffer on kernel queue\n");
+ dev_err(dev, "Failed to allocate buffer on kernel queue\n");
retval = -ENOMEM;
goto out;
}
@@ -373,6 +385,8 @@ out:
int pm_update_grace_period(struct packet_manager *pm, uint32_t grace_period)
{
+ struct kfd_node *node = pm->dqm->dev;
+ struct device *dev = node->adev->dev;
int retval = 0;
uint32_t *buffer, size;
@@ -386,7 +400,8 @@ int pm_update_grace_period(struct packet_manager *pm, uint32_t grace_period)
(unsigned int **)&buffer);
if (!buffer) {
- pr_err("Failed to allocate buffer on kernel queue\n");
+ dev_err(dev,
+ "Failed to allocate buffer on kernel queue\n");
retval = -ENOMEM;
goto out;
}
@@ -407,6 +422,8 @@ int pm_send_unmap_queue(struct packet_manager *pm,
enum kfd_unmap_queues_filter filter,
uint32_t filter_param, bool reset)
{
+ struct kfd_node *node = pm->dqm->dev;
+ struct device *dev = node->adev->dev;
uint32_t *buffer, size;
int retval = 0;
@@ -415,7 +432,7 @@ int pm_send_unmap_queue(struct packet_manager *pm,
kq_acquire_packet_buffer(pm->priv_queue,
size / sizeof(uint32_t), (unsigned int **)&buffer);
if (!buffer) {
- pr_err("Failed to allocate buffer on kernel queue\n");
+ dev_err(dev, "Failed to allocate buffer on kernel queue\n");
retval = -ENOMEM;
goto out;
}
@@ -464,6 +481,8 @@ out:
int pm_debugfs_hang_hws(struct packet_manager *pm)
{
+ struct kfd_node *node = pm->dqm->dev;
+ struct device *dev = node->adev->dev;
uint32_t *buffer, size;
int r = 0;
@@ -475,16 +494,16 @@ int pm_debugfs_hang_hws(struct packet_manager *pm)
kq_acquire_packet_buffer(pm->priv_queue,
size / sizeof(uint32_t), (unsigned int **)&buffer);
if (!buffer) {
- pr_err("Failed to allocate buffer on kernel queue\n");
+ dev_err(dev, "Failed to allocate buffer on kernel queue\n");
r = -ENOMEM;
goto out;
}
memset(buffer, 0x55, size);
kq_submit_packet(pm->priv_queue);
- pr_info("Submitting %x %x %x %x %x %x %x to HIQ to hang the HWS.",
- buffer[0], buffer[1], buffer[2], buffer[3],
- buffer[4], buffer[5], buffer[6]);
+ dev_info(dev, "Submitting %x %x %x %x %x %x %x to HIQ to hang the HWS.",
+ buffer[0], buffer[1], buffer[2], buffer[3], buffer[4],
+ buffer[5], buffer[6]);
out:
mutex_unlock(&pm->lock);
return r;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
index c51e908f6f19..2b3ec92981e8 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
@@ -1301,7 +1301,7 @@ struct device_queue_manager *device_queue_manager_init(struct kfd_node *dev);
void device_queue_manager_uninit(struct device_queue_manager *dqm);
struct kernel_queue *kernel_queue_init(struct kfd_node *dev,
enum kfd_queue_type type);
-void kernel_queue_uninit(struct kernel_queue *kq, bool hanging);
+void kernel_queue_uninit(struct kernel_queue *kq);
int kfd_dqm_evict_pasid(struct device_queue_manager *dqm, u32 pasid);
/* Process Queue Manager */
@@ -1407,7 +1407,7 @@ extern const struct packet_manager_funcs kfd_v9_pm_funcs;
extern const struct packet_manager_funcs kfd_aldebaran_pm_funcs;
int pm_init(struct packet_manager *pm, struct device_queue_manager *dqm);
-void pm_uninit(struct packet_manager *pm, bool hanging);
+void pm_uninit(struct packet_manager *pm);
int pm_send_set_resources(struct packet_manager *pm,
struct scheduling_resources *res);
int pm_send_runlist(struct packet_manager *pm, struct list_head *dqm_queues);
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
index 6251f37c312a..17e42161b015 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
@@ -1311,7 +1311,8 @@ int kfd_process_init_cwsr_apu(struct kfd_process *p, struct file *filep)
if (IS_ERR_VALUE(qpd->tba_addr)) {
int err = qpd->tba_addr;
- pr_err("Failure to set tba address. error %d.\n", err);
+ dev_err(dev->adev->dev,
+ "Failure to set tba address. error %d.\n", err);
qpd->tba_addr = 0;
qpd->cwsr_kaddr = NULL;
return err;
@@ -1611,7 +1612,8 @@ struct kfd_process_device *kfd_create_process_device_data(struct kfd_node *dev,
&pdd->proc_ctx_cpu_ptr,
false);
if (retval) {
- pr_err("failed to allocate process context bo\n");
+ dev_err(dev->adev->dev,
+ "failed to allocate process context bo\n");
goto err_free_pdd;
}
memset(pdd->proc_ctx_cpu_ptr, 0, AMDGPU_MES_PROC_CTX_SIZE);
@@ -1676,7 +1678,7 @@ int kfd_process_device_init_vm(struct kfd_process_device *pdd,
&p->kgd_process_info,
&ef);
if (ret) {
- pr_err("Failed to create process VM object\n");
+ dev_err(dev->adev->dev, "Failed to create process VM object\n");
return ret;
}
RCU_INIT_POINTER(p->ef, ef);
@@ -1723,7 +1725,7 @@ struct kfd_process_device *kfd_bind_process_to_device(struct kfd_node *dev,
pdd = kfd_get_process_device_data(dev, p);
if (!pdd) {
- pr_err("Process device data doesn't exist\n");
+ dev_err(dev->adev->dev, "Process device data doesn't exist\n");
return ERR_PTR(-ENOMEM);
}
@@ -1833,6 +1835,7 @@ int kfd_process_evict_queues(struct kfd_process *p, uint32_t trigger)
for (i = 0; i < p->n_pdds; i++) {
struct kfd_process_device *pdd = p->pdds[i];
+ struct device *dev = pdd->dev->adev->dev;
kfd_smi_event_queue_eviction(pdd->dev, p->lead_thread->pid,
trigger);
@@ -1844,7 +1847,7 @@ int kfd_process_evict_queues(struct kfd_process *p, uint32_t trigger)
* them been add back since they actually not be saved right now.
*/
if (r && r != -EIO) {
- pr_err("Failed to evict process queues\n");
+ dev_err(dev, "Failed to evict process queues\n");
goto fail;
}
n_evicted++;
@@ -1866,7 +1869,8 @@ fail:
if (pdd->dev->dqm->ops.restore_process_queues(pdd->dev->dqm,
&pdd->qpd))
- pr_err("Failed to restore queues\n");
+ dev_err(pdd->dev->adev->dev,
+ "Failed to restore queues\n");
n_evicted--;
}
@@ -1882,13 +1886,14 @@ int kfd_process_restore_queues(struct kfd_process *p)
for (i = 0; i < p->n_pdds; i++) {
struct kfd_process_device *pdd = p->pdds[i];
+ struct device *dev = pdd->dev->adev->dev;
kfd_smi_event_queue_restore(pdd->dev, p->lead_thread->pid);
r = pdd->dev->dqm->ops.restore_process_queues(pdd->dev->dqm,
&pdd->qpd);
if (r) {
- pr_err("Failed to restore process queues\n");
+ dev_err(dev, "Failed to restore process queues\n");
if (!ret)
ret = r;
}
@@ -2065,7 +2070,7 @@ int kfd_reserved_mem_mmap(struct kfd_node *dev, struct kfd_process *process,
struct qcm_process_device *qpd;
if ((vma->vm_end - vma->vm_start) != KFD_CWSR_TBA_TMA_SIZE) {
- pr_err("Incorrect CWSR mapping size.\n");
+ dev_err(dev->adev->dev, "Incorrect CWSR mapping size.\n");
return -EINVAL;
}
@@ -2077,7 +2082,8 @@ int kfd_reserved_mem_mmap(struct kfd_node *dev, struct kfd_process *process,
qpd->cwsr_kaddr = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
get_order(KFD_CWSR_TBA_TMA_SIZE));
if (!qpd->cwsr_kaddr) {
- pr_err("Error allocating per process CWSR buffer.\n");
+ dev_err(dev->adev->dev,
+ "Error allocating per process CWSR buffer.\n");
return -ENOMEM;
}
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 6bf79c435f2e..21f5a1fb3bf8 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
@@ -28,6 +28,7 @@
#include "kfd_priv.h"
#include "kfd_kernel_queue.h"
#include "amdgpu_amdkfd.h"
+#include "amdgpu_reset.h"
static inline struct process_queue_node *get_queue_by_qid(
struct process_queue_manager *pqm, unsigned int qid)
@@ -87,8 +88,12 @@ void kfd_process_dequeue_from_device(struct kfd_process_device *pdd)
return;
dev->dqm->ops.process_termination(dev->dqm, &pdd->qpd);
- if (dev->kfd->shared_resources.enable_mes)
- amdgpu_mes_flush_shader_debugger(dev->adev, pdd->proc_ctx_gpu_addr);
+ if (dev->kfd->shared_resources.enable_mes &&
+ down_read_trylock(&dev->adev->reset_domain->sem)) {
+ amdgpu_mes_flush_shader_debugger(dev->adev,
+ pdd->proc_ctx_gpu_addr);
+ up_read(&dev->adev->reset_domain->sem);
+ }
pdd->already_dequeued = true;
}
@@ -434,7 +439,7 @@ int pqm_create_queue(struct process_queue_manager *pqm,
err_create_queue:
uninit_queue(q);
if (kq)
- kernel_queue_uninit(kq, false);
+ kernel_queue_uninit(kq);
kfree(pqn);
err_allocate_pqn:
/* check if queues list is empty unregister process from device */
@@ -481,7 +486,7 @@ int pqm_destroy_queue(struct process_queue_manager *pqm, unsigned int qid)
/* destroy kernel queue (DIQ) */
dqm = pqn->kq->dev->dqm;
dqm->ops.destroy_kernel_queue(dqm, pqn->kq, &pdd->qpd);
- kernel_queue_uninit(pqn->kq, false);
+ kernel_queue_uninit(pqn->kq);
}
if (pqn->q) {
diff --git a/drivers/gpu/drm/amd/display/Kconfig b/drivers/gpu/drm/amd/display/Kconfig
index a64f890cbc0b..df17e79c45c7 100644
--- a/drivers/gpu/drm/amd/display/Kconfig
+++ b/drivers/gpu/drm/amd/display/Kconfig
@@ -10,7 +10,7 @@ config DRM_AMD_DC
depends on BROKEN || !CC_IS_CLANG || ARM64 || RISCV || SPARC64 || X86_64
select SND_HDA_COMPONENT if SND_HDA_CORE
# !CC_IS_CLANG: https://github.com/ClangBuiltLinux/linux/issues/1752
- select DRM_AMD_DC_FP if ARCH_HAS_KERNEL_FPU_SUPPORT && (!ARM64 || !CC_IS_CLANG)
+ select DRM_AMD_DC_FP if ARCH_HAS_KERNEL_FPU_SUPPORT && !(CC_IS_CLANG && (ARM64 || RISCV))
help
Choose this option if you want to use the new display engine
support for AMDGPU. This adds required support for Vega and
diff --git a/drivers/gpu/drm/amd/display/Makefile b/drivers/gpu/drm/amd/display/Makefile
index 8297fbce7749..89d605de0595 100644
--- a/drivers/gpu/drm/amd/display/Makefile
+++ b/drivers/gpu/drm/amd/display/Makefile
@@ -37,6 +37,13 @@ subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dpp
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/hubbub
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dccg
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/hubp
+subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dio
+subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dwb
+subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/hpo
+subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/mmhubbub
+subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/mpc
+subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/opp
+subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/pg
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/inc
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/freesync
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/color
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 6196de6cebbf..7e7929f24ae4 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -77,9 +77,11 @@
#include <linux/types.h>
#include <linux/pm_runtime.h>
#include <linux/pci.h>
+#include <linux/power_supply.h>
#include <linux/firmware.h>
#include <linux/component.h>
#include <linux/dmi.h>
+#include <linux/sort.h>
#include <drm/display/drm_dp_mst_helper.h>
#include <drm/display/drm_hdmi_helper.h>
@@ -366,13 +368,18 @@ static inline bool is_dc_timing_adjust_needed(struct dm_crtc_state *old_state,
return false;
}
-static inline void reverse_planes_order(struct dc_surface_update *array_of_surface_update,
- int planes_count)
+/*
+ * DC will program planes with their z-order determined by their ordering
+ * in the dc_surface_updates array. This comparator is used to sort them
+ * by descending zpos.
+ */
+static int dm_plane_layer_index_cmp(const void *a, const void *b)
{
- int i, j;
+ const struct dc_surface_update *sa = (struct dc_surface_update *)a;
+ const struct dc_surface_update *sb = (struct dc_surface_update *)b;
- for (i = 0, j = planes_count - 1; i < j; i++, j--)
- swap(array_of_surface_update[i], array_of_surface_update[j]);
+ /* Sort by descending dc_plane layer_index (i.e. normalized_zpos) */
+ return sb->surface->layer_index - sa->surface->layer_index;
}
/**
@@ -399,7 +406,8 @@ static inline bool update_planes_and_stream_adapter(struct dc *dc,
struct dc_stream_update *stream_update,
struct dc_surface_update *array_of_surface_update)
{
- reverse_planes_order(array_of_surface_update, planes_count);
+ sort(array_of_surface_update, planes_count,
+ sizeof(*array_of_surface_update), dm_plane_layer_index_cmp, NULL);
/*
* Previous frame finished and HW is ready for optimization.
@@ -534,7 +542,7 @@ static void dm_vupdate_high_irq(void *interrupt_params)
if (acrtc) {
vrr_active = amdgpu_dm_crtc_vrr_active_irq(acrtc);
drm_dev = acrtc->base.dev;
- vblank = &drm_dev->vblank[acrtc->base.index];
+ vblank = drm_crtc_vblank_crtc(&acrtc->base);
previous_timestamp = atomic64_read(&irq_params->previous_timestamp);
frame_duration_ns = vblank->time - previous_timestamp;
@@ -774,9 +782,9 @@ static void dmub_hpd_callback(struct amdgpu_device *adev,
aconnector = to_amdgpu_dm_connector(connector);
if (link && aconnector->dc_link == link) {
if (notify->type == DMUB_NOTIFICATION_HPD)
- DRM_INFO("DMUB HPD callback: link_index=%u\n", link_index);
- else if (notify->type == DMUB_NOTIFICATION_HPD_IRQ)
DRM_INFO("DMUB HPD IRQ callback: link_index=%u\n", link_index);
+ else if (notify->type == DMUB_NOTIFICATION_HPD_IRQ)
+ DRM_INFO("DMUB HPD RX IRQ callback: link_index=%u\n", link_index);
else
DRM_WARN("DMUB Unknown HPD callback type %d, link_index=%u\n",
notify->type, link_index);
@@ -788,10 +796,13 @@ static void dmub_hpd_callback(struct amdgpu_device *adev,
drm_connector_list_iter_end(&iter);
if (hpd_aconnector) {
- if (notify->type == DMUB_NOTIFICATION_HPD)
+ if (notify->type == DMUB_NOTIFICATION_HPD) {
+ if (hpd_aconnector->dc_link->hpd_status == (notify->hpd_status == DP_HPD_PLUG))
+ DRM_WARN("DMUB reported hpd status unchanged. link_index=%u\n", link_index);
handle_hpd_irq_helper(hpd_aconnector);
- else if (notify->type == DMUB_NOTIFICATION_HPD_IRQ)
+ } else if (notify->type == DMUB_NOTIFICATION_HPD_IRQ) {
handle_hpd_rx_irq(hpd_aconnector);
+ }
}
}
@@ -859,7 +870,31 @@ static void dm_dmub_outbox1_low_irq(void *interrupt_params)
struct dmcub_trace_buf_entry entry = { 0 };
u32 count = 0;
struct dmub_hpd_work *dmub_hpd_wrk;
- struct dc_link *plink = NULL;
+ static const char *const event_type[] = {
+ "NO_DATA",
+ "AUX_REPLY",
+ "HPD",
+ "HPD_IRQ",
+ "SET_CONFIGC_REPLY",
+ "DPIA_NOTIFICATION",
+ };
+
+ do {
+ if (dc_dmub_srv_get_dmub_outbox0_msg(dm->dc, &entry)) {
+ trace_amdgpu_dmub_trace_high_irq(entry.trace_code, entry.tick_count,
+ entry.param0, entry.param1);
+
+ DRM_DEBUG_DRIVER("trace_code:%u, tick_count:%u, param0:%u, param1:%u\n",
+ entry.trace_code, entry.tick_count, entry.param0, entry.param1);
+ } else
+ break;
+
+ count++;
+
+ } while (count <= DMUB_TRACE_MAX_READ);
+
+ if (count > DMUB_TRACE_MAX_READ)
+ DRM_DEBUG_DRIVER("Warning : count > DMUB_TRACE_MAX_READ");
if (dc_enable_dmub_notifications(adev->dm.dc) &&
irq_params->irq_src == DC_IRQ_SOURCE_DMCUB_OUTBOX) {
@@ -871,7 +906,8 @@ static void dm_dmub_outbox1_low_irq(void *interrupt_params)
continue;
}
if (!dm->dmub_callback[notify.type]) {
- DRM_DEBUG_DRIVER("DMUB notification skipped, no handler: type=%d\n", notify.type);
+ DRM_WARN("DMUB notification skipped due to no handler: type=%s\n",
+ event_type[notify.type]);
continue;
}
if (dm->dmub_thread_offload[notify.type] == true) {
@@ -889,37 +925,12 @@ static void dm_dmub_outbox1_low_irq(void *interrupt_params)
}
INIT_WORK(&dmub_hpd_wrk->handle_hpd_work, dm_handle_hpd_work);
dmub_hpd_wrk->adev = adev;
- if (notify.type == DMUB_NOTIFICATION_HPD) {
- plink = adev->dm.dc->links[notify.link_index];
- if (plink) {
- plink->hpd_status =
- notify.hpd_status == DP_HPD_PLUG;
- }
- }
queue_work(adev->dm.delayed_hpd_wq, &dmub_hpd_wrk->handle_hpd_work);
} else {
dm->dmub_callback[notify.type](adev, &notify);
}
} while (notify.pending_notification);
}
-
-
- do {
- if (dc_dmub_srv_get_dmub_outbox0_msg(dm->dc, &entry)) {
- trace_amdgpu_dmub_trace_high_irq(entry.trace_code, entry.tick_count,
- entry.param0, entry.param1);
-
- DRM_DEBUG_DRIVER("trace_code:%u, tick_count:%u, param0:%u, param1:%u\n",
- entry.trace_code, entry.tick_count, entry.param0, entry.param1);
- } else
- break;
-
- count++;
-
- } while (count <= DMUB_TRACE_MAX_READ);
-
- if (count > DMUB_TRACE_MAX_READ)
- DRM_DEBUG_DRIVER("Warning : count > DMUB_TRACE_MAX_READ");
}
static int dm_set_clockgating_state(void *handle,
@@ -957,8 +968,8 @@ static void amdgpu_dm_fbc_init(struct drm_connector *connector)
list_for_each_entry(mode, &connector->modes, head) {
- if (max_size < mode->htotal * mode->vtotal)
- max_size = mode->htotal * mode->vtotal;
+ if (max_size < (unsigned long) mode->htotal * mode->vtotal)
+ max_size = (unsigned long) mode->htotal * mode->vtotal;
}
if (max_size) {
@@ -1282,6 +1293,7 @@ static void dm_dmub_hw_resume(struct amdgpu_device *adev)
struct dmub_srv *dmub_srv = adev->dm.dmub_srv;
enum dmub_status status;
bool init;
+ int r;
if (!dmub_srv) {
/* DMUB isn't supported on the ASIC. */
@@ -1299,7 +1311,9 @@ static void dm_dmub_hw_resume(struct amdgpu_device *adev)
DRM_WARN("Wait for DMUB auto-load failed: %d\n", status);
} else {
/* Perform the full hardware initialization. */
- dm_dmub_hw_init(adev);
+ r = dm_dmub_hw_init(adev);
+ if (r)
+ DRM_ERROR("DMUB interface failed to initialize: status=%d\n", r);
}
}
@@ -2569,6 +2583,7 @@ static void resume_mst_branch_status(struct drm_dp_mst_topology_mgr *mgr)
ret = drm_dp_dpcd_writeb(mgr->aux, DP_MSTM_CTRL,
DP_MST_EN |
+ DP_UP_REQ_EN |
DP_UPSTREAM_IS_SRC);
if (ret < 0) {
drm_dbg_kms(mgr->dev, "mst write failed - undocked during suspend?\n");
@@ -2855,7 +2870,8 @@ static int dm_suspend(void *handle)
dm->cached_dc_state = dc_state_create_copy(dm->dc->current_state);
- dm_gpureset_toggle_interrupts(adev, dm->cached_dc_state, false);
+ if (dm->cached_dc_state)
+ dm_gpureset_toggle_interrupts(adev, dm->cached_dc_state, false);
amdgpu_dm_commit_zero_streams(dm->dc);
@@ -3159,7 +3175,7 @@ static int dm_resume(void *handle)
* this is the case when traversing through already created end sink
* MST connectors, should be skipped
*/
- if (aconnector && aconnector->mst_root)
+ if (aconnector->mst_root)
continue;
mutex_lock(&aconnector->hpd_lock);
@@ -3171,7 +3187,7 @@ static int dm_resume(void *handle)
} else {
mutex_lock(&dm->dc_lock);
dc_exit_ips_for_hw_access(dm->dc);
- dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD);
+ dc_link_detect(aconnector->dc_link, DETECT_REASON_RESUMEFROMS3S4);
mutex_unlock(&dm->dc_lock);
}
@@ -4571,6 +4587,7 @@ amdgpu_dm_register_backlight_device(struct amdgpu_dm_connector *aconnector)
struct drm_device *drm = aconnector->base.dev;
struct amdgpu_display_manager *dm = &drm_to_adev(drm)->dm;
struct backlight_properties props = { 0 };
+ struct amdgpu_dm_backlight_caps caps = { 0 };
char bl_name[16];
if (aconnector->bl_idx == -1)
@@ -4583,8 +4600,16 @@ amdgpu_dm_register_backlight_device(struct amdgpu_dm_connector *aconnector)
return;
}
+ amdgpu_acpi_get_backlight_caps(&caps);
+ if (caps.caps_valid) {
+ if (power_supply_is_system_supplied() > 0)
+ props.brightness = caps.ac_level;
+ else
+ props.brightness = caps.dc_level;
+ } else
+ props.brightness = AMDGPU_MAX_BL_LEVEL;
+
props.max_brightness = AMDGPU_MAX_BL_LEVEL;
- props.brightness = AMDGPU_MAX_BL_LEVEL;
props.type = BACKLIGHT_RAW;
snprintf(bl_name, sizeof(bl_name), "amdgpu_bl%d",
@@ -6392,13 +6417,13 @@ static void apply_dsc_policy_for_stream(struct amdgpu_dm_connector *aconnector,
dc_dsc_policy_set_enable_dsc_when_not_needed(
aconnector->dsc_settings.dsc_force_enable == DSC_CLK_FORCE_ENABLE);
- if (aconnector->dc_link && sink->sink_signal == SIGNAL_TYPE_EDP &&
+ if (sink->sink_signal == SIGNAL_TYPE_EDP &&
!aconnector->dc_link->panel_config.dsc.disable_dsc_edp &&
dc->caps.edp_dsc_support && aconnector->dsc_settings.dsc_force_enable != DSC_CLK_FORCE_DISABLE) {
apply_dsc_policy_for_edp(aconnector, sink, stream, dsc_caps, max_dsc_target_bpp_limit_override);
- } else if (aconnector->dc_link && sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT) {
+ } else if (sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT) {
if (sink->link->dpcd_caps.dongle_type == DISPLAY_DONGLE_NONE) {
if (dc_dsc_compute_config(aconnector->dc_link->ctx->dc->res_pool->dscs[0],
dsc_caps,
@@ -7073,7 +7098,8 @@ static void create_eml_sink(struct amdgpu_dm_connector *aconnector)
aconnector->dc_sink = aconnector->dc_link->local_sink ?
aconnector->dc_link->local_sink :
aconnector->dc_em_sink;
- dc_sink_retain(aconnector->dc_sink);
+ if (aconnector->dc_sink)
+ dc_sink_retain(aconnector->dc_sink);
}
}
@@ -7536,7 +7562,7 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
}
}
- if (j == dc_state->stream_count)
+ if (j == dc_state->stream_count || pbn_div == 0)
continue;
slot_num = DIV_ROUND_UP(pbn, pbn_div);
@@ -7900,7 +7926,8 @@ static int amdgpu_dm_connector_get_modes(struct drm_connector *connector)
drm_add_modes_noedid(connector, 1920, 1080);
} else {
amdgpu_dm_connector_ddc_get_modes(connector, edid);
- amdgpu_dm_connector_add_common_modes(encoder, connector);
+ if (encoder)
+ amdgpu_dm_connector_add_common_modes(encoder, connector);
amdgpu_dm_connector_add_freesync_modes(connector, edid);
}
amdgpu_dm_fbc_init(connector);
@@ -8745,8 +8772,24 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
* Disable the cursor first if we're disabling all the planes.
* It'll remain on the screen after the planes are re-enabled
* if we don't.
+ *
+ * If the cursor is transitioning from native to overlay mode, the
+ * native cursor needs to be disabled first.
*/
- if (acrtc_state->active_planes == 0)
+ if (acrtc_state->cursor_mode == DM_CURSOR_OVERLAY_MODE &&
+ dm_old_crtc_state->cursor_mode == DM_CURSOR_NATIVE_MODE) {
+ struct dc_cursor_position cursor_position = {0};
+
+ if (!dc_stream_set_cursor_position(acrtc_state->stream,
+ &cursor_position))
+ drm_err(dev, "DC failed to disable native cursor\n");
+
+ bundle->stream_update.cursor_position =
+ &acrtc_state->stream->cursor_position;
+ }
+
+ if (acrtc_state->active_planes == 0 &&
+ dm_old_crtc_state->cursor_mode == DM_CURSOR_NATIVE_MODE)
amdgpu_dm_commit_cursors(state);
/* update planes when needed */
@@ -8760,7 +8803,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
struct dm_plane_state *dm_new_plane_state = to_dm_plane_state(new_plane_state);
/* Cursor plane is handled after stream updates */
- if (plane->type == DRM_PLANE_TYPE_CURSOR) {
+ if (plane->type == DRM_PLANE_TYPE_CURSOR &&
+ acrtc_state->cursor_mode == DM_CURSOR_NATIVE_MODE) {
if ((fb && crtc == pcrtc) ||
(old_plane_state->fb && old_plane_state->crtc == pcrtc)) {
cursor_update = true;
@@ -9116,7 +9160,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
* to be disabling a single plane - those pipes are being disabled.
*/
if (acrtc_state->active_planes &&
- (!updated_planes_and_streams || amdgpu_ip_version(dm->adev, DCE_HWIP, 0) == 0))
+ (!updated_planes_and_streams || amdgpu_ip_version(dm->adev, DCE_HWIP, 0) == 0) &&
+ acrtc_state->cursor_mode == DM_CURSOR_NATIVE_MODE)
amdgpu_dm_commit_cursors(state);
cleanup:
@@ -9744,6 +9789,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
for (j = 0; j < status->plane_count; j++)
dummy_updates[j].surface = status->plane_states[0];
+ sort(dummy_updates, status->plane_count,
+ sizeof(*dummy_updates), dm_plane_layer_index_cmp, NULL);
mutex_lock(&dm->dc_lock);
dc_exit_ips_for_hw_access(dm->dc);
@@ -10434,7 +10481,8 @@ static bool should_reset_plane(struct drm_atomic_state *state,
{
struct drm_plane *other;
struct drm_plane_state *old_other_state, *new_other_state;
- struct drm_crtc_state *new_crtc_state;
+ struct drm_crtc_state *old_crtc_state, *new_crtc_state;
+ struct dm_crtc_state *old_dm_crtc_state, *new_dm_crtc_state;
struct amdgpu_device *adev = drm_to_adev(plane->dev);
int i;
@@ -10456,14 +10504,38 @@ static bool should_reset_plane(struct drm_atomic_state *state,
new_crtc_state =
drm_atomic_get_new_crtc_state(state, new_plane_state->crtc);
+ old_crtc_state =
+ drm_atomic_get_old_crtc_state(state, old_plane_state->crtc);
if (!new_crtc_state)
return true;
+ /*
+ * A change in cursor mode means a new dc pipe needs to be acquired or
+ * released from the state
+ */
+ old_dm_crtc_state = to_dm_crtc_state(old_crtc_state);
+ new_dm_crtc_state = to_dm_crtc_state(new_crtc_state);
+ if (plane->type == DRM_PLANE_TYPE_CURSOR &&
+ old_dm_crtc_state != NULL &&
+ old_dm_crtc_state->cursor_mode != new_dm_crtc_state->cursor_mode) {
+ return true;
+ }
+
/* CRTC Degamma changes currently require us to recreate planes. */
if (new_crtc_state->color_mgmt_changed)
return true;
+ /*
+ * On zpos change, planes need to be reordered by removing and re-adding
+ * them one by one to the dc state, in order of descending zpos.
+ *
+ * TODO: We can likely skip bandwidth validation if the only thing that
+ * changed about the plane was it'z z-ordering.
+ */
+ if (new_crtc_state->zpos_changed)
+ return true;
+
if (drm_atomic_crtc_needs_modeset(new_crtc_state))
return true;
@@ -10595,12 +10667,14 @@ static int dm_check_cursor_fb(struct amdgpu_crtc *new_acrtc,
* check tiling flags when the FB doesn't have a modifier.
*/
if (!(fb->flags & DRM_MODE_FB_MODIFIERS)) {
- if (adev->family < AMDGPU_FAMILY_AI) {
+ if (adev->family >= AMDGPU_FAMILY_GC_12_0_0) {
+ linear = AMDGPU_TILING_GET(afb->tiling_flags, GFX12_SWIZZLE_MODE) == 0;
+ } else if (adev->family >= AMDGPU_FAMILY_AI) {
+ linear = AMDGPU_TILING_GET(afb->tiling_flags, SWIZZLE_MODE) == 0;
+ } else {
linear = AMDGPU_TILING_GET(afb->tiling_flags, ARRAY_MODE) != DC_ARRAY_2D_TILED_THIN1 &&
AMDGPU_TILING_GET(afb->tiling_flags, ARRAY_MODE) != DC_ARRAY_1D_TILED_THIN1 &&
AMDGPU_TILING_GET(afb->tiling_flags, MICRO_TILE_MODE) == 0;
- } else {
- linear = AMDGPU_TILING_GET(afb->tiling_flags, SWIZZLE_MODE) == 0;
}
if (!linear) {
DRM_DEBUG_ATOMIC("Cursor FB not linear");
@@ -10611,6 +10685,68 @@ static int dm_check_cursor_fb(struct amdgpu_crtc *new_acrtc,
return 0;
}
+/*
+ * Helper function for checking the cursor in native mode
+ */
+static int dm_check_native_cursor_state(struct drm_crtc *new_plane_crtc,
+ struct drm_plane *plane,
+ struct drm_plane_state *new_plane_state,
+ bool enable)
+{
+
+ struct amdgpu_crtc *new_acrtc;
+ int ret;
+
+ if (!enable || !new_plane_crtc ||
+ drm_atomic_plane_disabling(plane->state, new_plane_state))
+ return 0;
+
+ new_acrtc = to_amdgpu_crtc(new_plane_crtc);
+
+ if (new_plane_state->src_x != 0 || new_plane_state->src_y != 0) {
+ DRM_DEBUG_ATOMIC("Cropping not supported for cursor plane\n");
+ return -EINVAL;
+ }
+
+ if (new_plane_state->fb) {
+ ret = dm_check_cursor_fb(new_acrtc, new_plane_state,
+ new_plane_state->fb);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static bool dm_should_update_native_cursor(struct drm_atomic_state *state,
+ struct drm_crtc *old_plane_crtc,
+ struct drm_crtc *new_plane_crtc,
+ bool enable)
+{
+ struct drm_crtc_state *old_crtc_state, *new_crtc_state;
+ struct dm_crtc_state *dm_old_crtc_state, *dm_new_crtc_state;
+
+ if (!enable) {
+ if (old_plane_crtc == NULL)
+ return true;
+
+ old_crtc_state = drm_atomic_get_old_crtc_state(
+ state, old_plane_crtc);
+ dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
+
+ return dm_old_crtc_state->cursor_mode == DM_CURSOR_NATIVE_MODE;
+ } else {
+ if (new_plane_crtc == NULL)
+ return true;
+
+ new_crtc_state = drm_atomic_get_new_crtc_state(
+ state, new_plane_crtc);
+ dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
+
+ return dm_new_crtc_state->cursor_mode == DM_CURSOR_NATIVE_MODE;
+ }
+}
+
static int dm_update_plane_state(struct dc *dc,
struct drm_atomic_state *state,
struct drm_plane *plane,
@@ -10626,8 +10762,7 @@ static int dm_update_plane_state(struct dc *dc,
struct drm_crtc_state *old_crtc_state, *new_crtc_state;
struct dm_crtc_state *dm_new_crtc_state, *dm_old_crtc_state;
struct dm_plane_state *dm_new_plane_state, *dm_old_plane_state;
- struct amdgpu_crtc *new_acrtc;
- bool needs_reset;
+ bool needs_reset, update_native_cursor;
int ret = 0;
@@ -10636,24 +10771,16 @@ static int dm_update_plane_state(struct dc *dc,
dm_new_plane_state = to_dm_plane_state(new_plane_state);
dm_old_plane_state = to_dm_plane_state(old_plane_state);
- if (plane->type == DRM_PLANE_TYPE_CURSOR) {
- if (!enable || !new_plane_crtc ||
- drm_atomic_plane_disabling(plane->state, new_plane_state))
- return 0;
-
- new_acrtc = to_amdgpu_crtc(new_plane_crtc);
+ update_native_cursor = dm_should_update_native_cursor(state,
+ old_plane_crtc,
+ new_plane_crtc,
+ enable);
- if (new_plane_state->src_x != 0 || new_plane_state->src_y != 0) {
- DRM_DEBUG_ATOMIC("Cropping not supported for cursor plane\n");
- return -EINVAL;
- }
-
- if (new_plane_state->fb) {
- ret = dm_check_cursor_fb(new_acrtc, new_plane_state,
- new_plane_state->fb);
- if (ret)
- return ret;
- }
+ if (plane->type == DRM_PLANE_TYPE_CURSOR && update_native_cursor) {
+ ret = dm_check_native_cursor_state(new_plane_crtc, plane,
+ new_plane_state, enable);
+ if (ret)
+ return ret;
return 0;
}
@@ -10719,20 +10846,14 @@ static int dm_update_plane_state(struct dc *dc,
ret = amdgpu_dm_plane_helper_check_state(new_plane_state, new_crtc_state);
if (ret)
- return ret;
+ goto out;
WARN_ON(dm_new_plane_state->dc_state);
dc_new_plane_state = dc_create_plane_state(dc);
- if (!dc_new_plane_state)
- return -ENOMEM;
-
- /* Block top most plane from being a video plane */
- if (plane->type == DRM_PLANE_TYPE_OVERLAY) {
- if (amdgpu_dm_plane_is_video_format(new_plane_state->fb->format->format) && *is_top_most_overlay)
- return -EINVAL;
-
- *is_top_most_overlay = false;
+ if (!dc_new_plane_state) {
+ ret = -ENOMEM;
+ goto out;
}
DRM_DEBUG_ATOMIC("Enabling DRM plane: %d on DRM crtc %d\n",
@@ -10745,13 +10866,13 @@ static int dm_update_plane_state(struct dc *dc,
new_crtc_state);
if (ret) {
dc_plane_state_release(dc_new_plane_state);
- return ret;
+ goto out;
}
ret = dm_atomic_get_state(state, &dm_state);
if (ret) {
dc_plane_state_release(dc_new_plane_state);
- return ret;
+ goto out;
}
/*
@@ -10768,7 +10889,8 @@ static int dm_update_plane_state(struct dc *dc,
dm_state->context)) {
dc_plane_state_release(dc_new_plane_state);
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
dm_new_plane_state->dc_state = dc_new_plane_state;
@@ -10783,6 +10905,16 @@ static int dm_update_plane_state(struct dc *dc,
*lock_and_validation_needed = true;
}
+out:
+ /* If enabling cursor overlay failed, attempt fallback to native mode */
+ if (enable && ret == -EINVAL && plane->type == DRM_PLANE_TYPE_CURSOR) {
+ ret = dm_check_native_cursor_state(new_plane_crtc, plane,
+ new_plane_state, enable);
+ if (ret)
+ return ret;
+
+ dm_new_crtc_state->cursor_mode = DM_CURSOR_NATIVE_MODE;
+ }
return ret;
}
@@ -10816,99 +10948,64 @@ dm_get_plane_scale(struct drm_plane_state *plane_state,
*out_plane_scale_h = plane_state->crtc_h * 1000 / plane_src_h;
}
-static int dm_check_crtc_cursor(struct drm_atomic_state *state,
- struct drm_crtc *crtc,
- struct drm_crtc_state *new_crtc_state)
+/*
+ * The normalized_zpos value cannot be used by this iterator directly. It's only
+ * calculated for enabled planes, potentially causing normalized_zpos collisions
+ * between enabled/disabled planes in the atomic state. We need a unique value
+ * so that the iterator will not generate the same object twice, or loop
+ * indefinitely.
+ */
+static inline struct __drm_planes_state *__get_next_zpos(
+ struct drm_atomic_state *state,
+ struct __drm_planes_state *prev)
{
- struct drm_plane *cursor = crtc->cursor, *plane, *underlying;
- struct drm_plane_state *old_plane_state, *new_plane_state;
- struct drm_plane_state *new_cursor_state, *new_underlying_state;
- int i;
- int cursor_scale_w, cursor_scale_h, underlying_scale_w, underlying_scale_h;
- bool any_relevant_change = false;
-
- /* On DCE and DCN there is no dedicated hardware cursor plane. We get a
- * cursor per pipe but it's going to inherit the scaling and
- * positioning from the underlying pipe. Check the cursor plane's
- * blending properties match the underlying planes'.
- */
-
- /* If no plane was enabled or changed scaling, no need to check again */
- for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) {
- int new_scale_w, new_scale_h, old_scale_w, old_scale_h;
-
- if (!new_plane_state || !new_plane_state->fb || new_plane_state->crtc != crtc)
- continue;
-
- if (!old_plane_state || !old_plane_state->fb || old_plane_state->crtc != crtc) {
- any_relevant_change = true;
- break;
- }
-
- if (new_plane_state->fb == old_plane_state->fb &&
- new_plane_state->crtc_w == old_plane_state->crtc_w &&
- new_plane_state->crtc_h == old_plane_state->crtc_h)
- continue;
-
- dm_get_plane_scale(new_plane_state, &new_scale_w, &new_scale_h);
- dm_get_plane_scale(old_plane_state, &old_scale_w, &old_scale_h);
+ unsigned int highest_zpos = 0, prev_zpos = 256;
+ uint32_t highest_id = 0, prev_id = UINT_MAX;
+ struct drm_plane_state *new_plane_state;
+ struct drm_plane *plane;
+ int i, highest_i = -1;
- if (new_scale_w != old_scale_w || new_scale_h != old_scale_h) {
- any_relevant_change = true;
- break;
- }
+ if (prev != NULL) {
+ prev_zpos = prev->new_state->zpos;
+ prev_id = prev->ptr->base.id;
}
- if (!any_relevant_change)
- return 0;
-
- new_cursor_state = drm_atomic_get_plane_state(state, cursor);
- if (IS_ERR(new_cursor_state))
- return PTR_ERR(new_cursor_state);
-
- if (!new_cursor_state->fb)
- return 0;
-
- dm_get_plane_scale(new_cursor_state, &cursor_scale_w, &cursor_scale_h);
-
- /* Need to check all enabled planes, even if this commit doesn't change
- * their state
- */
- i = drm_atomic_add_affected_planes(state, crtc);
- if (i)
- return i;
-
- for_each_new_plane_in_state_reverse(state, underlying, new_underlying_state, i) {
- /* Narrow down to non-cursor planes on the same CRTC as the cursor */
- if (new_underlying_state->crtc != crtc || underlying == crtc->cursor)
- continue;
-
- /* Ignore disabled planes */
- if (!new_underlying_state->fb)
+ for_each_new_plane_in_state(state, plane, new_plane_state, i) {
+ /* Skip planes with higher zpos than the previously returned */
+ if (new_plane_state->zpos > prev_zpos ||
+ (new_plane_state->zpos == prev_zpos &&
+ plane->base.id >= prev_id))
continue;
- dm_get_plane_scale(new_underlying_state,
- &underlying_scale_w, &underlying_scale_h);
-
- if (cursor_scale_w != underlying_scale_w ||
- cursor_scale_h != underlying_scale_h) {
- drm_dbg_atomic(crtc->dev,
- "Cursor [PLANE:%d:%s] scaling doesn't match underlying [PLANE:%d:%s]\n",
- cursor->base.id, cursor->name, underlying->base.id, underlying->name);
- return -EINVAL;
+ /* Save the index of the plane with highest zpos */
+ if (new_plane_state->zpos > highest_zpos ||
+ (new_plane_state->zpos == highest_zpos &&
+ plane->base.id > highest_id)) {
+ highest_zpos = new_plane_state->zpos;
+ highest_id = plane->base.id;
+ highest_i = i;
}
-
- /* If this plane covers the whole CRTC, no need to check planes underneath */
- if (new_underlying_state->crtc_x <= 0 &&
- new_underlying_state->crtc_y <= 0 &&
- new_underlying_state->crtc_x + new_underlying_state->crtc_w >= new_crtc_state->mode.hdisplay &&
- new_underlying_state->crtc_y + new_underlying_state->crtc_h >= new_crtc_state->mode.vdisplay)
- break;
}
- return 0;
+ if (highest_i < 0)
+ return NULL;
+
+ return &state->planes[highest_i];
}
+/*
+ * Use the uniqueness of the plane's (zpos, drm obj ID) combination to iterate
+ * by descending zpos, as read from the new plane state. This is the same
+ * ordering as defined by drm_atomic_normalize_zpos().
+ */
+#define for_each_oldnew_plane_in_descending_zpos(__state, plane, old_plane_state, new_plane_state) \
+ for (struct __drm_planes_state *__i = __get_next_zpos((__state), NULL); \
+ __i != NULL; __i = __get_next_zpos((__state), __i)) \
+ for_each_if(((plane) = __i->ptr, \
+ (void)(plane) /* Only to avoid unused-but-set-variable warning */, \
+ (old_plane_state) = __i->old_state, \
+ (new_plane_state) = __i->new_state, 1))
+
static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm_crtc *crtc)
{
struct drm_connector *connector;
@@ -10940,6 +11037,169 @@ static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm
}
/**
+ * DOC: Cursor Modes - Native vs Overlay
+ *
+ * In native mode, the cursor uses a integrated cursor pipe within each DCN hw
+ * plane. It does not require a dedicated hw plane to enable, but it is
+ * subjected to the same z-order and scaling as the hw plane. It also has format
+ * restrictions, a RGB cursor in native mode cannot be enabled within a non-RGB
+ * hw plane.
+ *
+ * In overlay mode, the cursor uses a separate DCN hw plane, and thus has its
+ * own scaling and z-pos. It also has no blending restrictions. It lends to a
+ * cursor behavior more akin to a DRM client's expectations. However, it does
+ * occupy an extra DCN plane, and therefore will only be used if a DCN plane is
+ * available.
+ */
+
+/**
+ * dm_crtc_get_cursor_mode() - Determine the required cursor mode on crtc
+ * @adev: amdgpu device
+ * @state: DRM atomic state
+ * @dm_crtc_state: amdgpu state for the CRTC containing the cursor
+ * @cursor_mode: Returns the required cursor mode on dm_crtc_state
+ *
+ * Get whether the cursor should be enabled in native mode, or overlay mode, on
+ * the dm_crtc_state.
+ *
+ * The cursor should be enabled in overlay mode if there exists an underlying
+ * plane - on which the cursor may be blended - that is either YUV formatted, or
+ * scaled differently from the cursor.
+ *
+ * Since zpos info is required, drm_atomic_normalize_zpos must be called before
+ * calling this function.
+ *
+ * Return: 0 on success, or an error code if getting the cursor plane state
+ * failed.
+ */
+static int dm_crtc_get_cursor_mode(struct amdgpu_device *adev,
+ struct drm_atomic_state *state,
+ struct dm_crtc_state *dm_crtc_state,
+ enum amdgpu_dm_cursor_mode *cursor_mode)
+{
+ struct drm_plane_state *old_plane_state, *plane_state, *cursor_state;
+ struct drm_crtc_state *crtc_state = &dm_crtc_state->base;
+ struct drm_plane *plane;
+ bool consider_mode_change = false;
+ bool entire_crtc_covered = false;
+ bool cursor_changed = false;
+ int underlying_scale_w, underlying_scale_h;
+ int cursor_scale_w, cursor_scale_h;
+ int i;
+
+ /* Overlay cursor not supported on HW before DCN
+ * DCN401 does not have the cursor-on-scaled-plane or cursor-on-yuv-plane restrictions
+ * as previous DCN generations, so enable native mode on DCN401 in addition to DCE
+ */
+ if (amdgpu_ip_version(adev, DCE_HWIP, 0) == 0 ||
+ amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(4, 0, 1)) {
+ *cursor_mode = DM_CURSOR_NATIVE_MODE;
+ return 0;
+ }
+
+ /* Init cursor_mode to be the same as current */
+ *cursor_mode = dm_crtc_state->cursor_mode;
+
+ /*
+ * Cursor mode can change if a plane's format changes, scale changes, is
+ * enabled/disabled, or z-order changes.
+ */
+ for_each_oldnew_plane_in_state(state, plane, old_plane_state, plane_state, i) {
+ int new_scale_w, new_scale_h, old_scale_w, old_scale_h;
+
+ /* Only care about planes on this CRTC */
+ if ((drm_plane_mask(plane) & crtc_state->plane_mask) == 0)
+ continue;
+
+ if (plane->type == DRM_PLANE_TYPE_CURSOR)
+ cursor_changed = true;
+
+ if (drm_atomic_plane_enabling(old_plane_state, plane_state) ||
+ drm_atomic_plane_disabling(old_plane_state, plane_state) ||
+ old_plane_state->fb->format != plane_state->fb->format) {
+ consider_mode_change = true;
+ break;
+ }
+
+ dm_get_plane_scale(plane_state, &new_scale_w, &new_scale_h);
+ dm_get_plane_scale(old_plane_state, &old_scale_w, &old_scale_h);
+ if (new_scale_w != old_scale_w || new_scale_h != old_scale_h) {
+ consider_mode_change = true;
+ break;
+ }
+ }
+
+ if (!consider_mode_change && !crtc_state->zpos_changed)
+ return 0;
+
+ /*
+ * If no cursor change on this CRTC, and not enabled on this CRTC, then
+ * no need to set cursor mode. This avoids needlessly locking the cursor
+ * state.
+ */
+ if (!cursor_changed &&
+ !(drm_plane_mask(crtc_state->crtc->cursor) & crtc_state->plane_mask)) {
+ return 0;
+ }
+
+ cursor_state = drm_atomic_get_plane_state(state,
+ crtc_state->crtc->cursor);
+ if (IS_ERR(cursor_state))
+ return PTR_ERR(cursor_state);
+
+ /* Cursor is disabled */
+ if (!cursor_state->fb)
+ return 0;
+
+ /* For all planes in descending z-order (all of which are below cursor
+ * as per zpos definitions), check their scaling and format
+ */
+ for_each_oldnew_plane_in_descending_zpos(state, plane, old_plane_state, plane_state) {
+
+ /* Only care about non-cursor planes on this CRTC */
+ if ((drm_plane_mask(plane) & crtc_state->plane_mask) == 0 ||
+ plane->type == DRM_PLANE_TYPE_CURSOR)
+ continue;
+
+ /* Underlying plane is YUV format - use overlay cursor */
+ if (amdgpu_dm_plane_is_video_format(plane_state->fb->format->format)) {
+ *cursor_mode = DM_CURSOR_OVERLAY_MODE;
+ return 0;
+ }
+
+ dm_get_plane_scale(plane_state,
+ &underlying_scale_w, &underlying_scale_h);
+ dm_get_plane_scale(cursor_state,
+ &cursor_scale_w, &cursor_scale_h);
+
+ /* Underlying plane has different scale - use overlay cursor */
+ if (cursor_scale_w != underlying_scale_w &&
+ cursor_scale_h != underlying_scale_h) {
+ *cursor_mode = DM_CURSOR_OVERLAY_MODE;
+ return 0;
+ }
+
+ /* If this plane covers the whole CRTC, no need to check planes underneath */
+ if (plane_state->crtc_x <= 0 && plane_state->crtc_y <= 0 &&
+ plane_state->crtc_x + plane_state->crtc_w >= crtc_state->mode.hdisplay &&
+ plane_state->crtc_y + plane_state->crtc_h >= crtc_state->mode.vdisplay) {
+ entire_crtc_covered = true;
+ break;
+ }
+ }
+
+ /* If planes do not cover the entire CRTC, use overlay mode to enable
+ * cursor over holes
+ */
+ if (entire_crtc_covered)
+ *cursor_mode = DM_CURSOR_NATIVE_MODE;
+ else
+ *cursor_mode = DM_CURSOR_OVERLAY_MODE;
+
+ return 0;
+}
+
+/**
* amdgpu_dm_atomic_check() - Atomic check implementation for AMDgpu DM.
*
* @dev: The DRM device
@@ -10975,7 +11235,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
struct drm_crtc *crtc;
struct drm_crtc_state *old_crtc_state, *new_crtc_state;
struct drm_plane *plane;
- struct drm_plane_state *old_plane_state, *new_plane_state;
+ struct drm_plane_state *old_plane_state, *new_plane_state, *new_cursor_state;
enum dc_status status;
int ret, i;
bool lock_and_validation_needed = false;
@@ -11108,8 +11368,23 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
goto fail;
}
+ /*
+ * Determine whether cursors on each CRTC should be enabled in native or
+ * overlay mode.
+ */
+ for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
+ dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
+
+ ret = dm_crtc_get_cursor_mode(adev, state, dm_new_crtc_state,
+ &dm_new_crtc_state->cursor_mode);
+ if (ret) {
+ drm_dbg(dev, "Failed to determine cursor mode\n");
+ goto fail;
+ }
+ }
+
/* Remove exiting planes if they are modified */
- for_each_oldnew_plane_in_state_reverse(state, plane, old_plane_state, new_plane_state, i) {
+ for_each_oldnew_plane_in_descending_zpos(state, plane, old_plane_state, new_plane_state) {
if (old_plane_state->fb && new_plane_state->fb &&
get_mem_type(old_plane_state->fb) !=
get_mem_type(new_plane_state->fb))
@@ -11154,7 +11429,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
}
/* Add new/modified planes */
- for_each_oldnew_plane_in_state_reverse(state, plane, old_plane_state, new_plane_state, i) {
+ for_each_oldnew_plane_in_descending_zpos(state, plane, old_plane_state, new_plane_state) {
ret = dm_update_plane_state(dc, state, plane,
old_plane_state,
new_plane_state,
@@ -11188,11 +11463,49 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
drm_dbg_atomic(dev, "MPO enablement requested on crtc:[%p]\n", crtc);
}
- /* Check cursor planes scaling */
+ /* Check cursor restrictions */
for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
- ret = dm_check_crtc_cursor(state, crtc, new_crtc_state);
+ enum amdgpu_dm_cursor_mode required_cursor_mode;
+ int is_rotated, is_scaled;
+
+ /* Overlay cusor not subject to native cursor restrictions */
+ dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
+ if (dm_new_crtc_state->cursor_mode == DM_CURSOR_OVERLAY_MODE)
+ continue;
+
+ /* Check if rotation or scaling is enabled on DCN401 */
+ if ((drm_plane_mask(crtc->cursor) & new_crtc_state->plane_mask) &&
+ amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(4, 0, 1)) {
+ new_cursor_state = drm_atomic_get_new_plane_state(state, crtc->cursor);
+
+ is_rotated = new_cursor_state &&
+ ((new_cursor_state->rotation & DRM_MODE_ROTATE_MASK) != DRM_MODE_ROTATE_0);
+ is_scaled = new_cursor_state && ((new_cursor_state->src_w >> 16 != new_cursor_state->crtc_w) ||
+ (new_cursor_state->src_h >> 16 != new_cursor_state->crtc_h));
+
+ if (is_rotated || is_scaled) {
+ drm_dbg_driver(
+ crtc->dev,
+ "[CRTC:%d:%s] cannot enable hardware cursor due to rotation/scaling\n",
+ crtc->base.id, crtc->name);
+ ret = -EINVAL;
+ goto fail;
+ }
+ }
+
+ /* If HW can only do native cursor, check restrictions again */
+ ret = dm_crtc_get_cursor_mode(adev, state, dm_new_crtc_state,
+ &required_cursor_mode);
if (ret) {
- drm_dbg_atomic(dev, "dm_check_crtc_cursor() failed\n");
+ drm_dbg_driver(crtc->dev,
+ "[CRTC:%d:%s] Checking cursor mode failed\n",
+ crtc->base.id, crtc->name);
+ goto fail;
+ } else if (required_cursor_mode == DM_CURSOR_OVERLAY_MODE) {
+ drm_dbg_driver(crtc->dev,
+ "[CRTC:%d:%s] Cannot enable native cursor due to scaling or YUV restrictions\n",
+ crtc->base.id, crtc->name);
+ ret = -EINVAL;
goto fail;
}
}
@@ -11553,6 +11866,49 @@ static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector,
return ret;
}
+static void parse_edid_displayid_vrr(struct drm_connector *connector,
+ struct edid *edid)
+{
+ u8 *edid_ext = NULL;
+ int i;
+ int j = 0;
+ u16 min_vfreq;
+ u16 max_vfreq;
+
+ if (edid == NULL || edid->extensions == 0)
+ return;
+
+ /* Find DisplayID extension */
+ for (i = 0; i < edid->extensions; i++) {
+ edid_ext = (void *)(edid + (i + 1));
+ if (edid_ext[0] == DISPLAYID_EXT)
+ break;
+ }
+
+ if (edid_ext == NULL)
+ return;
+
+ while (j < EDID_LENGTH) {
+ /* Get dynamic video timing range from DisplayID if available */
+ if (EDID_LENGTH - j > 13 && edid_ext[j] == 0x25 &&
+ (edid_ext[j+1] & 0xFE) == 0 && (edid_ext[j+2] == 9)) {
+ min_vfreq = edid_ext[j+9];
+ if (edid_ext[j+1] & 7)
+ max_vfreq = edid_ext[j+10] + ((edid_ext[j+11] & 3) << 8);
+ else
+ max_vfreq = edid_ext[j+10];
+
+ if (max_vfreq && min_vfreq) {
+ connector->display_info.monitor_range.max_vfreq = max_vfreq;
+ connector->display_info.monitor_range.min_vfreq = min_vfreq;
+
+ return;
+ }
+ }
+ j++;
+ }
+}
+
static int parse_amd_vsdb(struct amdgpu_dm_connector *aconnector,
struct edid *edid, struct amdgpu_hdmi_vsdb_info *vsdb_info)
{
@@ -11673,6 +12029,11 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
if (!adev->dm.freesync_module)
goto update;
+ /* Some eDP panels only have the refresh rate range info in DisplayID */
+ if ((connector->display_info.monitor_range.min_vfreq == 0 ||
+ connector->display_info.monitor_range.max_vfreq == 0))
+ parse_edid_displayid_vrr(connector, edid);
+
if (edid && (sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT ||
sink->sink_signal == SIGNAL_TYPE_EDP)) {
bool edid_check_required = false;
@@ -11680,9 +12041,11 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
if (is_dp_capable_without_timing_msa(adev->dm.dc,
amdgpu_dm_connector)) {
if (edid->features & DRM_EDID_FEATURE_CONTINUOUS_FREQ) {
- freesync_capable = true;
amdgpu_dm_connector->min_vfreq = connector->display_info.monitor_range.min_vfreq;
amdgpu_dm_connector->max_vfreq = connector->display_info.monitor_range.max_vfreq;
+ if (amdgpu_dm_connector->max_vfreq -
+ amdgpu_dm_connector->min_vfreq > 10)
+ freesync_capable = true;
} else {
edid_check_required = edid->version > 1 ||
(edid->version == 1 &&
@@ -11806,6 +12169,12 @@ void amdgpu_dm_trigger_timing_sync(struct drm_device *dev)
mutex_unlock(&adev->dm.dc_lock);
}
+static inline void amdgpu_dm_exit_ips_for_hw_access(struct dc *dc)
+{
+ if (dc->ctx->dmub_srv && !dc->ctx->dmub_srv->idle_exit_counter)
+ dc_exit_ips_for_hw_access(dc);
+}
+
void dm_write_reg_func(const struct dc_context *ctx, uint32_t address,
u32 value, const char *func_name)
{
@@ -11816,6 +12185,8 @@ void dm_write_reg_func(const struct dc_context *ctx, uint32_t address,
return;
}
#endif
+
+ amdgpu_dm_exit_ips_for_hw_access(ctx->dc);
cgs_write_register(ctx->cgs_device, address, value);
trace_amdgpu_dc_wreg(&ctx->perf_trace->write_count, address, value);
}
@@ -11839,6 +12210,8 @@ uint32_t dm_read_reg_func(const struct dc_context *ctx, uint32_t address,
return 0;
}
+ amdgpu_dm_exit_ips_for_hw_access(ctx->dc);
+
value = cgs_read_register(ctx->cgs_device, address);
trace_amdgpu_dc_rreg(&ctx->perf_trace->read_count, address, value);
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 94fc4c15d2db..2d7755e2b6c3 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -50,7 +50,7 @@
#define AMDGPU_DM_MAX_NUM_EDP 2
-#define AMDGPU_DMUB_NOTIFICATION_MAX 5
+#define AMDGPU_DMUB_NOTIFICATION_MAX 6
#define HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_IEEE_REGISTRATION_ID 0x00001A
#define AMD_VSDB_VERSION_3_FEATURECAP_REPLAYMODE 0x40
@@ -137,6 +137,13 @@ struct vblank_control_work {
bool enable;
};
+/**
+ * struct idle_workqueue - Work data for periodic action in idle
+ * @work: Kernel work data for the work event
+ * @dm: amdgpu display manager device
+ * @enable: true if idle worker is enabled
+ * @running: true if idle worker is running
+ */
struct idle_workqueue {
struct work_struct work;
struct amdgpu_display_manager *dm;
@@ -180,6 +187,14 @@ struct amdgpu_dm_backlight_caps {
* @aux_support: Describes if the display supports AUX backlight.
*/
bool aux_support;
+ /**
+ * @ac_level: the default brightness if booted on AC
+ */
+ u8 ac_level;
+ /**
+ * @dc_level: the default brightness if booted on DC
+ */
+ u8 dc_level;
};
/**
@@ -494,6 +509,12 @@ struct amdgpu_display_manager {
* Deferred work for vblank control events.
*/
struct workqueue_struct *vblank_control_workqueue;
+
+ /**
+ * @idle_workqueue:
+ *
+ * Periodic work for idle events.
+ */
struct idle_workqueue *idle_workqueue;
struct drm_atomic_state *cached_state;
@@ -579,7 +600,9 @@ struct amdgpu_display_manager {
*/
struct mutex dpia_aux_lock;
- /*
+ /**
+ * @bb_from_dmub:
+ *
* Bounding box data read from dmub during early initialization for DCN4+
*/
struct dml2_soc_bb *bb_from_dmub;
@@ -834,6 +857,11 @@ struct dm_plane_state {
enum amdgpu_transfer_function blend_tf;
};
+enum amdgpu_dm_cursor_mode {
+ DM_CURSOR_NATIVE_MODE = 0,
+ DM_CURSOR_OVERLAY_MODE,
+};
+
struct dm_crtc_state {
struct drm_crtc_state base;
struct dc_stream_state *stream;
@@ -864,6 +892,8 @@ struct dm_crtc_state {
* encoding.
*/
enum amdgpu_transfer_function regamma_tf;
+
+ enum amdgpu_dm_cursor_mode cursor_mode;
};
#define to_dm_crtc_state(x) container_of(x, struct dm_crtc_state, base)
@@ -974,4 +1004,7 @@ void *dm_allocate_gpu_mem(struct amdgpu_device *adev,
enum dc_gpu_mem_alloc_type type,
size_t size,
long long *addr);
+
+bool amdgpu_dm_is_headless(struct amdgpu_device *adev);
+
#endif /* __AMDGPU_DM_H__ */
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 83ea0afddda7..99014339aaa3 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
@@ -162,33 +162,63 @@ static void amdgpu_dm_crtc_set_panel_sr_feature(
}
}
+bool amdgpu_dm_is_headless(struct amdgpu_device *adev)
+{
+ struct drm_connector *connector;
+ struct drm_connector_list_iter iter;
+ struct drm_device *dev;
+ bool is_headless = true;
+
+ if (adev == NULL)
+ return true;
+
+ dev = adev->dm.ddev;
+
+ drm_connector_list_iter_begin(dev, &iter);
+ drm_for_each_connector_iter(connector, &iter) {
+
+ if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
+ continue;
+
+ if (connector->status == connector_status_connected) {
+ is_headless = false;
+ break;
+ }
+ }
+ drm_connector_list_iter_end(&iter);
+ return is_headless;
+}
+
static void amdgpu_dm_idle_worker(struct work_struct *work)
{
struct idle_workqueue *idle_work;
idle_work = container_of(work, struct idle_workqueue, work);
idle_work->dm->idle_workqueue->running = true;
- fsleep(HPD_DETECTION_PERIOD_uS);
- mutex_lock(&idle_work->dm->dc_lock);
+
while (idle_work->enable) {
- if (!idle_work->dm->dc->idle_optimizations_allowed)
+ fsleep(HPD_DETECTION_PERIOD_uS);
+ mutex_lock(&idle_work->dm->dc_lock);
+ if (!idle_work->dm->dc->idle_optimizations_allowed) {
+ mutex_unlock(&idle_work->dm->dc_lock);
break;
-
+ }
dc_allow_idle_optimizations(idle_work->dm->dc, false);
mutex_unlock(&idle_work->dm->dc_lock);
fsleep(HPD_DETECTION_TIME_uS);
mutex_lock(&idle_work->dm->dc_lock);
- if (!amdgpu_dm_psr_is_active_allowed(idle_work->dm))
+ if (!amdgpu_dm_is_headless(idle_work->dm->adev) &&
+ !amdgpu_dm_psr_is_active_allowed(idle_work->dm)) {
+ mutex_unlock(&idle_work->dm->dc_lock);
break;
+ }
- dc_allow_idle_optimizations(idle_work->dm->dc, true);
+ if (idle_work->enable)
+ dc_allow_idle_optimizations(idle_work->dm->dc, true);
mutex_unlock(&idle_work->dm->dc_lock);
- fsleep(HPD_DETECTION_PERIOD_uS);
- mutex_lock(&idle_work->dm->dc_lock);
}
- mutex_unlock(&idle_work->dm->dc_lock);
idle_work->dm->idle_workqueue->running = false;
}
@@ -361,6 +391,7 @@ static struct drm_crtc_state *amdgpu_dm_crtc_duplicate_state(struct drm_crtc *cr
state->regamma_tf = cur->regamma_tf;
state->crc_skip_count = cur->crc_skip_count;
state->mpo_requested = cur->mpo_requested;
+ state->cursor_mode = cur->cursor_mode;
/* TODO Duplicate dc_stream after objects are stream object is flattened */
return &state->base;
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 27d5c6077630..62cb59f00929 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
@@ -1008,6 +1008,7 @@ static int replay_capability_show(struct seq_file *m, void *data)
seq_printf(m, "Sink support: %s\n", str_yes_no(sink_support_replay));
seq_printf(m, "Driver support: %s\n", str_yes_no(driver_support_replay));
+ seq_printf(m, "Config support: %s\n", str_yes_no(link->replay_settings.config.replay_supported));
return 0;
}
@@ -1419,7 +1420,7 @@ static ssize_t trigger_hotplug(struct file *f, const char __user *buf,
uint8_t param_nums = 0;
bool ret = false;
- if (!aconnector || !aconnector->dc_link)
+ if (!aconnector->dc_link)
return -EINVAL;
if (size == 0)
@@ -3074,7 +3075,7 @@ static int psr_read_residency(void *data, u64 *val)
struct dc_link *link = connector->dc_link;
u32 residency = 0;
- link->dc->link_srv->edp_get_psr_residency(link, &residency);
+ link->dc->link_srv->edp_get_psr_residency(link, &residency, PSR_RESIDENCY_MODE_PHY);
*val = (u64)residency;
@@ -3794,6 +3795,7 @@ static int trigger_hpd_mst_set(void *data, u64 val)
struct amdgpu_dm_connector *aconnector;
struct drm_connector *connector;
struct dc_link *link = NULL;
+ int ret;
if (val == 1) {
drm_connector_list_iter_begin(dev, &iter);
@@ -3805,7 +3807,9 @@ static int trigger_hpd_mst_set(void *data, u64 val)
dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD);
mutex_unlock(&adev->dm.dc_lock);
- drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, true);
+ ret = drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, true);
+ if (ret < 0)
+ DRM_ERROR("DM_MST: Failed to set the device into MST mode!");
}
}
} else if (val == 0) {
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index 2648d2b5be3e..b490ae67b6be 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -575,10 +575,8 @@ bool dm_helpers_dp_write_dpcd(
{
struct amdgpu_dm_connector *aconnector = link->priv;
- if (!aconnector) {
- DRM_ERROR("Failed to find connector for link!");
+ if (!aconnector)
return false;
- }
return drm_dp_dpcd_write(&aconnector->dm_dp_aux.aux,
address, (uint8_t *)data, size) > 0;
@@ -807,9 +805,6 @@ bool dm_helpers_dp_write_dsc_enable(
uint8_t enable_passthrough = enable ? DSC_PASSTHROUGH : DSC_DISABLE;
uint8_t ret = 0;
- if (!stream)
- return false;
-
if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
if (!aconnector->dsc_aux)
return false;
@@ -1242,8 +1237,11 @@ void dm_helpers_enable_periodic_detection(struct dc_context *ctx, bool enable)
{
struct amdgpu_device *adev = ctx->driver_context;
- if (adev->dm.idle_workqueue)
+ if (adev->dm.idle_workqueue) {
adev->dm.idle_workqueue->enable = enable;
+ if (enable && !adev->dm.idle_workqueue->running && amdgpu_dm_is_headless(adev))
+ schedule_work(&adev->dm.idle_workqueue->work);
+ }
}
void dm_helpers_dp_mst_update_branch_bandwidth(
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 ac60f688660a..5442da90f508 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
@@ -23,6 +23,7 @@
*
*/
+#include <linux/vmalloc.h>
#include <drm/display/drm_dp_helper.h>
#include <drm/display/drm_dp_mst_helper.h>
#include <drm/drm_atomic.h>
@@ -182,6 +183,8 @@ amdgpu_dm_mst_connector_early_unregister(struct drm_connector *connector)
dc_sink_release(dc_sink);
aconnector->dc_sink = NULL;
aconnector->edid = NULL;
+ aconnector->dsc_aux = NULL;
+ port->passthrough_aux = NULL;
}
aconnector->mst_status = MST_STATUS_DEFAULT;
@@ -498,6 +501,8 @@ dm_dp_mst_detect(struct drm_connector *connector,
dc_sink_release(aconnector->dc_sink);
aconnector->dc_sink = NULL;
aconnector->edid = NULL;
+ aconnector->dsc_aux = NULL;
+ port->passthrough_aux = NULL;
amdgpu_dm_set_mst_status(&aconnector->mst_status,
MST_REMOTE_EDID | MST_ALLOCATE_NEW_PAYLOAD | MST_CLEAR_ALLOCATED_PAYLOAD,
@@ -1238,14 +1243,6 @@ static bool is_dsc_need_re_compute(
if (!aconnector || !aconnector->dsc_aux)
continue;
- /*
- * check if cached virtual MST DSC caps are available and DSC is supported
- * as per specifications in their Virtual DPCD registers.
- */
- if (!(aconnector->dc_sink->dsc_caps.dsc_dec_caps.is_dsc_supported ||
- aconnector->dc_link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_PASSTHROUGH_SUPPORT))
- continue;
-
stream_on_link[new_stream_on_link_num] = aconnector;
new_stream_on_link_num++;
@@ -1495,9 +1492,10 @@ int pre_validate_dsc(struct drm_atomic_state *state,
* from dm_state->context.
*/
- local_dc_state = kmemdup(dm_state->context, sizeof(struct dc_state), GFP_KERNEL);
+ local_dc_state = vmalloc(sizeof(struct dc_state));
if (!local_dc_state)
return -ENOMEM;
+ memcpy(local_dc_state, dm_state->context, sizeof(struct dc_state));
for (i = 0; i < local_dc_state->stream_count; i++) {
struct dc_stream_state *stream = dm_state->context->streams[i];
@@ -1567,7 +1565,7 @@ clean_exit:
dc_stream_release(local_dc_state->streams[i]);
}
- kfree(local_dc_state);
+ vfree(local_dc_state);
return ret;
}
@@ -1601,111 +1599,171 @@ static bool is_dsc_common_config_possible(struct dc_stream_state *stream,
}
#endif
+#if defined(CONFIG_DRM_AMD_DC_FP)
+static bool dp_get_link_current_set_bw(struct drm_dp_aux *aux, uint32_t *cur_link_bw)
+{
+ uint32_t total_data_bw_efficiency_x10000 = 0;
+ uint32_t link_rate_per_lane_kbps = 0;
+ enum dc_link_rate link_rate;
+ union lane_count_set lane_count;
+ u8 dp_link_encoding;
+ u8 link_bw_set = 0;
+
+ *cur_link_bw = 0;
+
+ if (drm_dp_dpcd_read(aux, DP_MAIN_LINK_CHANNEL_CODING_SET, &dp_link_encoding, 1) != 1 ||
+ drm_dp_dpcd_read(aux, DP_LANE_COUNT_SET, &lane_count.raw, 1) != 1 ||
+ drm_dp_dpcd_read(aux, DP_LINK_BW_SET, &link_bw_set, 1) != 1)
+ return false;
+
+ switch (dp_link_encoding) {
+ case DP_8b_10b_ENCODING:
+ link_rate = link_bw_set;
+ link_rate_per_lane_kbps = link_rate * LINK_RATE_REF_FREQ_IN_KHZ * BITS_PER_DP_BYTE;
+ total_data_bw_efficiency_x10000 = DATA_EFFICIENCY_8b_10b_x10000;
+ total_data_bw_efficiency_x10000 /= 100;
+ total_data_bw_efficiency_x10000 *= DATA_EFFICIENCY_8b_10b_FEC_EFFICIENCY_x100;
+ break;
+ case DP_128b_132b_ENCODING:
+ switch (link_bw_set) {
+ case DP_LINK_BW_10:
+ link_rate = LINK_RATE_UHBR10;
+ break;
+ case DP_LINK_BW_13_5:
+ link_rate = LINK_RATE_UHBR13_5;
+ break;
+ case DP_LINK_BW_20:
+ link_rate = LINK_RATE_UHBR20;
+ break;
+ default:
+ return false;
+ }
+
+ link_rate_per_lane_kbps = link_rate * 10000;
+ total_data_bw_efficiency_x10000 = DATA_EFFICIENCY_128b_132b_x10000;
+ break;
+ default:
+ return false;
+ }
+
+ *cur_link_bw = link_rate_per_lane_kbps * lane_count.bits.LANE_COUNT_SET / 10000 * total_data_bw_efficiency_x10000;
+ return true;
+}
+#endif
+
enum dc_status dm_dp_mst_is_port_support_mode(
struct amdgpu_dm_connector *aconnector,
struct dc_stream_state *stream)
{
- int branch_max_throughput_mps = 0;
#if defined(CONFIG_DRM_AMD_DC_FP)
+ int branch_max_throughput_mps = 0;
struct dc_link_settings cur_link_settings;
- int pbn;
- unsigned int end_to_end_bw_in_kbps = 0;
- unsigned int upper_link_bw_in_kbps = 0, down_link_bw_in_kbps = 0;
+ uint32_t end_to_end_bw_in_kbps = 0;
+ uint32_t root_link_bw_in_kbps = 0;
+ uint32_t virtual_channel_bw_in_kbps = 0;
struct dc_dsc_bw_range bw_range = {0};
struct dc_dsc_config_options dsc_options = {0};
+ uint32_t stream_kbps;
- /*
- * Consider the case with the depth of the mst topology tree is equal or less than 2
- * A. When dsc bitstream can be transmitted along the entire path
- * 1. dsc is possible between source and branch/leaf device (common dsc params is possible), AND
- * 2. dsc passthrough supported at MST branch, or
- * 3. dsc decoding supported at leaf MST device
- * Use maximum dsc compression as bw constraint
- * B. When dsc bitstream cannot be transmitted along the entire path
- * Use native bw as bw constraint
+ /* DSC unnecessary case
+ * Check if timing could be supported within end-to-end BW
*/
- if (is_dsc_common_config_possible(stream, &bw_range) &&
- (aconnector->mst_output_port->passthrough_aux ||
- aconnector->dsc_aux == &aconnector->mst_output_port->aux)) {
- cur_link_settings = stream->link->verified_link_cap;
- upper_link_bw_in_kbps = dc_link_bandwidth_kbps(aconnector->dc_link, &cur_link_settings);
- down_link_bw_in_kbps = kbps_from_pbn(aconnector->mst_output_port->full_pbn);
-
- /* pick the end to end bw bottleneck */
- end_to_end_bw_in_kbps = min(upper_link_bw_in_kbps, down_link_bw_in_kbps);
-
- if (end_to_end_bw_in_kbps < bw_range.min_kbps) {
- DRM_DEBUG_DRIVER("maximum dsc compression cannot fit into end-to-end bandwidth\n");
- return DC_FAIL_BANDWIDTH_VALIDATE;
- }
+ stream_kbps =
+ dc_bandwidth_in_kbps_from_timing(&stream->timing,
+ dc_link_get_highest_encoding_format(stream->link));
+ cur_link_settings = stream->link->verified_link_cap;
+ root_link_bw_in_kbps = dc_link_bandwidth_kbps(aconnector->dc_link, &cur_link_settings);
+ virtual_channel_bw_in_kbps = kbps_from_pbn(aconnector->mst_output_port->full_pbn);
+
+ /* pick the end to end bw bottleneck */
+ end_to_end_bw_in_kbps = min(root_link_bw_in_kbps, virtual_channel_bw_in_kbps);
+
+ if (stream_kbps <= end_to_end_bw_in_kbps) {
+ DRM_DEBUG_DRIVER("No DSC needed. End-to-end bw sufficient.");
+ return DC_OK;
+ }
- if (end_to_end_bw_in_kbps < bw_range.stream_kbps) {
- dc_dsc_get_default_config_option(stream->link->dc, &dsc_options);
- dsc_options.max_target_bpp_limit_override_x16 = aconnector->base.display_info.max_dsc_bpp * 16;
- if (dc_dsc_compute_config(stream->sink->ctx->dc->res_pool->dscs[0],
- &stream->sink->dsc_caps.dsc_dec_caps,
- &dsc_options,
- end_to_end_bw_in_kbps,
- &stream->timing,
- dc_link_get_highest_encoding_format(stream->link),
- &stream->timing.dsc_cfg)) {
- stream->timing.flags.DSC = 1;
- DRM_DEBUG_DRIVER("end-to-end bandwidth require dsc and dsc config found\n");
- } else {
- DRM_DEBUG_DRIVER("end-to-end bandwidth require dsc but dsc config not found\n");
+ /*DSC necessary case*/
+ if (!aconnector->dsc_aux)
+ return DC_FAIL_BANDWIDTH_VALIDATE;
+
+ if (is_dsc_common_config_possible(stream, &bw_range)) {
+
+ /*capable of dsc passthough. dsc bitstream along the entire path*/
+ if (aconnector->mst_output_port->passthrough_aux) {
+ if (bw_range.min_kbps > end_to_end_bw_in_kbps) {
+ DRM_DEBUG_DRIVER("DSC passthrough. Max dsc compression can't fit into end-to-end bw\n");
return DC_FAIL_BANDWIDTH_VALIDATE;
}
+ } else {
+ /*dsc bitstream decoded at the dp last link*/
+ struct drm_dp_mst_port *immediate_upstream_port = NULL;
+ uint32_t end_link_bw = 0;
+
+ /*Get last DP link BW capability*/
+ if (dp_get_link_current_set_bw(&aconnector->mst_output_port->aux, &end_link_bw)) {
+ if (stream_kbps > end_link_bw) {
+ DRM_DEBUG_DRIVER("DSC decode at last link. Mode required bw can't fit into available bw\n");
+ return DC_FAIL_BANDWIDTH_VALIDATE;
+ }
+ }
+
+ /*Get virtual channel bandwidth between source and the link before the last link*/
+ if (aconnector->mst_output_port->parent->port_parent)
+ immediate_upstream_port = aconnector->mst_output_port->parent->port_parent;
+
+ if (immediate_upstream_port) {
+ virtual_channel_bw_in_kbps = kbps_from_pbn(immediate_upstream_port->full_pbn);
+ virtual_channel_bw_in_kbps = min(root_link_bw_in_kbps, virtual_channel_bw_in_kbps);
+ if (bw_range.min_kbps > virtual_channel_bw_in_kbps) {
+ DRM_DEBUG_DRIVER("DSC decode at last link. Max dsc compression can't fit into MST available bw\n");
+ return DC_FAIL_BANDWIDTH_VALIDATE;
+ }
+ }
}
- } else {
- /* Check if mode could be supported within max slot
- * number of current mst link and full_pbn of mst links.
- */
- int pbn_div, slot_num, max_slot_num;
- enum dc_link_encoding_format link_encoding;
- uint32_t stream_kbps =
- dc_bandwidth_in_kbps_from_timing(&stream->timing,
- dc_link_get_highest_encoding_format(stream->link));
-
- pbn = kbps_to_peak_pbn(stream_kbps);
- pbn_div = dm_mst_get_pbn_divider(stream->link);
- slot_num = DIV_ROUND_UP(pbn, pbn_div);
-
- link_encoding = dc_link_get_highest_encoding_format(stream->link);
- if (link_encoding == DC_LINK_ENCODING_DP_8b_10b)
- max_slot_num = 63;
- else if (link_encoding == DC_LINK_ENCODING_DP_128b_132b)
- max_slot_num = 64;
- else {
- DRM_DEBUG_DRIVER("Invalid link encoding format\n");
+
+ /*Confirm if we can obtain dsc config*/
+ dc_dsc_get_default_config_option(stream->link->dc, &dsc_options);
+ dsc_options.max_target_bpp_limit_override_x16 = aconnector->base.display_info.max_dsc_bpp * 16;
+ if (dc_dsc_compute_config(stream->sink->ctx->dc->res_pool->dscs[0],
+ &stream->sink->dsc_caps.dsc_dec_caps,
+ &dsc_options,
+ end_to_end_bw_in_kbps,
+ &stream->timing,
+ dc_link_get_highest_encoding_format(stream->link),
+ &stream->timing.dsc_cfg)) {
+ stream->timing.flags.DSC = 1;
+ DRM_DEBUG_DRIVER("Require dsc and dsc config found\n");
+ } else {
+ DRM_DEBUG_DRIVER("Require dsc but can't find appropriate dsc config\n");
return DC_FAIL_BANDWIDTH_VALIDATE;
}
- if (slot_num > max_slot_num ||
- pbn > aconnector->mst_output_port->full_pbn) {
- DRM_DEBUG_DRIVER("Mode can not be supported within mst links!");
+ /* check is mst dsc output bandwidth branch_overall_throughput_0_mps */
+ switch (stream->timing.pixel_encoding) {
+ case PIXEL_ENCODING_RGB:
+ case PIXEL_ENCODING_YCBCR444:
+ branch_max_throughput_mps =
+ aconnector->dc_sink->dsc_caps.dsc_dec_caps.branch_overall_throughput_0_mps;
+ break;
+ case PIXEL_ENCODING_YCBCR422:
+ case PIXEL_ENCODING_YCBCR420:
+ branch_max_throughput_mps =
+ aconnector->dc_sink->dsc_caps.dsc_dec_caps.branch_overall_throughput_1_mps;
+ break;
+ default:
+ break;
+ }
+
+ if (branch_max_throughput_mps != 0 &&
+ ((stream->timing.pix_clk_100hz / 10) > branch_max_throughput_mps * 1000)) {
+ DRM_DEBUG_DRIVER("DSC is required but max throughput mps fails");
return DC_FAIL_BANDWIDTH_VALIDATE;
}
- }
- /* check is mst dsc output bandwidth branch_overall_throughput_0_mps */
- switch (stream->timing.pixel_encoding) {
- case PIXEL_ENCODING_RGB:
- case PIXEL_ENCODING_YCBCR444:
- branch_max_throughput_mps =
- aconnector->dc_sink->dsc_caps.dsc_dec_caps.branch_overall_throughput_0_mps;
- break;
- case PIXEL_ENCODING_YCBCR422:
- case PIXEL_ENCODING_YCBCR420:
- branch_max_throughput_mps =
- aconnector->dc_sink->dsc_caps.dsc_dec_caps.branch_overall_throughput_1_mps;
- break;
- default:
- break;
+ } else {
+ DRM_DEBUG_DRIVER("DSC is required but can't find common dsc config.");
+ return DC_FAIL_BANDWIDTH_VALIDATE;
}
#endif
-
- if (branch_max_throughput_mps != 0 &&
- ((stream->timing.pix_clk_100hz / 10) > branch_max_throughput_mps * 1000))
- return DC_FAIL_BANDWIDTH_VALIDATE;
-
return DC_OK;
}
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 a64f20fcddaa..a83bd0331c3b 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
@@ -104,8 +104,6 @@ void amdgpu_dm_plane_fill_blending_from_plane_state(const struct drm_plane_state
*global_alpha = false;
*global_alpha_value = 0xff;
- if (plane_state->plane->type != DRM_PLANE_TYPE_OVERLAY)
- return;
if (plane_state->pixel_blend_mode == DRM_MODE_BLEND_PREMULTI ||
plane_state->pixel_blend_mode == DRM_MODE_BLEND_COVERAGE) {
@@ -354,6 +352,46 @@ static int amdgpu_dm_plane_fill_gfx9_plane_attributes_from_modifiers(struct amdg
return ret;
}
+static int amdgpu_dm_plane_fill_gfx12_plane_attributes_from_modifiers(struct amdgpu_device *adev,
+ const struct amdgpu_framebuffer *afb,
+ const enum surface_pixel_format format,
+ const enum dc_rotation_angle rotation,
+ const struct plane_size *plane_size,
+ union dc_tiling_info *tiling_info,
+ struct dc_plane_dcc_param *dcc,
+ struct dc_plane_address *address,
+ const bool force_disable_dcc)
+{
+ const uint64_t modifier = afb->base.modifier;
+ int ret = 0;
+
+ /* TODO: Most of this function shouldn't be needed on GFX12. */
+ amdgpu_dm_plane_fill_gfx9_tiling_info_from_device(adev, tiling_info);
+
+ tiling_info->gfx9.swizzle = amdgpu_dm_plane_modifier_gfx9_swizzle_mode(modifier);
+
+ if (amdgpu_dm_plane_modifier_has_dcc(modifier) && !force_disable_dcc) {
+ int max_compressed_block = AMD_FMT_MOD_GET(DCC_MAX_COMPRESSED_BLOCK, modifier);
+
+ dcc->enable = 1;
+ dcc->independent_64b_blks = max_compressed_block == 0;
+
+ if (max_compressed_block == 0)
+ dcc->dcc_ind_blk = hubp_ind_block_64b;
+ else if (max_compressed_block == 1)
+ dcc->dcc_ind_blk = hubp_ind_block_128b;
+ else
+ dcc->dcc_ind_blk = hubp_ind_block_unconstrained;
+ }
+
+ /* TODO: This seems wrong because there is no DCC plane on GFX12. */
+ ret = amdgpu_dm_plane_validate_dcc(adev, format, rotation, tiling_info, dcc, address, plane_size);
+ if (ret)
+ drm_dbg_kms(adev_to_drm(adev), "amdgpu_dm_plane_validate_dcc: returned error: %d\n", ret);
+
+ return ret;
+}
+
static void amdgpu_dm_plane_add_gfx10_1_modifiers(const struct amdgpu_device *adev,
uint64_t **mods,
uint64_t *size,
@@ -650,13 +688,33 @@ static void amdgpu_dm_plane_add_gfx11_modifiers(struct amdgpu_device *adev,
static void amdgpu_dm_plane_add_gfx12_modifiers(struct amdgpu_device *adev,
uint64_t **mods, uint64_t *size, uint64_t *capacity)
{
- uint64_t mod_64K_2D = AMD_FMT_MOD |
- AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX12) |
- AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX12_64K_2D);
+ uint64_t ver = AMD_FMT_MOD | AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX12);
+ uint64_t mod_256k = ver | AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX12_256K_2D);
+ uint64_t mod_64k = ver | AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX12_64K_2D);
+ uint64_t mod_4k = ver | AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX12_4K_2D);
+ uint64_t mod_256b = ver | AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX12_256B_2D);
+ uint64_t dcc = ver | AMD_FMT_MOD_SET(DCC, 1);
+ uint8_t max_comp_block[] = {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};
+
+ 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 (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 */
+ for (i = 0; i < ARRAY_SIZE(gfx12_modifiers); i++)
+ amdgpu_dm_plane_add_modifier(mods, size, capacity, gfx12_modifiers[i]);
- /* 64K without DCC */
- amdgpu_dm_plane_add_modifier(mods, size, capacity, mod_64K_2D);
- amdgpu_dm_plane_add_modifier(mods, size, capacity, DRM_FORMAT_MOD_LINEAR);
}
static int amdgpu_dm_plane_get_plane_modifiers(struct amdgpu_device *adev, unsigned int plane_type, uint64_t **mods)
@@ -837,7 +895,15 @@ int amdgpu_dm_plane_fill_plane_buffer_attributes(struct amdgpu_device *adev,
upper_32_bits(chroma_addr);
}
- if (adev->family >= AMDGPU_FAMILY_AI) {
+ if (adev->family >= AMDGPU_FAMILY_GC_12_0_0) {
+ ret = amdgpu_dm_plane_fill_gfx12_plane_attributes_from_modifiers(adev, afb, format,
+ rotation, plane_size,
+ tiling_info, dcc,
+ address,
+ force_disable_dcc);
+ if (ret)
+ return ret;
+ } else if (adev->family >= AMDGPU_FAMILY_AI) {
ret = amdgpu_dm_plane_fill_gfx9_plane_attributes_from_modifiers(adev, afb, format,
rotation, plane_size,
tiling_info, dcc,
@@ -1190,10 +1256,21 @@ static int amdgpu_dm_plane_atomic_check(struct drm_plane *plane,
static int amdgpu_dm_plane_atomic_async_check(struct drm_plane *plane,
struct drm_atomic_state *state)
{
+ struct drm_crtc_state *new_crtc_state;
+ struct drm_plane_state *new_plane_state;
+ struct dm_crtc_state *dm_new_crtc_state;
+
/* Only support async updates on cursor planes. */
if (plane->type != DRM_PLANE_TYPE_CURSOR)
return -EINVAL;
+ new_plane_state = drm_atomic_get_new_plane_state(state, plane);
+ new_crtc_state = drm_atomic_get_new_crtc_state(state, new_plane_state->crtc);
+ dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
+ /* Reject overlay cursors for now*/
+ if (dm_new_crtc_state->cursor_mode == DM_CURSOR_OVERLAY_MODE)
+ return -EINVAL;
+
return 0;
}
@@ -1410,8 +1487,6 @@ static bool amdgpu_dm_plane_format_mod_supported(struct drm_plane *plane,
const struct drm_format_info *info = drm_format_info(format);
int i;
- enum dm_micro_swizzle microtile = amdgpu_dm_plane_modifier_gfx9_swizzle_mode(modifier) & 3;
-
if (!info)
return false;
@@ -1433,29 +1508,34 @@ static bool amdgpu_dm_plane_format_mod_supported(struct drm_plane *plane,
if (i == plane->modifier_count)
return false;
- /*
- * For D swizzle the canonical modifier depends on the bpp, so check
- * it here.
- */
- if (AMD_FMT_MOD_GET(TILE_VERSION, modifier) == AMD_FMT_MOD_TILE_VER_GFX9 &&
- adev->family >= AMDGPU_FAMILY_NV) {
- if (microtile == MICRO_SWIZZLE_D && info->cpp[0] == 4)
- return false;
- }
-
- if (adev->family >= AMDGPU_FAMILY_RV && microtile == MICRO_SWIZZLE_D &&
- info->cpp[0] < 8)
- return false;
+ /* GFX12 doesn't have these limitations. */
+ if (AMD_FMT_MOD_GET(TILE_VERSION, modifier) <= AMD_FMT_MOD_TILE_VER_GFX11) {
+ enum dm_micro_swizzle microtile = amdgpu_dm_plane_modifier_gfx9_swizzle_mode(modifier) & 3;
- if (amdgpu_dm_plane_modifier_has_dcc(modifier)) {
- /* Per radeonsi comments 16/64 bpp are more complicated. */
- if (info->cpp[0] != 4)
- return false;
- /* We support multi-planar formats, but not when combined with
- * additional DCC metadata planes.
+ /*
+ * For D swizzle the canonical modifier depends on the bpp, so check
+ * it here.
*/
- if (info->num_planes > 1)
+ if (AMD_FMT_MOD_GET(TILE_VERSION, modifier) == AMD_FMT_MOD_TILE_VER_GFX9 &&
+ adev->family >= AMDGPU_FAMILY_NV) {
+ if (microtile == MICRO_SWIZZLE_D && info->cpp[0] == 4)
+ return false;
+ }
+
+ if (adev->family >= AMDGPU_FAMILY_RV && microtile == MICRO_SWIZZLE_D &&
+ info->cpp[0] < 8)
return false;
+
+ if (amdgpu_dm_plane_modifier_has_dcc(modifier)) {
+ /* Per radeonsi comments 16/64 bpp are more complicated. */
+ if (info->cpp[0] != 4)
+ return false;
+ /* We support multi-planar formats, but not when combined with
+ * additional DCC metadata planes.
+ */
+ if (info->num_planes > 1)
+ return false;
+ }
}
return true;
@@ -1690,6 +1770,7 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
int res = -EPERM;
unsigned int supported_rotations;
uint64_t *modifiers = NULL;
+ unsigned int primary_zpos = dm->dc->caps.max_slave_planes;
num_formats = amdgpu_dm_plane_get_plane_formats(plane, plane_cap, formats,
ARRAY_SIZE(formats));
@@ -1719,10 +1800,19 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
}
if (plane->type == DRM_PLANE_TYPE_PRIMARY) {
- drm_plane_create_zpos_immutable_property(plane, 0);
+ /*
+ * Allow OVERLAY planes to be used as underlays by assigning an
+ * immutable zpos = # of OVERLAY planes to the PRIMARY plane.
+ */
+ drm_plane_create_zpos_immutable_property(plane, primary_zpos);
} else if (plane->type == DRM_PLANE_TYPE_OVERLAY) {
- unsigned int zpos = 1 + drm_plane_index(plane);
- drm_plane_create_zpos_property(plane, zpos, 1, 254);
+ /*
+ * OVERLAY planes can be below or above the PRIMARY, but cannot
+ * be above the CURSOR plane.
+ */
+ unsigned int zpos = primary_zpos + 1 + drm_plane_index(plane);
+
+ drm_plane_create_zpos_property(plane, zpos, 0, 254);
} else if (plane->type == DRM_PLANE_TYPE_CURSOR) {
drm_plane_create_zpos_immutable_property(plane, 255);
}
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c
index 633ab1c16dc6..f40240aafe98 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c
@@ -158,7 +158,7 @@ void amdgpu_dm_psr_enable(struct dc_stream_state *stream)
DRM_DEBUG_DRIVER("Enabling psr...\n");
vsync_rate_hz = div64_u64(div64_u64((
- stream->timing.pix_clk_100hz * 100),
+ stream->timing.pix_clk_100hz * (uint64_t)100),
stream->timing.v_total),
stream->timing.h_total);
diff --git a/drivers/gpu/drm/amd/display/dc/Makefile b/drivers/gpu/drm/amd/display/dc/Makefile
index 9c2f932217e4..80069651def3 100644
--- a/drivers/gpu/drm/amd/display/dc/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/Makefile
@@ -22,7 +22,7 @@
#
# Makefile for Display Core (dc) component.
-DC_LIBS = basics bios dml clk_mgr dce gpio hwss irq link virtual dsc resource optc dpp hubbub dccg hubp
+DC_LIBS = basics bios dml clk_mgr dce gpio hwss irq link virtual dsc resource optc dpp hubbub dccg hubp dio dwb hpo mmhubbub mpc opp pg
ifdef CONFIG_DRM_AMD_DC_FP
@@ -36,10 +36,6 @@ DC_LIBS += dcn30
DC_LIBS += dcn301
DC_LIBS += dcn31
DC_LIBS += dcn314
-DC_LIBS += dcn32
-DC_LIBS += dcn321
-DC_LIBS += dcn35
-DC_LIBS += dcn401
DC_LIBS += dml
DC_LIBS += dml2
endif
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 b30c2cdc1a61..e47e9db062f4 100644
--- a/drivers/gpu/drm/amd/display/dc/basics/dce_calcs.c
+++ b/drivers/gpu/drm/amd/display/dc/basics/dce_calcs.c
@@ -1853,7 +1853,7 @@ static void calculate_bandwidth(
/*compute total time to request one chunk from each active display pipe*/
for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
if (data->enable[i]) {
- data->chunk_request_time = bw_add(data->chunk_request_time, (bw_div((bw_div(bw_int_to_fixed(pixels_per_chunk * data->bytes_per_pixel[i]), data->useful_bytes_per_request[i])), bw_min2(sclk[data->sclk_level], bw_div(data->dispclk, bw_int_to_fixed(2))))));
+ data->chunk_request_time = bw_add(data->chunk_request_time, (bw_div((bw_div(bw_int_to_fixed(pixels_per_chunk * (int64_t)data->bytes_per_pixel[i]), data->useful_bytes_per_request[i])), bw_min2(sclk[data->sclk_level], bw_div(data->dispclk, bw_int_to_fixed(2))))));
}
}
/*compute total time to request cursor data*/
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 1726bdf89bae..506f82cd5cc6 100644
--- a/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c
+++ b/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c
@@ -140,8 +140,6 @@ struct fixed31_32 dc_fixpt_mul(struct fixed31_32 arg1, struct fixed31_32 arg2)
res.value = arg1_int * arg2_int;
- ASSERT(res.value <= LONG_MAX);
-
res.value <<= FIXED31_32_BITS_PER_FRACTIONAL_PART;
tmp = arg1_int * arg2_fra;
@@ -185,8 +183,6 @@ struct fixed31_32 dc_fixpt_sqr(struct fixed31_32 arg)
res.value = arg_int * arg_int;
- ASSERT(res.value <= LONG_MAX);
-
res.value <<= FIXED31_32_BITS_PER_FRACTIONAL_PART;
tmp = arg_int * arg_fra;
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 25fe1a124029..3bacf470f7c5 100644
--- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
+++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
@@ -665,6 +665,9 @@ static enum bp_result get_ss_info_v3_1(
ss_table_header_include = ((ATOM_ASIC_INTERNAL_SS_INFO_V3 *) bios_get_image(&bp->base,
DATA_TABLES(ASIC_InternalSS_Info),
struct_size(ss_table_header_include, asSpreadSpectrum, 1)));
+ if (!ss_table_header_include)
+ return BP_RESULT_UNSUPPORTED;
+
table_size =
(le16_to_cpu(ss_table_header_include->sHeader.usStructureSize)
- sizeof(ATOM_COMMON_TABLE_HEADER))
@@ -1034,6 +1037,8 @@ static enum bp_result get_ss_info_from_internal_ss_info_tbl_V2_1(
&bp->base,
DATA_TABLES(ASIC_InternalSS_Info),
struct_size(header, asSpreadSpectrum, 1)));
+ if (!header)
+ return result;
memset(info, 0, sizeof(struct spread_spectrum_info));
@@ -1107,6 +1112,8 @@ static enum bp_result get_ss_info_from_ss_info_table(
get_atom_data_table_revision(header, &revision);
tbl = GET_IMAGE(ATOM_SPREAD_SPECTRUM_INFO, DATA_TABLES(SS_Info));
+ if (!tbl)
+ return result;
if (1 != revision.major || 2 > revision.minor)
return result;
@@ -1634,6 +1641,8 @@ static uint32_t get_ss_entry_number_from_ss_info_tbl(
tbl = GET_IMAGE(ATOM_SPREAD_SPECTRUM_INFO,
DATA_TABLES(SS_Info));
+ if (!tbl)
+ return number;
if (1 != revision.major || 2 > revision.minor)
return number;
@@ -1716,6 +1725,8 @@ static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_v2_1(
&bp->base,
DATA_TABLES(ASIC_InternalSS_Info),
struct_size(header_include, asSpreadSpectrum, 1)));
+ if (!header_include)
+ return 0;
size = (le16_to_cpu(header_include->sHeader.usStructureSize)
- sizeof(ATOM_COMMON_TABLE_HEADER))
@@ -1755,6 +1766,9 @@ static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_V3_1(
header_include = ((ATOM_ASIC_INTERNAL_SS_INFO_V3 *) bios_get_image(&bp->base,
DATA_TABLES(ASIC_InternalSS_Info),
struct_size(header_include, asSpreadSpectrum, 1)));
+ if (!header_include)
+ return number;
+
size = (le16_to_cpu(header_include->sHeader.usStructureSize) -
sizeof(ATOM_COMMON_TABLE_HEADER)) /
sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3);
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 cc000833d300..4254bdfefe38 100644
--- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c
+++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c
@@ -227,7 +227,8 @@ static void init_transmitter_control(struct bios_parser *bp)
uint8_t frev;
uint8_t crev = 0;
- BIOS_CMD_TABLE_REVISION(dig1transmittercontrol, frev, crev);
+ if (!BIOS_CMD_TABLE_REVISION(dig1transmittercontrol, frev, crev))
+ BREAK_TO_DEBUGGER();
switch (crev) {
case 6:
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c
index 2a5dd3a296b2..26feefbb8990 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c
@@ -131,7 +131,7 @@ int dce_get_dp_ref_freq_khz(struct clk_mgr *clk_mgr_base)
struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
int dprefclk_wdivider;
int dprefclk_src_sel;
- int dp_ref_clk_khz = 600000;
+ int dp_ref_clk_khz;
int target_div;
/* ASSERT DP Reference Clock source is from DFS*/
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn201/dcn201_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn201/dcn201_clk_mgr.c
index f77840dd051e..7920f6f1aa62 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn201/dcn201_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn201/dcn201_clk_mgr.c
@@ -113,8 +113,6 @@ static void dcn201_update_clocks(struct clk_mgr *clk_mgr_base,
dcn2_read_clocks_from_hw_dentist(clk_mgr_base);
}
- clk_mgr_helper_get_active_display_cnt(dc, context);
-
if (should_set_clock(safe_to_lower, new_clocks->phyclk_khz, clk_mgr_base->clks.phyclk_khz))
clk_mgr_base->clks.phyclk_khz = new_clocks->phyclk_khz;
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 aea4bb46856e..e18097f82091 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
@@ -320,16 +320,16 @@ static void rn_dump_clk_registers(struct clk_state_registers_and_bypass *regs_an
regs_and_bypass->dppclk = internal.CLK1_CLK1_CURRENT_CNT / 10;
regs_and_bypass->dppclk_bypass = internal.CLK1_CLK1_BYPASS_CNTL & 0x0007;
- if (regs_and_bypass->dppclk_bypass < 0 || regs_and_bypass->dppclk_bypass > 4)
+ if (regs_and_bypass->dppclk_bypass > 4)
regs_and_bypass->dppclk_bypass = 0;
regs_and_bypass->dcfclk_bypass = internal.CLK1_CLK3_BYPASS_CNTL & 0x0007;
- if (regs_and_bypass->dcfclk_bypass < 0 || regs_and_bypass->dcfclk_bypass > 4)
+ if (regs_and_bypass->dcfclk_bypass > 4)
regs_and_bypass->dcfclk_bypass = 0;
regs_and_bypass->dispclk_bypass = internal.CLK1_CLK0_BYPASS_CNTL & 0x0007;
- if (regs_and_bypass->dispclk_bypass < 0 || regs_and_bypass->dispclk_bypass > 4)
+ if (regs_and_bypass->dispclk_bypass > 4)
regs_and_bypass->dispclk_bypass = 0;
regs_and_bypass->dprefclk_bypass = internal.CLK1_CLK2_BYPASS_CNTL & 0x0007;
- if (regs_and_bypass->dprefclk_bypass < 0 || regs_and_bypass->dprefclk_bypass > 4)
+ if (regs_and_bypass->dprefclk_bypass > 4)
regs_and_bypass->dprefclk_bypass = 0;
if (log_info->enabled) {
@@ -772,7 +772,7 @@ void rn_clk_mgr_construct(
status = pp_smu->rn_funcs.get_dpm_clock_table(&pp_smu->rn_funcs.pp_smu, &clock_table);
if (status == PP_SMU_RESULT_OK &&
- ctx->dc_bios && ctx->dc_bios->integrated_info) {
+ ctx->dc_bios->integrated_info) {
rn_clk_mgr_helper_populate_bw_params (clk_mgr->base.bw_params, &clock_table, ctx->dc_bios->integrated_info);
/* treat memory config as single channel if memory is asymmetrics. */
if (ctx->dc->config.is_asymmetric_memory)
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 191d8b969d19..9e2ef0e724fc 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
@@ -252,16 +252,16 @@ static void vg_dump_clk_registers(struct clk_state_registers_and_bypass *regs_an
regs_and_bypass->dppclk = internal.CLK1_CLK1_CURRENT_CNT / 10;
regs_and_bypass->dppclk_bypass = internal.CLK1_CLK1_BYPASS_CNTL & 0x0007;
- if (regs_and_bypass->dppclk_bypass < 0 || regs_and_bypass->dppclk_bypass > 4)
+ if (regs_and_bypass->dppclk_bypass > 4)
regs_and_bypass->dppclk_bypass = 0;
regs_and_bypass->dcfclk_bypass = internal.CLK1_CLK3_BYPASS_CNTL & 0x0007;
- if (regs_and_bypass->dcfclk_bypass < 0 || regs_and_bypass->dcfclk_bypass > 4)
+ if (regs_and_bypass->dcfclk_bypass > 4)
regs_and_bypass->dcfclk_bypass = 0;
regs_and_bypass->dispclk_bypass = internal.CLK1_CLK0_BYPASS_CNTL & 0x0007;
- if (regs_and_bypass->dispclk_bypass < 0 || regs_and_bypass->dispclk_bypass > 4)
+ if (regs_and_bypass->dispclk_bypass > 4)
regs_and_bypass->dispclk_bypass = 0;
regs_and_bypass->dprefclk_bypass = internal.CLK1_CLK2_BYPASS_CNTL & 0x0007;
- if (regs_and_bypass->dprefclk_bypass < 0 || regs_and_bypass->dprefclk_bypass > 4)
+ if (regs_and_bypass->dprefclk_bypass > 4)
regs_and_bypass->dprefclk_bypass = 0;
if (log_info->enabled) {
@@ -731,7 +731,7 @@ void vg_clk_mgr_construct(
clk_mgr->base.base.bw_params = &vg_bw_params;
vg_get_dpm_table_from_smu(&clk_mgr->base, &smu_dpm_clks);
- if (ctx->dc_bios && ctx->dc_bios->integrated_info) {
+ if (ctx->dc_bios->integrated_info) {
vg_clk_mgr_helper_populate_bw_params(
&clk_mgr->base,
ctx->dc_bios->integrated_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 12a7752758b8..e93df3d6222e 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
@@ -785,7 +785,7 @@ void dcn31_clk_mgr_construct(
i, smu_dpm_clks.dpm_clks->DfPstateTable[i].MemClk,
i, smu_dpm_clks.dpm_clks->DfPstateTable[i].Voltage);
}
- if (ctx->dc_bios && ctx->dc_bios->integrated_info) {
+ if (ctx->dc_bios->integrated_info) {
dcn31_clk_mgr_helper_populate_bw_params(
&clk_mgr->base,
ctx->dc_bios->integrated_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 a84f1e376dee..29eff386505a 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
@@ -896,7 +896,7 @@ void dcn314_clk_mgr_construct(
i, smu_dpm_clks.dpm_clks->DfPstateTable[i].Voltage);
}
- if (ctx->dc_bios && ctx->dc_bios->integrated_info && ctx->dc->config.use_default_clock_table == false) {
+ if (ctx->dc_bios->integrated_info && ctx->dc->config.use_default_clock_table == false) {
dcn314_clk_mgr_helper_populate_bw_params(
&clk_mgr->base,
ctx->dc_bios->integrated_info,
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 5506cf9b3672..a0fb4481d2f1 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
@@ -712,7 +712,7 @@ void dcn315_clk_mgr_construct(
i, smu_dpm_clks.dpm_clks->DfPstateTable[i].Voltage);
}
- if (ctx->dc_bios && ctx->dc_bios->integrated_info) {
+ if (ctx->dc_bios->integrated_info) {
dcn315_clk_mgr_helper_populate_bw_params(
&clk_mgr->base,
ctx->dc_bios->integrated_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 20ca7afa9cb4..c3e50c3aaa60 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
@@ -652,7 +652,7 @@ void dcn316_clk_mgr_construct(
if (clk_mgr->base.base.ctx->dc->debug.pstate_enabled) {
dcn316_get_dpm_table_from_smu(&clk_mgr->base, &smu_dpm_clks);
- if (ctx->dc_bios && ctx->dc_bios->integrated_info) {
+ if (ctx->dc_bios->integrated_info) {
dcn316_clk_mgr_helper_populate_bw_params(
&clk_mgr->base,
ctx->dc_bios->integrated_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 ff5fdc7b1198..084994c650c4 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
@@ -36,7 +36,7 @@
#include "link.h"
#include "dc_state_priv.h"
#include "atomfirmware.h"
-#include "smu13_driver_if.h"
+#include "dcn32_smu13_driver_if.h"
#include "dcn/dcn_3_2_0_offset.h"
#include "dcn/dcn_3_2_0_sh_mask.h"
@@ -163,9 +163,14 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base)
{
struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
unsigned int num_levels;
- struct clk_limit_num_entries *num_entries_per_clk = &clk_mgr_base->bw_params->clk_table.num_entries_per_clk;
+ struct clk_limit_num_entries *num_entries_per_clk;
unsigned int i;
+ if (!clk_mgr_base->bw_params)
+ return;
+
+ num_entries_per_clk = &clk_mgr_base->bw_params->clk_table.num_entries_per_clk;
+
memset(&(clk_mgr_base->clks), 0, sizeof(struct dc_clocks));
clk_mgr_base->clks.p_state_change_support = true;
clk_mgr_base->clks.prev_p_state_change_support = true;
@@ -173,9 +178,6 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base)
clk_mgr->smu_present = false;
clk_mgr->dpm_present = false;
- if (!clk_mgr_base->bw_params)
- return;
-
if (!clk_mgr_base->force_smu_not_present && dcn30_smu_get_smu_version(clk_mgr, &clk_mgr->smu_ver))
clk_mgr->smu_present = true;
@@ -553,7 +555,7 @@ static void dcn32_auto_dpm_test_log(
//
// AutoDPMTest: clk1:%d - clk2:%d - clk3:%d - clk4:%d\n"
////////////////////////////////////////////////////////////////////////////
- if (new_clocks && active_pipe_count > 0 &&
+ if (active_pipe_count > 0 &&
new_clocks->dramclk_khz > 0 &&
new_clocks->fclk_khz > 0 &&
new_clocks->dcfclk_khz > 0 &&
@@ -574,7 +576,7 @@ static void dcn32_auto_dpm_test_log(
p_state_list[i] = curr_pipe_ctx->p_state_type;
refresh_rate = (curr_pipe_ctx->stream->timing.pix_clk_100hz * (uint64_t)100 +
- curr_pipe_ctx->stream->timing.v_total * curr_pipe_ctx->stream->timing.h_total - (uint64_t)1);
+ curr_pipe_ctx->stream->timing.v_total * (uint64_t)curr_pipe_ctx->stream->timing.h_total - (uint64_t)1);
refresh_rate = div_u64(refresh_rate, curr_pipe_ctx->stream->timing.v_total);
refresh_rate = div_u64(refresh_rate, curr_pipe_ctx->stream->timing.h_total);
disp_src_refresh_list[i] = refresh_rate;
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr_smu_msg.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr_smu_msg.c
index f2f60478b1a6..cf2d35363e8b 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr_smu_msg.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr_smu_msg.c
@@ -28,7 +28,7 @@
#include "clk_mgr_internal.h"
#include "reg_helper.h"
#include "dalsmc.h"
-#include "smu13_driver_if.h"
+#include "dcn32_smu13_driver_if.h"
#define mmDAL_MSG_REG 0x1628A
#define mmDAL_ARG_REG 0x16273
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/smu13_driver_if.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/smu13_driver_if.h
deleted file mode 100644
index deeb85047e7b..000000000000
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/smu13_driver_if.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright 2021 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 SMU13_DRIVER_IF_DCN32_H
-#define SMU13_DRIVER_IF_DCN32_H
-
-// *** IMPORTANT ***
-// PMFW TEAM: Always increment the interface version on any change to this file
-#define SMU13_DRIVER_IF_VERSION 0x18
-
-//Only Clks that have DPM descriptors are listed here
-typedef enum {
- PPCLK_GFXCLK = 0,
- PPCLK_SOCCLK,
- PPCLK_UCLK,
- PPCLK_FCLK,
- PPCLK_DCLK_0,
- PPCLK_VCLK_0,
- PPCLK_DCLK_1,
- PPCLK_VCLK_1,
- PPCLK_DISPCLK,
- PPCLK_DPPCLK,
- PPCLK_DPREFCLK,
- PPCLK_DCFCLK,
- PPCLK_DTBCLK,
- PPCLK_COUNT,
-} PPCLK_e;
-
-typedef enum {
- UCLK_DIV_BY_1 = 0,
- UCLK_DIV_BY_2,
- UCLK_DIV_BY_4,
- UCLK_DIV_BY_8,
-} UCLK_DIV_e;
-
-typedef struct {
- uint8_t WmSetting;
- uint8_t Flags;
- uint8_t Padding[2];
-
-} WatermarkRowGeneric_t;
-
-#define NUM_WM_RANGES 4
-
-typedef enum {
- WATERMARKS_CLOCK_RANGE = 0,
- WATERMARKS_DUMMY_PSTATE,
- WATERMARKS_MALL,
- WATERMARKS_COUNT,
-} WATERMARKS_FLAGS_e;
-
-typedef struct {
- // Watermarks
- WatermarkRowGeneric_t WatermarkRow[NUM_WM_RANGES];
-} Watermarks_t;
-
-typedef struct {
- Watermarks_t Watermarks;
- uint32_t Spare[16];
-
- uint32_t MmHubPadding[8]; // SMU internal use
-} WatermarksExternal_t;
-
-// These defines are used with the following messages:
-// SMC_MSG_TransferTableDram2Smu
-// SMC_MSG_TransferTableSmu2Dram
-
-// Table transfer status
-#define TABLE_TRANSFER_OK 0x0
-#define TABLE_TRANSFER_FAILED 0xFF
-#define TABLE_TRANSFER_PENDING 0xAB
-
-// Table types
-#define TABLE_PMFW_PPTABLE 0
-#define TABLE_COMBO_PPTABLE 1
-#define TABLE_WATERMARKS 2
-#define TABLE_AVFS_PSM_DEBUG 3
-#define TABLE_PMSTATUSLOG 4
-#define TABLE_SMU_METRICS 5
-#define TABLE_DRIVER_SMU_CONFIG 6
-#define TABLE_ACTIVITY_MONITOR_COEFF 7
-#define TABLE_OVERDRIVE 8
-#define TABLE_I2C_COMMANDS 9
-#define TABLE_DRIVER_INFO 10
-#define TABLE_COUNT 11
-
-#endif
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 6c9b4e6491a5..70ee0089a20d 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
@@ -137,8 +137,8 @@ static void dcn35_disable_otg_wa(struct clk_mgr *clk_mgr_base, struct dc_state *
if (pipe->stream && (pipe->stream->dpms_off || dc_is_virtual_signal(pipe->stream->signal) ||
!pipe->stream->link_enc)) {
if (disable) {
- if (pipe->stream_res.tg && pipe->stream_res.tg->funcs->immediate_disable_crtc)
- pipe->stream_res.tg->funcs->immediate_disable_crtc(pipe->stream_res.tg);
+ if (pipe->stream_res.tg && pipe->stream_res.tg->funcs->disable_crtc)
+ pipe->stream_res.tg->funcs->disable_crtc(pipe->stream_res.tg);
reset_sync_context_for_pipe(dc, context, i);
} else {
@@ -218,6 +218,57 @@ static void dcn35_update_clocks_update_dpp_dto(struct clk_mgr_internal *clk_mgr,
}
}
+static uint8_t get_lowest_dpia_index(const struct dc_link *link)
+{
+ const struct dc *dc_struct = link->dc;
+ uint8_t idx = 0xFF;
+ int i;
+
+ for (i = 0; i < MAX_PIPES * 2; ++i) {
+ if (!dc_struct->links[i] || dc_struct->links[i]->ep_type != DISPLAY_ENDPOINT_USB4_DPIA)
+ continue;
+
+ if (idx > dc_struct->links[i]->link_index)
+ idx = dc_struct->links[i]->link_index;
+ }
+
+ return idx;
+}
+
+static void dcn35_notify_host_router_bw(struct clk_mgr *clk_mgr_base, struct dc_state *context,
+ bool safe_to_lower)
+{
+ struct dc_clocks *new_clocks = &context->bw_ctx.bw.dcn.clk;
+ struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+ uint32_t host_router_bw_kbps[MAX_HOST_ROUTERS_NUM] = { 0 };
+ int i;
+
+ for (i = 0; i < context->stream_count; ++i) {
+ const struct dc_stream_state *stream = context->streams[i];
+ const struct dc_link *link = stream->link;
+ uint8_t lowest_dpia_index = 0, hr_index = 0;
+
+ if (!link)
+ continue;
+
+ lowest_dpia_index = get_lowest_dpia_index(link);
+ if (link->link_index < lowest_dpia_index)
+ continue;
+
+ hr_index = (link->link_index - lowest_dpia_index) / 2;
+ host_router_bw_kbps[hr_index] += dc_bandwidth_in_kbps_from_timing(
+ &stream->timing, dc_link_get_highest_encoding_format(link));
+ }
+
+ for (i = 0; i < MAX_HOST_ROUTERS_NUM; ++i) {
+ new_clocks->host_router_bw_kbps[i] = host_router_bw_kbps[i];
+ if (should_set_clock(safe_to_lower, new_clocks->host_router_bw_kbps[i], clk_mgr_base->clks.host_router_bw_kbps[i])) {
+ clk_mgr_base->clks.host_router_bw_kbps[i] = new_clocks->host_router_bw_kbps[i];
+ dcn35_smu_notify_host_router_bw(clk_mgr, i, new_clocks->host_router_bw_kbps[i]);
+ }
+ }
+}
+
void dcn35_update_clocks(struct clk_mgr *clk_mgr_base,
struct dc_state *context,
bool safe_to_lower)
@@ -342,6 +393,10 @@ void dcn35_update_clocks(struct clk_mgr *clk_mgr_base,
dcn35_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower);
}
+ // notify PMFW of bandwidth per DPIA tunnel
+ if (dc->debug.notify_dpia_hr_bw)
+ dcn35_notify_host_router_bw(clk_mgr_base, context, safe_to_lower);
+
// notify DMCUB of latest clocks
memset(&cmd, 0, sizeof(cmd));
cmd.notify_clocks.header.type = DMUB_CMD__CLK_MGR;
@@ -1127,7 +1182,7 @@ void dcn35_clk_mgr_construct(
i, smu_dpm_clks.dpm_clks->MemPstateTable[i].Voltage);
}
- if (ctx->dc_bios && ctx->dc_bios->integrated_info && ctx->dc->config.use_default_clock_table == false) {
+ if (ctx->dc_bios->integrated_info && ctx->dc->config.use_default_clock_table == false) {
dcn35_clk_mgr_helper_populate_bw_params(
&clk_mgr->base,
ctx->dc_bios->integrated_info,
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.c
index 1399b41dfd1c..f6f0e6a33001 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.c
@@ -89,7 +89,8 @@
#define VBIOSSMC_MSG_DisableLSdma 0x1A ///< Disable LSDMA; only sent by VBIOS
#define VBIOSSMC_MSG_DpControllerPhyStatus 0x1B ///< Inform PMFW about the pre conditions for turning SLDO2 on/off . bit[0]==1 precondition is met, bit[1-2] are for DPPHY number
#define VBIOSSMC_MSG_QueryIPS2Support 0x1C ///< Return 1: support; else not supported
-#define VBIOSSMC_Message_Count 0x1D
+#define VBIOSSMC_MSG_NotifyHostRouterBW 0x1D
+#define VBIOSSMC_Message_Count 0x1E
#define VBIOSSMC_Status_BUSY 0x0
#define VBIOSSMC_Result_OK 0x1
@@ -98,6 +99,14 @@
#define VBIOSSMC_Result_CmdRejectedPrereq 0xFD
#define VBIOSSMC_Result_CmdRejectedBusy 0xFC
+union dcn35_dpia_host_router_bw {
+ struct {
+ uint32_t hr_id : 16;
+ uint32_t bw_mbps : 16;
+ } bits;
+ uint32_t all;
+};
+
/*
* Function to be used instead of REG_WAIT macro because the wait ends when
* the register is NOT EQUAL to zero, and because `the translation in msg_if.h
@@ -487,3 +496,13 @@ int dcn35_smu_get_ips_supported(struct clk_mgr_internal *clk_mgr)
//smu_print("%s: VBIOSSMC_MSG_QueryIPS2Support return = %x\n", __func__, retv);
return retv;
}
+
+void dcn35_smu_notify_host_router_bw(struct clk_mgr_internal *clk_mgr, uint32_t hr_id, uint32_t bw_kbps)
+{
+ union dcn35_dpia_host_router_bw msg_data = { 0 };
+
+ msg_data.bits.hr_id = hr_id;
+ msg_data.bits.bw_mbps = bw_kbps / 1000;
+
+ dcn35_smu_send_msg_with_param(clk_mgr, VBIOSSMC_MSG_NotifyHostRouterBW, msg_data.all);
+}
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.h
index 06cd3cc6d36e..3fae13c73934 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.h
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.h
@@ -198,4 +198,6 @@ int dcn35_smu_exit_low_power_state(struct clk_mgr_internal *clk_mgr);
int dcn35_smu_get_ips_supported(struct clk_mgr_internal *clk_mgr);
int dcn35_smu_get_dtbclk(struct clk_mgr_internal *clk_mgr);
int dcn35_smu_get_dprefclk(struct clk_mgr_internal *clk_mgr);
+void dcn35_smu_notify_host_router_bw(struct clk_mgr_internal *clk_mgr, uint32_t hr_id, uint32_t bw_kbps);
+
#endif /* DAL_DC_35_SMU_H_ */
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 0975986f5989..45fe17a46890 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
@@ -207,9 +207,14 @@ static void dcn401_build_wm_range_table(struct clk_mgr *clk_mgr)
void dcn401_init_clocks(struct clk_mgr *clk_mgr_base)
{
struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
- struct clk_limit_num_entries *num_entries_per_clk = &clk_mgr_base->bw_params->clk_table.num_entries_per_clk;
+ struct clk_limit_num_entries *num_entries_per_clk;
unsigned int i;
+ if (!clk_mgr_base->bw_params)
+ return;
+
+ num_entries_per_clk = &clk_mgr_base->bw_params->clk_table.num_entries_per_clk;
+
memset(&(clk_mgr_base->clks), 0, sizeof(struct dc_clocks));
clk_mgr_base->clks.p_state_change_support = true;
clk_mgr_base->clks.prev_p_state_change_support = true;
@@ -217,9 +222,6 @@ void dcn401_init_clocks(struct clk_mgr *clk_mgr_base)
clk_mgr->smu_present = false;
clk_mgr->dpm_present = false;
- if (!clk_mgr_base->bw_params)
- return;
-
if (!clk_mgr_base->force_smu_not_present && dcn30_smu_get_smu_version(clk_mgr, &clk_mgr->smu_ver))
clk_mgr->smu_present = true;
@@ -304,27 +306,29 @@ static void dcn401_update_clocks_update_dtb_dto(struct clk_mgr_internal *clk_mgr
struct dc_state *context,
int ref_dtbclk_khz)
{
- struct dccg *dccg = clk_mgr->dccg;
- uint32_t tg_mask = 0;
int i;
+ struct dccg *dccg = clk_mgr->dccg;
+ struct pipe_ctx *otg_master;
+ bool use_hpo_encoder;
- for (i = 0; i < clk_mgr->base.ctx->dc->res_pool->pipe_count; i++) {
- struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
-
- /* use mask to program DTO once per tg */
- if (pipe_ctx->stream_res.tg &&
- !(tg_mask & (1 << pipe_ctx->stream_res.tg->inst))) {
- tg_mask |= (1 << pipe_ctx->stream_res.tg->inst);
-
- if (dccg->ctx->dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) {
- pipe_ctx->clock_source->funcs->program_pix_clk(
- pipe_ctx->clock_source,
- &pipe_ctx->stream_res.pix_clk_params,
- dccg->ctx->dc->link_srv->dp_get_encoding_format(&pipe_ctx->link_config.dp_link_settings),
- &pipe_ctx->pll_settings);
- }
- }
+ for (i = 0; i < context->stream_count; i++) {
+ otg_master = resource_get_otg_master_for_stream(
+ &context->res_ctx, context->streams[i]);
+ ASSERT(otg_master);
+ ASSERT(otg_master->clock_source);
+ ASSERT(otg_master->clock_source->funcs->program_pix_clk);
+ ASSERT(otg_master->stream_res.pix_clk_params.controller_id >= CONTROLLER_ID_D0);
+
+ use_hpo_encoder = dccg->ctx->dc->link_srv->dp_is_128b_132b_signal(otg_master);
+ if (!use_hpo_encoder)
+ continue;
+
+ otg_master->clock_source->funcs->program_pix_clk(
+ otg_master->clock_source,
+ &otg_master->stream_res.pix_clk_params,
+ dccg->ctx->dc->link_srv->dp_get_encoding_format(&otg_master->link_config.dp_link_settings),
+ &otg_master->pll_settings);
}
}
@@ -791,14 +795,16 @@ static unsigned int dcn401_build_update_bandwidth_clocks_sequence(
block_sequence[num_steps].func = CLK_MGR401_UPDATE_FCLK_PSTATE_SUPPORT;
num_steps++;
}
- } else {
- /* P-State is not supported so force max clocks */
- idle_fclk_mhz =
- clk_mgr_base->bw_params->clk_table.entries[clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_fclk_levels - 1].fclk_mhz;
- active_fclk_mhz = idle_fclk_mhz;
}
}
+ if (!clk_mgr_base->clks.fclk_p_state_change_support && dcn401_is_ppclk_dpm_enabled(clk_mgr_internal, PPCLK_FCLK)) {
+ /* when P-State switching disabled, set UCLK min = max */
+ idle_fclk_mhz =
+ clk_mgr_base->bw_params->clk_table.entries[clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_fclk_levels - 1].fclk_mhz;
+ active_fclk_mhz = idle_fclk_mhz;
+ }
+
/* UPDATE DCFCLK */
if (dc->debug.force_min_dcfclk_mhz > 0)
new_clocks->dcfclk_khz = (new_clocks->dcfclk_khz > (dc->debug.force_min_dcfclk_mhz * 1000)) ?
@@ -872,19 +878,21 @@ static unsigned int dcn401_build_update_bandwidth_clocks_sequence(
block_sequence[num_steps].func = CLK_MGR401_UPDATE_UCLK_PSTATE_SUPPORT;
num_steps++;
}
+ }
+ }
+
+ if (!clk_mgr_base->clks.p_state_change_support && dcn401_is_ppclk_dpm_enabled(clk_mgr_internal, PPCLK_UCLK)) {
+ /* when P-State switching disabled, set UCLK min = max */
+ if (dc->clk_mgr->dc_mode_softmax_enabled) {
+ /* will never have the functional UCLK min above the softmax
+ * since we calculate mode support based on softmax being the max UCLK
+ * frequency.
+ */
+ active_uclk_mhz = clk_mgr_base->bw_params->dc_mode_softmax_memclk;
} else {
- /* when disabling P-State switching, set UCLK min = max */
- if (dc->clk_mgr->dc_mode_softmax_enabled) {
- /* will never have the functional UCLK min above the softmax
- * since we calculate mode support based on softmax being the max UCLK
- * frequency.
- */
- active_uclk_mhz = clk_mgr_base->bw_params->dc_mode_softmax_memclk;
- } else {
- active_uclk_mhz = clk_mgr_base->bw_params->max_memclk_mhz;
- }
- idle_uclk_mhz = active_uclk_mhz;
+ active_uclk_mhz = clk_mgr_base->bw_params->max_memclk_mhz;
}
+ idle_uclk_mhz = active_uclk_mhz;
}
/* Always update saved value, even if new value not set due to P-State switching unsupported */
@@ -936,7 +944,7 @@ static unsigned int dcn401_build_update_bandwidth_clocks_sequence(
}
/* CLK_MGR401_UPDATE_IDLE_HARDMINS */
- if ((update_idle_uclk || update_idle_uclk) && is_idle_dpm_enabled) {
+ if ((update_idle_uclk || update_idle_fclk) && is_idle_dpm_enabled) {
block_sequence[num_steps].params.update_idle_hardmin_params.uclk_mhz = idle_uclk_mhz;
block_sequence[num_steps].params.update_idle_hardmin_params.fclk_mhz = idle_fclk_mhz;
block_sequence[num_steps].func = CLK_MGR401_UPDATE_IDLE_HARDMINS;
@@ -1455,6 +1463,22 @@ static int dcn401_get_dtb_ref_freq_khz(struct clk_mgr *clk_mgr_base)
return dtb_ref_clk_khz;
}
+static int dcn401_get_dispclk_from_dentist(struct clk_mgr *clk_mgr_base)
+{
+ struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+ uint32_t dispclk_wdivider;
+ int disp_divider;
+
+ REG_GET(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER, &dispclk_wdivider);
+ disp_divider = dentist_get_divider_from_did(dispclk_wdivider);
+
+ /* Return DISPCLK freq in Khz */
+ if (disp_divider)
+ return (DENTIST_DIVIDER_RANGE_SCALE_FACTOR * clk_mgr->base.dentist_vco_freq_khz) / disp_divider;
+
+ return 0;
+}
+
static struct clk_mgr_funcs dcn401_funcs = {
.get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
.get_dtb_ref_clk_frequency = dcn401_get_dtb_ref_freq_khz,
@@ -1468,6 +1492,7 @@ static struct clk_mgr_funcs dcn401_funcs = {
.are_clock_states_equal = dcn401_are_clock_states_equal,
.enable_pme_wa = dcn401_enable_pme_wa,
.is_smu_present = dcn401_is_smu_present,
+ .get_dispclk_from_dentist = dcn401_get_dispclk_from_dentist,
};
struct clk_mgr_internal *dcn401_clk_mgr_construct(
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 0d97611c4817..85a2ef82afa5 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -1233,11 +1233,14 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context)
*/
if (is_phantom) {
if (tg->funcs->enable_crtc) {
- int main_pipe_width, main_pipe_height;
+ int main_pipe_width = 0, main_pipe_height = 0;
struct dc_stream_state *old_paired_stream = dc_state_get_paired_subvp_stream(dc->current_state, old_stream);
- main_pipe_width = old_paired_stream->dst.width;
- main_pipe_height = old_paired_stream->dst.height;
+ if (old_paired_stream) {
+ main_pipe_width = old_paired_stream->dst.width;
+ main_pipe_height = old_paired_stream->dst.height;
+ }
+
if (dc->hwss.blank_phantom)
dc->hwss.blank_phantom(dc, tg, main_pipe_width, main_pipe_height);
tg->funcs->enable_crtc(tg);
@@ -1261,6 +1264,9 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context)
apply_ctx_interdependent_lock(dc, dc->current_state, old_stream, false);
dc->hwss.post_unlock_program_front_end(dc, dangling_context);
}
+
+ if (dc->res_pool->funcs->prepare_mcache_programming)
+ dc->res_pool->funcs->prepare_mcache_programming(dc, dangling_context);
if (dc->hwss.program_front_end_for_ctx) {
dc->hwss.interdependent_update_lock(dc, dc->current_state, true);
dc->hwss.program_front_end_for_ctx(dc, dangling_context);
@@ -1628,6 +1634,9 @@ static void program_timing_sync(
for (k = 0; k < group_size; k++) {
struct dc_stream_status *status = dc_state_get_stream_status(ctx, pipe_set[k]->stream);
+ if (!status)
+ continue;
+
status->timing_sync_info.group_id = num_group;
status->timing_sync_info.group_size = group_size;
if (k == 0)
@@ -2031,6 +2040,8 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
}
/* Program all planes within new context*/
+ if (dc->res_pool->funcs->prepare_mcache_programming)
+ dc->res_pool->funcs->prepare_mcache_programming(dc, context);
if (dc->hwss.program_front_end_for_ctx) {
dc->hwss.interdependent_update_lock(dc, context, true);
dc->hwss.program_front_end_for_ctx(dc, context);
@@ -2225,6 +2236,9 @@ enum dc_status dc_commit_streams(struct dc *dc, struct dc_commit_streams_params
if (dc_is_embedded_signal(params->streams[i]->signal)) {
struct dc_stream_status *status = dc_state_get_stream_status(context, params->streams[i]);
+ if (!status)
+ continue;
+
if (dc->hwss.is_abm_supported)
status->is_abm_supported = dc->hwss.is_abm_supported(dc, context, params->streams[i]);
else
@@ -2631,7 +2645,7 @@ static enum surface_update_type det_surface_update(const struct dc *dc,
if (u->plane_info)
format = u->plane_info->format;
- else if (u->surface)
+ else
format = u->surface->format;
if (dce_use_lut(format))
@@ -2732,7 +2746,7 @@ static enum surface_update_type check_update_surfaces_for_stream(
if (stream_update->mst_bw_update)
su_flags->bits.mst_bw = 1;
- if (stream_update->stream && stream_update->stream->freesync_on_desktop &&
+ if (stream_update->stream->freesync_on_desktop &&
(stream_update->vrr_infopacket || stream_update->allow_freesync ||
stream_update->vrr_active_variable || stream_update->vrr_active_fixed))
su_flags->bits.fams_changed = 1;
@@ -3875,6 +3889,9 @@ static void commit_planes_for_stream(struct dc *dc,
odm_pipe->ttu_regs.min_ttu_vblank = MAX_TTU;
}
+ if (update_type != UPDATE_TYPE_FAST && dc->res_pool->funcs->prepare_mcache_programming)
+ dc->res_pool->funcs->prepare_mcache_programming(dc, context);
+
if ((update_type != UPDATE_TYPE_FAST) && stream->update_flags.bits.dsc_changed)
if (top_pipe_to_program &&
top_pipe_to_program->stream_res.tg->funcs->lock_doublebuffer_enable) {
@@ -3894,6 +3911,10 @@ static void commit_planes_for_stream(struct dc *dc,
top_pipe_to_program->stream_res.tg);
}
+ if (dc->hwss.wait_for_dcc_meta_propagation) {
+ dc->hwss.wait_for_dcc_meta_propagation(dc, top_pipe_to_program);
+ }
+
if (should_lock_all_pipes && dc->hwss.interdependent_update_lock) {
if (dc->hwss.subvp_pipe_control_lock)
dc->hwss.subvp_pipe_control_lock(dc, context, true, should_lock_all_pipes, NULL, subvp_prev_use);
@@ -4023,7 +4044,7 @@ static void commit_planes_for_stream(struct dc *dc,
stream_status =
stream_get_status(context, pipe_ctx->stream);
- if (dc->hwss.apply_ctx_for_surface)
+ if (dc->hwss.apply_ctx_for_surface && stream_status)
dc->hwss.apply_ctx_for_surface(
dc, pipe_ctx->stream, stream_status->plane_count, context);
}
@@ -5332,6 +5353,16 @@ bool dc_set_replay_allow_active(struct dc *dc, bool active)
return true;
}
+/* set IPS disable state */
+bool dc_set_ips_disable(struct dc *dc, unsigned int disable_ips)
+{
+ dc_exit_ips_for_hw_access(dc);
+
+ dc->config.disable_ips = disable_ips;
+
+ return true;
+}
+
void dc_allow_idle_optimizations_internal(struct dc *dc, bool allow, char const *caller_name)
{
if (dc->debug.disable_idle_power_optimizations)
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 33318a112282..87e36d51c56d 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
@@ -505,7 +505,7 @@ void set_p_state_switch_method(
struct vba_vars_st *vba = &context->bw_ctx.dml.vba;
bool enable_subvp;
- if (!dc->ctx || !dc->ctx->dmub_srv || !pipe_ctx || !vba || !context)
+ if (!dc->ctx || !dc->ctx->dmub_srv || !pipe_ctx || !vba)
return;
if (vba->DRAMClockChangeSupport[vba->VoltageLevel][vba->maxMpcComb] !=
@@ -595,6 +595,12 @@ void hwss_build_fast_sequence(struct dc *dc,
if (!plane || !stream)
return;
+ if (dc->hwss.wait_for_dcc_meta_propagation) {
+ block_sequence[*num_steps].params.wait_for_dcc_meta_propagation_params.dc = dc;
+ block_sequence[*num_steps].params.wait_for_dcc_meta_propagation_params.top_pipe_to_program = pipe_ctx;
+ block_sequence[*num_steps].func = HUBP_WAIT_FOR_DCC_META_PROP;
+ (*num_steps)++;
+ }
if (dc->hwss.subvp_pipe_control_lock_fast) {
block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.dc = dc;
block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.lock = true;
@@ -835,6 +841,11 @@ void hwss_execute_sequence(struct dc *dc,
case DMUB_SUBVP_SAVE_SURF_ADDR:
hwss_subvp_save_surf_addr(params);
break;
+ case HUBP_WAIT_FOR_DCC_META_PROP:
+ dc->hwss.wait_for_dcc_meta_propagation(
+ params->wait_for_dcc_meta_propagation_params.dc,
+ params->wait_for_dcc_meta_propagation_params.top_pipe_to_program);
+ break;
case DMUB_FAMS2_GLOBAL_CONTROL_LOCK_FAST:
dc->hwss.fams2_global_control_lock_fast(params);
break;
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 234236c43d21..bcb5267b5a6b 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -888,21 +888,21 @@ static struct rect calculate_plane_rec_in_timing_active(
struct rect rec_out = {0};
struct fixed31_32 temp;
- temp = dc_fixpt_from_fraction(rec_in->x * stream->dst.width,
+ temp = dc_fixpt_from_fraction(rec_in->x * (long long)stream->dst.width,
stream->src.width);
rec_out.x = stream->dst.x + dc_fixpt_round(temp);
temp = dc_fixpt_from_fraction(
- (rec_in->x + rec_in->width) * stream->dst.width,
+ (rec_in->x + rec_in->width) * (long long)stream->dst.width,
stream->src.width);
rec_out.width = stream->dst.x + dc_fixpt_round(temp) - rec_out.x;
- temp = dc_fixpt_from_fraction(rec_in->y * stream->dst.height,
+ temp = dc_fixpt_from_fraction(rec_in->y * (long long)stream->dst.height,
stream->src.height);
rec_out.y = stream->dst.y + dc_fixpt_round(temp);
temp = dc_fixpt_from_fraction(
- (rec_in->y + rec_in->height) * stream->dst.height,
+ (rec_in->y + rec_in->height) * (long long)stream->dst.height,
stream->src.height);
rec_out.height = stream->dst.y + dc_fixpt_round(temp) - rec_out.y;
@@ -1917,9 +1917,15 @@ int resource_get_opp_heads_for_otg_master(const struct pipe_ctx *otg_master,
struct pipe_ctx *opp_heads[MAX_PIPES])
{
struct pipe_ctx *opp_head = &res_ctx->pipe_ctx[otg_master->pipe_idx];
+ struct dc *dc = otg_master->stream->ctx->dc;
int i = 0;
+ DC_LOGGER_INIT(dc->ctx->logger);
+
if (!resource_is_pipe_type(otg_master, OTG_MASTER)) {
+ DC_LOG_WARNING("%s called from a non OTG master, something "
+ "is wrong in the pipe configuration",
+ __func__);
ASSERT(0);
return 0;
}
@@ -2077,17 +2083,32 @@ int resource_get_odm_slice_index(const struct pipe_ctx *pipe_ctx)
int resource_get_odm_slice_dst_width(struct pipe_ctx *otg_master,
bool is_last_segment)
{
- const struct dc_crtc_timing *timing = &otg_master->stream->timing;
- int count = resource_get_odm_slice_count(otg_master);
- int h_active = timing->h_addressable +
- timing->h_border_left +
- timing->h_border_right;
- int width = h_active / count;
+ const struct dc_crtc_timing *timing;
+ int count;
+ int h_active;
+ int width;
bool two_pixel_alignment_required = false;
- if (otg_master && otg_master->stream_res.tg && otg_master->stream)
- two_pixel_alignment_required = otg_master->stream_res.tg->funcs->is_two_pixels_per_container(timing);
+ if (!otg_master || !otg_master->stream)
+ return 0;
+ timing = &otg_master->stream->timing;
+ count = resource_get_odm_slice_count(otg_master);
+ h_active = timing->h_addressable +
+ timing->h_border_left +
+ timing->h_border_right;
+ width = h_active / count;
+
+ if (otg_master->stream_res.tg)
+ two_pixel_alignment_required =
+ otg_master->stream_res.tg->funcs->is_two_pixels_per_container(timing) ||
+ /*
+ * 422 is sub-sampled horizontally. 1 set of chromas
+ * (Cb/Cr) is shared for 2 lumas (i.e 2 Y values).
+ * Therefore even if 422 is still 1 pixel per container,
+ * ODM segment width still needs to be 2 pixel aligned.
+ */
+ timing->pixel_encoding == PIXEL_ENCODING_YCBCR422;
if ((width % 2) && two_pixel_alignment_required)
width++;
@@ -2596,6 +2617,17 @@ static void remove_hpo_dp_link_enc_from_ctx(struct resource_context *res_ctx,
}
}
+static int get_num_of_free_pipes(const struct resource_pool *pool, const struct dc_state *context)
+{
+ int i;
+ int count = 0;
+
+ for (i = 0; i < pool->pipe_count; i++)
+ if (resource_is_pipe_type(&context->res_ctx.pipe_ctx[i], FREE_PIPE))
+ count++;
+ return count;
+}
+
enum dc_status resource_add_otg_master_for_stream_output(struct dc_state *new_ctx,
const struct resource_pool *pool,
struct dc_stream_state *stream)
@@ -2729,37 +2761,33 @@ static bool acquire_secondary_dpp_pipes_and_add_plane(
struct dc_state *cur_ctx,
struct resource_pool *pool)
{
- struct pipe_ctx *opp_head_pipe, *sec_pipe, *tail_pipe;
+ struct pipe_ctx *sec_pipe, *tail_pipe;
+ struct pipe_ctx *opp_heads[MAX_PIPES];
+ int opp_head_count;
+ int i;
if (!pool->funcs->acquire_free_pipe_as_secondary_dpp_pipe) {
ASSERT(0);
return false;
}
- opp_head_pipe = otg_master_pipe;
- while (opp_head_pipe) {
+ opp_head_count = resource_get_opp_heads_for_otg_master(otg_master_pipe,
+ &new_ctx->res_ctx, opp_heads);
+ if (get_num_of_free_pipes(pool, new_ctx) < opp_head_count)
+ /* not enough free pipes */
+ return false;
+
+ for (i = 0; i < opp_head_count; i++) {
sec_pipe = pool->funcs->acquire_free_pipe_as_secondary_dpp_pipe(
cur_ctx,
new_ctx,
pool,
- opp_head_pipe);
- if (!sec_pipe) {
- /* try tearing down MPCC combine */
- int pipe_idx = acquire_first_split_pipe(
- &new_ctx->res_ctx, pool,
- otg_master_pipe->stream);
-
- if (pipe_idx >= 0)
- sec_pipe = &new_ctx->res_ctx.pipe_ctx[pipe_idx];
- }
-
- if (!sec_pipe)
- return false;
-
+ opp_heads[i]);
+ ASSERT(sec_pipe);
sec_pipe->plane_state = plane_state;
/* establish pipe relationship */
- tail_pipe = get_tail_pipe(opp_head_pipe);
+ tail_pipe = get_tail_pipe(opp_heads[i]);
tail_pipe->bottom_pipe = sec_pipe;
sec_pipe->top_pipe = tail_pipe;
sec_pipe->bottom_pipe = NULL;
@@ -2770,8 +2798,6 @@ static bool acquire_secondary_dpp_pipes_and_add_plane(
} else {
sec_pipe->prev_odm_pipe = NULL;
}
-
- opp_head_pipe = opp_head_pipe->next_odm_pipe;
}
return true;
}
@@ -2784,6 +2810,7 @@ bool resource_append_dpp_pipes_for_plane_composition(
struct dc_plane_state *plane_state)
{
bool success;
+
if (otg_master_pipe->plane_state == NULL)
success = add_plane_to_opp_head_pipes(otg_master_pipe,
plane_state, new_ctx);
@@ -2791,10 +2818,15 @@ bool resource_append_dpp_pipes_for_plane_composition(
success = acquire_secondary_dpp_pipes_and_add_plane(
otg_master_pipe, plane_state, new_ctx,
cur_ctx, pool);
- if (success)
+ if (success) {
/* when appending a plane mpc slice count changes from 0 to 1 */
success = update_pipe_params_after_mpc_slice_count_change(
plane_state, new_ctx, pool);
+ if (!success)
+ resource_remove_dpp_pipes_for_plane_composition(new_ctx,
+ pool, plane_state);
+ }
+
return success;
}
@@ -2804,6 +2836,7 @@ void resource_remove_dpp_pipes_for_plane_composition(
const struct dc_plane_state *plane_state)
{
int i;
+
for (i = pool->pipe_count - 1; i >= 0; i--) {
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
@@ -3100,9 +3133,14 @@ bool resource_update_pipes_for_stream_with_slice_count(
int i;
struct pipe_ctx *otg_master = resource_get_otg_master_for_stream(
&new_ctx->res_ctx, stream);
- int cur_slice_count = resource_get_odm_slice_count(otg_master);
+ int cur_slice_count;
bool result = true;
+ if (!otg_master)
+ return false;
+
+ cur_slice_count = resource_get_odm_slice_count(otg_master);
+
if (new_slice_count == cur_slice_count)
return result;
@@ -4287,7 +4325,7 @@ static void set_avi_info_frame(
}
if (rid != 0 && fr_ind != 0) {
- hdmi_info.bits.header.version = 5;
+ hdmi_info.bits.header.version = 4;
hdmi_info.bits.header.length = 15;
hdmi_info.bits.FR0_FR3 = fr_ind & 0xF;
@@ -4749,6 +4787,9 @@ void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream,
enum dc_status dc_validate_stream(struct dc *dc, struct dc_stream_state *stream)
{
+ if (dc == NULL || stream == NULL)
+ return DC_ERROR_UNEXPECTED;
+
struct dc_link *link = stream->link;
struct timing_generator *tg = dc->res_pool->timing_generators[0];
enum dc_status res = DC_OK;
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 8ea9391c60b7..e990346e51f6 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_state.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_state.c
@@ -192,15 +192,14 @@ static void init_state(struct dc *dc, struct dc_state *state)
/* Public dc_state functions */
struct dc_state *dc_state_create(struct dc *dc, struct dc_state_create_params *params)
{
+ struct dc_state *state;
#ifdef CONFIG_DRM_AMD_DC_FP
- struct dml2_configuration_options *dml2_opt;
+ struct dml2_configuration_options *dml2_opt = &dc->dml2_tmp;
- dml2_opt = kmemdup(&dc->dml2_options, sizeof(*dml2_opt), GFP_KERNEL);
- if (!dml2_opt)
- return NULL;
+ memcpy(dml2_opt, &dc->dml2_options, sizeof(dc->dml2_options));
#endif
- struct dc_state *state = kvzalloc(sizeof(struct dc_state),
- GFP_KERNEL);
+
+ state = kvzalloc(sizeof(struct dc_state), GFP_KERNEL);
if (!state)
return NULL;
@@ -217,8 +216,6 @@ struct dc_state *dc_state_create(struct dc *dc, struct dc_state_create_params *p
dml2_opt->use_clock_dc_limits = true;
dml2_create(dc, dml2_opt, &state->bw_ctx.dml2_dc_power_source);
}
-
- kfree(dml2_opt);
#endif
kref_init(&state->refcount);
@@ -445,6 +442,19 @@ enum dc_status dc_state_remove_stream(
return DC_OK;
}
+static void remove_mpc_combine_for_stream(const struct dc *dc,
+ struct dc_state *new_ctx,
+ const struct dc_state *cur_ctx,
+ struct dc_stream_status *status)
+{
+ int i;
+
+ for (i = 0; i < status->plane_count; i++)
+ resource_update_pipes_for_plane_with_slice_count(
+ new_ctx, cur_ctx, dc->res_pool,
+ status->plane_states[i], 1);
+}
+
bool dc_state_add_plane(
const struct dc *dc,
struct dc_stream_state *stream,
@@ -455,8 +465,12 @@ bool dc_state_add_plane(
struct pipe_ctx *otg_master_pipe;
struct dc_stream_status *stream_status = NULL;
bool added = false;
+ int odm_slice_count;
+ int i;
stream_status = dc_state_get_stream_status(state, stream);
+ otg_master_pipe = resource_get_otg_master_for_stream(
+ &state->res_ctx, stream);
if (stream_status == NULL) {
dm_error("Existing stream not found; failed to attach surface!\n");
goto out;
@@ -464,22 +478,39 @@ bool dc_state_add_plane(
dm_error("Surface: can not attach plane_state %p! Maximum is: %d\n",
plane_state, MAX_SURFACE_NUM);
goto out;
+ } else if (!otg_master_pipe) {
+ goto out;
}
- if (stream_status->plane_count == 0 && dc->config.enable_windowed_mpo_odm)
- /* ODM combine could prevent us from supporting more planes
- * we will reset ODM slice count back to 1 when all planes have
- * been removed to maximize the amount of planes supported when
- * new planes are added.
- */
- resource_update_pipes_for_stream_with_slice_count(
- state, dc->current_state, dc->res_pool, stream, 1);
+ added = resource_append_dpp_pipes_for_plane_composition(state,
+ dc->current_state, pool, otg_master_pipe, plane_state);
- otg_master_pipe = resource_get_otg_master_for_stream(
- &state->res_ctx, stream);
- if (otg_master_pipe)
+ if (!added) {
+ /* try to remove MPC combine to free up pipes */
+ for (i = 0; i < state->stream_count; i++)
+ remove_mpc_combine_for_stream(dc, state,
+ dc->current_state,
+ &state->stream_status[i]);
added = resource_append_dpp_pipes_for_plane_composition(state,
- dc->current_state, pool, otg_master_pipe, plane_state);
+ dc->current_state, pool,
+ otg_master_pipe, plane_state);
+ }
+
+ if (!added) {
+ /* try to decrease ODM slice count gradually to free up pipes */
+ odm_slice_count = resource_get_odm_slice_count(otg_master_pipe);
+ for (i = odm_slice_count - 1; i > 0; i--) {
+ resource_update_pipes_for_stream_with_slice_count(state,
+ dc->current_state, dc->res_pool, stream,
+ i);
+ added = resource_append_dpp_pipes_for_plane_composition(
+ state,
+ dc->current_state, pool,
+ otg_master_pipe, plane_state);
+ if (added)
+ break;
+ }
+ }
if (added) {
stream_status->plane_states[stream_status->plane_count] =
@@ -539,15 +570,6 @@ bool dc_state_remove_plane(
stream_status->plane_states[stream_status->plane_count] = NULL;
- if (stream_status->plane_count == 0 && dc->config.enable_windowed_mpo_odm)
- /* ODM combine could prevent us from supporting more planes
- * we will reset ODM slice count back to 1 when all planes have
- * been removed to maximize the amount of planes supported when
- * new planes are added.
- */
- resource_update_pipes_for_stream_with_slice_count(
- state, dc->current_state, dc->res_pool, stream, 1);
-
return true;
}
@@ -772,11 +794,16 @@ enum dc_status dc_state_add_phantom_stream(const struct dc *dc,
/* setup subvp meta */
main_stream_status = dc_state_get_stream_status(state, main_stream);
+ if (main_stream_status) {
+ main_stream_status->mall_stream_config.type = SUBVP_MAIN;
+ main_stream_status->mall_stream_config.paired_stream = phantom_stream;
+ }
+
phantom_stream_status = dc_state_get_stream_status(state, phantom_stream);
- phantom_stream_status->mall_stream_config.type = SUBVP_PHANTOM;
- phantom_stream_status->mall_stream_config.paired_stream = main_stream;
- main_stream_status->mall_stream_config.type = SUBVP_MAIN;
- main_stream_status->mall_stream_config.paired_stream = phantom_stream;
+ if (phantom_stream_status) {
+ phantom_stream_status->mall_stream_config.type = SUBVP_PHANTOM;
+ phantom_stream_status->mall_stream_config.paired_stream = main_stream;
+ }
return res;
}
@@ -785,14 +812,17 @@ enum dc_status dc_state_remove_phantom_stream(const struct dc *dc,
struct dc_state *state,
struct dc_stream_state *phantom_stream)
{
- struct dc_stream_status *main_stream_status;
+ struct dc_stream_status *main_stream_status = NULL;
struct dc_stream_status *phantom_stream_status;
/* reset subvp meta */
phantom_stream_status = dc_state_get_stream_status(state, phantom_stream);
- main_stream_status = dc_state_get_stream_status(state, phantom_stream_status->mall_stream_config.paired_stream);
- phantom_stream_status->mall_stream_config.type = SUBVP_NONE;
- phantom_stream_status->mall_stream_config.paired_stream = NULL;
+ if (phantom_stream_status) {
+ main_stream_status = dc_state_get_stream_status(state, phantom_stream_status->mall_stream_config.paired_stream);
+ phantom_stream_status->mall_stream_config.type = SUBVP_NONE;
+ phantom_stream_status->mall_stream_config.paired_stream = NULL;
+ }
+
if (main_stream_status) {
main_stream_status->mall_stream_config.type = SUBVP_NONE;
main_stream_status->mall_stream_config.paired_stream = NULL;
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 55e1c19b97f1..be2638c763d7 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
@@ -416,6 +416,35 @@ bool dc_stream_program_cursor_position(
if (reset_idle_optimizations && !dc->debug.disable_dmub_reallow_idle)
dc_allow_idle_optimizations(dc, true);
+ /* apply/update visual confirm */
+ if (dc->debug.visual_confirm == VISUAL_CONFIRM_HW_CURSOR) {
+ /* update software state */
+ uint32_t color_value = MAX_TG_COLOR_VALUE;
+ int i;
+
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx *pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
+
+ /* adjust visual confirm color for all pipes with current stream */
+ if (stream == pipe_ctx->stream) {
+ if (stream->cursor_position.enable) {
+ pipe_ctx->visual_confirm_color.color_r_cr = color_value;
+ pipe_ctx->visual_confirm_color.color_g_y = 0;
+ pipe_ctx->visual_confirm_color.color_b_cb = 0;
+ } else {
+ pipe_ctx->visual_confirm_color.color_r_cr = 0;
+ pipe_ctx->visual_confirm_color.color_g_y = 0;
+ pipe_ctx->visual_confirm_color.color_b_cb = color_value;
+ }
+
+ /* programming hardware */
+ if (pipe_ctx->plane_state)
+ dc->hwss.update_visual_confirm_color(dc, pipe_ctx,
+ pipe_ctx->plane_res.hubp->mpcc_id);
+ }
+ }
+ }
+
return true;
}
@@ -946,7 +975,7 @@ static int dc_stream_calculate_flickerless_refresh_rate(struct dc_stream_state *
}
if (search_for_max_increase)
- return (int)div64_s64((long long)stream->timing.pix_clk_100hz*100, stream->timing.v_total*stream->timing.h_total);
+ return (int)div64_s64((long long)stream->timing.pix_clk_100hz*100, stream->timing.v_total*(long long)stream->timing.h_total);
else
return stream->lumin_data.refresh_rate_hz[0];
}
@@ -995,7 +1024,7 @@ static unsigned int dc_stream_get_max_flickerless_instant_vtotal_delta(struct dc
if (stream->timing.v_total * stream->timing.h_total == 0)
return 0;
- int current_refresh_hz = (int)div64_s64((long long)stream->timing.pix_clk_100hz*100, stream->timing.v_total*stream->timing.h_total);
+ int current_refresh_hz = (int)div64_s64((long long)stream->timing.pix_clk_100hz*100, stream->timing.v_total*(long long)stream->timing.h_total);
int safe_refresh_hz = dc_stream_calculate_flickerless_refresh_rate(stream,
dc_stream_get_brightness_millinits_from_refresh(stream, current_refresh_hz),
@@ -1003,12 +1032,12 @@ static unsigned int dc_stream_get_max_flickerless_instant_vtotal_delta(struct dc
is_gaming,
increase);
- int safe_refresh_v_total = (int)div64_s64((long long)stream->timing.pix_clk_100hz*100, safe_refresh_hz*stream->timing.h_total);
+ int safe_refresh_v_total = (int)div64_s64((long long)stream->timing.pix_clk_100hz*100, safe_refresh_hz*(long long)stream->timing.h_total);
if (increase)
- return ((stream->timing.v_total - safe_refresh_v_total) >= 0) ? (stream->timing.v_total - safe_refresh_v_total) : 0;
+ return (((int) stream->timing.v_total - safe_refresh_v_total) >= 0) ? (stream->timing.v_total - safe_refresh_v_total) : 0;
- return ((safe_refresh_v_total - stream->timing.v_total) >= 0) ? (safe_refresh_v_total - stream->timing.v_total) : 0;
+ return ((safe_refresh_v_total - (int) stream->timing.v_total) >= 0) ? (safe_refresh_v_total - stream->timing.v_total) : 0;
}
/*
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 067f6555cfdf..ccbb15f1638c 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c
@@ -143,7 +143,8 @@ const struct dc_plane_status *dc_plane_get_status(
if (pipe_ctx->plane_state != plane_state)
continue;
- pipe_ctx->plane_state->status.is_flip_pending = false;
+ if (pipe_ctx->plane_state)
+ pipe_ctx->plane_state->status.is_flip_pending = false;
break;
}
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index a06015165a61..73cdebcd9f37 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -55,13 +55,14 @@ struct aux_payload;
struct set_config_cmd_payload;
struct dmub_notification;
-#define DC_VER "3.2.286"
+#define DC_VER "3.2.291"
#define MAX_SURFACES 3
#define MAX_PLANES 6
#define MAX_STREAMS 6
#define MIN_VIEWPORT_SIZE 12
#define MAX_NUM_EDP 2
+#define MAX_HOST_ROUTERS_NUM 2
/* Display Core Interfaces */
struct dc_versions {
@@ -291,6 +292,9 @@ struct dc_caps {
uint8_t subvp_drr_vblank_start_margin_us;
bool cursor_not_scaled;
bool dcmode_power_limits_present;
+ bool sequential_ono;
+ /* Conservative limit for DCC cases which require ODM4:1 to support*/
+ uint32_t dcc_plane_width_limit;
};
struct dc_bug_wa {
@@ -304,6 +308,7 @@ struct dc_bug_wa {
uint8_t dcfclk : 1;
uint8_t dcfclk_ds: 1;
} clock_update_disable_mask;
+ bool skip_psr_ips_crtc_disable;
//Customer Specific WAs
uint32_t force_backlight_start_level;
};
@@ -330,6 +335,9 @@ struct dc_dcc_setting {
uint32_t dcc_128_128_uncontrained : 1; //available in ASICs before DCN 3.0
uint32_t dcc_256_128_128 : 1; //available starting with DCN 3.0
uint32_t dcc_256_256_unconstrained : 1; //available in ASICs before DCN 3.0 (the best compression case)
+ uint32_t dcc_256_256 : 1; //available in ASICs starting with DCN 4.0x (the best compression case)
+ uint32_t dcc_256_128 : 1; //available in ASICs starting with DCN 4.0x
+ uint32_t dcc_256_64 : 1; //available in ASICs starting with DCN 4.0x (the worst compression case)
} dcc_controls;
};
@@ -473,6 +481,7 @@ enum visual_confirm {
VISUAL_CONFIRM_SUBVP = 14,
VISUAL_CONFIRM_MCLK_SWITCH = 16,
VISUAL_CONFIRM_FAMS2 = 19,
+ VISUAL_CONFIRM_HW_CURSOR = 20,
};
enum dc_psr_power_opts {
@@ -592,6 +601,7 @@ struct dc_clocks {
bool prev_p_state_change_support;
bool fclk_prev_p_state_change_support;
int num_ways;
+ int host_router_bw_kbps[MAX_HOST_ROUTERS_NUM];
/*
* @fw_based_mclk_switching
@@ -922,6 +932,7 @@ struct dc_debug_options {
bool disable_z9_mpc;
unsigned int force_fclk_khz;
bool enable_tri_buf;
+ bool ips_disallow_entry;
bool dmub_offload_enabled;
bool dmcub_emulation;
bool disable_idle_power_optimizations;
@@ -1031,9 +1042,10 @@ struct dc_debug_options {
unsigned int static_screen_wait_frames;
uint32_t pwm_freq;
bool force_chroma_subsampling_1tap;
+ unsigned int dcc_meta_propagation_delay_us;
bool disable_422_left_edge_pixel;
bool dml21_force_pstate_method;
- uint32_t dml21_force_pstate_method_value;
+ uint32_t dml21_force_pstate_method_values[MAX_PIPES];
uint32_t dml21_disable_pstate_method_mask;
union dmub_fams2_global_feature_config fams2_config;
bool enable_legacy_clock_update;
@@ -1042,7 +1054,7 @@ struct dc_debug_options {
unsigned int force_easf;
unsigned int force_sharpness;
unsigned int force_lls;
- bool edp_oled_no_backlight_enable;
+ bool notify_dpia_hr_bw;
};
@@ -1445,6 +1457,7 @@ struct dc {
} scratch;
struct dml2_configuration_options dml2_options;
+ struct dml2_configuration_options dml2_tmp;
enum dc_acpi_cm_power_state power_state;
};
@@ -2467,6 +2480,8 @@ bool dc_set_psr_allow_active(struct dc *dc, bool enable);
bool dc_set_replay_allow_active(struct dc *dc, bool active);
+bool dc_set_ips_disable(struct dc *dc, unsigned int disable_ips);
+
void dc_z10_restore(const struct dc *dc);
void dc_z10_save_init(struct dc *dc);
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 0e70b95573ae..ded13026c8ff 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
+++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
@@ -245,7 +245,9 @@ bool dc_dmub_srv_cmd_run_list(struct dc_dmub_srv *dc_dmub_srv, unsigned int coun
if (status == DMUB_STATUS_POWER_STATE_D3)
return false;
- dmub_srv_wait_for_idle(dmub, 100000);
+ status = dmub_srv_wait_for_idle(dmub, 100000);
+ if (status != DMUB_STATUS_OK)
+ return false;
/* Requeue the command. */
status = dmub_srv_cmd_queue(dmub, &cmd_list[i]);
@@ -444,7 +446,6 @@ bool dc_dmub_srv_p_state_delegate(struct dc *dc, bool should_manage_pstate, stru
for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
- stream_status = NULL;
if (!pipe->stream)
continue;
@@ -464,7 +465,6 @@ bool dc_dmub_srv_p_state_delegate(struct dc *dc, bool should_manage_pstate, stru
for (i = 0, k = 0; context && i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
- stream_status = NULL;
if (!resource_is_pipe_type(pipe, OTG_MASTER))
continue;
@@ -519,7 +519,8 @@ void dc_dmub_srv_get_visual_confirm_color_cmd(struct dc *dc, struct pipe_ctx *pi
union dmub_rb_cmd cmd = { 0 };
unsigned int panel_inst = 0;
- dc_get_edp_link_panel_inst(dc, pipe_ctx->stream->link, &panel_inst);
+ if (!dc_get_edp_link_panel_inst(dc, pipe_ctx->stream->link, &panel_inst))
+ return;
memset(&cmd, 0, sizeof(cmd));
@@ -564,7 +565,7 @@ static void populate_subvp_cmd_drr_info(struct dc *dc,
{
struct dc_stream_state *phantom_stream = dc_state_get_paired_subvp_stream(context, subvp_pipe->stream);
struct dc_crtc_timing *main_timing = &subvp_pipe->stream->timing;
- struct dc_crtc_timing *phantom_timing = &phantom_stream->timing;
+ struct dc_crtc_timing *phantom_timing;
struct dc_crtc_timing *drr_timing = &vblank_pipe->stream->timing;
uint16_t drr_frame_us = 0;
uint16_t min_drr_supported_us = 0;
@@ -578,6 +579,11 @@ static void populate_subvp_cmd_drr_info(struct dc *dc,
uint16_t min_vtotal_supported = 0;
uint16_t max_vtotal_supported = 0;
+ if (!phantom_stream)
+ return;
+
+ phantom_timing = &phantom_stream->timing;
+
pipe_data->pipe_config.vblank_data.drr_info.drr_in_use = true;
pipe_data->pipe_config.vblank_data.drr_info.use_ramping = false; // for now don't use ramping
pipe_data->pipe_config.vblank_data.drr_info.drr_window_size_ms = 4; // hardcode 4ms DRR window for now
@@ -701,7 +707,13 @@ static void update_subvp_prefetch_end_to_mall_start(struct dc *dc,
struct dmub_cmd_fw_assisted_mclk_switch_pipe_data_v2 *pipe_data = NULL;
phantom_stream0 = dc_state_get_paired_subvp_stream(context, subvp_pipes[0]->stream);
+ if (!phantom_stream0)
+ return;
+
phantom_stream1 = dc_state_get_paired_subvp_stream(context, subvp_pipes[1]->stream);
+ if (!phantom_stream1)
+ return;
+
phantom_timing0 = &phantom_stream0->timing;
phantom_timing1 = &phantom_stream1->timing;
@@ -756,9 +768,14 @@ static void populate_subvp_cmd_pipe_info(struct dc *dc,
&cmd->fw_assisted_mclk_switch_v2.config_data.pipe_data[cmd_pipe_index];
struct dc_stream_state *phantom_stream = dc_state_get_paired_subvp_stream(context, subvp_pipe->stream);
struct dc_crtc_timing *main_timing = &subvp_pipe->stream->timing;
- struct dc_crtc_timing *phantom_timing = &phantom_stream->timing;
+ struct dc_crtc_timing *phantom_timing;
uint32_t out_num_stream, out_den_stream, out_num_plane, out_den_plane, out_num, out_den;
+ if (!phantom_stream)
+ return;
+
+ phantom_timing = &phantom_stream->timing;
+
pipe_data->mode = SUBVP;
pipe_data->pipe_config.subvp_data.pix_clk_100hz = subvp_pipe->stream->timing.pix_clk_100hz;
pipe_data->pipe_config.subvp_data.htotal = subvp_pipe->stream->timing.h_total;
@@ -1256,6 +1273,9 @@ static void dc_dmub_srv_notify_idle(const struct dc *dc, bool allow_idle)
cmd.idle_opt_notify_idle.cntl_data.driver_idle = allow_idle;
+ if (dc->work_arounds.skip_psr_ips_crtc_disable)
+ cmd.idle_opt_notify_idle.cntl_data.skip_otg_disable = true;
+
if (allow_idle) {
volatile struct dmub_shared_state_ips_driver *ips_driver =
&dc_dmub_srv->dmub->shared_state[DMUB_SHARED_SHARE_FEATURE__IPS_DRIVER].data.ips_driver;
@@ -1505,6 +1525,8 @@ void dc_dmub_srv_apply_idle_power_optimizations(const struct dc *dc, bool allow_
if (!dc_dmub_srv || !dc_dmub_srv->dmub)
return;
+ allow_idle &= (!dc->debug.ips_disallow_entry);
+
if (dc_dmub_srv->idle_allowed == allow_idle)
return;
@@ -1653,6 +1675,8 @@ void dc_dmub_srv_fams2_update_config(struct dc *dc,
/* send global configuration parameters */
global_cmd->config.global.max_allow_delay_us = 100 * 1000; //100ms
global_cmd->config.global.lock_wait_time_us = 5000; //5ms
+ global_cmd->config.global.recovery_timeout_us = 5000; //5ms
+ global_cmd->config.global.hwfq_flip_programming_delay_us = 100; //100us
/* copy static feature configuration */
global_cmd->config.global.features.all = dc->debug.fams2_config.all;
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 bc760448a378..582606319764 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c
+++ b/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c
@@ -70,6 +70,8 @@ void translate_SPL_in_params_from_pipe_ctx(struct pipe_ctx *pipe_ctx, struct spl
{
const struct dc_plane_state *plane_state = pipe_ctx->plane_state;
const struct dc_stream_state *stream = pipe_ctx->stream;
+ struct rect odm_slice_src = resource_get_odm_slice_src_rect(pipe_ctx);
+
// Assign the function to calculate the number of partitions in the line buffer
// This is used to determine the vtap support
switch (plane_state->ctx->dce_version) {
@@ -112,7 +114,8 @@ void translate_SPL_in_params_from_pipe_ctx(struct pipe_ctx *pipe_ctx, struct spl
else
spl_in->basic_in.mpc_combine_v = resource_get_mpc_slice_index(pipe_ctx);
- spl_in->basic_out.odm_combine_factor = resource_get_odm_slice_count(pipe_ctx);
+ populate_splrect_from_rect(&spl_in->basic_out.odm_slice_rect, &odm_slice_src);
+ spl_in->basic_out.odm_combine_factor = 0;
spl_in->odm_slice_index = resource_get_odm_slice_index(pipe_ctx);
// Make spl input basic out info output_size width point to stream h active
spl_in->basic_out.output_size.width =
diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h
index cee012587e6e..c550e8997033 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_types.h
@@ -1036,6 +1036,7 @@ enum replay_FW_Message_type {
Replay_Set_Residency_Frameupdate_Timer,
Replay_Set_Pseudo_VTotal,
Replay_Disabled_Adaptive_Sync_SDP,
+ Replay_Set_General_Cmd,
};
union replay_error_status {
@@ -1091,6 +1092,8 @@ struct replay_settings {
uint32_t coasting_vtotal;
/* Coasting vtotal table */
uint32_t coasting_vtotal_table[PR_COASTING_TYPE_NUM];
+ /* Defer Update Coasting vtotal table */
+ uint32_t defer_update_coasting_vtotal_table[PR_COASTING_TYPE_NUM];
/* Maximum link off frame count */
uint32_t link_off_frame_count;
/* Replay pseudo vtotal for abm + ips on full screen video which can improve ips residency */
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 3538e190f217..07f1f396ba52 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
@@ -603,6 +603,10 @@ static void dccg401_set_dp_dto(
BREAK_TO_DEBUGGER();
return;
}
+ if (!params->refclk_hz) {
+ BREAK_TO_DEBUGGER();
+ return;
+ }
if (!dc_is_tmds_signal(params->signal)) {
uint64_t dto_integer;
@@ -849,43 +853,30 @@ static void dccg401_enable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst
}
/*get other front end connected to this backend*/
-static uint8_t dccg401_get_other_enabled_symclk_fe(struct dccg *dccg, uint32_t stream_enc_inst, uint32_t link_enc_inst)
+static uint8_t dccg401_get_number_enabled_symclk_fe_connected_to_be(struct dccg *dccg, uint32_t link_enc_inst)
{
uint8_t num_enabled_symclk_fe = 0;
- uint32_t be_clk_en = 0, fe_clk_en[4] = {0}, be_clk_sel[4] = {0};
+ uint32_t fe_clk_en[4] = {0}, be_clk_sel[4] = {0};
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+ uint8_t i;
- switch (link_enc_inst) {
- case 0:
- REG_GET_3(SYMCLKA_CLOCK_ENABLE, SYMCLKA_CLOCK_ENABLE, &be_clk_en,
- SYMCLKA_FE_EN, &fe_clk_en[0],
- SYMCLKA_FE_SRC_SEL, &be_clk_sel[0]);
- break;
- case 1:
- REG_GET_3(SYMCLKB_CLOCK_ENABLE, SYMCLKB_CLOCK_ENABLE, &be_clk_en,
- SYMCLKB_FE_EN, &fe_clk_en[1],
- SYMCLKB_FE_SRC_SEL, &be_clk_sel[1]);
- break;
- case 2:
- REG_GET_3(SYMCLKC_CLOCK_ENABLE, SYMCLKC_CLOCK_ENABLE, &be_clk_en,
- SYMCLKC_FE_EN, &fe_clk_en[2],
- SYMCLKC_FE_SRC_SEL, &be_clk_sel[2]);
- break;
- case 3:
- REG_GET_3(SYMCLKD_CLOCK_ENABLE, SYMCLKD_CLOCK_ENABLE, &be_clk_en,
- SYMCLKD_FE_EN, &fe_clk_en[3],
- SYMCLKD_FE_SRC_SEL, &be_clk_sel[3]);
- break;
- }
- if (be_clk_en) {
- /* for DPMST, this backend could be used by multiple front end.
- only disable the backend if this stream_enc_ins is the last active stream enc connected to this back_end*/
- uint8_t i;
- for (i = 0; i != link_enc_inst && i < sizeof(fe_clk_en); i++) {
- if (fe_clk_en[i] && be_clk_sel[i] == link_enc_inst)
- num_enabled_symclk_fe++;
- }
+ REG_GET_2(SYMCLKA_CLOCK_ENABLE, SYMCLKA_FE_EN, &fe_clk_en[0],
+ SYMCLKA_FE_SRC_SEL, &be_clk_sel[0]);
+
+ REG_GET_2(SYMCLKB_CLOCK_ENABLE, SYMCLKB_FE_EN, &fe_clk_en[1],
+ SYMCLKB_FE_SRC_SEL, &be_clk_sel[1]);
+
+ REG_GET_2(SYMCLKC_CLOCK_ENABLE, SYMCLKC_FE_EN, &fe_clk_en[2],
+ SYMCLKC_FE_SRC_SEL, &be_clk_sel[2]);
+
+ REG_GET_2(SYMCLKD_CLOCK_ENABLE, SYMCLKD_FE_EN, &fe_clk_en[3],
+ SYMCLKD_FE_SRC_SEL, &be_clk_sel[3]);
+
+ for (i = 0; i < ARRAY_SIZE(fe_clk_en); i++) {
+ if (fe_clk_en[i] && be_clk_sel[i] == link_enc_inst)
+ num_enabled_symclk_fe++;
}
+
return num_enabled_symclk_fe;
}
@@ -917,9 +908,9 @@ static void dccg401_disable_symclk_se(struct dccg *dccg, uint32_t stream_enc_ins
break;
}
- /*check other enabled symclk fe */
- num_enabled_symclk_fe = dccg401_get_other_enabled_symclk_fe(dccg, stream_enc_inst, link_enc_inst);
- /*only turn off backend clk if other front end attachecd to this backend are all off,
+ /*check other enabled symclk fe connected to this be */
+ num_enabled_symclk_fe = dccg401_get_number_enabled_symclk_fe_connected_to_be(dccg, link_enc_inst);
+ /*only turn off backend clk if other front ends attached to this backend are all off,
for mst, only turn off the backend if this is the last front end*/
if (num_enabled_symclk_fe == 0) {
switch (link_enc_inst) {
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 12f3c35b3a34..cf5f84fb9c69 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c
@@ -353,7 +353,7 @@ static uint32_t calculate_required_audio_bw_in_symbols(
/* 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(
- crtc_info->requested_pixel_clock_100Hz, crtc_info->h_total * 10);
+ crtc_info->requested_pixel_clock_100Hz, (long long)crtc_info->h_total * 10);
struct fixed31_32 samples_per_line;
struct fixed31_32 layouts_per_line;
struct fixed31_32 symbols_per_sdp_max_layout;
@@ -455,7 +455,8 @@ static uint32_t calculate_available_hblank_bw_in_symbols(
available_hblank_bw -= crtc_info->dsc_num_slices * 4; /* EOC overhead */
if (available_hblank_bw < dp_link_info->hblank_min_symbol_width)
- available_hblank_bw = dp_link_info->hblank_min_symbol_width;
+ /* Each symbol takes 4 frames */
+ available_hblank_bw = 4 * dp_link_info->hblank_min_symbol_width;
if (available_hblank_bw < 12)
available_hblank_bw = 0;
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 63deb5b60548..b700608e4240 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
@@ -217,7 +217,7 @@ static bool calc_fb_divider_checking_tolerance(
actual_calc_clk_100hz = (uint64_t)feedback_divider *
calc_pll_cs->fract_fb_divider_factor +
fract_feedback_divider;
- actual_calc_clk_100hz *= calc_pll_cs->ref_freq_khz * 10;
+ actual_calc_clk_100hz *= (uint64_t)calc_pll_cs->ref_freq_khz * 10;
actual_calc_clk_100hz =
div_u64(actual_calc_clk_100hz,
ref_divider * post_divider *
@@ -680,7 +680,7 @@ static bool calculate_ss(
* so have to divided by 100 * 100*/
ss_amount = dc_fixpt_mul(
fb_div, dc_fixpt_from_fraction(ss_data->percentage,
- 100 * ss_data->percentage_divider));
+ 100 * (long long)ss_data->percentage_divider));
ds_data->feedback_amount = dc_fixpt_floor(ss_amount);
ss_nslip_amount = dc_fixpt_sub(ss_amount,
@@ -695,8 +695,8 @@ static bool calculate_ss(
/* compute SS_STEP_SIZE_DSFRAC */
modulation_time = dc_fixpt_from_fraction(
- pll_settings->reference_freq * 1000,
- pll_settings->reference_divider * ss_data->modulation_freq_hz);
+ pll_settings->reference_freq * (uint64_t)1000,
+ pll_settings->reference_divider * (uint64_t)ss_data->modulation_freq_hz);
if (ss_data->flags.CENTER_SPREAD)
modulation_time = dc_fixpt_div_int(modulation_time, 4);
@@ -1088,11 +1088,15 @@ static bool dcn401_program_pix_clk(
dto_params.clk_src = DPREFCLK;
if (e) {
- dto_params.pixclk_hz = e->target_pixel_rate_khz * e->mult_factor;
- dto_params.refclk_hz = dtbclk_p_src_clk_khz * e->div_factor;
+ dto_params.pixclk_hz = e->target_pixel_rate_khz;
+ dto_params.pixclk_hz *= e->mult_factor;
+ dto_params.refclk_hz = dtbclk_p_src_clk_khz;
+ dto_params.refclk_hz *= e->div_factor;
} else {
- dto_params.pixclk_hz = pix_clk_params->requested_pix_clk_100hz * 100;
- dto_params.refclk_hz = dtbclk_p_src_clk_khz * 1000;
+ dto_params.pixclk_hz = pix_clk_params->requested_pix_clk_100hz;
+ dto_params.pixclk_hz *= 100;
+ dto_params.refclk_hz = dtbclk_p_src_clk_khz;
+ dto_params.refclk_hz *= 1000;
}
/* enable DP DTO */
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 136bd93c3b65..4a9d07c31bc5 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
@@ -1361,7 +1361,10 @@ void dce110_link_encoder_dp_set_lane_settings(
cntl.lane_settings = training_lane_set.raw;
/* call VBIOS table to set voltage swing and pre-emphasis */
- link_transmitter_control(enc110, &cntl);
+ if (link_transmitter_control(enc110, &cntl) != BP_RESULT_OK) {
+ DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n", __func__);
+ BREAK_TO_DEBUGGER();
+ }
}
}
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 4cdd4dacb761..f5e1d9caee4c 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
@@ -642,8 +642,7 @@ static void dce_mi_program_surface_config(
program_tiling(dce_mi, tiling_info);
program_size_and_rotation(dce_mi, rotation, plane_size);
- if (format >= SURFACE_PIXEL_FORMAT_GRPH_BEGIN &&
- format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
+ if (format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
program_grph_pixel_format(dce_mi, format);
}
@@ -663,8 +662,7 @@ static void dce60_mi_program_surface_config(
program_tiling(dce_mi, tiling_info);
dce60_program_size(dce_mi, rotation, plane_size);
- if (format >= SURFACE_PIXEL_FORMAT_GRPH_BEGIN &&
- format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
+ if (format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
program_grph_pixel_format(dce_mi, format);
}
#endif
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c b/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c
index 5bca67407c5b..de31fb1b6819 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c
@@ -218,7 +218,7 @@ static void dce_driver_set_backlight(struct panel_cntl *panel_cntl,
* contain integer component, lower 16 bits contain fractional component
* of active duty cycle e.g. 0x21BDC0 = 0xEFF0 * 0x24
*/
- active_duty_cycle = backlight_pwm_u16_16 * masked_pwm_period;
+ active_duty_cycle = backlight_pwm_u16_16 * (uint64_t)masked_pwm_period;
/* 1.3 Calculate 16 bit active duty cycle from integer and fractional
* components shift by bitCount then mask 16 bits and add rounding bit
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 f4987e96fbf9..0d7e7f3b81a1 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
@@ -258,7 +258,7 @@ bool dmub_abm_set_pipe(struct abm *abm,
{
union dmub_rb_cmd cmd;
struct dc_context *dc = abm->ctx;
- uint32_t ramping_boundary = 0xFFFF;
+ uint8_t ramping_boundary = 0xFF;
memset(&cmd, 0, sizeof(cmd));
cmd.abm_set_pipe.header.type = DMUB_CMD__ABM;
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c
index 3e243e407bb8..ccf153b7a467 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c
@@ -445,10 +445,13 @@ static void dmub_psr_force_static(struct dmub_psr *dmub, uint8_t panel_inst)
/*
* Get PSR residency from firmware.
*/
-static void dmub_psr_get_residency(struct dmub_psr *dmub, uint32_t *residency, uint8_t panel_inst)
+static void dmub_psr_get_residency(struct dmub_psr *dmub, uint32_t *residency,
+ uint8_t panel_inst, enum psr_residency_mode mode)
{
uint16_t param = (uint16_t)(panel_inst << 8);
+ param |= mode;
+
/* Send gpint command and wait for ack */
dc_wake_and_execute_gpint(dmub->ctx, DMUB_GPINT__PSR_RESIDENCY, param, residency,
DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY);
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h
index 289e42070ece..a6e282d950c3 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h
+++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h
@@ -27,6 +27,7 @@
#define _DMUB_PSR_H_
#include "dc_types.h"
+#include "dmub_cmd.h"
struct dc_link;
struct dmub_psr_funcs;
@@ -46,7 +47,7 @@ struct dmub_psr_funcs {
uint8_t panel_inst);
void (*psr_force_static)(struct dmub_psr *dmub, uint8_t panel_inst);
void (*psr_get_residency)(struct dmub_psr *dmub, uint32_t *residency,
- uint8_t panel_inst);
+ uint8_t panel_inst, enum psr_residency_mode mode);
void (*psr_set_sink_vtotal_in_psr_active)(struct dmub_psr *dmub,
uint16_t psr_vtotal_idle, uint16_t psr_vtotal_su);
void (*psr_set_power_opt)(struct dmub_psr *dmub, unsigned int power_opt, uint8_t panel_inst);
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 2873ac8f16fb..2a21bcf5224f 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c
@@ -1,27 +1,6 @@
-/*
- * Copyright 2023 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
- *
- */
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2024 Advanced Micro Devices, Inc.
#include "dc.h"
#include "dc_dmub_srv.h"
@@ -33,26 +12,23 @@
#define MAX_PIPES 6
+static const uint8_t DP_SINK_DEVICE_STR_ID_1[] = {7, 1, 8, 7, 3};
+static const uint8_t DP_SINK_DEVICE_STR_ID_2[] = {7, 1, 8, 7, 5};
+
/*
* Get Replay state from firmware.
*/
static void dmub_replay_get_state(struct dmub_replay *dmub, enum replay_state *state, uint8_t panel_inst)
{
- struct dmub_srv *srv = dmub->ctx->dmub_srv->dmub;
- /* uint32_t raw_state = 0; */
uint32_t retry_count = 0;
- enum dmub_status status;
do {
// Send gpint command and wait for ack
- status = dmub_srv_send_gpint_command(srv, DMUB_GPINT__GET_REPLAY_STATE, panel_inst, 30);
-
- if (status == DMUB_STATUS_OK) {
- // GPINT was executed, get response
- dmub_srv_get_gpint_response(srv, (uint32_t *)state);
- } else
+ if (!dc_wake_and_execute_gpint(dmub->ctx, DMUB_GPINT__GET_REPLAY_STATE, panel_inst,
+ (uint32_t *)state, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)) {
// Return invalid state when GPINT times out
*state = REPLAY_STATE_INVALID;
+ }
} while (++retry_count <= 1000 && *state == REPLAY_STATE_INVALID);
// Assert if max retry hit
@@ -84,7 +60,7 @@ static void dmub_replay_enable(struct dmub_replay *dmub, bool enable, bool wait,
cmd.replay_enable.header.payload_bytes = sizeof(struct dmub_rb_cmd_replay_enable_data);
- dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
+ dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
/* Below loops 1000 x 500us = 500 ms.
* Exit REPLAY may need to wait 1-2 frames to power up. Timeout after at
@@ -102,7 +78,8 @@ static void dmub_replay_enable(struct dmub_replay *dmub, bool enable, bool wait,
break;
}
- fsleep(500);
+ /* must *not* be fsleep - this can be called from high irq levels */
+ udelay(500);
}
/* assert if max retry hit */
@@ -126,7 +103,7 @@ static void dmub_replay_set_power_opt(struct dmub_replay *dmub, unsigned int pow
cmd.replay_set_power_opt.replay_set_power_opt_data.power_opt = power_opt;
cmd.replay_set_power_opt.replay_set_power_opt_data.panel_inst = panel_inst;
- dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
+ dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
/*
@@ -199,11 +176,11 @@ static bool dmub_replay_copy_settings(struct dmub_replay *dmub,
(link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_SUPPORT &&
!link->panel_config.dsc.disable_dsc_edp &&
link->dc->caps.edp_dsc_support)) &&
- link->dpcd_caps.sink_dev_id == DP_DEVICE_ID_38EC11 /*&&
+ link->dpcd_caps.sink_dev_id == DP_DEVICE_ID_38EC11 &&
(!memcmp(link->dpcd_caps.sink_dev_id_str, DP_SINK_DEVICE_STR_ID_1,
sizeof(DP_SINK_DEVICE_STR_ID_1)) ||
!memcmp(link->dpcd_caps.sink_dev_id_str, DP_SINK_DEVICE_STR_ID_2,
- sizeof(DP_SINK_DEVICE_STR_ID_2)))*/)
+ sizeof(DP_SINK_DEVICE_STR_ID_2))))
copy_settings_data->flags.bitfields.force_wakeup_by_tps3 = 1;
else
copy_settings_data->flags.bitfields.force_wakeup_by_tps3 = 0;
@@ -218,42 +195,62 @@ static bool dmub_replay_copy_settings(struct dmub_replay *dmub,
* Set coasting vtotal.
*/
static void dmub_replay_set_coasting_vtotal(struct dmub_replay *dmub,
- uint16_t coasting_vtotal,
+ uint32_t coasting_vtotal,
uint8_t panel_inst)
{
union dmub_rb_cmd cmd;
struct dc_context *dc = dmub->ctx;
+ struct dmub_rb_cmd_replay_set_coasting_vtotal *pCmd = NULL;
+
+ pCmd = &(cmd.replay_set_coasting_vtotal);
memset(&cmd, 0, sizeof(cmd));
- cmd.replay_set_coasting_vtotal.header.type = DMUB_CMD__REPLAY;
- cmd.replay_set_coasting_vtotal.header.sub_type = DMUB_CMD__REPLAY_SET_COASTING_VTOTAL;
- cmd.replay_set_coasting_vtotal.header.payload_bytes = sizeof(struct dmub_cmd_replay_set_coasting_vtotal_data);
- cmd.replay_set_coasting_vtotal.replay_set_coasting_vtotal_data.coasting_vtotal = coasting_vtotal;
+ pCmd->header.type = DMUB_CMD__REPLAY;
+ pCmd->header.sub_type = DMUB_CMD__REPLAY_SET_COASTING_VTOTAL;
+ pCmd->header.payload_bytes = sizeof(struct dmub_cmd_replay_set_coasting_vtotal_data);
+ pCmd->replay_set_coasting_vtotal_data.coasting_vtotal = (coasting_vtotal & 0xFFFF);
+ pCmd->replay_set_coasting_vtotal_data.coasting_vtotal_high = (coasting_vtotal & 0xFFFF0000) >> 16;
- dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
+ dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
/*
* Get Replay residency from firmware.
*/
static void dmub_replay_residency(struct dmub_replay *dmub, uint8_t panel_inst,
- uint32_t *residency, const bool is_start, const bool is_alpm)
+ uint32_t *residency, const bool is_start, enum pr_residency_mode mode)
{
- struct dmub_srv *srv = dmub->ctx->dmub_srv->dmub;
uint16_t param = (uint16_t)(panel_inst << 8);
- if (is_alpm)
+ switch (mode) {
+ case PR_RESIDENCY_MODE_PHY:
+ param |= REPLAY_RESIDENCY_FIELD_MODE_PHY;
+ break;
+ case PR_RESIDENCY_MODE_ALPM:
param |= REPLAY_RESIDENCY_FIELD_MODE_ALPM;
+ break;
+ case PR_RESIDENCY_MODE_IPS2:
+ param |= REPLAY_RESIDENCY_REVISION_1;
+ param |= REPLAY_RESIDENCY_FIELD_MODE2_IPS;
+ break;
+ case PR_RESIDENCY_MODE_FRAME_CNT:
+ param |= REPLAY_RESIDENCY_REVISION_1;
+ param |= REPLAY_RESIDENCY_FIELD_MODE2_FRAME_CNT;
+ break;
+ case PR_RESIDENCY_MODE_ENABLEMENT_PERIOD:
+ param |= REPLAY_RESIDENCY_REVISION_1;
+ param |= REPLAY_RESIDENCY_FIELD_MODE2_EN_PERIOD;
+ break;
+ default:
+ break;
+ }
if (is_start)
param |= REPLAY_RESIDENCY_ENABLE;
// Send gpint command and wait for ack
- dmub_srv_send_gpint_command(srv, DMUB_GPINT__REPLAY_RESIDENCY, param, 30);
-
- if (!is_start)
- dmub_srv_get_gpint_response(srv, residency);
- else
+ if (!dc_wake_and_execute_gpint(dmub->ctx, DMUB_GPINT__REPLAY_RESIDENCY, param,
+ residency, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY))
*residency = 0;
}
@@ -261,20 +258,22 @@ static void dmub_replay_residency(struct dmub_replay *dmub, uint8_t panel_inst,
* Set REPLAY power optimization flags and coasting vtotal.
*/
static void dmub_replay_set_power_opt_and_coasting_vtotal(struct dmub_replay *dmub,
- unsigned int power_opt, uint8_t panel_inst, uint16_t coasting_vtotal)
+ unsigned int power_opt, uint8_t panel_inst, uint32_t coasting_vtotal)
{
union dmub_rb_cmd cmd;
struct dc_context *dc = dmub->ctx;
+ struct dmub_rb_cmd_replay_set_power_opt_and_coasting_vtotal *pCmd = NULL;
+
+ pCmd = &(cmd.replay_set_power_opt_and_coasting_vtotal);
memset(&cmd, 0, sizeof(cmd));
- cmd.replay_set_power_opt_and_coasting_vtotal.header.type = DMUB_CMD__REPLAY;
- cmd.replay_set_power_opt_and_coasting_vtotal.header.sub_type =
- DMUB_CMD__REPLAY_SET_POWER_OPT_AND_COASTING_VTOTAL;
- cmd.replay_set_power_opt_and_coasting_vtotal.header.payload_bytes =
- sizeof(struct dmub_rb_cmd_replay_set_power_opt_and_coasting_vtotal);
- cmd.replay_set_power_opt_and_coasting_vtotal.replay_set_power_opt_data.power_opt = power_opt;
- cmd.replay_set_power_opt_and_coasting_vtotal.replay_set_power_opt_data.panel_inst = panel_inst;
- cmd.replay_set_power_opt_and_coasting_vtotal.replay_set_coasting_vtotal_data.coasting_vtotal = coasting_vtotal;
+ pCmd->header.type = DMUB_CMD__REPLAY;
+ pCmd->header.sub_type = DMUB_CMD__REPLAY_SET_POWER_OPT_AND_COASTING_VTOTAL;
+ pCmd->header.payload_bytes = sizeof(struct dmub_rb_cmd_replay_set_power_opt_and_coasting_vtotal);
+ pCmd->replay_set_power_opt_data.power_opt = power_opt;
+ pCmd->replay_set_power_opt_data.panel_inst = panel_inst;
+ pCmd->replay_set_coasting_vtotal_data.coasting_vtotal = (coasting_vtotal & 0xFFFF);
+ pCmd->replay_set_coasting_vtotal_data.coasting_vtotal_high = (coasting_vtotal & 0xFFFF0000) >> 16;
dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
@@ -330,6 +329,46 @@ static void dmub_replay_send_cmd(struct dmub_replay *dmub,
cmd.replay_set_frameupdate_timer.data.frameupdate_count =
cmd_element->timer_data.frameupdate_count;
break;
+ case Replay_Set_Pseudo_VTotal:
+ //Header
+ cmd.replay_set_pseudo_vtotal.header.sub_type =
+ DMUB_CMD__REPLAY_SET_PSEUDO_VTOTAL;
+ cmd.replay_set_pseudo_vtotal.header.payload_bytes =
+ sizeof(struct dmub_rb_cmd_replay_set_pseudo_vtotal);
+ //Cmd Body
+ cmd.replay_set_pseudo_vtotal.data.panel_inst =
+ cmd_element->pseudo_vtotal_data.panel_inst;
+ cmd.replay_set_pseudo_vtotal.data.vtotal =
+ cmd_element->pseudo_vtotal_data.vtotal;
+ break;
+ case Replay_Disabled_Adaptive_Sync_SDP:
+ //Header
+ cmd.replay_disabled_adaptive_sync_sdp.header.sub_type =
+ DMUB_CMD__REPLAY_DISABLED_ADAPTIVE_SYNC_SDP;
+ cmd.replay_disabled_adaptive_sync_sdp.header.payload_bytes =
+ sizeof(struct dmub_rb_cmd_replay_disabled_adaptive_sync_sdp);
+ //Cmd Body
+ cmd.replay_disabled_adaptive_sync_sdp.data.panel_inst =
+ cmd_element->disabled_adaptive_sync_sdp_data.panel_inst;
+ cmd.replay_disabled_adaptive_sync_sdp.data.force_disabled =
+ cmd_element->disabled_adaptive_sync_sdp_data.force_disabled;
+ break;
+ case Replay_Set_General_Cmd:
+ //Header
+ cmd.replay_set_general_cmd.header.sub_type =
+ DMUB_CMD__REPLAY_SET_GENERAL_CMD;
+ cmd.replay_set_general_cmd.header.payload_bytes =
+ sizeof(struct dmub_rb_cmd_replay_set_general_cmd);
+ //Cmd Body
+ cmd.replay_set_general_cmd.data.panel_inst =
+ cmd_element->set_general_cmd_data.panel_inst;
+ cmd.replay_set_general_cmd.data.subtype =
+ cmd_element->set_general_cmd_data.subtype;
+ cmd.replay_set_general_cmd.data.param1 =
+ cmd_element->set_general_cmd_data.param1;
+ cmd.replay_set_general_cmd.data.param2 =
+ cmd_element->set_general_cmd_data.param2;
+ break;
case Replay_Msg_Not_Support:
default:
return;
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.h b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.h
index 3613aff994d7..e6346c0ffc0e 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.h
+++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.h
@@ -1,27 +1,6 @@
-/*
- * Copyright 2023 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
- *
- */
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2024 Advanced Micro Devices, Inc.
#ifndef _DMUB_REPLAY_H_
#define _DMUB_REPLAY_H_
@@ -47,12 +26,12 @@ struct dmub_replay_funcs {
uint8_t panel_inst);
void (*replay_send_cmd)(struct dmub_replay *dmub,
enum replay_FW_Message_type msg, union dmub_replay_cmd_set *cmd_element);
- void (*replay_set_coasting_vtotal)(struct dmub_replay *dmub, uint16_t coasting_vtotal,
+ void (*replay_set_coasting_vtotal)(struct dmub_replay *dmub, uint32_t coasting_vtotal,
uint8_t panel_inst);
void (*replay_residency)(struct dmub_replay *dmub,
- uint8_t panel_inst, uint32_t *residency, const bool is_start, const bool is_alpm);
+ uint8_t panel_inst, uint32_t *residency, const bool is_start, const enum pr_residency_mode mode);
void (*replay_set_power_opt_and_coasting_vtotal)(struct dmub_replay *dmub,
- unsigned int power_opt, uint8_t panel_inst, uint16_t coasting_vtotal);
+ unsigned int power_opt, uint8_t panel_inst, uint32_t coasting_vtotal);
};
struct dmub_replay *dmub_replay_create(struct dc_context *ctx);
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile
index 68484264831b..9923d0d620d4 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile
@@ -27,7 +27,6 @@ DCN10 = dcn10_ipp.o \
dcn10_opp.o \
dcn10_mpc.o \
dcn10_cm_common.o \
- dcn10_stream_encoder.o dcn10_link_encoder.o
AMD_DAL_DCN10 = $(addprefix $(AMDDALPATH)/dc/dcn10/,$(DCN10))
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/Makefile b/drivers/gpu/drm/amd/display/dc/dcn20/Makefile
index 1ca1cbeabbca..b3aeabc4d605 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/Makefile
@@ -2,7 +2,6 @@
# Copyright © 2019-2024 Advanced Micro Devices, Inc. All rights reserved.
DCN20 = dcn20_mpc.o dcn20_opp.o dcn20_mmhubbub.o \
- dcn20_stream_encoder.o dcn20_link_encoder.o \
dcn20_vmid.o dcn20_dwb.o dcn20_dwb_scl.o
AMD_DAL_DCN20 = $(addprefix $(AMDDALPATH)/dc/dcn20/,$(DCN20))
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 994fb732a7cb..a0d437f0ce2b 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
@@ -690,6 +690,9 @@ static void wbscl_set_scaler_filter(
int pair;
uint16_t odd_coef, even_coef;
+ if (!filter)
+ return;
+
for (phase = 0; phase < (NUM_PHASES / 2 + 1); phase++) {
for (pair = 0; pair < tap_pairs; pair++) {
even_coef = filter[phase * taps + 2 * pair];
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/Makefile b/drivers/gpu/drm/amd/display/dc/dcn30/Makefile
index 2131d228f6fb..4c43af867d86 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/Makefile
@@ -25,12 +25,10 @@
DCN30 := dcn30_mpc.o dcn30_vpg.o \
dcn30_afmt.o \
- dcn30_dio_stream_encoder.o \
dcn30_dwb.o \
dcn30_dwb_cm.o \
dcn30_cm_common.o \
dcn30_mmhubbub.o \
- dcn30_dio_link_encoder.o
diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/Makefile b/drivers/gpu/drm/amd/display/dc/dcn301/Makefile
index fadf5e872e38..dc37dbf870df 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn301/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dcn301/Makefile
@@ -1,12 +1,5 @@
-#
-# (c) Copyright 2020 Advanced Micro Devices, Inc. All the rights reserved
-#
-# All rights reserved. This notice is intended as a precaution against
-# inadvertent publication and does not imply publication or any waiver
-# of confidentiality. The year included in the foregoing notice is the
-# year of creation of the work.
-#
-# Authors: AMD
+# SPDX-License-Identifier: MIT
+# Copyright © 2024 Advanced Micro Devices, Inc. All rights reserved.
#
# Makefile for dcn30.
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/Makefile b/drivers/gpu/drm/amd/display/dc/dcn31/Makefile
index 62c8ab0e45aa..e2601d0aba41 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/Makefile
@@ -1,16 +1,10 @@
+# SPDX-License-Identifier: MIT
+# Copyright © 2024 Advanced Micro Devices, Inc. All rights reserved.
#
-# Copyright 2020 Advanced Micro Devices, Inc. All the rights reserved
-#
-# All rights reserved. This notice is intended as a precaution against
-# inadvertent publication and does not imply publication or any waiver
-# of confidentiality. The year included in the foregoing notice is the
-# year of creation of the work.
-#
-# Authors: AMD
#
# Makefile for dcn31.
-DCN31 = dcn31_dio_link_encoder.o dcn31_panel_cntl.o \
+DCN31 = dcn31_panel_cntl.o \
dcn31_apg.o dcn31_hpo_dp_stream_encoder.o dcn31_hpo_dp_link_encoder.o \
dcn31_afmt.o dcn31_vpg.o
diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/Makefile b/drivers/gpu/drm/amd/display/dc/dcn314/Makefile
index cac756c75b7f..15fdcf7c6466 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn314/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dcn314/Makefile
@@ -1,12 +1,5 @@
-#
-# (c) Copyright 2022 Advanced Micro Devices, Inc. All the rights reserved
-#
-# All rights reserved. This notice is intended as a precaution against
-# inadvertent publication and does not imply publication or any waiver
-# of confidentiality. The year included in the foregoing notice is the
-# year of creation of the work.
-#
-# Authors: AMD
+# SPDX-License-Identifier: MIT
+# Copyright © 2024 Advanced Micro Devices, Inc. All rights reserved.
#
# Makefile for dcn314.
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/Makefile b/drivers/gpu/drm/amd/display/dc/dcn32/Makefile
deleted file mode 100644
index 2d0eb203ab69..000000000000
--- a/drivers/gpu/drm/amd/display/dc/dcn32/Makefile
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# (c) Copyright 2022 Advanced Micro Devices, Inc. All the rights reserved
-#
-# All rights reserved. This notice is intended as a precaution against
-# inadvertent publication and does not imply publication or any waiver
-# of confidentiality. The year included in the foregoing notice is the
-# year of creation of the work.
-#
-# Authors: AMD
-#
-# Makefile for dcn32.
-
-DCN32 = dcn32_mmhubbub.o dcn32_mpc.o \
- dcn32_dio_stream_encoder.o dcn32_dio_link_encoder.o dcn32_resource_helpers.o \
- dcn32_hpo_dp_link_encoder.o
-
-AMD_DAL_DCN32 = $(addprefix $(AMDDALPATH)/dc/dcn32/,$(DCN32))
-
-AMD_DISPLAY_FILES += $(AMD_DAL_DCN32)
diff --git a/drivers/gpu/drm/amd/display/dc/dcn321/Makefile b/drivers/gpu/drm/amd/display/dc/dcn321/Makefile
deleted file mode 100644
index c195c47f58b4..000000000000
--- a/drivers/gpu/drm/amd/display/dc/dcn321/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-#
-# (c) Copyright 2020 Advanced Micro Devices, Inc. All the rights reserved
-#
-# All rights reserved. This notice is intended as a precaution against
-# inadvertent publication and does not imply publication or any waiver
-# of confidentiality. The year included in the foregoing notice is the
-# year of creation of the work.
-#
-# Authors: AMD
-#
-# Makefile for dcn321.
-
-DCN321 = dcn321_dio_link_encoder.o
-
-AMD_DAL_DCN321 = $(addprefix $(AMDDALPATH)/dc/dcn321/,$(DCN321))
-
-AMD_DISPLAY_FILES += $(AMD_DAL_DCN321)
diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/Makefile b/drivers/gpu/drm/amd/display/dc/dcn35/Makefile
deleted file mode 100644
index d0fab60e7cd9..000000000000
--- a/drivers/gpu/drm/amd/display/dc/dcn35/Makefile
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# (c) Copyright 2022 Advanced Micro Devices, Inc. All the rights reserved
-#
-# All rights reserved. This notice is intended as a precaution against
-# inadvertent publication and does not imply publication or any waiver
-# of confidentiality. The year included in the foregoing notice is the
-# year of creation of the work.
-#
-# Authors: AMD
-#
-# Makefile for DCN35.
-
-DCN35 = dcn35_dio_stream_encoder.o \
- dcn35_dio_link_encoder.o \
- dcn35_mmhubbub.o dcn35_opp.o dcn35_pg_cntl.o dcn35_dwb.o
-
-AMD_DAL_DCN35 = $(addprefix $(AMDDALPATH)/dc/dcn35/,$(DCN35))
-
-AMD_DISPLAY_FILES += $(AMD_DAL_DCN35)
diff --git a/drivers/gpu/drm/amd/display/dc/dcn401/Makefile b/drivers/gpu/drm/amd/display/dc/dcn401/Makefile
index 2989e706bccf..ded1f3140beb 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn401/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dcn401/Makefile
@@ -1,6 +1,5 @@
-#
-# Copyright © 2023 Advanced Micro Devices, Inc. All rights reserved.
-#
+# SPDX-License-Identifier: MIT
+# Copyright © 2024 Advanced Micro Devices, Inc. All rights reserved.
DCN401 += dcn401_dio_link_encoder.o
DCN401 += dcn401_dio_stream_encoder.o
diff --git a/drivers/gpu/drm/amd/display/dc/dio/Makefile b/drivers/gpu/drm/amd/display/dc/dio/Makefile
new file mode 100644
index 000000000000..67840e474d7a
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dio/Makefile
@@ -0,0 +1,99 @@
+#
+# Copyright 2020 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
+#
+#
+
+ifdef CONFIG_DRM_AMD_DC_FP
+###############################################################################
+# DCN10
+###############################################################################
+DIO_DCN10 = dcn10_link_encoder.o dcn10_stream_encoder.o
+
+AMD_DAL_DIO_DCN10 = $(addprefix $(AMDDALPATH)/dc/dio/dcn10/,$(DIO_DCN10))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_DIO_DCN10)
+
+###############################################################################
+# DCN20
+###############################################################################
+DIO_DCN20 = dcn20_link_encoder.o dcn20_stream_encoder.o
+
+AMD_DAL_DIO_DCN20 = $(addprefix $(AMDDALPATH)/dc/dio/dcn20/,$(DIO_DCN20))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_DIO_DCN20)
+
+###############################################################################
+# DCN30
+###############################################################################
+DIO_DCN30 = dcn30_dio_link_encoder.o dcn30_dio_stream_encoder.o
+
+AMD_DAL_DIO_DCN30 = $(addprefix $(AMDDALPATH)/dc/dio/dcn30/,$(DIO_DCN30))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_DIO_DCN30)
+
+###############################################################################
+# DCN31
+###############################################################################
+DIO_DCN31 = dcn31_dio_link_encoder.o
+
+AMD_DAL_DIO_DCN31 = $(addprefix $(AMDDALPATH)/dc/dio/dcn31/,$(DIO_DCN31))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_DIO_DCN31)
+
+###############################################################################
+# DCN32
+###############################################################################
+DIO_DCN32 = dcn32_dio_link_encoder.o dcn32_dio_stream_encoder.o
+
+AMD_DAL_DIO_DCN32 = $(addprefix $(AMDDALPATH)/dc/dio/dcn32/,$(DIO_DCN32))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_DIO_DCN32)
+
+###############################################################################
+# DCN35
+###############################################################################
+DIO_DCN35 = dcn35_dio_link_encoder.o dcn35_dio_stream_encoder.o
+
+AMD_DAL_DIO_DCN35 = $(addprefix $(AMDDALPATH)/dc/dio/dcn35/,$(DIO_DCN35))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_DIO_DCN35)
+
+###############################################################################
+# DCN321
+###############################################################################
+DIO_DCN321 = dcn321_dio_link_encoder.o
+
+AMD_DAL_DIO_DCN321 = $(addprefix $(AMDDALPATH)/dc/dio/dcn321/,$(DIO_DCN321))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_DIO_DCN321)
+
+
+###############################################################################
+# DCN401
+###############################################################################
+DIO_DCN401 = dcn401_dio_link_encoder.o dcn401_dio_stream_encoder.o
+
+AMD_DAL_DIO_DCN401 = $(addprefix $(AMDDALPATH)/dc/dio/dcn401/,$(DIO_DCN401))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_DIO_DCN401)
+endif
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.c
index 4d0eed7598b2..e0558a78b11c 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.c
@@ -1104,6 +1104,7 @@ void dcn10_link_encoder_dp_set_lane_settings(
union dpcd_training_lane_set training_lane_set = { { 0 } };
int32_t lane = 0;
struct bp_transmitter_control cntl = { 0 };
+ enum bp_result result;
if (!link_settings) {
BREAK_TO_DEBUGGER();
@@ -1138,7 +1139,12 @@ void dcn10_link_encoder_dp_set_lane_settings(
cntl.lane_settings = training_lane_set.raw;
/* call VBIOS table to set voltage swing and pre-emphasis */
- link_transmitter_control(enc10, &cntl);
+ result = link_transmitter_control(enc10, &cntl);
+
+ if (result != BP_RESULT_OK) {
+ DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n", __func__);
+ BREAK_TO_DEBUGGER();
+ }
}
}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.h
index b7a89c39f445..b7a89c39f445 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.h
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c
index f496e952ceec..f496e952ceec 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.h
index 54a6a4ebd636..54a6a4ebd636 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.h
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_link_encoder.c
index 51a57dae1811..51a57dae1811 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_link_encoder.c
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_link_encoder.h
index 762c579fcb44..762c579fcb44 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_link_encoder.h
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_stream_encoder.c
index 0b47aeb60e79..0b47aeb60e79 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_stream_encoder.c
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_stream_encoder.h
index baa1e539f341..baa1e539f341 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_stream_encoder.h
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_link_encoder.c
index b8e31b5ea114..b8e31b5ea114 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_link_encoder.c
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_link_encoder.h
index 5b6177c2ae98..5b6177c2ae98 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_link_encoder.h
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_stream_encoder.c
index 425b830b88d2..425b830b88d2 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_stream_encoder.c
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_stream_encoder.h
index 06310973ded2..06310973ded2 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_stream_encoder.h
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn31/dcn31_dio_link_encoder.c
index b2cea59ba5d4..b2cea59ba5d4 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn31/dcn31_dio_link_encoder.c
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn31/dcn31_dio_link_encoder.h
index ee78ba80797c..ee78ba80797c 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn31/dcn31_dio_link_encoder.h
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_link_encoder.c
index 06907e8a4eda..06907e8a4eda 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_link_encoder.c
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_link_encoder.h
index 35d23d9db45e..35d23d9db45e 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_link_encoder.h
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_stream_encoder.c
index 1a9bb614c41e..1a9bb614c41e 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_stream_encoder.c
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_stream_encoder.h
index ca53d39561d2..ca53d39561d2 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_stream_encoder.h
diff --git a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn321/dcn321_dio_link_encoder.c
index 05783daa62ac..05783daa62ac 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_dio_link_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn321/dcn321_dio_link_encoder.c
diff --git a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_dio_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn321/dcn321_dio_link_encoder.h
index 2205f39b0a24..2205f39b0a24 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_dio_link_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn321/dcn321_dio_link_encoder.h
diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_link_encoder.c
index 20f810a6646c..d4a3e811aa39 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_link_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_link_encoder.c
@@ -183,13 +183,13 @@ void dcn35_link_encoder_construct(
enc10->base.hpd_source = init_data->hpd_source;
enc10->base.connector = init_data->connector;
- if (enc10->base.connector.id == CONNECTOR_ID_USBC)
- enc10->base.features.flags.bits.DP_IS_USB_C = 1;
-
enc10->base.preferred_engine = ENGINE_ID_UNKNOWN;
enc10->base.features = *enc_features;
+ if (enc10->base.connector.id == CONNECTOR_ID_USBC)
+ enc10->base.features.flags.bits.DP_IS_USB_C = 1;
+
enc10->base.transmitter = init_data->transmitter;
/* set the flag to indicate whether driver poll the I2C data pin
@@ -255,10 +255,6 @@ void dcn35_link_encoder_construct(
enc10->base.features.flags.bits.IS_UHBR10_CAPABLE = bp_cap_info.DP_UHBR10_EN;
enc10->base.features.flags.bits.IS_UHBR13_5_CAPABLE = bp_cap_info.DP_UHBR13_5_EN;
enc10->base.features.flags.bits.IS_UHBR20_CAPABLE = bp_cap_info.DP_UHBR20_EN;
- if (bp_cap_info.DP_IS_USB_C) {
- /*BIOS not switch to use CONNECTOR_ID_USBC = 24 yet*/
- enc10->base.features.flags.bits.DP_IS_USB_C = 1;
- }
} else {
DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n",
diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_link_encoder.h
index d546a3676304..d546a3676304 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_link_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_link_encoder.h
diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_stream_encoder.c
index 1325db3a4ed0..6a179e5ab417 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_stream_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_stream_encoder.c
@@ -392,7 +392,7 @@ static void enc35_reset_fifo(struct stream_encoder *enc, bool reset)
udelay(10);
}
-static void enc35_disable_fifo(struct stream_encoder *enc)
+void enc35_disable_fifo(struct stream_encoder *enc)
{
struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
@@ -401,7 +401,7 @@ static void enc35_disable_fifo(struct stream_encoder *enc)
REG_UPDATE(DIG_FE_CLK_CNTL, DIG_FE_CLK_EN, 0);
}
-static void enc35_enable_fifo(struct stream_encoder *enc)
+void enc35_enable_fifo(struct stream_encoder *enc)
{
struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_stream_encoder.h
index 1212fcee38f2..ddb33fdfb4ee 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_stream_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_stream_encoder.h
@@ -322,5 +322,11 @@ void enc3_dp_set_dsc_pps_info_packet(
uint8_t *dsc_packed_pps,
bool immediate_update);
+void enc35_disable_fifo(
+ struct stream_encoder *enc);
+
+void enc35_enable_fifo(
+ struct stream_encoder *enc);
+
#endif /* __DC_DIO_STREAM_ENCODER_DCN35_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/dcn401/dcn401_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.c
index 7e558ca195ef..7e558ca195ef 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn401/dcn401_dio_link_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.c
diff --git a/drivers/gpu/drm/amd/display/dc/dcn401/dcn401_dio_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.h
index 6baab8302b81..6baab8302b81 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn401/dcn401_dio_link_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.h
diff --git a/drivers/gpu/drm/amd/display/dc/dcn401/dcn401_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c
index 2ebfca4769aa..0a27e0942a12 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn401/dcn401_dio_stream_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c
@@ -27,6 +27,7 @@
#include "dc_bios_types.h"
#include "dcn30/dcn30_dio_stream_encoder.h"
#include "dcn32/dcn32_dio_stream_encoder.h"
+#include "dcn35/dcn35_dio_stream_encoder.h"
#include "dcn401_dio_stream_encoder.h"
#include "reg_helper.h"
@@ -764,7 +765,8 @@ static const struct stream_encoder_funcs dcn401_str_enc_funcs = {
.enable_stream = enc401_stream_encoder_enable,
.set_input_mode = enc401_set_dig_input_mode,
- .enable_fifo = enc32_enable_fifo,
+ .enable_fifo = enc35_enable_fifo,
+ .disable_fifo = enc35_disable_fifo,
.map_stream_to_link = enc401_stream_encoder_map_to_link,
};
diff --git a/drivers/gpu/drm/amd/display/dc/dcn401/dcn401_dio_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.h
index d751839598f8..d751839598f8 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn401/dcn401_dio_stream_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.h
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 f1cde1e4265f..39525721c976 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
@@ -690,7 +690,7 @@ static void hack_disable_optional_pipe_split(struct dcn_bw_internal_vars *v)
static void hack_force_pipe_split(struct dcn_bw_internal_vars *v,
unsigned int pixel_rate_100hz)
{
- float pixel_rate_mhz = pixel_rate_100hz / 10000;
+ float pixel_rate_mhz = pixel_rate_100hz / 10000.0;
/*
* force enabling pipe split by lower dpp clock for DPM0 to just
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 74da9ebda016..8a8efe408a9d 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
@@ -1084,7 +1084,7 @@ static enum dcn_zstate_support_state decide_zstate_support(struct dc *dc, struc
struct dc_stream_status *stream_status = &context->stream_status[0];
int minmum_z8_residency = dc->debug.minimum_z8_residency_time > 0 ? dc->debug.minimum_z8_residency_time : 1000;
bool allow_z8 = context->bw_ctx.dml.vba.StutterPeriod > (double)minmum_z8_residency;
- bool is_pwrseq0 = link->link_index == 0;
+ bool is_pwrseq0 = (link && link->link_index == 0);
bool is_psr = (link && (link->psr_settings.psr_version == DC_PSR_VERSION_1 ||
link->psr_settings.psr_version == DC_PSR_VERSION_SU_1) && !link->panel_config.psr.disable_psr);
bool is_replay = link && link->replay_settings.replay_feature_enabled;
@@ -1882,10 +1882,10 @@ void dcn20_update_bounding_box(struct dc *dc,
bb->clock_limits[i].fabricclk_mhz = (min_fclk_required_by_uclk < min_dcfclk) ?
min_dcfclk : min_fclk_required_by_uclk;
- bb->clock_limits[i].socclk_mhz = (bb->clock_limits[i].fabricclk_mhz > max_clocks->socClockInKhz / 1000) ?
+ bb->clock_limits[i].socclk_mhz = (bb->clock_limits[i].fabricclk_mhz > max_clocks->socClockInKhz / 1000.0) ?
max_clocks->socClockInKhz / 1000 : bb->clock_limits[i].fabricclk_mhz;
- bb->clock_limits[i].dcfclk_mhz = (bb->clock_limits[i].fabricclk_mhz > max_clocks->dcfClockInKhz / 1000) ?
+ bb->clock_limits[i].dcfclk_mhz = (bb->clock_limits[i].fabricclk_mhz > max_clocks->dcfClockInKhz / 1000.0) ?
max_clocks->dcfClockInKhz / 1000 : bb->clock_limits[i].fabricclk_mhz;
bb->clock_limits[i].dispclk_mhz = max_clocks->displayClockInKhz / 1000;
@@ -1917,35 +1917,35 @@ void dcn20_cap_soc_clocks(struct _vcs_dpi_soc_bounding_box_st *bb,
// First pass - cap all clocks higher than the reported max
for (i = 0; i < bb->num_states; i++) {
- if ((bb->clock_limits[i].dcfclk_mhz > (max_clocks.dcfClockInKhz / 1000))
+ if ((bb->clock_limits[i].dcfclk_mhz > (max_clocks.dcfClockInKhz / 1000.0))
&& max_clocks.dcfClockInKhz != 0)
bb->clock_limits[i].dcfclk_mhz = (max_clocks.dcfClockInKhz / 1000);
- if ((bb->clock_limits[i].dram_speed_mts > (max_clocks.uClockInKhz / 1000) * 16)
+ if ((bb->clock_limits[i].dram_speed_mts > (max_clocks.uClockInKhz / 1000.0) * 16)
&& max_clocks.uClockInKhz != 0)
bb->clock_limits[i].dram_speed_mts = (max_clocks.uClockInKhz / 1000) * 16;
- if ((bb->clock_limits[i].fabricclk_mhz > (max_clocks.fabricClockInKhz / 1000))
+ if ((bb->clock_limits[i].fabricclk_mhz > (max_clocks.fabricClockInKhz / 1000.0))
&& max_clocks.fabricClockInKhz != 0)
bb->clock_limits[i].fabricclk_mhz = (max_clocks.fabricClockInKhz / 1000);
- if ((bb->clock_limits[i].dispclk_mhz > (max_clocks.displayClockInKhz / 1000))
+ if ((bb->clock_limits[i].dispclk_mhz > (max_clocks.displayClockInKhz / 1000.0))
&& max_clocks.displayClockInKhz != 0)
bb->clock_limits[i].dispclk_mhz = (max_clocks.displayClockInKhz / 1000);
- if ((bb->clock_limits[i].dppclk_mhz > (max_clocks.dppClockInKhz / 1000))
+ if ((bb->clock_limits[i].dppclk_mhz > (max_clocks.dppClockInKhz / 1000.0))
&& max_clocks.dppClockInKhz != 0)
bb->clock_limits[i].dppclk_mhz = (max_clocks.dppClockInKhz / 1000);
- if ((bb->clock_limits[i].phyclk_mhz > (max_clocks.phyClockInKhz / 1000))
+ if ((bb->clock_limits[i].phyclk_mhz > (max_clocks.phyClockInKhz / 1000.0))
&& max_clocks.phyClockInKhz != 0)
bb->clock_limits[i].phyclk_mhz = (max_clocks.phyClockInKhz / 1000);
- if ((bb->clock_limits[i].socclk_mhz > (max_clocks.socClockInKhz / 1000))
+ if ((bb->clock_limits[i].socclk_mhz > (max_clocks.socClockInKhz / 1000.0))
&& max_clocks.socClockInKhz != 0)
bb->clock_limits[i].socclk_mhz = (max_clocks.socClockInKhz / 1000);
- if ((bb->clock_limits[i].dscclk_mhz > (max_clocks.dscClockInKhz / 1000))
+ if ((bb->clock_limits[i].dscclk_mhz > (max_clocks.dscClockInKhz / 1000.0))
&& max_clocks.dscClockInKhz != 0)
bb->clock_limits[i].dscclk_mhz = (max_clocks.dscClockInKhz / 1000);
}
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 7bf4bb7ad044..565f3c492477 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
@@ -1017,7 +1017,7 @@ static unsigned int CalculateVMAndRowBytes(
if (ScanDirection == dm_horz)
FractionOfPTEReturnDrop = 0;
else
- FractionOfPTEReturnDrop = 7 / 8;
+ FractionOfPTEReturnDrop = 7.0 / 8;
} else if (VMMPageSize == 4096 && MacroTileSizeBytes > 4096) {
PixelPTEReqHeight = 16 * BlockHeight256Bytes;
PixelPTEReqWidth = 16 * BlockWidth256Bytes;
@@ -3231,22 +3231,22 @@ static unsigned int TruncToValidBPP(
if (Format == dm_420) {
if (DecimalBPP < 6)
return BPP_INVALID;
- else if (DecimalBPP >= 1.5 * DSCInputBitPerComponent - 1 / 16)
- return 1.5 * DSCInputBitPerComponent - 1 / 16;
+ else if (DecimalBPP >= 1.5 * DSCInputBitPerComponent - 1.0 / 16)
+ return 1.5 * DSCInputBitPerComponent - 1.0 / 16;
else
return dml_floor(16 * DecimalBPP, 1) / 16;
} else if (Format == dm_n422) {
if (DecimalBPP < 7)
return BPP_INVALID;
- else if (DecimalBPP >= 2 * DSCInputBitPerComponent - 1 / 16)
- return 2 * DSCInputBitPerComponent - 1 / 16;
+ else if (DecimalBPP >= 2 * DSCInputBitPerComponent - 1.0 / 16)
+ return 2 * DSCInputBitPerComponent - 1.0 / 16;
else
return dml_floor(16 * DecimalBPP, 1) / 16;
} else {
if (DecimalBPP < 8)
return BPP_INVALID;
- else if (DecimalBPP >= 3 * DSCInputBitPerComponent - 1 / 16)
- return 3 * DSCInputBitPerComponent - 1 / 16;
+ else if (DecimalBPP >= 3 * DSCInputBitPerComponent - 1.0 / 16)
+ return 3 * DSCInputBitPerComponent - 1.0 / 16;
else
return dml_floor(16 * DecimalBPP, 1) / 16;
}
@@ -4322,7 +4322,7 @@ void dml20_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
locals->RoundedUpMaxSwathSizeBytesC = 0;
}
- if (locals->RoundedUpMaxSwathSizeBytesY + locals->RoundedUpMaxSwathSizeBytesC <= locals->DETBufferSizeInKByte[0] * 1024 / 2) {
+ if (locals->RoundedUpMaxSwathSizeBytesY + locals->RoundedUpMaxSwathSizeBytesC <= locals->DETBufferSizeInKByte[0] * 1024.0 / 2) {
locals->SwathHeightYPerState[i][j][k] = locals->MaxSwathHeightY[k];
locals->SwathHeightCPerState[i][j][k] = locals->MaxSwathHeightC[k];
} else {
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 989d83ee3842..9d6675ecc5f1 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
@@ -1077,7 +1077,7 @@ static unsigned int CalculateVMAndRowBytes(
if (ScanDirection == dm_horz)
FractionOfPTEReturnDrop = 0;
else
- FractionOfPTEReturnDrop = 7 / 8;
+ FractionOfPTEReturnDrop = 7.0 / 8;
} else if (VMMPageSize == 4096 && MacroTileSizeBytes > 4096) {
PixelPTEReqHeight = 16 * BlockHeight256Bytes;
PixelPTEReqWidth = 16 * BlockWidth256Bytes;
@@ -4443,7 +4443,7 @@ void dml20v2_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode
locals->RoundedUpMaxSwathSizeBytesC = 0;
}
- if (locals->RoundedUpMaxSwathSizeBytesY + locals->RoundedUpMaxSwathSizeBytesC <= locals->DETBufferSizeInKByte[0] * 1024 / 2) {
+ if (locals->RoundedUpMaxSwathSizeBytesY + locals->RoundedUpMaxSwathSizeBytesC <= locals->DETBufferSizeInKByte[0] * 1024.0 / 2) {
locals->SwathHeightYPerState[i][j][k] = locals->MaxSwathHeightY[k];
locals->SwathHeightCPerState[i][j][k] = locals->MaxSwathHeightC[k];
} else {
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 548cdef8a8ad..7c56ad0f8812 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
@@ -688,12 +688,11 @@ static void get_surf_rq_param(struct display_mode_lib *mode_lib,
const display_pipe_source_params_st *pipe_src_param,
bool is_chroma)
{
- bool mode_422 = false;
unsigned int vp_width = 0;
unsigned int vp_height = 0;
unsigned int data_pitch = 0;
unsigned int meta_pitch = 0;
- unsigned int ppe = mode_422 ? 2 : 1;
+ unsigned int ppe = 1;
// TODO check if ppe apply for both luma and chroma in 422 case
if (is_chroma) {
@@ -825,7 +824,6 @@ static void dml20_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib,
double min_dst_y_ttu_vblank;
unsigned int dlg_vblank_start;
bool dual_plane;
- bool mode_422;
unsigned int access_dir;
unsigned int vp_height_l;
unsigned int vp_width_l;
@@ -971,7 +969,6 @@ static void dml20_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib,
// Source
// dcc_en = src.dcc;
dual_plane = is_dual_plane((enum source_format_class)(src->source_format));
- mode_422 = false; // TODO
access_dir = (src->source_scan == dm_vert); // vp access direction: horizontal or vertical accessed
// bytes_per_element_l = get_bytes_per_element(source_format_class(src.source_format), 0);
// bytes_per_element_c = get_bytes_per_element(source_format_class(src.source_format), 1);
@@ -1148,18 +1145,8 @@ static void dml20_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib,
dpte_row_height_l = rq_dlg_param->rq_l.dpte_row_height;
dpte_row_height_c = rq_dlg_param->rq_c.dpte_row_height;
- if (mode_422) {
- swath_width_pixels_ub_l = swath_width_ub_l * 2; // *2 for 2 pixel per element
- swath_width_pixels_ub_c = swath_width_ub_c * 2;
- } else {
- swath_width_pixels_ub_l = swath_width_ub_l * 1;
- swath_width_pixels_ub_c = swath_width_ub_c * 1;
- }
-
- hscale_pixel_rate_l = 0.;
- hscale_pixel_rate_c = 0.;
- min_hratio_fact_l = 1.0;
- min_hratio_fact_c = 1.0;
+ swath_width_pixels_ub_l = swath_width_ub_l;
+ swath_width_pixels_ub_c = swath_width_ub_c;
if (htaps_l <= 1)
min_hratio_fact_l = 2.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 0fc9f3e3ffae..3d95bfa5aca2 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
@@ -688,12 +688,11 @@ static void get_surf_rq_param(struct display_mode_lib *mode_lib,
const display_pipe_source_params_st *pipe_src_param,
bool is_chroma)
{
- bool mode_422 = false;
unsigned int vp_width = 0;
unsigned int vp_height = 0;
unsigned int data_pitch = 0;
unsigned int meta_pitch = 0;
- unsigned int ppe = mode_422 ? 2 : 1;
+ unsigned int ppe = 1;
// TODO check if ppe apply for both luma and chroma in 422 case
if (is_chroma) {
@@ -825,7 +824,6 @@ static void dml20v2_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib,
double min_dst_y_ttu_vblank;
unsigned int dlg_vblank_start;
bool dual_plane;
- bool mode_422;
unsigned int access_dir;
unsigned int vp_height_l;
unsigned int vp_width_l;
@@ -972,7 +970,6 @@ static void dml20v2_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib,
// Source
// dcc_en = src.dcc;
dual_plane = is_dual_plane((enum source_format_class)(src->source_format));
- mode_422 = false; // TODO
access_dir = (src->source_scan == dm_vert); // vp access direction: horizontal or vertical accessed
// bytes_per_element_l = get_bytes_per_element(source_format_class(src.source_format), 0);
// bytes_per_element_c = get_bytes_per_element(source_format_class(src.source_format), 1);
@@ -1149,18 +1146,8 @@ static void dml20v2_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib,
dpte_row_height_l = rq_dlg_param->rq_l.dpte_row_height;
dpte_row_height_c = rq_dlg_param->rq_c.dpte_row_height;
- if (mode_422) {
- swath_width_pixels_ub_l = swath_width_ub_l * 2; // *2 for 2 pixel per element
- swath_width_pixels_ub_c = swath_width_ub_c * 2;
- } else {
- swath_width_pixels_ub_l = swath_width_ub_l * 1;
- swath_width_pixels_ub_c = swath_width_ub_c * 1;
- }
-
- hscale_pixel_rate_l = 0.;
- hscale_pixel_rate_c = 0.;
- min_hratio_fact_l = 1.0;
- min_hratio_fact_c = 1.0;
+ swath_width_pixels_ub_l = swath_width_ub_l;
+ swath_width_pixels_ub_c = swath_width_ub_c;
if (htaps_l <= 1)
min_hratio_fact_l = 2.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 57cf0358cc43..eb3ed965e48b 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
@@ -1399,7 +1399,7 @@ static unsigned int CalculateVMAndRowBytes(
if (ScanDirection == dm_horz)
FractionOfPTEReturnDrop = 0;
else
- FractionOfPTEReturnDrop = 7 / 8;
+ FractionOfPTEReturnDrop = 7.0 / 8;
} else if (VMMPageSize == 4096 && MacroTileSizeBytes > 4096) {
PixelPTEReqHeightPTEs = 16;
*PixelPTEReqHeight = 16 * BlockHeight256Bytes;
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 618f4b682ab1..98502a4f0567 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
@@ -297,9 +297,6 @@ static void handle_det_buf_split(
if (swath_height_c > 0)
log2_swath_height_c = dml_log2(swath_height_c);
-
- if (req128_c && log2_swath_height_c > 0)
- log2_swath_height_c -= 1;
}
rq_param->dlg.rq_l.swath_height = 1 << log2_swath_height_l;
@@ -697,12 +694,11 @@ static void get_surf_rq_param(
const display_pipe_params_st *pipe_param,
bool is_chroma)
{
- bool mode_422 = false;
unsigned int vp_width = 0;
unsigned int vp_height = 0;
unsigned int data_pitch = 0;
unsigned int meta_pitch = 0;
- unsigned int ppe = mode_422 ? 2 : 1;
+ unsigned int ppe = 1;
// FIXME check if ppe apply for both luma and chroma in 422 case
if (is_chroma) {
@@ -871,7 +867,6 @@ static void dml_rq_dlg_get_dlg_params(
double min_dst_y_ttu_vblank;
unsigned int dlg_vblank_start;
bool dual_plane;
- bool mode_422;
unsigned int access_dir;
unsigned int vp_height_l;
unsigned int vp_width_l;
@@ -1023,7 +1018,6 @@ static void dml_rq_dlg_get_dlg_params(
// Source
// dcc_en = src.dcc;
dual_plane = is_dual_plane((enum source_format_class) (src->source_format));
- mode_422 = false; // FIXME
access_dir = (src->source_scan == dm_vert); // vp access direction: horizontal or vertical accessed
// bytes_per_element_l = get_bytes_per_element(source_format_class(src.source_format), 0);
// bytes_per_element_c = get_bytes_per_element(source_format_class(src.source_format), 1);
@@ -1200,18 +1194,8 @@ static void dml_rq_dlg_get_dlg_params(
dpte_row_height_l = rq_dlg_param->rq_l.dpte_row_height;
dpte_row_height_c = rq_dlg_param->rq_c.dpte_row_height;
- if (mode_422) {
- swath_width_pixels_ub_l = swath_width_ub_l * 2; // *2 for 2 pixel per element
- swath_width_pixels_ub_c = swath_width_ub_c * 2;
- } else {
- swath_width_pixels_ub_l = swath_width_ub_l * 1;
- swath_width_pixels_ub_c = swath_width_ub_c * 1;
- }
-
- hscale_pixel_rate_l = 0.;
- hscale_pixel_rate_c = 0.;
- min_hratio_fact_l = 1.0;
- min_hratio_fact_c = 1.0;
+ swath_width_pixels_ub_l = swath_width_ub_l;
+ swath_width_pixels_ub_c = swath_width_ub_c;
if (hratio_l <= 1)
min_hratio_fact_l = 2.0;
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 e0b52db2c210..1c10ba4dcdde 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
@@ -1783,7 +1783,7 @@ static unsigned int CalculateVMAndRowBytes(
if (ScanDirection != dm_vert)
FractionOfPTEReturnDrop = 0;
else
- FractionOfPTEReturnDrop = 7 / 8;
+ FractionOfPTEReturnDrop = 7.0 / 8;
} else if (GPUVMMinPageSize == 4 && MacroTileSizeBytes > 4096) {
PixelPTEReqHeightPTEs = 16;
*PixelPTEReqHeight = 16 * BlockHeight256Bytes;
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 0497a5d74a62..b28fcc8608ff 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
@@ -660,13 +660,12 @@ static void get_surf_rq_param(struct display_mode_lib *mode_lib,
bool is_chroma,
bool is_alpha)
{
- bool mode_422 = 0;
unsigned int vp_width = 0;
unsigned int vp_height = 0;
unsigned int data_pitch = 0;
unsigned int meta_pitch = 0;
unsigned int surface_height = 0;
- unsigned int ppe = mode_422 ? 2 : 1;
+ unsigned int ppe = 1;
// FIXME check if ppe apply for both luma and chroma in 422 case
if (is_chroma | is_alpha) {
@@ -934,7 +933,6 @@ static void dml_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib,
double min_dst_y_ttu_vblank = 0;
unsigned int dlg_vblank_start = 0;
bool dual_plane = false;
- bool mode_422 = false;
unsigned int access_dir = 0;
unsigned int vp_height_l = 0;
unsigned int vp_width_l = 0;
@@ -1083,7 +1081,6 @@ static void dml_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib,
// Source
// dcc_en = src.dcc;
dual_plane = is_dual_plane((enum source_format_class)(src->source_format));
- mode_422 = false; // TODO
access_dir = (src->source_scan == dm_vert); // vp access direction: horizontal or vertical accessed
vp_height_l = src->viewport_height;
vp_width_l = src->viewport_width;
@@ -1301,18 +1298,8 @@ static void dml_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib,
dpte_row_height_l = rq_dlg_param.rq_l.dpte_row_height;
dpte_row_height_c = rq_dlg_param.rq_c.dpte_row_height;
- if (mode_422) {
- swath_width_pixels_ub_l = swath_width_ub_l * 2; // *2 for 2 pixel per element
- swath_width_pixels_ub_c = swath_width_ub_c * 2;
- } else {
- swath_width_pixels_ub_l = swath_width_ub_l * 1;
- swath_width_pixels_ub_c = swath_width_ub_c * 1;
- }
-
- hscale_pixel_rate_l = 0.;
- hscale_pixel_rate_c = 0.;
- min_hratio_fact_l = 1.0;
- min_hratio_fact_c = 1.0;
+ swath_width_pixels_ub_l = swath_width_ub_l;
+ swath_width_pixels_ub_c = swath_width_ub_c;
if (hratio_l <= 1)
min_hratio_fact_l = 2.0;
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 33cf824c5da1..0b132ce1d2cd 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
@@ -1932,7 +1932,7 @@ static unsigned int CalculateVMAndRowBytes(
if (ScanDirection != dm_vert)
FractionOfPTEReturnDrop = 0;
else
- FractionOfPTEReturnDrop = 7 / 8;
+ FractionOfPTEReturnDrop = 7.0 / 8;
} else if (GPUVMMinPageSize == 4 && MacroTileSizeBytes > 4096) {
PixelPTEReqHeightPTEs = 16;
*PixelPTEReqHeight = 16 * BlockHeight256Bytes;
@@ -3617,7 +3617,7 @@ static double TruncToValidBPP(
NonDSCBPP1 = 15;
NonDSCBPP2 = 18;
MinDSCBPP = 6;
- MaxDSCBPP = 1.5 * DSCInputBitPerComponent - 1 / 16;
+ MaxDSCBPP = 1.5 * DSCInputBitPerComponent - 1.0 / 16;
} else if (Format == dm_444) {
NonDSCBPP0 = 24;
NonDSCBPP1 = 30;
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 4113ce79c4af..b57b095cd4a8 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
@@ -655,13 +655,12 @@ static void get_surf_rq_param(
bool is_chroma,
bool is_alpha)
{
- bool mode_422 = 0;
unsigned int vp_width = 0;
unsigned int vp_height = 0;
unsigned int data_pitch = 0;
unsigned int meta_pitch = 0;
unsigned int surface_height = 0;
- unsigned int ppe = mode_422 ? 2 : 1;
+ unsigned int ppe = 1;
// FIXME check if ppe apply for both luma and chroma in 422 case
if (is_chroma | is_alpha) {
@@ -888,7 +887,6 @@ static void dml_rq_dlg_get_dlg_params(
double min_ttu_vblank;
unsigned int dlg_vblank_start;
bool dual_plane;
- bool mode_422;
unsigned int access_dir;
unsigned int vp_height_l;
unsigned int vp_width_l;
@@ -1004,7 +1002,6 @@ static void dml_rq_dlg_get_dlg_params(
// Prefetch Calc
// Source
dual_plane = is_dual_plane((enum source_format_class) (src->source_format));
- mode_422 = 0;
access_dir = (src->source_scan == dm_vert); // vp access direction: horizontal or vertical accessed
vp_height_l = src->viewport_height;
vp_width_l = src->viewport_width;
@@ -1142,18 +1139,8 @@ static void dml_rq_dlg_get_dlg_params(
dpte_row_height_l = rq_dlg_param->rq_l.dpte_row_height;
dpte_row_height_c = rq_dlg_param->rq_c.dpte_row_height;
- if (mode_422) {
- swath_width_pixels_ub_l = swath_width_ub_l * 2; // *2 for 2 pixel per element
- swath_width_pixels_ub_c = swath_width_ub_c * 2;
- } else {
- swath_width_pixels_ub_l = swath_width_ub_l * 1;
- swath_width_pixels_ub_c = swath_width_ub_c * 1;
- }
-
- hscale_pixel_rate_l = 0.;
- hscale_pixel_rate_c = 0.;
- min_hratio_fact_l = 1.0;
- min_hratio_fact_c = 1.0;
+ swath_width_pixels_ub_l = swath_width_ub_l;
+ swath_width_pixels_ub_c = swath_width_ub_c;
if (hratio_l <= 1)
min_hratio_fact_l = 2.0;
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 f52b9e3d2bee..debfa31583a6 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
@@ -1941,15 +1941,6 @@ static unsigned int CalculateVMAndRowBytes(
*PixelPTEReqWidth = 32768.0 / BytePerPixel;
*PTERequestSize = 64;
FractionOfPTEReturnDrop = 0;
- } else if (MacroTileSizeBytes == 4096) {
- PixelPTEReqHeightPTEs = 1;
- *PixelPTEReqHeight = MacroTileHeight;
- *PixelPTEReqWidth = 8 * *MacroTileWidth;
- *PTERequestSize = 64;
- if (ScanDirection != dm_vert)
- FractionOfPTEReturnDrop = 0;
- else
- FractionOfPTEReturnDrop = 7 / 8;
} else if (GPUVMMinPageSize == 4 && MacroTileSizeBytes > 4096) {
PixelPTEReqHeightPTEs = 16;
*PixelPTEReqHeight = 16 * BlockHeight256Bytes;
@@ -3723,7 +3714,7 @@ static double TruncToValidBPP(
NonDSCBPP1 = 15;
NonDSCBPP2 = 18;
MinDSCBPP = 6;
- MaxDSCBPP = 1.5 * DSCInputBitPerComponent - 1 / 16;
+ MaxDSCBPP = 1.5 * DSCInputBitPerComponent - 1.0 / 16;
} else if (Format == dm_444) {
NonDSCBPP0 = 24;
NonDSCBPP1 = 30;
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 b3e8dc08030c..61b3bebf24c9 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
@@ -743,13 +743,12 @@ static void get_surf_rq_param(
bool is_chroma,
bool is_alpha)
{
- bool mode_422 = 0;
unsigned int vp_width = 0;
unsigned int vp_height = 0;
unsigned int data_pitch = 0;
unsigned int meta_pitch = 0;
unsigned int surface_height = 0;
- unsigned int ppe = mode_422 ? 2 : 1;
+ unsigned int ppe = 1;
// FIXME check if ppe apply for both luma and chroma in 422 case
if (is_chroma | is_alpha) {
@@ -973,7 +972,6 @@ static void dml_rq_dlg_get_dlg_params(
double min_ttu_vblank;
unsigned int dlg_vblank_start;
bool dual_plane;
- bool mode_422;
unsigned int access_dir;
unsigned int vp_height_l;
unsigned int vp_width_l;
@@ -1091,7 +1089,6 @@ static void dml_rq_dlg_get_dlg_params(
// Prefetch Calc
// Source
dual_plane = is_dual_plane((enum source_format_class) (src->source_format));
- mode_422 = 0;
access_dir = (src->source_scan == dm_vert); // vp access direction: horizontal or vertical accessed
vp_height_l = src->viewport_height;
vp_width_l = src->viewport_width;
@@ -1230,18 +1227,8 @@ static void dml_rq_dlg_get_dlg_params(
dpte_row_height_l = rq_dlg_param->rq_l.dpte_row_height;
dpte_row_height_c = rq_dlg_param->rq_c.dpte_row_height;
- if (mode_422) {
- swath_width_pixels_ub_l = swath_width_ub_l * 2; // *2 for 2 pixel per element
- swath_width_pixels_ub_c = swath_width_ub_c * 2;
- } else {
- swath_width_pixels_ub_l = swath_width_ub_l * 1;
- swath_width_pixels_ub_c = swath_width_ub_c * 1;
- }
-
- hscale_pixel_rate_l = 0.;
- hscale_pixel_rate_c = 0.;
- min_hratio_fact_l = 1.0;
- min_hratio_fact_c = 1.0;
+ swath_width_pixels_ub_l = swath_width_ub_l;
+ swath_width_pixels_ub_c = swath_width_ub_c;
if (hratio_l <= 1)
min_hratio_fact_l = 2.0;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
index 194422dd979d..9d399c4ce957 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
@@ -738,9 +738,9 @@ static bool subvp_subvp_schedulable(struct dc *dc, struct dc_state *context)
/* Loop to calculate the maximum microschedule time between the two SubVP pipes,
* and also to store the two main SubVP pipe pointers in subvp_pipes[2].
*/
- if (pipe->stream && pipe->plane_state && !pipe->top_pipe &&
+ phantom = dc_state_get_paired_subvp_stream(context, pipe->stream);
+ if (phantom && pipe->stream && pipe->plane_state && !pipe->top_pipe &&
dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_MAIN) {
- phantom = dc_state_get_paired_subvp_stream(context, pipe->stream);
microschedule_lines = (phantom->timing.v_total - phantom->timing.v_front_porch) +
phantom->timing.v_addressable;
@@ -845,8 +845,8 @@ static bool subvp_drr_schedulable(struct dc *dc, struct dc_state *context)
}
}
- if (subvp_found && drr_found) {
- phantom_stream = dc_state_get_paired_subvp_stream(context, pipe->stream);
+ phantom_stream = dc_state_get_paired_subvp_stream(context, pipe->stream);
+ if (phantom_stream && subvp_found && drr_found) {
main_timing = &pipe->stream->timing;
phantom_timing = &phantom_stream->timing;
drr_timing = &drr_pipe->stream->timing;
@@ -997,7 +997,7 @@ static bool subvp_subvp_admissable(struct dc *dc,
if (pipe->plane_state && !pipe->top_pipe &&
dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_MAIN) {
refresh_rate = (pipe->stream->timing.pix_clk_100hz * (uint64_t)100 +
- pipe->stream->timing.v_total * pipe->stream->timing.h_total - (uint64_t)1);
+ pipe->stream->timing.v_total * (uint64_t)pipe->stream->timing.h_total - (uint64_t)1);
refresh_rate = div_u64(refresh_rate, pipe->stream->timing.v_total);
refresh_rate = div_u64(refresh_rate, pipe->stream->timing.h_total);
@@ -1177,6 +1177,9 @@ static void init_pipe_slice_table_from_context(
stream = context->streams[i];
otg_master = resource_get_otg_master_for_stream(
&context->res_ctx, stream);
+ if (!otg_master)
+ continue;
+
count = resource_get_odm_slice_count(otg_master);
update_slice_table_for_stream(table, stream, count);
@@ -2154,6 +2157,8 @@ bool dcn32_internal_validate_bw(struct dc *dc,
dc->res_pool->funcs->update_soc_for_wm_a(dc, context);
+ for (i = 0; i < context->stream_count; i++)
+ resource_update_pipes_for_stream_with_slice_count(context, dc->current_state, dc->res_pool, context->streams[i], 1);
pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate);
if (!pipe_cnt) {
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c
index 6c84b0fa40f4..0782a34689a0 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c
@@ -3364,6 +3364,9 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
&mode_lib->vba.UrgentBurstFactorLumaPre[k],
&mode_lib->vba.UrgentBurstFactorChromaPre[k],
&mode_lib->vba.NotUrgentLatencyHidingPre[k]);
+
+ v->cursor_bw_pre[k] = mode_lib->vba.NumberOfCursors[k] * mode_lib->vba.CursorWidth[k][0] * mode_lib->vba.CursorBPP[k][0] /
+ 8.0 / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) * v->VRatioPreY[i][j][k];
}
{
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 ba1310c8fd77..d92fb428ee96 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
@@ -1401,13 +1401,13 @@ void dml32_CalculateOutputLink(
if (Output == dm_dp2p0) {
*OutBpp = 0;
if ((OutputLinkDPRate == dm_dp_rate_na || OutputLinkDPRate == dm_dp_rate_uhbr10) &&
- PHYCLKD32PerState >= 10000 / 32) {
+ PHYCLKD32PerState >= 10000.0 / 32) {
*OutBpp = dml32_TruncToValidBPP((1 - Downspreading / 100) * 10000,
OutputLinkDPLanes, HTotal, HActive, PixelClockBackEnd,
ForcedOutputLinkBPP, LinkDSCEnable, Output, OutputFormat,
DSCInputBitPerComponent, NumberOfDSCSlices, AudioSampleRate,
AudioSampleLayout, ODMModeNoDSC, ODMModeDSC, RequiredSlots);
- if (*OutBpp == 0 && PHYCLKD32PerState < 13500 / 32 && DSCEnable == true &&
+ if (*OutBpp == 0 && PHYCLKD32PerState < 13500.0 / 32 && DSCEnable == true &&
ForcedOutputLinkBPP == 0) {
*RequiresDSC = true;
LinkDSCEnable = true;
@@ -1423,7 +1423,7 @@ void dml32_CalculateOutputLink(
*OutputRate = dm_output_rate_dp_rate_uhbr10;
}
if ((OutputLinkDPRate == dm_dp_rate_na || OutputLinkDPRate == dm_dp_rate_uhbr13p5) &&
- *OutBpp == 0 && PHYCLKD32PerState >= 13500 / 32) {
+ *OutBpp == 0 && PHYCLKD32PerState >= 13500.0 / 32) {
*OutBpp = dml32_TruncToValidBPP((1 - Downspreading / 100) * 13500,
OutputLinkDPLanes, HTotal, HActive, PixelClockBackEnd,
ForcedOutputLinkBPP, LinkDSCEnable, Output, OutputFormat,
@@ -1601,7 +1601,7 @@ double dml32_TruncToValidBPP(
NonDSCBPP1 = 15;
NonDSCBPP2 = 18;
MinDSCBPP = 6;
- MaxDSCBPP = 1.5 * DSCInputBitPerComponent - 1 / 16;
+ MaxDSCBPP = 1.5 * DSCInputBitPerComponent - 1.0 / 16;
} else if (Format == dm_444) {
NonDSCBPP0 = 24;
NonDSCBPP1 = 30;
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 60f251cf973b..beed7adbbd43 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
@@ -177,7 +177,7 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_5_soc = {
.urgent_latency_pixel_data_only_us = 4.0,
.urgent_latency_pixel_mixed_with_vm_data_us = 4.0,
.urgent_latency_vm_data_only_us = 4.0,
- .dram_clock_change_latency_us = 11.72,
+ .dram_clock_change_latency_us = 34.0,
.urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096,
.urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096,
.urgent_out_of_order_return_per_channel_vm_only_bytes = 4096,
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 e4f333d4fb54..a201dbb743d7 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
@@ -215,7 +215,7 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_51_soc = {
.urgent_latency_pixel_data_only_us = 4.0,
.urgent_latency_pixel_mixed_with_vm_data_us = 4.0,
.urgent_latency_vm_data_only_us = 4.0,
- .dram_clock_change_latency_us = 11.72,
+ .dram_clock_change_latency_us = 34,
.urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096,
.urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096,
.urgent_out_of_order_return_per_channel_vm_only_bytes = 4096,
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 3df559c591f8..dae13f202220 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
@@ -1596,11 +1596,6 @@ void dml1_rq_dlg_get_dlg_params(
swath_width_pixels_ub_c = swath_width_ub_c * 1;
}
- hscale_pixel_rate_l = 0.;
- hscale_pixel_rate_c = 0.;
- min_hratio_fact_l = 1.0;
- min_hratio_fact_c = 1.0;
-
if (htaps_l <= 1)
min_hratio_fact_l = 2.0;
else if (htaps_l <= 6) {
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/display_mode_core.c b/drivers/gpu/drm/amd/display/dc/dml2/display_mode_core.c
index ff2adc9eab0d..547dfcc80fde 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/display_mode_core.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2/display_mode_core.c
@@ -115,6 +115,7 @@ static void CalculateODMMode(
dml_float_t DISPCLKDPPCLKDSCCLKDownSpreading,
dml_float_t DISPCLKRampingMargin,
dml_float_t DISPCLKDPPCLKVCOSpeed,
+ dml_uint_t NumberOfDSCSlices,
// Output
dml_bool_t *TotalAvailablePipesSupport,
@@ -2732,7 +2733,7 @@ static dml_float_t TruncToValidBPP(
NonDSCBPP1 = 15;
NonDSCBPP2 = 18;
MinDSCBPP = 6;
- MaxDSCBPP = 1.5 * DSCInputBitPerComponent - 1 / 16;
+ MaxDSCBPP = 1.5 * DSCInputBitPerComponent - 1.0 / 16;
} else if (Format == dml_444) {
NonDSCBPP0 = 24;
NonDSCBPP1 = 30;
@@ -4282,7 +4283,7 @@ static void CalculateSwathAndDETConfiguration(struct display_mode_lib_scratch_st
}
*p->compbuf_reserved_space_64b = 2 * p->PixelChunkSizeInKByte * 1024 / 64;
- if (p->UnboundedRequestEnabled) {
+ if (*p->UnboundedRequestEnabled) {
*p->compbuf_reserved_space_64b = dml_max(*p->compbuf_reserved_space_64b,
(dml_float_t)(p->ROBBufferSizeInKByte * 1024/64)
- (dml_float_t)(RoundedUpSwathSizeBytesY[SurfaceDoingUnboundedRequest] * TTUFIFODEPTH / MAXIMUMCOMPRESSION/64));
@@ -5403,10 +5404,10 @@ static void CalculateOutputLink(
}
if (Output == dml_dp2p0) {
*OutBpp = 0;
- if ((OutputLinkDPRate == dml_dp_rate_na || OutputLinkDPRate == dml_dp_rate_uhbr10) && PHYCLKD32PerState >= 10000 / 32) {
+ if ((OutputLinkDPRate == dml_dp_rate_na || OutputLinkDPRate == dml_dp_rate_uhbr10) && PHYCLKD32PerState >= 10000 / 32.0) {
*OutBpp = TruncToValidBPP((1 - Downspreading / 100) * 10000, OutputLinkDPLanes, HTotal, HActive, PixelClockBackEnd, ForcedOutputLinkBPP, LinkDSCEnable, Output,
OutputFormat, DSCInputBitPerComponent, NumberOfDSCSlices, (dml_uint_t)AudioSampleRate, AudioSampleLayout, ODMModeNoDSC, ODMModeDSC, RequiredSlots);
- if (*OutBpp == 0 && PHYCLKD32PerState < 13500 / 32 && DSCEnable == dml_dsc_enable_if_necessary && ForcedOutputLinkBPP == 0) {
+ if (*OutBpp == 0 && PHYCLKD32PerState < 13500 / 32.0 && DSCEnable == dml_dsc_enable_if_necessary && ForcedOutputLinkBPP == 0) {
*RequiresDSC = true;
LinkDSCEnable = true;
*OutBpp = TruncToValidBPP((1 - Downspreading / 100) * 10000, OutputLinkDPLanes, HTotal, HActive, PixelClockBackEnd, ForcedOutputLinkBPP, LinkDSCEnable, Output,
@@ -5416,7 +5417,7 @@ static void CalculateOutputLink(
*OutputType = dml_output_type_dp2p0;
*OutputRate = dml_output_rate_dp_rate_uhbr10;
}
- if ((OutputLinkDPRate == dml_dp_rate_na || OutputLinkDPRate == dml_dp_rate_uhbr13p5) && *OutBpp == 0 && PHYCLKD32PerState >= 13500 / 32) {
+ if ((OutputLinkDPRate == dml_dp_rate_na || OutputLinkDPRate == dml_dp_rate_uhbr13p5) && *OutBpp == 0 && PHYCLKD32PerState >= 13500 / 32.0) {
*OutBpp = TruncToValidBPP((1 - Downspreading / 100) * 13500, OutputLinkDPLanes, HTotal, HActive, PixelClockBackEnd, ForcedOutputLinkBPP, LinkDSCEnable, Output,
OutputFormat, DSCInputBitPerComponent, NumberOfDSCSlices, (dml_uint_t)AudioSampleRate, AudioSampleLayout, ODMModeNoDSC, ODMModeDSC, RequiredSlots);
@@ -5516,6 +5517,7 @@ static void CalculateODMMode(
dml_float_t DISPCLKDPPCLKDSCCLKDownSpreading,
dml_float_t DISPCLKRampingMargin,
dml_float_t DISPCLKDPPCLKVCOSpeed,
+ dml_uint_t NumberOfDSCSlices,
// Output
dml_bool_t *TotalAvailablePipesSupport,
@@ -5563,7 +5565,7 @@ static void CalculateODMMode(
*NumberOfDPP = 0;
if (!(Output == dml_hdmi || Output == dml_dp || Output == dml_edp) && (ODMUse == dml_odm_use_policy_combine_4to1 || (ODMUse == dml_odm_use_policy_combine_as_needed &&
- (SurfaceRequiredDISPCLKWithODMCombineTwoToOne > StateDispclk || (DSCEnable && (HActive > 2 * MaximumPixelsPerLinePerDSCUnit)))))) {
+ (SurfaceRequiredDISPCLKWithODMCombineTwoToOne > StateDispclk || (DSCEnable && (HActive > 2 * MaximumPixelsPerLinePerDSCUnit)) || NumberOfDSCSlices > 8)))) {
if (TotalNumberOfActiveDPP + 4 <= MaxNumDPP) {
*ODMMode = dml_odm_mode_combine_4to1;
*RequiredDISPCLKPerSurface = SurfaceRequiredDISPCLKWithODMCombineFourToOne;
@@ -5573,7 +5575,7 @@ static void CalculateODMMode(
}
} else if (Output != dml_hdmi && (ODMUse == dml_odm_use_policy_combine_2to1 || (ODMUse == dml_odm_use_policy_combine_as_needed &&
((SurfaceRequiredDISPCLKWithoutODMCombine > StateDispclk && SurfaceRequiredDISPCLKWithODMCombineTwoToOne <= StateDispclk) ||
- (DSCEnable && (HActive > MaximumPixelsPerLinePerDSCUnit)))))) {
+ (DSCEnable && (HActive > MaximumPixelsPerLinePerDSCUnit)) || (NumberOfDSCSlices <= 8 && NumberOfDSCSlices > 4))))) {
if (TotalNumberOfActiveDPP + 2 <= MaxNumDPP) {
*ODMMode = dml_odm_mode_combine_2to1;
*RequiredDISPCLKPerSurface = SurfaceRequiredDISPCLKWithODMCombineTwoToOne;
@@ -5880,11 +5882,11 @@ static dml_uint_t DSCDelayRequirement(
if (DSCEnabled == true && OutputBpp != 0) {
if (ODMMode == dml_odm_mode_combine_4to1) {
- DSCDelayRequirement_val = 4 * (dscceComputeDelay(DSCInputBitPerComponent, OutputBpp, (dml_uint_t)(dml_ceil((dml_float_t) HActive / (dml_float_t) NumberOfDSCSlices, 1.0)),
- (dml_uint_t) (NumberOfDSCSlices / 4.0), OutputFormat, Output) + dscComputeDelay(OutputFormat, Output));
+ DSCDelayRequirement_val = dscceComputeDelay(DSCInputBitPerComponent, OutputBpp, (dml_uint_t)(dml_ceil((dml_float_t) HActive / (dml_float_t) NumberOfDSCSlices, 1.0)),
+ (dml_uint_t) (NumberOfDSCSlices / 4.0), OutputFormat, Output) + dscComputeDelay(OutputFormat, Output);
} else if (ODMMode == dml_odm_mode_combine_2to1) {
- DSCDelayRequirement_val = 2 * (dscceComputeDelay(DSCInputBitPerComponent, OutputBpp, (dml_uint_t)(dml_ceil((dml_float_t) HActive / (dml_float_t) NumberOfDSCSlices, 1.0)),
- (dml_uint_t) (NumberOfDSCSlices / 2.0), OutputFormat, Output) + dscComputeDelay(OutputFormat, Output));
+ DSCDelayRequirement_val = dscceComputeDelay(DSCInputBitPerComponent, OutputBpp, (dml_uint_t)(dml_ceil((dml_float_t) HActive / (dml_float_t) NumberOfDSCSlices, 1.0)),
+ (dml_uint_t) (NumberOfDSCSlices / 2.0), OutputFormat, Output) + dscComputeDelay(OutputFormat, Output);
} else {
DSCDelayRequirement_val = dscceComputeDelay(DSCInputBitPerComponent, OutputBpp, (dml_uint_t)((dml_float_t) dml_ceil(HActive / (dml_float_t) NumberOfDSCSlices, 1.0)),
NumberOfDSCSlices, OutputFormat, Output) + dscComputeDelay(OutputFormat, Output);
@@ -6938,20 +6940,25 @@ dml_bool_t dml_core_mode_support(struct display_mode_lib_st *mode_lib)
/*Number Of DSC Slices*/
for (k = 0; k < mode_lib->ms.num_active_planes; ++k) {
- if (mode_lib->ms.cache_display_cfg.plane.BlendingAndTiming[k] == k) {
- if (mode_lib->ms.cache_display_cfg.output.PixelClockBackEnd[k] > 4800) {
- mode_lib->ms.support.NumberOfDSCSlices[k] = (dml_uint_t)(dml_ceil(mode_lib->ms.cache_display_cfg.output.PixelClockBackEnd[k] / 600, 4));
- } else if (mode_lib->ms.cache_display_cfg.output.PixelClockBackEnd[k] > 2400) {
- mode_lib->ms.support.NumberOfDSCSlices[k] = 8;
- } else if (mode_lib->ms.cache_display_cfg.output.PixelClockBackEnd[k] > 1200) {
- mode_lib->ms.support.NumberOfDSCSlices[k] = 4;
- } else if (mode_lib->ms.cache_display_cfg.output.PixelClockBackEnd[k] > 340) {
- mode_lib->ms.support.NumberOfDSCSlices[k] = 2;
- } else {
- mode_lib->ms.support.NumberOfDSCSlices[k] = 1;
+ if (mode_lib->ms.cache_display_cfg.plane.BlendingAndTiming[k] == k &&
+ mode_lib->ms.cache_display_cfg.output.DSCEnable[k] != dml_dsc_disable) {
+ mode_lib->ms.support.NumberOfDSCSlices[k] = mode_lib->ms.cache_display_cfg.output.DSCSlices[k];
+
+ if (mode_lib->ms.support.NumberOfDSCSlices[k] == 0) {
+ if (mode_lib->ms.cache_display_cfg.output.PixelClockBackEnd[k] > 4800) {
+ mode_lib->ms.support.NumberOfDSCSlices[k] = (dml_uint_t)(dml_ceil(mode_lib->ms.cache_display_cfg.output.PixelClockBackEnd[k] / 600, 4));
+ } else if (mode_lib->ms.cache_display_cfg.output.PixelClockBackEnd[k] > 2400) {
+ mode_lib->ms.support.NumberOfDSCSlices[k] = 8;
+ } else if (mode_lib->ms.cache_display_cfg.output.PixelClockBackEnd[k] > 1200) {
+ mode_lib->ms.support.NumberOfDSCSlices[k] = 4;
+ } else if (mode_lib->ms.cache_display_cfg.output.PixelClockBackEnd[k] > 340) {
+ mode_lib->ms.support.NumberOfDSCSlices[k] = 2;
+ } else {
+ mode_lib->ms.support.NumberOfDSCSlices[k] = 1;
+ }
}
} else {
- mode_lib->ms.support.NumberOfDSCSlices[k] = 0;
+ mode_lib->ms.support.NumberOfDSCSlices[k] = 1;
}
}
@@ -7050,6 +7057,7 @@ dml_bool_t dml_core_mode_support(struct display_mode_lib_st *mode_lib)
mode_lib->ms.soc.dcn_downspread_percent,
mode_lib->ms.ip.dispclk_ramp_margin_percent,
mode_lib->ms.soc.dispclk_dppclk_vco_speed_mhz,
+ mode_lib->ms.support.NumberOfDSCSlices[k],
/* Output */
&s->TotalAvailablePipesSupportNoDSC,
@@ -7072,6 +7080,7 @@ dml_bool_t dml_core_mode_support(struct display_mode_lib_st *mode_lib)
mode_lib->ms.soc.dcn_downspread_percent,
mode_lib->ms.ip.dispclk_ramp_margin_percent,
mode_lib->ms.soc.dispclk_dppclk_vco_speed_mhz,
+ mode_lib->ms.support.NumberOfDSCSlices[k],
/* Output */
&s->TotalAvailablePipesSupportDSC,
@@ -9692,7 +9701,7 @@ void dml_core_mode_programming(struct display_mode_lib_st *mode_lib, const struc
+ dml_max(1.0, dml_ceil((dml_float_t) locals->WritebackDelay[k] / ((dml_float_t) mode_lib->ms.cache_display_cfg.timing.HTotal[k] / mode_lib->ms.cache_display_cfg.timing.PixelClock[k]), 1.0))
+ dml_floor(4.0 * locals->TSetup[k] / ((dml_float_t) mode_lib->ms.cache_display_cfg.timing.HTotal[k] / mode_lib->ms.cache_display_cfg.timing.PixelClock[k]), 1.0) / 4.0;
- if (((locals->VUpdateOffsetPix[k] + locals->VUpdateWidthPix[k] + locals->VReadyOffsetPix[k]) / mode_lib->ms.cache_display_cfg.timing.HTotal[k]) <=
+ if (((locals->VUpdateOffsetPix[k] + locals->VUpdateWidthPix[k] + locals->VReadyOffsetPix[k]) / (double) mode_lib->ms.cache_display_cfg.timing.HTotal[k]) <=
(isInterlaceTiming ?
dml_floor((mode_lib->ms.cache_display_cfg.timing.VTotal[k] - mode_lib->ms.cache_display_cfg.timing.VActive[k] - mode_lib->ms.cache_display_cfg.timing.VFrontPorch[k] - locals->VStartup[k]) / 2.0, 1.0) :
(int) (mode_lib->ms.cache_display_cfg.timing.VTotal[k] - mode_lib->ms.cache_display_cfg.timing.VActive[k] - mode_lib->ms.cache_display_cfg.timing.VFrontPorch[k] - locals->VStartup[k]))) {
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/display_mode_core_structs.h b/drivers/gpu/drm/amd/display/dc/dml2/display_mode_core_structs.h
index f595e48ae7b8..f951936bb579 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/display_mode_core_structs.h
+++ b/drivers/gpu/drm/amd/display/dc/dml2/display_mode_core_structs.h
@@ -575,6 +575,7 @@ struct dml_output_cfg_st {
dml_uint_t AudioSampleRate[__DML_NUM_PLANES__];
dml_uint_t AudioSampleLayout[__DML_NUM_PLANES__];
dml_bool_t OutputDisabled[__DML_NUM_PLANES__];
+ dml_uint_t DSCSlices[__DML_NUM_PLANES__];
}; // dml_timing_cfg_st;
/// @brief Writeback Setting
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c
index a7d02da16bb5..06387b8b0aee 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c
@@ -102,9 +102,7 @@ void dml21_apply_soc_bb_overrides(struct dml2_initialize_instance_in_out *dml_in
struct dml2_soc_state_table *dml_clk_table = &dml_soc_bb->clk_table;
/* override clocks if smu is present */
- if (in_dc->clk_mgr &&
- in_dc->clk_mgr->funcs->is_smu_present &&
- in_dc->clk_mgr->funcs->is_smu_present(in_dc->clk_mgr)) {
+ if (in_dc->clk_mgr->funcs->is_smu_present && in_dc->clk_mgr->funcs->is_smu_present(in_dc->clk_mgr)) {
/* dcfclk */
if (dc_clk_table->num_entries_per_clk.num_dcfclk_levels) {
dml_clk_table->dcfclk.num_clk_values = dc_clk_table->num_entries_per_clk.num_dcfclk_levels;
@@ -1002,7 +1000,7 @@ bool dml21_map_dc_state_into_dml_display_cfg(const struct dc *in_dc, struct dc_s
/* apply forced pstate policy */
if (dml_ctx->config.pmo.force_pstate_method_enable) {
dml_dispcfg->plane_descriptors[disp_cfg_plane_location].overrides.uclk_pstate_change_strategy =
- dml21_force_pstate_method_to_uclk_state_change_strategy(dml_ctx->config.pmo.force_pstate_method_value);
+ dml21_force_pstate_method_to_uclk_state_change_strategy(dml_ctx->config.pmo.force_pstate_method_values[stream_index]);
}
}
}
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_utils.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_utils.c
index 8c9e95b25eb3..d276458e50fd 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_utils.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_utils.c
@@ -85,8 +85,8 @@ void find_pipe_regs_idx(const struct dml2_context *dml_ctx,
int dml21_find_dc_pipes_for_plane(const struct dc *in_dc,
struct dc_state *context,
struct dml2_context *dml_ctx,
- struct pipe_ctx **dc_main_pipes,
- struct pipe_ctx **dc_phantom_pipes,
+ struct pipe_ctx *dc_main_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__],
+ struct pipe_ctx *dc_phantom_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__],
int dml_plane_idx)
{
unsigned int dml_stream_index;
@@ -100,11 +100,16 @@ int dml21_find_dc_pipes_for_plane(const struct dc *in_dc,
struct dc_plane_state *dc_phantom_plane;
int num_pipes = 0;
+ memset(dc_main_pipes, 0, sizeof(struct pipe_ctx *) * __DML2_WRAPPER_MAX_STREAMS_PLANES__);
+ memset(dc_phantom_pipes, 0, sizeof(struct pipe_ctx *) * __DML2_WRAPPER_MAX_STREAMS_PLANES__);
+
dml_stream_index = dml_ctx->v21.mode_programming.programming->plane_programming[dml_plane_idx].plane_descriptor->stream_index;
main_stream_id = dml_ctx->v21.dml_to_dc_pipe_mapping.dml_pipe_idx_to_stream_id[dml_stream_index];
dc_main_stream = dml_ctx->config.callbacks.get_stream_from_id(context, main_stream_id);
dc_main_stream_status = dml_ctx->config.callbacks.get_stream_status(context, dc_main_stream);
+ if (!dc_main_stream_status)
+ return num_pipes;
/* find main plane based on id */
dc_plane_index = dml21_get_dc_plane_idx_from_plane_id(dml_ctx->v21.dml_to_dc_pipe_mapping.dml_pipe_idx_to_plane_id[dml_plane_idx]);
@@ -115,7 +120,8 @@ int dml21_find_dc_pipes_for_plane(const struct dc *in_dc,
} else {
/* stream was configured with dummy plane, so get pipes from opp head */
struct pipe_ctx *otg_master_pipe = dml_ctx->config.callbacks.get_otg_master_for_stream(&context->res_ctx, dc_main_stream);
- num_pipes = dml_ctx->config.callbacks.get_opp_heads_for_otg_master(otg_master_pipe, &context->res_ctx, dc_main_pipes);
+ if (otg_master_pipe != NULL)
+ num_pipes = dml_ctx->config.callbacks.get_opp_heads_for_otg_master(otg_master_pipe, &context->res_ctx, dc_main_pipes);
}
/* if phantom exists, find associated pipes */
@@ -123,10 +129,15 @@ int dml21_find_dc_pipes_for_plane(const struct dc *in_dc,
if (dc_phantom_stream && num_pipes > 0) {
dc_phantom_stream_status = dml_ctx->config.callbacks.get_stream_status(context, dc_phantom_stream);
- /* phantom plane will have same index as main */
- dc_phantom_plane = dc_phantom_stream_status->plane_states[dc_plane_index];
+ if (dc_phantom_stream_status) {
+ /* phantom plane will have same index as main */
+ dc_phantom_plane = dc_phantom_stream_status->plane_states[dc_plane_index];
- dml_ctx->config.callbacks.get_dpp_pipes_for_plane(dc_phantom_plane, &context->res_ctx, dc_phantom_pipes);
+ if (dc_phantom_plane) {
+ /* only care about phantom pipes if they contain the phantom plane */
+ dml_ctx->config.callbacks.get_dpp_pipes_for_plane(dc_phantom_plane, &context->res_ctx, dc_phantom_pipes);
+ }
+ }
}
return num_pipes;
@@ -317,6 +328,8 @@ static struct dc_stream_state *dml21_add_phantom_stream(struct dml2_context *dml
struct dml2_stream_parameters *phantom_stream_descriptor = &stream_programming->phantom_stream.descriptor;
phantom_stream = dml_ctx->config.svp_pstate.callbacks.create_phantom_stream(dc, context, main_stream);
+ if (!phantom_stream)
+ return NULL;
/* copy details of phantom stream from main */
memcpy(&phantom_stream->timing, &main_stream->timing, sizeof(phantom_stream->timing));
@@ -352,6 +365,8 @@ static struct dc_plane_state *dml21_add_phantom_plane(struct dml2_context *dml_c
struct dc_plane_state *phantom_plane;
phantom_plane = dml_ctx->config.svp_pstate.callbacks.create_phantom_plane(dc, context, main_plane);
+ if (!phantom_plane)
+ return NULL;
phantom_plane->format = main_plane->format;
phantom_plane->rotation = main_plane->rotation;
@@ -401,7 +416,7 @@ void dml21_handle_phantom_streams_planes(const struct dc *dc, struct dc_state *c
main_stream_status = dml_ctx->config.callbacks.get_stream_status(context, main_stream);
- if (main_stream_status->plane_count == 0)
+ if (!main_stream_status || main_stream_status->plane_count == 0)
continue;
/* create phantom stream for subvp enabled stream */
@@ -411,6 +426,9 @@ void dml21_handle_phantom_streams_planes(const struct dc *dc, struct dc_state *c
main_stream,
&dml_ctx->v21.mode_programming.programming->stream_programming[dml_stream_index]);
+ if (!phantom_stream)
+ continue;
+
/* iterate through DML planes associated with this stream */
for (dml_plane_index = 0; dml_plane_index < dml_ctx->v21.mode_programming.programming->display_config.num_planes; dml_plane_index++) {
if (dml_ctx->v21.mode_programming.programming->plane_programming[dml_plane_index].plane_descriptor->stream_index == dml_stream_index) {
@@ -499,6 +517,9 @@ void dml21_build_fams2_programming(const struct dc *dc,
break;
case FAMS2_STREAM_TYPE_SUBVP:
phantom_stream = dml_ctx->config.svp_pstate.callbacks.get_paired_subvp_stream(context, stream);
+ if (!phantom_stream)
+ break;
+
phantom_status = dml_ctx->config.callbacks.get_stream_status(context, phantom_stream);
/* phantom status should always be present */
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_utils.h b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_utils.h
index 82080397a50e..d5153fbac921 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_utils.h
+++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_utils.h
@@ -33,8 +33,8 @@ void find_pipe_regs_idx(const struct dml2_context *dml_ctx,
int dml21_find_dc_pipes_for_plane(const struct dc *in_dc,
struct dc_state *context,
struct dml2_context *dml_ctx,
- struct pipe_ctx **dc_main_pipes,
- struct pipe_ctx **dc_phantom_pipes,
+ struct pipe_ctx *dc_main_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__],
+ struct pipe_ctx *dc_phantom_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__],
int dml_plane_idx);
void dml21_program_dc_pipe(struct dml2_context *dml_ctx,
struct dc_state *context,
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c
index 08f001cb61c5..41ecf00ed196 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c
@@ -47,7 +47,8 @@ static void dml21_apply_debug_options(const struct dc *in_dc, struct dml2_contex
/* UCLK P-State options */
if (in_dc->debug.dml21_force_pstate_method) {
dml_ctx->config.pmo.force_pstate_method_enable = true;
- dml_ctx->config.pmo.force_pstate_method_value = in_dc->debug.dml21_force_pstate_method_value;
+ 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;
}
@@ -156,7 +157,7 @@ static void dml21_calculate_rq_and_dlg_params(const struct dc *dc, struct dc_sta
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) {
+ 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);
}
}
@@ -196,9 +197,14 @@ static bool dml21_mode_check_and_programming(const struct dc *in_dc, struct dc_s
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 || context->stream_count == 0)
+ if (!context)
return true;
+ if (context->stream_count == 0) {
+ 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);
@@ -257,6 +263,7 @@ static bool dml21_check_mode_support(const struct dc *in_dc, struct dc_state *co
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;
@@ -278,7 +285,8 @@ bool dml21_validate(const struct dc *in_dc, struct dc_state *context, struct dml
void dml21_prepare_mcache_programming(struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx)
{
- unsigned int num_pipes, dml_prog_idx, dml_phantom_prog_idx, dc_pipe_index;
+ 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};
@@ -312,10 +320,8 @@ void dml21_prepare_mcache_programming(struct dc *in_dc, struct dc_state *context
}
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)
+ if (num_pipes <= 0 || dc_main_pipes[0]->stream == NULL ||
+ dc_main_pipes[0]->plane_state == NULL)
continue;
/* get config for each pipe */
@@ -325,7 +331,10 @@ void dml21_prepare_mcache_programming(struct dc *in_dc, struct dc_state *context
}
/* get config for each phantom pipe */
- if (pln_prog->phantom_plane.valid) {
+ 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;
@@ -351,10 +360,8 @@ void dml21_prepare_mcache_programming(struct dc *in_dc, struct dc_state *context
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)
+ if (num_pipes <= 0 || dc_main_pipes[0]->stream == NULL ||
+ dc_main_pipes[0]->plane_state == NULL)
continue;
/* get config for each pipe */
@@ -368,7 +375,10 @@ void dml21_prepare_mcache_programming(struct dc *in_dc, struct dc_state *context
}
/* get config for each phantom pipe */
- if (pln_prog->phantom_plane.valid) {
+ 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]) {
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4.c
index 4b8691c43523..04edcde423a9 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4.c
@@ -235,7 +235,6 @@ static void create_phantom_stream_from_main_stream(struct dml2_stream_parameters
phantom->timing.v_active = meta->v_active;
phantom->timing.v_front_porch = meta->v_front_porch;
phantom->timing.vblank_nom = phantom->timing.v_total - phantom->timing.v_active;
- phantom->timing.dsc.enable = dml2_dsc_disable;
phantom->timing.drr_config.enabled = false;
}
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c
index e7e6751f4477..6f4026e396e0 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c
@@ -4202,10 +4202,10 @@ static void CalculateOutputLink(
}
if (Output == dml2_dp2p0) {
*OutBpp = 0;
- if ((OutputLinkDPRate == dml2_dp_rate_na || OutputLinkDPRate == dml2_dp_rate_uhbr10) && PHYCLKD32 >= 10000 / 32) {
+ if ((OutputLinkDPRate == dml2_dp_rate_na || OutputLinkDPRate == dml2_dp_rate_uhbr10) && PHYCLKD32 >= 10000.0 / 32) {
*OutBpp = TruncToValidBPP(&s->TruncToValidBPP_locals, (1 - Downspreading / 100) * 10000, OutputLinkDPLanes, HTotal, HActive, PixelClockBackEnd, ForcedOutputLinkBPP, LinkDSCEnable, Output,
OutputFormat, DSCInputBitPerComponent, NumberOfDSCSlices, (unsigned int)AudioSampleRate, AudioSampleLayout, ODMModeNoDSC, ODMModeDSC, RequiredSlots);
- if (*OutBpp == 0 && PHYCLKD32 < 13500 / 32 && DSCEnable == dml2_dsc_enable_if_necessary && ForcedOutputLinkBPP == 0) {
+ if (*OutBpp == 0 && PHYCLKD32 < 13500.0 / 32 && DSCEnable == dml2_dsc_enable_if_necessary && ForcedOutputLinkBPP == 0) {
*RequiresDSC = true;
LinkDSCEnable = true;
*OutBpp = TruncToValidBPP(&s->TruncToValidBPP_locals, (1 - Downspreading / 100) * 10000, OutputLinkDPLanes, HTotal, HActive, PixelClockBackEnd, ForcedOutputLinkBPP, LinkDSCEnable, Output,
@@ -4215,11 +4215,11 @@ static void CalculateOutputLink(
*OutputType = dml2_core_internal_output_type_dp2p0;
*OutputRate = dml2_core_internal_output_rate_dp_rate_uhbr10;
}
- if ((OutputLinkDPRate == dml2_dp_rate_na || OutputLinkDPRate == dml2_dp_rate_uhbr13p5) && *OutBpp == 0 && PHYCLKD32 >= 13500 / 32) {
+ if ((OutputLinkDPRate == dml2_dp_rate_na || OutputLinkDPRate == dml2_dp_rate_uhbr13p5) && *OutBpp == 0 && PHYCLKD32 >= 13500.0 / 32) {
*OutBpp = TruncToValidBPP(&s->TruncToValidBPP_locals, (1 - Downspreading / 100) * 13500, OutputLinkDPLanes, HTotal, HActive, PixelClockBackEnd, ForcedOutputLinkBPP, LinkDSCEnable, Output,
OutputFormat, DSCInputBitPerComponent, NumberOfDSCSlices, (unsigned int)AudioSampleRate, AudioSampleLayout, ODMModeNoDSC, ODMModeDSC, RequiredSlots);
- if (*OutBpp == 0 && PHYCLKD32 < 20000 / 32 && DSCEnable == dml2_dsc_enable_if_necessary && ForcedOutputLinkBPP == 0) {
+ if (*OutBpp == 0 && PHYCLKD32 < 20000.0 / 32 && DSCEnable == dml2_dsc_enable_if_necessary && ForcedOutputLinkBPP == 0) {
*RequiresDSC = true;
LinkDSCEnable = true;
*OutBpp = TruncToValidBPP(&s->TruncToValidBPP_locals, (1 - Downspreading / 100) * 13500, OutputLinkDPLanes, HTotal, HActive, PixelClockBackEnd, ForcedOutputLinkBPP, LinkDSCEnable, Output,
@@ -4229,7 +4229,7 @@ static void CalculateOutputLink(
*OutputType = dml2_core_internal_output_type_dp2p0;
*OutputRate = dml2_core_internal_output_rate_dp_rate_uhbr13p5;
}
- if ((OutputLinkDPRate == dml2_dp_rate_na || OutputLinkDPRate == dml2_dp_rate_uhbr20) && *OutBpp == 0 && PHYCLKD32 >= 20000 / 32) {
+ if ((OutputLinkDPRate == dml2_dp_rate_na || OutputLinkDPRate == dml2_dp_rate_uhbr20) && *OutBpp == 0 && PHYCLKD32 >= 20000.0 / 32) {
*OutBpp = TruncToValidBPP(&s->TruncToValidBPP_locals, (1 - Downspreading / 100) * 20000, OutputLinkDPLanes, HTotal, HActive, PixelClockBackEnd, ForcedOutputLinkBPP, LinkDSCEnable, Output,
OutputFormat, DSCInputBitPerComponent, NumberOfDSCSlices, (unsigned int)AudioSampleRate, AudioSampleLayout, ODMModeNoDSC, ODMModeDSC, RequiredSlots);
if (*OutBpp == 0 && DSCEnable == dml2_dsc_enable_if_necessary && ForcedOutputLinkBPP == 0) {
@@ -4306,33 +4306,33 @@ static void CalculateOutputLink(
*RequiresFEC = false;
}
*OutBpp = 0;
- if (PHYCLKD18 >= 3000 / 18) {
+ if (PHYCLKD18 >= 3000.0 / 18) {
*OutBpp = TruncToValidBPP(&s->TruncToValidBPP_locals, 3000, 3, HTotal, HActive, PixelClockBackEnd, ForcedOutputLinkBPP, LinkDSCEnable, Output, OutputFormat, DSCInputBitPerComponent, NumberOfDSCSlices, (unsigned int)AudioSampleRate, AudioSampleLayout, ODMModeNoDSC, ODMModeDSC, &dummy);
//OutputTypeAndRate = Output & "3x3";
*OutputType = dml2_core_internal_output_type_hdmifrl;
*OutputRate = dml2_core_internal_output_rate_hdmi_rate_3x3;
}
- if (*OutBpp == 0 && PHYCLKD18 >= 6000 / 18) {
+ if (*OutBpp == 0 && PHYCLKD18 >= 6000.0 / 18) {
*OutBpp = TruncToValidBPP(&s->TruncToValidBPP_locals, 6000, 3, HTotal, HActive, PixelClockBackEnd, ForcedOutputLinkBPP, LinkDSCEnable, Output, OutputFormat, DSCInputBitPerComponent, NumberOfDSCSlices, (unsigned int)AudioSampleRate, AudioSampleLayout, ODMModeNoDSC, ODMModeDSC, &dummy);
//OutputTypeAndRate = Output & "6x3";
*OutputType = dml2_core_internal_output_type_hdmifrl;
*OutputRate = dml2_core_internal_output_rate_hdmi_rate_6x3;
}
- if (*OutBpp == 0 && PHYCLKD18 >= 6000 / 18) {
+ if (*OutBpp == 0 && PHYCLKD18 >= 6000.0 / 18) {
*OutBpp = TruncToValidBPP(&s->TruncToValidBPP_locals, 6000, 4, HTotal, HActive, PixelClockBackEnd, ForcedOutputLinkBPP, LinkDSCEnable, Output, OutputFormat, DSCInputBitPerComponent, NumberOfDSCSlices, (unsigned int)AudioSampleRate, AudioSampleLayout, ODMModeNoDSC, ODMModeDSC, &dummy);
//OutputTypeAndRate = Output & "6x4";
*OutputType = dml2_core_internal_output_type_hdmifrl;
*OutputRate = dml2_core_internal_output_rate_hdmi_rate_6x4;
}
- if (*OutBpp == 0 && PHYCLKD18 >= 8000 / 18) {
+ if (*OutBpp == 0 && PHYCLKD18 >= 8000.0 / 18) {
*OutBpp = TruncToValidBPP(&s->TruncToValidBPP_locals, 8000, 4, HTotal, HActive, PixelClockBackEnd, ForcedOutputLinkBPP, LinkDSCEnable, Output, OutputFormat, DSCInputBitPerComponent, NumberOfDSCSlices, (unsigned int)AudioSampleRate, AudioSampleLayout, ODMModeNoDSC, ODMModeDSC, &dummy);
//OutputTypeAndRate = Output & "8x4";
*OutputType = dml2_core_internal_output_type_hdmifrl;
*OutputRate = dml2_core_internal_output_rate_hdmi_rate_8x4;
}
- if (*OutBpp == 0 && PHYCLKD18 >= 10000 / 18) {
+ if (*OutBpp == 0 && PHYCLKD18 >= 10000.0 / 18) {
*OutBpp = TruncToValidBPP(&s->TruncToValidBPP_locals, 10000, 4, HTotal, HActive, PixelClockBackEnd, ForcedOutputLinkBPP, LinkDSCEnable, Output, OutputFormat, DSCInputBitPerComponent, NumberOfDSCSlices, (unsigned int)AudioSampleRate, AudioSampleLayout, ODMModeNoDSC, ODMModeDSC, &dummy);
- if (*OutBpp == 0 && DSCEnable == dml2_dsc_enable_if_necessary && ForcedOutputLinkBPP == 0 && PHYCLKD18 < 12000 / 18) {
+ if (*OutBpp == 0 && DSCEnable == dml2_dsc_enable_if_necessary && ForcedOutputLinkBPP == 0 && PHYCLKD18 < 12000.0 / 18) {
*RequiresDSC = true;
LinkDSCEnable = true;
*RequiresFEC = true;
@@ -4342,7 +4342,7 @@ static void CalculateOutputLink(
*OutputType = dml2_core_internal_output_type_hdmifrl;
*OutputRate = dml2_core_internal_output_rate_hdmi_rate_10x4;
}
- if (*OutBpp == 0 && PHYCLKD18 >= 12000 / 18) {
+ if (*OutBpp == 0 && PHYCLKD18 >= 12000.0 / 18) {
*OutBpp = TruncToValidBPP(&s->TruncToValidBPP_locals, 12000, 4, HTotal, HActive, PixelClockBackEnd, ForcedOutputLinkBPP, LinkDSCEnable, Output, OutputFormat, DSCInputBitPerComponent, NumberOfDSCSlices, (unsigned int)AudioSampleRate, AudioSampleLayout, ODMModeNoDSC, ODMModeDSC, &dummy);
if (*OutBpp == 0 && DSCEnable == dml2_dsc_enable_if_necessary && ForcedOutputLinkBPP == 0) {
*RequiresDSC = true;
@@ -4501,24 +4501,6 @@ static void CalculateSurfaceSizeInMall(
math_floor2((double)composition->viewport.plane1.y_start + composition->viewport.plane1.height + ReadBlockHeightC[k] - 1, ReadBlockHeightC[k]) -
math_floor2(composition->viewport.plane1.y_start, ReadBlockHeightC[k])) * BytesPerPixelC[k]);
}
- if (surface->dcc.enable) {
- SurfaceSizeInMALL[k] = (unsigned int)(SurfaceSizeInMALL[k] +
- math_min2(math_ceil2(surface->plane0.width, 8 * Read256BytesBlockWidthY[k]),
- math_floor2(composition->viewport.plane0.x_start + composition->viewport.plane0.width + 8 * Read256BytesBlockWidthY[k] - 1, 8 * Read256BytesBlockWidthY[k]) -
- math_floor2(composition->viewport.plane0.x_start, 8 * Read256BytesBlockWidthY[k])) *
- math_min2(math_ceil2(surface->plane0.height, 8 * Read256BytesBlockHeightY[k]),
- math_floor2(composition->viewport.plane0.y_start + composition->viewport.plane0.height + 8 * Read256BytesBlockHeightY[k] - 1, 8 * Read256BytesBlockHeightY[k]) -
- math_floor2(composition->viewport.plane0.y_start, 8 * Read256BytesBlockHeightY[k])) * BytesPerPixelY[k] / 256) + (64 * 1024);
- if (Read256BytesBlockWidthC[k] > 0) {
- SurfaceSizeInMALL[k] = (unsigned int)(SurfaceSizeInMALL[k] +
- math_min2(math_ceil2(surface->plane1.width, 8 * Read256BytesBlockWidthC[k]),
- math_floor2(composition->viewport.plane1.y_start + composition->viewport.plane1.width + 8 * Read256BytesBlockWidthC[k] - 1, 8 * Read256BytesBlockWidthC[k]) -
- math_floor2(composition->viewport.plane1.y_start, 8 * Read256BytesBlockWidthC[k])) *
- math_min2(math_ceil2(surface->plane1.height, 8 * Read256BytesBlockHeightC[k]),
- math_floor2(composition->viewport.plane1.y_start + composition->viewport.plane1.height + 8 * Read256BytesBlockHeightC[k] - 1, 8 * Read256BytesBlockHeightC[k]) -
- math_floor2(composition->viewport.plane1.y_start, 8 * Read256BytesBlockHeightC[k])) * BytesPerPixelC[k] / 256);
- }
- }
} else {
SurfaceSizeInMALL[k] = (unsigned int)(math_ceil2(math_min2(surface->plane0.width, composition->viewport.plane0.width + ReadBlockWidthY[k] - 1), ReadBlockWidthY[k]) *
math_ceil2(math_min2(surface->plane0.height, composition->viewport.plane0.height + ReadBlockHeightY[k] - 1), ReadBlockHeightY[k]) * BytesPerPixelY[k]);
@@ -4527,17 +4509,6 @@ static void CalculateSurfaceSizeInMall(
math_ceil2(math_min2(surface->plane1.width, composition->viewport.plane1.width + ReadBlockWidthC[k] - 1), ReadBlockWidthC[k]) *
math_ceil2(math_min2(surface->plane1.height, composition->viewport.plane1.height + ReadBlockHeightC[k] - 1), ReadBlockHeightC[k]) * BytesPerPixelC[k]);
}
- if (surface->dcc.enable) {
- SurfaceSizeInMALL[k] = (unsigned int)(SurfaceSizeInMALL[k] +
- math_ceil2(math_min2(surface->plane0.width, composition->viewport.plane0.width + 8 * Read256BytesBlockWidthY[k] - 1), 8 * Read256BytesBlockWidthY[k]) *
- math_ceil2(math_min2(surface->plane0.height, composition->viewport.plane0.height + 8 * Read256BytesBlockHeightY[k] - 1), 8 * Read256BytesBlockHeightY[k]) * BytesPerPixelY[k] / 256) + (64 * 1024);
-
- if (Read256BytesBlockWidthC[k] > 0) {
- SurfaceSizeInMALL[k] = (unsigned int)(SurfaceSizeInMALL[k] +
- math_ceil2(math_min2(surface->plane1.width, composition->viewport.plane1.width + 8 * Read256BytesBlockWidthC[k] - 1), 8 * Read256BytesBlockWidthC[k]) *
- math_ceil2(math_min2(surface->plane1.height, composition->viewport.plane1.height + 8 * Read256BytesBlockHeightC[k] - 1), 8 * Read256BytesBlockHeightC[k]) * BytesPerPixelC[k] / 256);
- }
- }
}
}
@@ -7155,7 +7126,7 @@ static bool dml_core_mode_support(struct dml2_core_calcs_mode_support_ex *in_out
mode_lib->ms.support.WritebackLatencySupport = true;
for (k = 0; k <= mode_lib->ms.num_active_planes - 1; k++) {
if (display_cfg->stream_descriptors[display_cfg->plane_descriptors[k].stream_index].writeback.enable == true &&
- (mode_lib->ms.WriteBandwidth[k] > mode_lib->ip.writeback_interface_buffer_size_kbytes * 1024 / mode_lib->soc.qos_parameters.writeback.base_latency_us)) {
+ (mode_lib->ms.WriteBandwidth[k] > mode_lib->ip.writeback_interface_buffer_size_kbytes * 1024.0 / mode_lib->soc.qos_parameters.writeback.base_latency_us)) {
mode_lib->ms.support.WritebackLatencySupport = false;
}
}
@@ -7742,7 +7713,8 @@ static bool dml_core_mode_support(struct dml2_core_calcs_mode_support_ex *in_out
mode_lib->ms.support.DTBCLKRequiredMoreThanSupported = false;
for (k = 0; k < mode_lib->ms.num_active_planes; ++k) {
- if (display_cfg->stream_descriptors[display_cfg->plane_descriptors[k].stream_index].output.output_encoder == dml2_hdmifrl) {
+ if (display_cfg->stream_descriptors[display_cfg->plane_descriptors[k].stream_index].output.output_encoder == dml2_hdmifrl &&
+ !dml_is_phantom_pipe(&display_cfg->plane_descriptors[k])) {
mode_lib->ms.RequiredDTBCLK[k] = RequiredDTBCLK(
mode_lib->ms.RequiresDSC[k],
s->PixelClockBackEnd[k],
@@ -7757,6 +7729,13 @@ static bool dml_core_mode_support(struct dml2_core_calcs_mode_support_ex *in_out
if (mode_lib->ms.RequiredDTBCLK[k] > ((double)min_clk_table->max_clocks_khz.dtbclk / 1000)) {
mode_lib->ms.support.DTBCLKRequiredMoreThanSupported = true;
}
+ } else {
+ /* Phantom DTBCLK can be calculated different from main because phantom has no DSC and thus
+ * will have a different output BPP. Ignore phantom DTBCLK requirement and only consider
+ * non-phantom DTBCLK requirements. In map_mode_to_soc_dpm we choose the highest DTBCLK
+ * required - by setting phantom dtbclk to 0 we ignore it.
+ */
+ mode_lib->ms.RequiredDTBCLK[k] = 0;
}
}
@@ -8940,10 +8919,6 @@ static bool dml_core_mode_support(struct dml2_core_calcs_mode_support_ex *in_out
} // prefetch schedule
}
- for (k = 0; k < mode_lib->ms.num_active_planes; ++k) {
- mode_lib->ms.use_one_row_for_frame[k] = mode_lib->ms.use_one_row_for_frame[k];
- }
-
s->mSOCParameters.UrgentLatency = mode_lib->ms.UrgLatency;
s->mSOCParameters.ExtraLatency = mode_lib->ms.ExtraLatency;
s->mSOCParameters.ExtraLatency_sr = mode_lib->ms.ExtraLatency_sr;
@@ -11375,7 +11350,7 @@ static bool dml_core_mode_programming(struct dml2_core_calcs_mode_programming_ex
mode_lib->mp.MIN_DST_Y_NEXT_START[k] = s->dlg_vblank_start + s->blank_lines_remaining + s->LSetup;
// debug only
- if (((mode_lib->mp.VUpdateOffsetPix[k] + mode_lib->mp.VUpdateWidthPix[k] + mode_lib->mp.VReadyOffsetPix[k]) / display_cfg->stream_descriptors[display_cfg->plane_descriptors[k].stream_index].timing.h_total) <=
+ if (((mode_lib->mp.VUpdateOffsetPix[k] + mode_lib->mp.VUpdateWidthPix[k] + mode_lib->mp.VReadyOffsetPix[k]) / (double) display_cfg->stream_descriptors[display_cfg->plane_descriptors[k].stream_index].timing.h_total) <=
(isInterlaceTiming ?
math_floor2((display_cfg->stream_descriptors[display_cfg->plane_descriptors[k].stream_index].timing.v_total - display_cfg->stream_descriptors[display_cfg->plane_descriptors[k].stream_index].timing.v_active - display_cfg->stream_descriptors[display_cfg->plane_descriptors[k].stream_index].timing.v_front_porch - mode_lib->mp.VStartup[k]) / 2.0, 1.0) :
(int)(display_cfg->stream_descriptors[display_cfg->plane_descriptors[k].stream_index].timing.v_total - display_cfg->stream_descriptors[display_cfg->plane_descriptors[k].stream_index].timing.v_active - display_cfg->stream_descriptors[display_cfg->plane_descriptors[k].stream_index].timing.v_front_porch - mode_lib->mp.VStartup[k]))) {
@@ -11546,8 +11521,8 @@ void dml2_core_calcs_get_dpte_row_height(
unsigned int MacroTileWidthC;
unsigned int MacroTileHeightY;
unsigned int MacroTileHeightC;
- bool surf_linear_128_l;
- bool surf_linear_128_c;
+ bool surf_linear_128_l = false;
+ bool surf_linear_128_c = false;
CalculateBytePerPixelAndBlockSizes(
SourcePixelFormat,
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_factory.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_factory.c
index 1a0da8c6df5a..f56abe9ab919 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_factory.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_factory.c
@@ -11,7 +11,7 @@ bool dml2_core_create(enum dml2_project_id project_id, struct dml2_core_instance
{
bool result = false;
- if (out == 0)
+ if (!out)
return false;
memset(out, 0, sizeof(struct dml2_core_instance));
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_shared.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_shared.c
index 6eb3fec87ec1..81f0a6f19f87 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_shared.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_shared.c
@@ -942,7 +942,7 @@ bool dml2_core_shared_mode_support(struct dml2_core_calcs_mode_support_ex *in_ou
mode_lib->ms.support.WritebackLatencySupport = true;
for (k = 0; k <= mode_lib->ms.num_active_planes - 1; k++) {
if (display_cfg->stream_descriptors[display_cfg->plane_descriptors[k].stream_index].writeback.enable == true &&
- (mode_lib->ms.WriteBandwidth[k] > mode_lib->ip.writeback_interface_buffer_size_kbytes * 1024 / mode_lib->soc.qos_parameters.writeback.base_latency_us)) {
+ (mode_lib->ms.WriteBandwidth[k] > mode_lib->ip.writeback_interface_buffer_size_kbytes * 1024.0 / mode_lib->soc.qos_parameters.writeback.base_latency_us)) {
mode_lib->ms.support.WritebackLatencySupport = false;
}
}
@@ -2647,10 +2647,6 @@ bool dml2_core_shared_mode_support(struct dml2_core_calcs_mode_support_ex *in_ou
} // prefetch schedule
}
- for (k = 0; k < mode_lib->ms.num_active_planes; ++k) {
- mode_lib->ms.use_one_row_for_frame[k] = mode_lib->ms.use_one_row_for_frame[k];
- }
-
s->mSOCParameters.UrgentLatency = mode_lib->ms.UrgLatency;
s->mSOCParameters.ExtraLatency = mode_lib->ms.ExtraLatency;
s->mSOCParameters.ExtraLatency_sr = mode_lib->ms.ExtraLatency_sr;
@@ -3146,62 +3142,62 @@ static unsigned int dml_get_tile_block_size_bytes(enum dml2_swizzle_mode sw_mode
{
switch (sw_mode) {
case (dml2_sw_linear):
- return 256; break;
+ return 256;
case (dml2_sw_256b_2d):
- return 256; break;
+ return 256;
case (dml2_sw_4kb_2d):
- return 4096; break;
+ return 4096;
case (dml2_sw_64kb_2d):
- return 65536; break;
+ return 65536;
case (dml2_sw_256kb_2d):
- return 262144; break;
+ return 262144;
case (dml2_gfx11_sw_linear):
- return 256; break;
+ return 256;
case (dml2_gfx11_sw_64kb_d):
- return 65536; break;
+ return 65536;
case (dml2_gfx11_sw_64kb_d_t):
- return 65536; break;
+ return 65536;
case (dml2_gfx11_sw_64kb_d_x):
- return 65536; break;
+ return 65536;
case (dml2_gfx11_sw_64kb_r_x):
- return 65536; break;
+ return 65536;
case (dml2_gfx11_sw_256kb_d_x):
- return 262144; break;
+ return 262144;
case (dml2_gfx11_sw_256kb_r_x):
- return 262144; break;
+ return 262144;
default:
DML2_ASSERT(0);
return 256;
- };
+ }
}
const char *dml2_core_internal_bw_type_str(enum dml2_core_internal_bw_type bw_type)
{
switch (bw_type) {
case (dml2_core_internal_bw_sdp):
- return("dml2_core_internal_bw_sdp"); break;
+ return("dml2_core_internal_bw_sdp");
case (dml2_core_internal_bw_dram):
- return("dml2_core_internal_bw_dram"); break;
+ return("dml2_core_internal_bw_dram");
case (dml2_core_internal_bw_max):
- return("dml2_core_internal_bw_max"); break;
+ return("dml2_core_internal_bw_max");
default:
- return("dml2_core_internal_bw_unknown"); break;
- };
+ return("dml2_core_internal_bw_unknown");
+ }
}
const char *dml2_core_internal_soc_state_type_str(enum dml2_core_internal_soc_state_type dml2_core_internal_soc_state_type)
{
switch (dml2_core_internal_soc_state_type) {
case (dml2_core_internal_soc_state_sys_idle):
- return("dml2_core_internal_soc_state_sys_idle"); break;
+ return("dml2_core_internal_soc_state_sys_idle");
case (dml2_core_internal_soc_state_sys_active):
- return("dml2_core_internal_soc_state_sys_active"); break;
+ return("dml2_core_internal_soc_state_sys_active");
case (dml2_core_internal_soc_state_svp_prefetch):
- return("dml2_core_internal_soc_state_svp_prefetch"); break;
+ return("dml2_core_internal_soc_state_svp_prefetch");
case dml2_core_internal_soc_state_max:
default:
- return("dml2_core_internal_soc_state_unknown"); break;
- };
+ return("dml2_core_internal_soc_state_unknown");
+ }
}
static bool dml_is_vertical_rotation(enum dml2_rotation_angle Scan)
@@ -6735,10 +6731,10 @@ static void CalculateOutputLink(
}
if (Output == dml2_dp2p0) {
*OutBpp = 0;
- if ((OutputLinkDPRate == dml2_dp_rate_na || OutputLinkDPRate == dml2_dp_rate_uhbr10) && PHYCLKD32 >= 10000 / 32) {
+ if ((OutputLinkDPRate == dml2_dp_rate_na || OutputLinkDPRate == dml2_dp_rate_uhbr10) && PHYCLKD32 >= 10000.0 / 32) {
*OutBpp = TruncToValidBPP(&s->TruncToValidBPP_locals, (1 - Downspreading / 100) * 10000, OutputLinkDPLanes, HTotal, HActive, PixelClockBackEnd, ForcedOutputLinkBPP, LinkDSCEnable, Output,
OutputFormat, DSCInputBitPerComponent, NumberOfDSCSlices, (unsigned int)AudioSampleRate, AudioSampleLayout, ODMModeNoDSC, ODMModeDSC, RequiredSlots);
- if (*OutBpp == 0 && PHYCLKD32 < 13500 / 32 && DSCEnable == dml2_dsc_enable_if_necessary && ForcedOutputLinkBPP == 0) {
+ if (*OutBpp == 0 && PHYCLKD32 < 13500.0 / 32 && DSCEnable == dml2_dsc_enable_if_necessary && ForcedOutputLinkBPP == 0) {
*RequiresDSC = true;
LinkDSCEnable = true;
*OutBpp = TruncToValidBPP(&s->TruncToValidBPP_locals, (1 - Downspreading / 100) * 10000, OutputLinkDPLanes, HTotal, HActive, PixelClockBackEnd, ForcedOutputLinkBPP, LinkDSCEnable, Output,
@@ -6748,7 +6744,7 @@ static void CalculateOutputLink(
*OutputType = dml2_core_internal_output_type_dp2p0;
*OutputRate = dml2_core_internal_output_rate_dp_rate_uhbr10;
}
- if ((OutputLinkDPRate == dml2_dp_rate_na || OutputLinkDPRate == dml2_dp_rate_uhbr13p5) && *OutBpp == 0 && PHYCLKD32 >= 13500 / 32) {
+ if ((OutputLinkDPRate == dml2_dp_rate_na || OutputLinkDPRate == dml2_dp_rate_uhbr13p5) && *OutBpp == 0 && PHYCLKD32 >= 13500.0 / 32) {
*OutBpp = TruncToValidBPP(&s->TruncToValidBPP_locals, (1 - Downspreading / 100) * 13500, OutputLinkDPLanes, HTotal, HActive, PixelClockBackEnd, ForcedOutputLinkBPP, LinkDSCEnable, Output,
OutputFormat, DSCInputBitPerComponent, NumberOfDSCSlices, (unsigned int)AudioSampleRate, AudioSampleLayout, ODMModeNoDSC, ODMModeDSC, RequiredSlots);
@@ -6839,33 +6835,33 @@ static void CalculateOutputLink(
*RequiresFEC = false;
}
*OutBpp = 0;
- if (PHYCLKD18 >= 3000 / 18) {
+ if (PHYCLKD18 >= 3000.0 / 18) {
*OutBpp = TruncToValidBPP(&s->TruncToValidBPP_locals, 3000, 3, HTotal, HActive, PixelClockBackEnd, ForcedOutputLinkBPP, LinkDSCEnable, Output, OutputFormat, DSCInputBitPerComponent, NumberOfDSCSlices, (unsigned int)AudioSampleRate, AudioSampleLayout, ODMModeNoDSC, ODMModeDSC, &dummy);
//OutputTypeAndRate = Output & "3x3";
*OutputType = dml2_core_internal_output_type_hdmifrl;
*OutputRate = dml2_core_internal_output_rate_hdmi_rate_3x3;
}
- if (*OutBpp == 0 && PHYCLKD18 >= 6000 / 18) {
+ if (*OutBpp == 0 && PHYCLKD18 >= 6000.0 / 18) {
*OutBpp = TruncToValidBPP(&s->TruncToValidBPP_locals, 6000, 3, HTotal, HActive, PixelClockBackEnd, ForcedOutputLinkBPP, LinkDSCEnable, Output, OutputFormat, DSCInputBitPerComponent, NumberOfDSCSlices, (unsigned int)AudioSampleRate, AudioSampleLayout, ODMModeNoDSC, ODMModeDSC, &dummy);
//OutputTypeAndRate = Output & "6x3";
*OutputType = dml2_core_internal_output_type_hdmifrl;
*OutputRate = dml2_core_internal_output_rate_hdmi_rate_6x3;
}
- if (*OutBpp == 0 && PHYCLKD18 >= 6000 / 18) {
+ if (*OutBpp == 0 && PHYCLKD18 >= 6000.0 / 18) {
*OutBpp = TruncToValidBPP(&s->TruncToValidBPP_locals, 6000, 4, HTotal, HActive, PixelClockBackEnd, ForcedOutputLinkBPP, LinkDSCEnable, Output, OutputFormat, DSCInputBitPerComponent, NumberOfDSCSlices, (unsigned int)AudioSampleRate, AudioSampleLayout, ODMModeNoDSC, ODMModeDSC, &dummy);
//OutputTypeAndRate = Output & "6x4";
*OutputType = dml2_core_internal_output_type_hdmifrl;
*OutputRate = dml2_core_internal_output_rate_hdmi_rate_6x4;
}
- if (*OutBpp == 0 && PHYCLKD18 >= 8000 / 18) {
+ if (*OutBpp == 0 && PHYCLKD18 >= 8000.0 / 18) {
*OutBpp = TruncToValidBPP(&s->TruncToValidBPP_locals, 8000, 4, HTotal, HActive, PixelClockBackEnd, ForcedOutputLinkBPP, LinkDSCEnable, Output, OutputFormat, DSCInputBitPerComponent, NumberOfDSCSlices, (unsigned int)AudioSampleRate, AudioSampleLayout, ODMModeNoDSC, ODMModeDSC, &dummy);
//OutputTypeAndRate = Output & "8x4";
*OutputType = dml2_core_internal_output_type_hdmifrl;
*OutputRate = dml2_core_internal_output_rate_hdmi_rate_8x4;
}
- if (*OutBpp == 0 && PHYCLKD18 >= 10000 / 18) {
+ if (*OutBpp == 0 && PHYCLKD18 >= 10000.0 / 18) {
*OutBpp = TruncToValidBPP(&s->TruncToValidBPP_locals, 10000, 4, HTotal, HActive, PixelClockBackEnd, ForcedOutputLinkBPP, LinkDSCEnable, Output, OutputFormat, DSCInputBitPerComponent, NumberOfDSCSlices, (unsigned int)AudioSampleRate, AudioSampleLayout, ODMModeNoDSC, ODMModeDSC, &dummy);
- if (*OutBpp == 0 && DSCEnable == dml2_dsc_enable_if_necessary && ForcedOutputLinkBPP == 0 && PHYCLKD18 < 12000 / 18) {
+ if (*OutBpp == 0 && DSCEnable == dml2_dsc_enable_if_necessary && ForcedOutputLinkBPP == 0 && PHYCLKD18 < 12000.0 / 18) {
*RequiresDSC = true;
LinkDSCEnable = true;
*RequiresFEC = true;
@@ -6875,7 +6871,7 @@ static void CalculateOutputLink(
*OutputType = dml2_core_internal_output_type_hdmifrl;
*OutputRate = dml2_core_internal_output_rate_hdmi_rate_10x4;
}
- if (*OutBpp == 0 && PHYCLKD18 >= 12000 / 18) {
+ if (*OutBpp == 0 && PHYCLKD18 >= 12000.0 / 18) {
*OutBpp = TruncToValidBPP(&s->TruncToValidBPP_locals, 12000, 4, HTotal, HActive, PixelClockBackEnd, ForcedOutputLinkBPP, LinkDSCEnable, Output, OutputFormat, DSCInputBitPerComponent, NumberOfDSCSlices, (unsigned int)AudioSampleRate, AudioSampleLayout, ODMModeNoDSC, ODMModeDSC, &dummy);
if (*OutBpp == 0 && DSCEnable == dml2_dsc_enable_if_necessary && ForcedOutputLinkBPP == 0) {
*RequiresDSC = true;
@@ -11240,7 +11236,7 @@ bool dml2_core_shared_mode_programming(struct dml2_core_calcs_mode_programming_e
mode_lib->mp.MIN_DST_Y_NEXT_START[k] = s->dlg_vblank_start + s->blank_lines_remaining + s->LSetup;
// debug only
- if (((mode_lib->mp.VUpdateOffsetPix[k] + mode_lib->mp.VUpdateWidthPix[k] + mode_lib->mp.VReadyOffsetPix[k]) / display_cfg->stream_descriptors[display_cfg->plane_descriptors[k].stream_index].timing.h_total) <=
+ if (((mode_lib->mp.VUpdateOffsetPix[k] + mode_lib->mp.VUpdateWidthPix[k] + (double) mode_lib->mp.VReadyOffsetPix[k]) / display_cfg->stream_descriptors[display_cfg->plane_descriptors[k].stream_index].timing.h_total) <=
(isInterlaceTiming ?
math_floor2((display_cfg->stream_descriptors[display_cfg->plane_descriptors[k].stream_index].timing.v_total - display_cfg->stream_descriptors[display_cfg->plane_descriptors[k].stream_index].timing.v_active - display_cfg->stream_descriptors[display_cfg->plane_descriptors[k].stream_index].timing.v_front_porch - mode_lib->mp.VStartup[k]) / 2.0, 1.0) :
(int)(display_cfg->stream_descriptors[display_cfg->plane_descriptors[k].stream_index].timing.v_total - display_cfg->stream_descriptors[display_cfg->plane_descriptors[k].stream_index].timing.v_active - display_cfg->stream_descriptors[display_cfg->plane_descriptors[k].stream_index].timing.v_front_porch - mode_lib->mp.VStartup[k]))) {
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_dpmm/dml2_dpmm_factory.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_dpmm/dml2_dpmm_factory.c
index 657ec2e1b119..2c983daf2dad 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_dpmm/dml2_dpmm_factory.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_dpmm/dml2_dpmm_factory.c
@@ -21,7 +21,7 @@ bool dml2_dpmm_create(enum dml2_project_id project_id, struct dml2_dpmm_instance
{
bool result = false;
- if (out == 0)
+ if (!out)
return false;
memset(out, 0, sizeof(struct dml2_dpmm_instance));
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_mcg/dml2_mcg_factory.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_mcg/dml2_mcg_factory.c
index ce83c10253a2..55085b85f8ed 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_mcg/dml2_mcg_factory.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_mcg/dml2_mcg_factory.c
@@ -16,7 +16,7 @@ bool dml2_mcg_create(enum dml2_project_id project_id, struct dml2_mcg_instance *
{
bool result = false;
- if (out == 0)
+ if (!out)
return false;
memset(out, 0, sizeof(struct dml2_mcg_instance));
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c
index 85c64dcefa82..603036df68ba 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c
@@ -929,7 +929,8 @@ static bool all_timings_support_svp(const struct dml2_pmo_instance *pmo,
/* check recout height covers entire otg vactive, and single plane */
if (num_planes_per_stream[plane_descriptor->stream_index] > 1 ||
- !plane_descriptor->composition.rect_out_height_spans_vactive) {
+ !plane_descriptor->composition.rect_out_height_spans_vactive ||
+ plane_descriptor->composition.rotation_angle != dml2_rotation_0) {
return false;
}
}
@@ -1081,12 +1082,17 @@ static bool is_timing_group_schedulable(
/* init allow start and end lines for timing group */
stream_method_fams2_meta = get_per_method_common_meta(pmo, per_stream_pstate_strategy[base_stream_idx], base_stream_idx);
+ if (!stream_method_fams2_meta)
+ return false;
+
group_fams2_meta->allow_start_otg_vline = stream_method_fams2_meta->allow_start_otg_vline;
group_fams2_meta->allow_end_otg_vline = stream_method_fams2_meta->allow_end_otg_vline;
group_fams2_meta->period_us = stream_method_fams2_meta->period_us;
for (i = base_stream_idx + 1; i < display_cfg->display_config.num_streams; i++) {
if (is_bit_set_in_bitfield(pmo->scratch.pmo_dcn4.synchronized_timing_group_masks[timing_group_idx], i)) {
stream_method_fams2_meta = get_per_method_common_meta(pmo, per_stream_pstate_strategy[i], i);
+ if (!stream_method_fams2_meta)
+ continue;
if (group_fams2_meta->allow_start_otg_vline < stream_method_fams2_meta->allow_start_otg_vline) {
/* set group allow start to larger otg vline */
@@ -1157,7 +1163,6 @@ static bool is_config_schedulable(
schedulable = true;
/* sort disallow times from greatest to least */
- unsigned int temp;
for (i = 0; i < s->pmo_dcn4.num_timing_groups; i++) {
bool swapped = false;
@@ -1166,9 +1171,8 @@ static bool is_config_schedulable(
double jp1_disallow_us = s->pmo_dcn4.group_common_fams2_meta[s->pmo_dcn4.sorted_group_gtl_disallow_index[j + 1]].disallow_time_us;
if (j_disallow_us < jp1_disallow_us) {
/* swap as A < B */
- temp = s->pmo_dcn4.sorted_group_gtl_disallow_index[j];
- s->pmo_dcn4.sorted_group_gtl_disallow_index[j] = s->pmo_dcn4.sorted_group_gtl_disallow_index[j + 1];
- s->pmo_dcn4.sorted_group_gtl_disallow_index[j + 1] = temp;
+ swap(s->pmo_dcn4.sorted_group_gtl_disallow_index[j],
+ s->pmo_dcn4.sorted_group_gtl_disallow_index[j+1]);
swapped = true;
}
}
@@ -1226,9 +1230,8 @@ static bool is_config_schedulable(
double jp1_period_us = s->pmo_dcn4.group_common_fams2_meta[s->pmo_dcn4.sorted_group_gtl_period_index[j + 1]].period_us;
if (j_period_us < jp1_period_us) {
/* swap as A < B */
- temp = s->pmo_dcn4.sorted_group_gtl_period_index[j];
- s->pmo_dcn4.sorted_group_gtl_period_index[j] = s->pmo_dcn4.sorted_group_gtl_period_index[j + 1];
- s->pmo_dcn4.sorted_group_gtl_period_index[j + 1] = temp;
+ swap(s->pmo_dcn4.sorted_group_gtl_period_index[j],
+ s->pmo_dcn4.sorted_group_gtl_period_index[j+1]);
swapped = true;
}
}
@@ -1361,7 +1364,7 @@ static bool validate_pstate_support_strategy_cofunctionality(struct dml2_pmo_ins
break;
}
- strategy_matches_drr_requirements =
+ strategy_matches_drr_requirements &=
stream_matches_drr_policy(pmo, display_cfg, per_stream_pstate_strategy[stream_index], stream_index);
if (per_stream_pstate_strategy[stream_index] == dml2_pmo_pstate_strategy_fw_svp ||
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_pmo/dml2_pmo_factory.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_pmo/dml2_pmo_factory.c
index a34506a78c50..e0b9ece7901d 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_pmo/dml2_pmo_factory.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_pmo/dml2_pmo_factory.c
@@ -28,7 +28,7 @@ bool dml2_pmo_create(enum dml2_project_id project_id, struct dml2_pmo_instance *
{
bool result = false;
- if (out == 0)
+ if (!out)
return false;
memset(out, 0, sizeof(struct dml2_pmo_instance));
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_standalone_libraries/lib_float_math.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_standalone_libraries/lib_float_math.c
index defe13436a2c..e73579f1a88e 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_standalone_libraries/lib_float_math.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_standalone_libraries/lib_float_math.c
@@ -64,8 +64,6 @@ double math_ceil(const double arg)
double math_ceil2(const double arg, const double significance)
{
- ASSERT(significance != 0);
-
return ((int)(arg / significance + 0.99999)) * significance;
}
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_top/dml_top.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_top/dml_top.c
index 1142fdade334..2fb3e2f45e07 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_top/dml_top.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_top/dml_top.c
@@ -96,10 +96,15 @@ bool dml2_check_mode_supported(struct dml2_check_mode_supported_in_out *in_out)
{
struct dml2_instance *dml = (struct dml2_instance *)in_out->dml2_instance;
struct dml2_check_mode_supported_locals *l = &dml->scratch.check_mode_supported_locals;
+ /* Borrow the build_mode_programming_locals programming struct for DPMM call. */
+ struct dml2_display_cfg_programming *dpmm_programming = dml->scratch.build_mode_programming_locals.mode_programming_params.programming;
bool result = false;
bool mcache_success = false;
+ if (dpmm_programming)
+ memset(dpmm_programming, 0, sizeof(struct dml2_display_cfg_programming));
+
setup_unoptimized_display_config_with_meta(dml, &l->base_display_config_with_meta, in_out->display_config);
l->mode_support_params.instance = &dml->core_instance;
@@ -122,6 +127,18 @@ bool dml2_check_mode_supported(struct dml2_check_mode_supported_in_out *in_out)
mcache_success = dml2_top_optimization_perform_optimization_phase(&l->optimization_phase_locals, &mcache_phase);
}
+ /*
+ * Call DPMM to map all requirements to minimum clock state
+ */
+ if (result && dpmm_programming) {
+ l->dppm_map_mode_params.min_clk_table = &dml->min_clk_table;
+ l->dppm_map_mode_params.display_cfg = &l->base_display_config_with_meta;
+ l->dppm_map_mode_params.programming = dpmm_programming;
+ l->dppm_map_mode_params.soc_bb = &dml->soc_bbox;
+ l->dppm_map_mode_params.ip = &dml->core_instance.clean_me_up.mode_lib.ip;
+ result = dml->dpmm_instance.map_mode_to_soc_dpm(&l->dppm_map_mode_params);
+ }
+
in_out->is_supported = mcache_success;
result = result && in_out->is_supported;
@@ -259,7 +276,7 @@ bool dml2_build_mode_programming(struct dml2_build_mode_programming_in_out *in_o
/*
* Phase 5: Optimize for Stutter
*/
- memset(&l->vmin_phase, 0, sizeof(struct optimization_phase_params));
+ memset(&l->stutter_phase, 0, sizeof(struct optimization_phase_params));
l->stutter_phase.dml = dml;
l->stutter_phase.display_config = &l->base_display_config_with_meta;
l->stutter_phase.init_function = dml2_top_optimization_init_function_stutter;
@@ -272,7 +289,7 @@ bool dml2_build_mode_programming(struct dml2_build_mode_programming_in_out *in_o
if (stutter_success) {
memcpy(&l->base_display_config_with_meta, &l->optimized_display_config_with_meta, sizeof(struct display_configuation_with_meta));
- l->base_display_config_with_meta.stage4.success = true;
+ l->base_display_config_with_meta.stage5.success = true;
}
/*
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/inc/dml2_internal_shared_types.h b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/inc/dml2_internal_shared_types.h
index dd90c5df5a5a..5632cdacb7f4 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/inc/dml2_internal_shared_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/inc/dml2_internal_shared_types.h
@@ -870,6 +870,7 @@ struct dml2_check_mode_supported_locals {
struct dml2_optimization_phase_locals optimization_phase_locals;
struct display_configuation_with_meta base_display_config_with_meta;
struct display_configuation_with_meta optimized_display_config_with_meta;
+ struct dml2_dpmm_map_mode_to_soc_dpm_params_in_out dppm_map_mode_params;
};
struct optimization_init_function_params {
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c
index 02fb2cb1c43c..6eccf0241d85 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c
@@ -68,7 +68,7 @@ static bool get_plane_id(struct dml2_context *dml2, const struct dc_state *state
if (state->streams[i]->stream_id == stream_id) {
for (j = 0; j < state->stream_status[i].plane_count; j++) {
if (state->stream_status[i].plane_states[j] == plane &&
- (!is_plane_duplicate || (is_plane_duplicate && (j == plane_index)))) {
+ (!is_plane_duplicate || (j == plane_index))) {
*plane_id = (i << 16) | j;
return true;
}
@@ -707,8 +707,8 @@ static void free_unused_pipes_for_plane(struct dml2_context *ctx, struct dc_stat
for (i = 0; i < ctx->config.dcn_pipe_count; i++) {
if (state->res_ctx.pipe_ctx[i].plane_state == plane &&
state->res_ctx.pipe_ctx[i].stream->stream_id == stream_id &&
- (!is_plane_duplicate || (is_plane_duplicate &&
- ctx->v20.scratch.dml_to_dc_pipe_mapping.dml_pipe_idx_to_plane_index[state->res_ctx.pipe_ctx[i].pipe_idx] == plane_index)) &&
+ (!is_plane_duplicate ||
+ ctx->v20.scratch.dml_to_dc_pipe_mapping.dml_pipe_idx_to_plane_index[state->res_ctx.pipe_ctx[i].pipe_idx] == plane_index) &&
!is_pipe_used(pool, state->res_ctx.pipe_ctx[i].pipe_idx)) {
free_pipe(&state->res_ctx.pipe_ctx[i]);
}
@@ -874,13 +874,14 @@ static unsigned int get_target_odm_factor(
default:
break;
}
- }
- else if (ctx->architecture == dml2_architecture_21) {
+ } else if (ctx->architecture == dml2_architecture_21) {
if (ctx->config.svp_pstate.callbacks.get_stream_subvp_type(state, stream) == SUBVP_PHANTOM) {
struct dc_stream_state *main_stream;
/* get stream id of main stream */
main_stream = ctx->config.svp_pstate.callbacks.get_paired_subvp_stream(state, stream);
+ if (!main_stream)
+ goto failed;
/* get cfg idx for associated main stream */
cfg_idx = find_disp_cfg_idx_by_stream_id(
@@ -893,6 +894,7 @@ static unsigned int get_target_odm_factor(
return ctx->v21.mode_programming.programming->stream_programming[cfg_idx].num_odms_required;
}
+failed:
ASSERT(false);
return 1;
}
@@ -903,6 +905,9 @@ static unsigned int get_source_odm_factor(const struct dml2_context *ctx,
{
struct pipe_ctx *otg_master = ctx->config.callbacks.get_otg_master_for_stream(&state->res_ctx, stream);
+ if (!otg_master)
+ return 0;
+
return ctx->config.callbacks.get_odm_slice_count(otg_master);
}
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_mall_phantom.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_mall_phantom.c
index 282d70e2b18a..3d29169dd6bb 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_mall_phantom.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_mall_phantom.c
@@ -750,6 +750,8 @@ static void enable_phantom_plane(struct dml2_context *ctx,
ctx->config.svp_pstate.callbacks.dc,
state,
curr_pipe->plane_state);
+ if (!phantom_plane)
+ return;
}
memcpy(&phantom_plane->address, &curr_pipe->plane_state->address, sizeof(phantom_plane->address));
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c
index c04ebf5434c9..8b9dcee77266 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c
@@ -296,6 +296,7 @@ void dml2_init_socbb_params(struct dml2_context *dml2, const struct dc *in_dc, s
out->round_trip_ping_latency_dcfclk_cycles = 106;
out->smn_latency_us = 2;
out->dispclk_dppclk_vco_speed_mhz = 3600;
+ out->pct_ideal_dram_bw_after_urgent_pixel_only = 65.0;
break;
case dml_project_dcn401:
@@ -739,6 +740,7 @@ static void populate_dml_output_cfg_from_stream_state(struct dml_output_cfg_st *
out->DSCEnable[location] = (enum dml_dsc_enable)in->timing.flags.DSC;
out->OutputLinkDPLanes[location] = 4; // As per code in dcn20_resource.c
out->DSCInputBitPerComponent[location] = 12; // As per code in dcn20_resource.c
+ out->DSCSlices[location] = in->timing.dsc_cfg.num_slices_h;
switch (in->signal) {
case SIGNAL_TYPE_DISPLAY_PORT_MST:
@@ -1109,7 +1111,7 @@ static bool get_plane_id(struct dml2_context *dml2, const struct dc_state *conte
if (context->streams[i]->stream_id == stream_id) {
for (j = 0; j < context->stream_status[i].plane_count; j++) {
if (context->stream_status[i].plane_states[j] == plane &&
- (!is_plane_duplicate || (is_plane_duplicate && (j == plane_index)))) {
+ (!is_plane_duplicate || (j == plane_index))) {
*plane_id = (i << 16) | j;
return true;
}
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.c
index 0f8b3336e26d..92238ff333a4 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.c
@@ -288,13 +288,12 @@ void dml2_calculate_rq_and_dlg_params(const struct dc *dc, struct dc_state *cont
{
unsigned int dc_pipe_ctx_index, dml_pipe_idx, plane_id;
enum mall_stream_type pipe_mall_type;
- bool unbounded_req_enabled = false;
struct dml2_calculate_rq_and_dlg_params_scratch *s = &in_ctx->v20.scratch.calculate_rq_and_dlg_params_scratch;
context->bw_ctx.bw.dcn.clk.dcfclk_deep_sleep_khz = (unsigned int)in_ctx->v20.dml_core_ctx.mp.DCFCLKDeepSleep * 1000;
context->bw_ctx.bw.dcn.clk.dppclk_khz = 0;
- if (in_ctx->v20.dml_core_ctx.ms.support.FCLKChangeSupport[in_ctx->v20.scratch.mode_support_params.out_lowest_state_idx] == dml_fclock_change_unsupported)
+ if (in_ctx->v20.dml_core_ctx.ms.support.FCLKChangeSupport[0] == dml_fclock_change_unsupported)
context->bw_ctx.bw.dcn.clk.fclk_p_state_change_support = false;
else
context->bw_ctx.bw.dcn.clk.fclk_p_state_change_support = true;
@@ -302,14 +301,6 @@ void dml2_calculate_rq_and_dlg_params(const struct dc *dc, struct dc_state *cont
if (context->bw_ctx.bw.dcn.clk.dispclk_khz < dc->debug.min_disp_clk_khz)
context->bw_ctx.bw.dcn.clk.dispclk_khz = dc->debug.min_disp_clk_khz;
- unbounded_req_enabled = in_ctx->v20.dml_core_ctx.ms.UnboundedRequestEnabledThisState;
-
- if (unbounded_req_enabled && pipe_cnt > 1) {
- // Unbounded requesting should not ever be used when more than 1 pipe is enabled.
- //ASSERT(false);
- unbounded_req_enabled = false;
- }
-
context->bw_ctx.bw.dcn.compbuf_size_kb = in_ctx->v20.dml_core_ctx.ip.config_return_buffer_size_in_kbytes;
for (dc_pipe_ctx_index = 0; dc_pipe_ctx_index < pipe_cnt; dc_pipe_ctx_index++) {
@@ -344,7 +335,8 @@ void dml2_calculate_rq_and_dlg_params(const struct dc *dc, struct dc_state *cont
context->res_ctx.pipe_ctx[dc_pipe_ctx_index].unbounded_req = false;
} else {
context->res_ctx.pipe_ctx[dc_pipe_ctx_index].det_buffer_size_kb = dml_get_det_buffer_size_kbytes(&context->bw_ctx.dml2->v20.dml_core_ctx, dml_pipe_idx);
- context->res_ctx.pipe_ctx[dc_pipe_ctx_index].unbounded_req = unbounded_req_enabled;
+ // Unbounded requesting should not ever be used when more than 1 pipe is enabled.
+ context->res_ctx.pipe_ctx[dc_pipe_ctx_index].unbounded_req = in_ctx->v20.dml_core_ctx.ms.UnboundedRequestEnabledThisState;
}
context->bw_ctx.bw.dcn.compbuf_size_kb -= context->res_ctx.pipe_ctx[dc_pipe_ctx_index].det_buffer_size_kb;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c
index 17cc2fdd7d34..d5dcc8b77281 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c
@@ -442,7 +442,6 @@ static bool optimize_pstate_with_svp_and_drr(struct dml2_context *dml2, struct d
bool result = false;
int drr_display_index = 0, non_svp_streams = 0;
bool force_svp = dml2->config.svp_pstate.force_enable_subvp;
- bool advanced_pstate_switching = false;
display_state->bw_ctx.bw.dcn.clk.fw_based_mclk_switching = false;
display_state->bw_ctx.bw.dcn.legacy_svp_drr_stream_index_valid = false;
@@ -451,8 +450,7 @@ static bool optimize_pstate_with_svp_and_drr(struct dml2_context *dml2, struct d
if (!result) {
pstate_optimization_done = true;
- } else if (!advanced_pstate_switching ||
- (s->mode_support_info.DRAMClockChangeSupport[0] != dml_dram_clock_change_unsupported && !force_svp)) {
+ } else if (s->mode_support_info.DRAMClockChangeSupport[0] != dml_dram_clock_change_unsupported && !force_svp) {
pstate_optimization_success = true;
pstate_optimization_done = true;
}
@@ -573,10 +571,7 @@ static bool dml2_validate_and_build_resource(const struct dc *in_dc, struct dc_s
bool need_recalculation = false;
uint32_t cstate_enter_plus_exit_z8_ns;
- if (!context)
- return true;
-
- else if (context->stream_count == 0) {
+ if (context->stream_count == 0) {
unsigned int lowest_state_idx = 0;
out_clks.p_state_supported = true;
@@ -675,12 +670,14 @@ static bool dml2_validate_and_build_resource(const struct dc *in_dc, struct dc_s
static bool dml2_validate_only(struct dc_state *context)
{
- struct dml2_context *dml2 = context->bw_ctx.dml2;
+ struct dml2_context *dml2;
unsigned int result = 0;
if (!context || context->stream_count == 0)
return true;
+ dml2 = context->bw_ctx.dml2;
+
/* Zero out before each call before proceeding */
memset(&dml2->v20.scratch, 0, sizeof(struct dml2_wrapper_scratch));
memset(&dml2->v20.dml_core_ctx.policy, 0, sizeof(struct dml_mode_eval_policy_st));
@@ -740,6 +737,7 @@ static void dml2_init(const struct dc *in_dc, const struct dml2_configuration_op
// TODO : Temporarily add DCN_VERSION_3_2 for N-1 validation. Remove DCN_VERSION_3_2 after N-1 validation phase is complete.
if ((in_dc->debug.using_dml21) && (in_dc->ctx->dce_version == DCN_VERSION_4_01 || in_dc->ctx->dce_version == DCN_VERSION_3_2)) {
dml21_reinit(in_dc, dml2, config);
+ return;
}
// Store config options
@@ -808,6 +806,12 @@ void dml2_extract_dram_and_fclk_change_support(struct dml2_context *dml2,
*dram_clk_change_support = (unsigned int) dml2->v20.dml_core_ctx.ms.support.DRAMClockChangeSupport[0];
}
+void dml2_prepare_mcache_programming(struct dc *in_dc, struct dc_state *context, struct dml2_context *dml2)
+{
+ if (dml2->architecture == dml2_architecture_21)
+ dml21_prepare_mcache_programming(in_dc, context, dml2);
+}
+
void dml2_copy(struct dml2_context *dst_dml2,
struct dml2_context *src_dml2)
{
@@ -841,9 +845,10 @@ void dml2_reinit(const struct dc *in_dc,
struct dml2_context **dml2)
{
// TODO : Temporarily add DCN_VERSION_3_2 for N-1 validation. Remove DCN_VERSION_3_2 after N-1 validation phase is complete.
- if ((in_dc->debug.using_dml21) && (in_dc->ctx->dce_version == DCN_VERSION_4_01 || in_dc->ctx->dce_version == DCN_VERSION_3_2)) {
- dml21_reinit(in_dc, dml2, config);
- }
+ if ((in_dc->debug.using_dml21) && (in_dc->ctx->dce_version == DCN_VERSION_4_01 || in_dc->ctx->dce_version == DCN_VERSION_3_2)) {
+ dml21_reinit(in_dc, dml2, config);
+ return;
+ }
dml2_init(in_dc, config, dml2);
}
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h
index 20b3970c0857..023325e8f6e2 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h
+++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h
@@ -230,7 +230,7 @@ struct dml2_configuration_options {
struct socbb_ip_params_external *external_socbb_ip_params;
struct {
bool force_pstate_method_enable;
- enum dml2_force_pstate_methods force_pstate_method_value;
+ enum dml2_force_pstate_methods force_pstate_method_values[MAX_PIPES];
} pmo;
bool map_dc_pipes_with_callbacks;
@@ -301,5 +301,5 @@ bool dml2_validate(const struct dc *in_dc,
*/
void dml2_extract_dram_and_fclk_change_support(struct dml2_context *dml2,
unsigned int *fclk_change_support, unsigned int *dram_clk_change_support);
-
+void dml2_prepare_mcache_programming(struct dc *in_dc, struct dc_state *context, struct dml2_context *dml2);
#endif //_DML2_WRAPPER_H_
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 f8c0cee34080..40acebd13e46 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
@@ -64,22 +64,23 @@ void dpp30_read_state(struct dpp *dpp_base, struct dcn_dpp_state *s)
}
// Shaper LUT (RAM), 3D LUT (mode, bit-depth, size)
- REG_GET(CM_SHAPER_CONTROL,
- CM_SHAPER_LUT_MODE, &s->shaper_lut_mode);
- REG_GET(CM_3DLUT_MODE,
- CM_3DLUT_MODE_CURRENT, &s->lut3d_mode);
- REG_GET(CM_3DLUT_READ_WRITE_CONTROL,
- CM_3DLUT_30BIT_EN, &s->lut3d_bit_depth);
- REG_GET(CM_3DLUT_MODE,
- CM_3DLUT_SIZE, &s->lut3d_size);
+ if (REG(CM_SHAPER_CONTROL))
+ REG_GET(CM_SHAPER_CONTROL, CM_SHAPER_LUT_MODE, &s->shaper_lut_mode);
+ if (REG(CM_3DLUT_MODE))
+ REG_GET(CM_3DLUT_MODE, CM_3DLUT_MODE_CURRENT, &s->lut3d_mode);
+ if (REG(CM_3DLUT_READ_WRITE_CONTROL))
+ REG_GET(CM_3DLUT_READ_WRITE_CONTROL, CM_3DLUT_30BIT_EN, &s->lut3d_bit_depth);
+ if (REG(CM_3DLUT_MODE))
+ REG_GET(CM_3DLUT_MODE, CM_3DLUT_SIZE, &s->lut3d_size);
// Blend/Out Gamma (RAM)
- REG_GET(CM_BLNDGAM_CONTROL,
- CM_BLNDGAM_MODE_CURRENT, &s->rgam_lut_mode);
- if (s->rgam_lut_mode){
- REG_GET(CM_BLNDGAM_CONTROL, CM_BLNDGAM_SELECT_CURRENT, &rgam_lut_mode);
- if (!rgam_lut_mode)
- s->rgam_lut_mode = LUT_RAM_A; // Otherwise, LUT_RAM_B
+ if (REG(CM_BLNDGAM_CONTROL)) {
+ REG_GET(CM_BLNDGAM_CONTROL, CM_BLNDGAM_MODE_CURRENT, &s->rgam_lut_mode);
+ if (s->rgam_lut_mode) {
+ REG_GET(CM_BLNDGAM_CONTROL, CM_BLNDGAM_SELECT_CURRENT, &rgam_lut_mode);
+ if (!rgam_lut_mode)
+ s->rgam_lut_mode = LUT_RAM_A; // Otherwise, LUT_RAM_B
+ }
}
}
@@ -218,7 +219,6 @@ void dpp3_cnv_setup (
uint32_t alpha_plane_enable = 0;
uint32_t dealpha_en = 0, dealpha_ablnd_en = 0;
uint32_t realpha_en = 0, realpha_ablnd_en = 0;
- uint32_t program_prealpha_dealpha = 0;
struct out_csc_color_matrix tbl_entry;
int i;
@@ -346,10 +346,6 @@ void dpp3_cnv_setup (
CNVC_ALPHA_PLANE_ENABLE, alpha_plane_enable);
REG_UPDATE(FORMAT_CONTROL, FORMAT_CONTROL__ALPHA_EN, alpha_en);
- if (program_prealpha_dealpha) {
- dealpha_en = 1;
- realpha_en = 1;
- }
REG_SET_2(PRE_DEALPHA, 0,
PRE_DEALPHA_EN, dealpha_en,
PRE_DEALPHA_ABLND_EN, dealpha_ablnd_en);
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.c
index eee64d8e1013..7cae18fd7be9 100644
--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.c
+++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.c
@@ -68,7 +68,6 @@ void dpp401_dpp_setup(
uint32_t alpha_plane_enable = 0;
uint32_t dealpha_en = 0, dealpha_ablnd_en = 0;
uint32_t realpha_en = 0, realpha_ablnd_en = 0;
- uint32_t program_prealpha_dealpha = 0;
struct out_csc_color_matrix tbl_entry;
int i;
@@ -192,10 +191,6 @@ void dpp401_dpp_setup(
CNVC_ALPHA_PLANE_ENABLE, alpha_plane_enable);
REG_UPDATE(FORMAT_CONTROL, FORMAT_CONTROL__ALPHA_EN, alpha_en);
- if (program_prealpha_dealpha) {
- dealpha_en = 1;
- realpha_en = 1;
- }
REG_SET_2(PRE_DEALPHA, 0,
PRE_DEALPHA_EN, dealpha_en,
PRE_DEALPHA_ABLND_EN, dealpha_ablnd_en);
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 aef73bd1221a..d0f8c9ff5232 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
@@ -153,58 +153,8 @@ void dpp401_set_cursor_position(
uint32_t height)
{
struct dcn401_dpp *dpp = TO_DCN401_DPP(dpp_base);
- int x_pos = pos->x - param->recout.x;
- int y_pos = pos->y - param->recout.y;
- int x_hotspot = pos->x_hotspot;
- int y_hotspot = pos->y_hotspot;
- int rec_x_offset = x_pos - pos->x_hotspot;
- int rec_y_offset = y_pos - pos->y_hotspot;
- int cursor_height = (int)height;
- int cursor_width = (int)width;
uint32_t cur_en = pos->enable ? 1 : 0;
- // Transform cursor width / height and hotspots for offset calculations
- if (param->rotation == ROTATION_ANGLE_90 || param->rotation == ROTATION_ANGLE_270) {
- swap(cursor_height, cursor_width);
- swap(x_hotspot, y_hotspot);
-
- if (param->rotation == ROTATION_ANGLE_90) {
- // hotspot = (-y, x)
- rec_x_offset = x_pos - (cursor_width - x_hotspot);
- rec_y_offset = y_pos - y_hotspot;
- } else if (param->rotation == ROTATION_ANGLE_270) {
- // hotspot = (y, -x)
- rec_x_offset = x_pos - x_hotspot;
- rec_y_offset = y_pos - (cursor_height - y_hotspot);
- }
- } else if (param->rotation == ROTATION_ANGLE_180) {
- // hotspot = (-x, -y)
- if (!param->mirror)
- rec_x_offset = x_pos - (cursor_width - x_hotspot);
-
- rec_y_offset = y_pos - (cursor_height - y_hotspot);
- }
-
- if (param->rotation == ROTATION_ANGLE_0 && !param->mirror) {
- if (rec_x_offset >= (int)param->recout.width)
- cur_en = 0; /* not visible beyond right edge*/
-
- if (rec_y_offset >= (int)param->recout.height)
- cur_en = 0; /* not visible beyond bottom edge*/
- } else {
- if (rec_x_offset > (int)param->recout.width)
- cur_en = 0; /* not visible beyond right edge*/
-
- if (rec_y_offset > (int)param->recout.height)
- cur_en = 0; /* not visible beyond bottom edge*/
- }
-
- if (rec_x_offset + cursor_width <= 0)
- cur_en = 0; /* not visible beyond left edge*/
-
- if (rec_y_offset + cursor_height <= 0)
- cur_en = 0; /* not visible beyond top edge*/
-
REG_UPDATE(CURSOR0_CONTROL, CUR0_ENABLE, cur_en);
dpp_base->pos.cur0_ctl.bits.cur0_enable = cur_en;
diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.c
index d6b2334d5364..75128fd34306 100644
--- a/drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.c
+++ b/drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.c
@@ -32,16 +32,6 @@
static void dsc_write_to_registers(struct display_stream_compressor *dsc, const struct dsc_reg_values *reg_vals);
-/* Object I/F functions */
-static void dsc2_read_state(struct display_stream_compressor *dsc, struct dcn_dsc_state *s);
-static bool dsc2_validate_stream(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg);
-static void dsc2_set_config(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg,
- struct dsc_optc_config *dsc_optc_cfg);
-static void dsc2_enable(struct display_stream_compressor *dsc, int opp_pipe);
-static void dsc2_disable(struct display_stream_compressor *dsc);
-static void dsc2_disconnect(struct display_stream_compressor *dsc);
-static void dsc2_wait_disconnect_pending_clear(struct display_stream_compressor *dsc);
-
static const struct dsc_funcs dcn20_dsc_funcs = {
.dsc_get_enc_caps = dsc2_get_enc_caps,
.dsc_read_state = dsc2_read_state,
@@ -156,7 +146,7 @@ void dsc2_get_enc_caps(struct dsc_enc_caps *dsc_enc_caps, int pixel_clock_100Hz)
/* this function read dsc related register fields to be logged later in dcn10_log_hw_state
* into a dcn_dsc_state struct.
*/
-static void dsc2_read_state(struct display_stream_compressor *dsc, struct dcn_dsc_state *s)
+void dsc2_read_state(struct display_stream_compressor *dsc, struct dcn_dsc_state *s)
{
struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc);
@@ -173,7 +163,7 @@ static void dsc2_read_state(struct display_stream_compressor *dsc, struct dcn_ds
}
-static bool dsc2_validate_stream(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg)
+bool dsc2_validate_stream(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg)
{
struct dsc_optc_config dsc_optc_cfg;
struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc);
@@ -196,7 +186,7 @@ void dsc_config_log(struct display_stream_compressor *dsc, const struct dsc_conf
DC_LOG_DSC("\tcolor_depth %d", config->color_depth);
}
-static void dsc2_set_config(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg,
+void dsc2_set_config(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg,
struct dsc_optc_config *dsc_optc_cfg)
{
bool is_config_ok;
@@ -233,7 +223,7 @@ bool dsc2_get_packed_pps(struct display_stream_compressor *dsc, const struct dsc
}
-static void dsc2_enable(struct display_stream_compressor *dsc, int opp_pipe)
+void dsc2_enable(struct display_stream_compressor *dsc, int opp_pipe)
{
struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc);
int dsc_clock_en;
@@ -258,7 +248,7 @@ static void dsc2_enable(struct display_stream_compressor *dsc, int opp_pipe)
}
-static void dsc2_disable(struct display_stream_compressor *dsc)
+void dsc2_disable(struct display_stream_compressor *dsc)
{
struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc);
int dsc_clock_en;
@@ -277,14 +267,14 @@ static void dsc2_disable(struct display_stream_compressor *dsc)
DSC_CLOCK_EN, 0);
}
-static void dsc2_wait_disconnect_pending_clear(struct display_stream_compressor *dsc)
+void dsc2_wait_disconnect_pending_clear(struct display_stream_compressor *dsc)
{
struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc);
REG_WAIT(DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_DOUBLE_BUFFER_REG_UPDATE_PENDING, 0, 2, 50000);
}
-static void dsc2_disconnect(struct display_stream_compressor *dsc)
+void dsc2_disconnect(struct display_stream_compressor *dsc)
{
struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc);
diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.h b/drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.h
index a136b26c914c..1fb90b52b814 100644
--- a/drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.h
+++ b/drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.h
@@ -454,7 +454,9 @@
type DSCCIF_UPDATE_TAKEN_ACK; \
type DSCRM_DSC_FORWARD_EN; \
type DSCRM_DSC_OPP_PIPE_SOURCE; \
- type DSCRM_DSC_DOUBLE_BUFFER_REG_UPDATE_PENDING
+ type DSCRM_DSC_DOUBLE_BUFFER_REG_UPDATE_PENDING; \
+ type DSCRM_DSC_FORWARD_EN_STATUS
+
struct dcn20_dsc_registers {
uint32_t DSC_TOP_CONTROL;
@@ -597,5 +599,14 @@ bool dsc2_get_packed_pps(struct display_stream_compressor *dsc,
const struct dsc_config *dsc_cfg,
uint8_t *dsc_packed_pps);
+void dsc2_read_state(struct display_stream_compressor *dsc, struct dcn_dsc_state *s);
+bool dsc2_validate_stream(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg);
+void dsc2_set_config(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg,
+ struct dsc_optc_config *dsc_optc_cfg);
+void dsc2_enable(struct display_stream_compressor *dsc, int opp_pipe);
+void dsc2_disable(struct display_stream_compressor *dsc);
+void dsc2_disconnect(struct display_stream_compressor *dsc);
+void dsc2_wait_disconnect_pending_clear(struct display_stream_compressor *dsc);
+
#endif
diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dcn35/dcn35_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dcn35/dcn35_dsc.c
index 71d2dff9986d..6f4f5a3c4861 100644
--- a/drivers/gpu/drm/amd/display/dc/dsc/dcn35/dcn35_dsc.c
+++ b/drivers/gpu/drm/amd/display/dc/dsc/dcn35/dcn35_dsc.c
@@ -27,6 +27,20 @@
#include "dcn35_dsc.h"
#include "reg_helper.h"
+static void dsc35_enable(struct display_stream_compressor *dsc, int opp_pipe);
+
+static const struct dsc_funcs dcn35_dsc_funcs = {
+ .dsc_get_enc_caps = dsc2_get_enc_caps,
+ .dsc_read_state = dsc2_read_state,
+ .dsc_validate_stream = dsc2_validate_stream,
+ .dsc_set_config = dsc2_set_config,
+ .dsc_get_packed_pps = dsc2_get_packed_pps,
+ .dsc_enable = dsc35_enable,
+ .dsc_disable = dsc2_disable,
+ .dsc_disconnect = dsc2_disconnect,
+ .dsc_wait_disconnect_pending_clear = dsc2_wait_disconnect_pending_clear,
+};
+
/* Macro definitios for REG_SET macros*/
#define CTX \
dsc20->base.ctx
@@ -49,9 +63,47 @@ void dsc35_construct(struct dcn20_dsc *dsc,
const struct dcn35_dsc_shift *dsc_shift,
const struct dcn35_dsc_mask *dsc_mask)
{
- dsc2_construct(dsc, ctx, inst, dsc_regs,
- (const struct dcn20_dsc_shift *)(dsc_shift),
- (const struct dcn20_dsc_mask *)(dsc_mask));
+ dsc->base.ctx = ctx;
+ dsc->base.inst = inst;
+ dsc->base.funcs = &dcn35_dsc_funcs;
+
+ dsc->dsc_regs = dsc_regs;
+ dsc->dsc_shift = (const struct dcn20_dsc_shift *)(dsc_shift);
+ dsc->dsc_mask = (const struct dcn20_dsc_mask *)(dsc_mask);
+
+ dsc->max_image_width = 5184;
+}
+
+static void dsc35_enable(struct display_stream_compressor *dsc, int opp_pipe)
+{
+ struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc);
+ int dsc_clock_en;
+ int dsc_fw_config;
+ int enabled_opp_pipe;
+
+ DC_LOG_DSC("enable DSC %d at opp pipe %d", dsc->inst, opp_pipe);
+
+ // TODO: After an idle exit, the HW default values for power control
+ // are changed intermittently due to unknown reasons. There are cases
+ // when dscc memory are still in shutdown state during enablement.
+ // Reset power control to hw default values.
+ REG_UPDATE_2(DSCC_MEM_POWER_CONTROL,
+ DSCC_MEM_PWR_FORCE, 0,
+ DSCC_MEM_PWR_DIS, 0);
+
+ REG_GET(DSC_TOP_CONTROL, DSC_CLOCK_EN, &dsc_clock_en);
+ REG_GET_2(DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_FORWARD_EN, &dsc_fw_config, DSCRM_DSC_OPP_PIPE_SOURCE, &enabled_opp_pipe);
+ if ((dsc_clock_en || dsc_fw_config) && enabled_opp_pipe != opp_pipe) {
+ DC_LOG_DSC("ERROR: DSC %d at opp pipe %d already enabled!", dsc->inst, enabled_opp_pipe);
+ ASSERT(0);
+ }
+
+ REG_UPDATE(DSC_TOP_CONTROL,
+ DSC_CLOCK_EN, 1);
+
+ REG_UPDATE_2(DSCRM_DSC_FORWARD_CONFIG,
+ DSCRM_DSC_FORWARD_EN, 1,
+ DSCRM_DSC_OPP_PIPE_SOURCE, opp_pipe);
}
void dsc35_set_fgcg(struct dcn20_dsc *dsc20, bool enable)
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 52f23bb554af..6acb6699f146 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
@@ -208,7 +208,7 @@ static void dsc401_wait_disconnect_pending_clear(struct display_stream_compresso
{
struct dcn401_dsc *dsc401 = TO_DCN401_DSC(dsc);
- REG_WAIT(DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_DOUBLE_BUFFER_REG_UPDATE_PENDING, 0, 2, 50000);
+ REG_WAIT(DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_FORWARD_EN_STATUS, 0, 2, 50000);
}
static void dsc401_disconnect(struct display_stream_compressor *dsc)
diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.h b/drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.h
index 2143e81ca22a..3c9fa8988974 100644
--- a/drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.h
+++ b/drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.h
@@ -196,7 +196,8 @@
DSC2_SF(DSCCIF0, DSCCIF_CONFIG0__BITS_PER_COMPONENT, mask_sh), \
DSC_SF(DSCCIF0_DSCCIF_CONFIG0, DOUBLE_BUFFER_REG_UPDATE_PENDING, mask_sh), \
DSC_SF(DSCRM0_DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_FORWARD_EN, mask_sh), \
- DSC_SF(DSCRM0_DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_OPP_PIPE_SOURCE, mask_sh)
+ DSC_SF(DSCRM0_DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_OPP_PIPE_SOURCE, mask_sh), \
+ DSC_SF(DSCRM0_DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_FORWARD_EN_STATUS, mask_sh)
struct dcn401_dsc_registers {
uint32_t DSC_TOP_CONTROL;
diff --git a/drivers/gpu/drm/amd/display/dc/dwb/Makefile b/drivers/gpu/drm/amd/display/dc/dwb/Makefile
new file mode 100644
index 000000000000..16f7a454fed9
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dwb/Makefile
@@ -0,0 +1,37 @@
+#
+# Copyright 2020 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
+#
+#
+
+ifdef CONFIG_DRM_AMD_DC_FP
+###############################################################################
+# DCN35
+###############################################################################
+DWB_DCN35 = dcn35_dwb.o
+
+AMD_DAL_DWB_DCN35 = $(addprefix $(AMDDALPATH)/dc/dwb/dcn35/,$(DWB_DCN35))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_DWB_DCN35)
+
+
+endif
diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dwb.c b/drivers/gpu/drm/amd/display/dc/dwb/dcn35/dcn35_dwb.c
index b23a809999ed..b23a809999ed 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dwb.c
+++ b/drivers/gpu/drm/amd/display/dc/dwb/dcn35/dcn35_dwb.c
diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dwb.h b/drivers/gpu/drm/amd/display/dc/dwb/dcn35/dcn35_dwb.h
index 886e727ed080..886e727ed080 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dwb.h
+++ b/drivers/gpu/drm/amd/display/dc/dwb/dcn35/dcn35_dwb.h
diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c
index 525bc8881950..d9e6e70dc394 100644
--- a/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c
+++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c
@@ -170,8 +170,7 @@ static enum gpio_result set_config(
return GPIO_RESULT_OK;
case GPIO_DDC_CONFIG_TYPE_POLL_FOR_CONNECT:
- if ((hw_gpio->base.en >= GPIO_DDC_LINE_DDC1) &&
- (hw_gpio->base.en <= GPIO_DDC_LINE_DDC_VGA)) {
+ if (hw_gpio->base.en <= GPIO_DDC_LINE_DDC_VGA) {
REG_UPDATE_3(ddc_setup,
DC_I2C_DDC1_ENABLE, 1,
DC_I2C_DDC1_EDID_DETECT_ENABLE, 1,
@@ -180,8 +179,7 @@ static enum gpio_result set_config(
}
break;
case GPIO_DDC_CONFIG_TYPE_POLL_FOR_DISCONNECT:
- if ((hw_gpio->base.en >= GPIO_DDC_LINE_DDC1) &&
- (hw_gpio->base.en <= GPIO_DDC_LINE_DDC_VGA)) {
+ if (hw_gpio->base.en <= GPIO_DDC_LINE_DDC_VGA) {
REG_UPDATE_3(ddc_setup,
DC_I2C_DDC1_ENABLE, 1,
DC_I2C_DDC1_EDID_DETECT_ENABLE, 1,
@@ -190,8 +188,7 @@ static enum gpio_result set_config(
}
break;
case GPIO_DDC_CONFIG_TYPE_DISABLE_POLLING:
- if ((hw_gpio->base.en >= GPIO_DDC_LINE_DDC1) &&
- (hw_gpio->base.en <= GPIO_DDC_LINE_DDC_VGA)) {
+ if (hw_gpio->base.en <= GPIO_DDC_LINE_DDC_VGA) {
REG_UPDATE_2(ddc_setup,
DC_I2C_DDC1_ENABLE, 0,
DC_I2C_DDC1_EDID_DETECT_ENABLE, 0);
@@ -231,7 +228,7 @@ void dal_hw_ddc_init(
enum gpio_id id,
uint32_t en)
{
- if ((en < GPIO_DDC_LINE_MIN) || (en > GPIO_DDC_LINE_MAX)) {
+ if (en > GPIO_DDC_LINE_MAX) {
ASSERT_CRITICAL(false);
*hw_ddc = NULL;
}
diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_generic.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_generic.c
index f9e847e6555d..6cd50232c432 100644
--- a/drivers/gpu/drm/amd/display/dc/gpio/hw_generic.c
+++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_generic.c
@@ -106,7 +106,7 @@ void dal_hw_generic_init(
enum gpio_id id,
uint32_t en)
{
- if ((en < GPIO_DDC_LINE_MIN) || (en > GPIO_DDC_LINE_MAX)) {
+ if (en > GPIO_DDC_LINE_MAX) {
ASSERT_CRITICAL(false);
*hw_generic = NULL;
}
diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.c
index 1489fdfaf0e7..3f13a744d07d 100644
--- a/drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.c
+++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.c
@@ -127,7 +127,7 @@ void dal_hw_hpd_init(
enum gpio_id id,
uint32_t en)
{
- if ((en < GPIO_DDC_LINE_MIN) || (en > GPIO_DDC_LINE_MAX)) {
+ if (en > GPIO_DDC_LINE_MAX) {
ASSERT_CRITICAL(false);
*hw_hpd = NULL;
}
diff --git a/drivers/gpu/drm/amd/display/dc/hpo/Makefile b/drivers/gpu/drm/amd/display/dc/hpo/Makefile
new file mode 100644
index 000000000000..c248bd86b477
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/hpo/Makefile
@@ -0,0 +1,35 @@
+#
+# Copyright 2020 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
+#
+#
+
+ifdef CONFIG_DRM_AMD_DC_FP
+###############################################################################
+# DCN32
+###############################################################################
+HPO_DCN32 = dcn32_hpo_dp_link_encoder.o
+
+AMD_DAL_HPO_DCN32 = $(addprefix $(AMDDALPATH)/dc/hpo/dcn32/,$(HPO_DCN32))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_HPO_DCN32)
+endif
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hpo_dp_link_encoder.c b/drivers/gpu/drm/amd/display/dc/hpo/dcn32/dcn32_hpo_dp_link_encoder.c
index 8af01f579690..8af01f579690 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hpo_dp_link_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/hpo/dcn32/dcn32_hpo_dp_link_encoder.c
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hpo_dp_link_encoder.h b/drivers/gpu/drm/amd/display/dc/hpo/dcn32/dcn32_hpo_dp_link_encoder.h
index 176b1537d2a1..176b1537d2a1 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hpo_dp_link_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/hpo/dcn32/dcn32_hpo_dp_link_encoder.h
diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn20/dcn20_hubbub.c b/drivers/gpu/drm/amd/display/dc/hubbub/dcn20/dcn20_hubbub.c
index 8901bd80f7d1..5c6f7ddafd6b 100644
--- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn20/dcn20_hubbub.c
+++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn20/dcn20_hubbub.c
@@ -616,7 +616,8 @@ static bool hubbub2_program_watermarks(
hubbub1->base.ctx->dc->clk_mgr->clks.p_state_change_support == false)
safe_to_lower = true;
- hubbub1_program_pstate_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower);
+ if (hubbub1_program_pstate_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower))
+ wm_pending = true;
REG_SET(DCHUBBUB_ARB_SAT_LEVEL, 0,
DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz);
diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn30/dcn30_hubbub.c b/drivers/gpu/drm/amd/display/dc/hubbub/dcn30/dcn30_hubbub.c
index 6a5af3da4b45..fe741100c0f8 100644
--- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn30/dcn30_hubbub.c
+++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn30/dcn30_hubbub.c
@@ -339,6 +339,7 @@ bool hubbub3_get_dcc_compression_cap(struct hubbub *hubbub,
return false;
switch (dcc_control) {
+ case dcc_control__256_256:
case dcc_control__256_256_xxx:
output->grph.rgb.max_uncompressed_blk_size = 256;
output->grph.rgb.max_compressed_blk_size = 256;
@@ -346,6 +347,7 @@ bool hubbub3_get_dcc_compression_cap(struct hubbub *hubbub,
output->grph.rgb.dcc_controls.dcc_256_256_unconstrained = 1;
output->grph.rgb.dcc_controls.dcc_256_128_128 = 1;
break;
+ case dcc_control__256_128:
case dcc_control__128_128_xxx:
output->grph.rgb.max_uncompressed_blk_size = 128;
output->grph.rgb.max_compressed_blk_size = 128;
@@ -353,6 +355,7 @@ bool hubbub3_get_dcc_compression_cap(struct hubbub *hubbub,
output->grph.rgb.dcc_controls.dcc_128_128_uncontrained = 1;
output->grph.rgb.dcc_controls.dcc_256_128_128 = 1;
break;
+ case dcc_control__256_64:
case dcc_control__256_64_64:
output->grph.rgb.max_uncompressed_blk_size = 256;
output->grph.rgb.max_compressed_blk_size = 64;
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 b906db6e7355..7fb5523f9722 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
@@ -866,6 +866,7 @@ static bool hubbub31_get_dcc_compression_cap(struct hubbub *hubbub,
return false;
switch (dcc_control) {
+ case dcc_control__256_256:
case dcc_control__256_256_xxx:
output->grph.rgb.max_uncompressed_blk_size = 256;
output->grph.rgb.max_compressed_blk_size = 256;
@@ -881,12 +882,14 @@ static bool hubbub31_get_dcc_compression_cap(struct hubbub *hubbub,
output->grph.rgb.dcc_controls.dcc_256_128_128 = 1;
break;
case dcc_control__256_64_64:
+ case dcc_control__256_64:
output->grph.rgb.max_uncompressed_blk_size = 256;
output->grph.rgb.max_compressed_blk_size = 64;
output->grph.rgb.independent_64b_blks = true;
output->grph.rgb.dcc_controls.dcc_256_64_64 = 1;
break;
case dcc_control__256_128_128:
+ case dcc_control__256_128:
output->grph.rgb.max_uncompressed_blk_size = 256;
output->grph.rgb.max_compressed_blk_size = 128;
output->grph.rgb.independent_64b_blks = false;
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 054607c944a3..181041d6d177 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
@@ -824,6 +824,291 @@ void hubbub401_det_request_size(
}
}
}
+bool hubbub401_get_dcc_compression_cap(struct hubbub *hubbub,
+ const struct dc_dcc_surface_param *input,
+ struct dc_surface_dcc_cap *output)
+{
+ struct dc *dc = hubbub->ctx->dc;
+ const unsigned int max_dcc_plane_width = dc->caps.dcc_plane_width_limit;
+ /* DCN4_Programming_Guide_DCHUB.docx, Section 5.11.2.2 */
+ enum dcc_control dcc_control;
+ unsigned int plane0_bpe, plane1_bpe;
+ enum segment_order segment_order_horz, segment_order_vert;
+ enum segment_order p1_segment_order_horz, p1_segment_order_vert;
+ bool req128_horz_wc, req128_vert_wc;
+ unsigned int plane0_width = 0, plane0_height = 0, plane1_width = 0, plane1_height = 0;
+ bool p1_req128_horz_wc, p1_req128_vert_wc, is_dual_plane;
+
+ memset(output, 0, sizeof(*output));
+
+ if (dc->debug.disable_dcc == DCC_DISABLE)
+ return false;
+
+ /* Conservatively disable DCC for cases where ODM4:1 may be required. */
+ if (max_dcc_plane_width != 0 &&
+ (input->surface_size.width > max_dcc_plane_width || input->plane1_size.width > max_dcc_plane_width))
+ return false;
+
+ switch (input->format) {
+ default:
+ is_dual_plane = false;
+
+ plane1_width = 0;
+ plane1_height = 0;
+
+ if (input->surface_size.width > 6144 + 16)
+ plane0_width = 6160;
+ else
+ plane0_width = input->surface_size.width;
+
+ if (input->surface_size.height > 6144 + 16)
+ plane0_height = 6160;
+ else
+ plane0_height = input->surface_size.height;
+
+ break;
+ case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
+ case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
+ case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
+ case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
+ is_dual_plane = true;
+
+ if (input->surface_size.width > 7680 + 16)
+ plane0_width = 7696;
+ else
+ plane0_width = input->surface_size.width;
+
+ if (input->surface_size.height > 4320 + 16)
+ plane0_height = 4336;
+ else
+ plane0_height = input->surface_size.height;
+
+ if (input->plane1_size.width > 7680 + 16)
+ plane1_width = 7696 / 2;
+ else
+ plane1_width = input->plane1_size.width;
+
+ if (input->plane1_size.height > 4320 + 16)
+ plane1_height = 4336 / 2;
+ else
+ plane1_height = input->plane1_size.height;
+
+ break;
+
+ case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA:
+ is_dual_plane = true;
+
+ if (input->surface_size.width > 5120 + 16)
+ plane0_width = 5136;
+ else
+ plane0_width = input->surface_size.width;
+
+ if (input->surface_size.height > 5120 + 16)
+ plane0_height = 5136;
+ else
+ plane0_height = input->surface_size.height;
+
+ if (input->plane1_size.width > 5120 + 16)
+ plane1_width = 5136;
+ else
+ plane1_width = input->plane1_size.width;
+
+ if (input->plane1_size.height > 5120 + 16)
+ plane1_height = 5136;
+ else
+ plane1_height = input->plane1_size.height;
+
+ break;
+ }
+
+ if (!hubbub->funcs->dcc_support_pixel_format_plane0_plane1(input->format,
+ &plane0_bpe, &plane1_bpe))
+ return false;
+
+ /* Find plane0 DCC Controls */
+ if (!is_dual_plane) {
+
+ if (!hubbub->funcs->dcc_support_swizzle_addr3(input->swizzle_mode_addr3,
+ input->plane0_pitch, plane0_bpe,
+ &segment_order_horz, &segment_order_vert))
+ return false;
+
+ hubbub401_det_request_size(TO_DCN20_HUBBUB(hubbub)->detile_buf_size, input->format,
+ plane0_height, plane0_width, plane0_bpe,
+ plane1_height, plane1_width, plane1_bpe,
+ &req128_horz_wc, &req128_vert_wc, &p1_req128_horz_wc, &p1_req128_vert_wc);
+
+ if (!req128_horz_wc && !req128_vert_wc) {
+ dcc_control = dcc_control__256_256;
+ } else if (input->scan == SCAN_DIRECTION_HORIZONTAL) {
+ if (!req128_horz_wc)
+ dcc_control = dcc_control__256_256;
+ else if (segment_order_horz == segment_order__contiguous)
+ dcc_control = dcc_control__256_128;
+ else
+ dcc_control = dcc_control__256_64;
+ } else if (input->scan == SCAN_DIRECTION_VERTICAL) {
+ if (!req128_vert_wc)
+ dcc_control = dcc_control__256_256;
+ else if (segment_order_vert == segment_order__contiguous)
+ dcc_control = dcc_control__256_128;
+ else
+ dcc_control = dcc_control__256_64;
+ } else {
+ if ((req128_horz_wc &&
+ segment_order_horz == segment_order__non_contiguous) ||
+ (req128_vert_wc &&
+ segment_order_vert == segment_order__non_contiguous))
+ /* access_dir not known, must use most constraining */
+ dcc_control = dcc_control__256_64;
+ else
+ /* req128 is true for either horz and vert
+ * but segment_order is contiguous
+ */
+ dcc_control = dcc_control__256_128;
+ }
+
+ if (dc->debug.disable_dcc == DCC_HALF_REQ_DISALBE &&
+ dcc_control != dcc_control__256_256)
+ return false;
+
+ switch (dcc_control) {
+ case dcc_control__256_256:
+ output->grph.rgb.dcc_controls.dcc_256_256 = 1;
+ output->grph.rgb.dcc_controls.dcc_256_128 = 1;
+ output->grph.rgb.dcc_controls.dcc_256_64 = 1;
+ break;
+ case dcc_control__256_128:
+ output->grph.rgb.dcc_controls.dcc_256_128 = 1;
+ output->grph.rgb.dcc_controls.dcc_256_64 = 1;
+ break;
+ case dcc_control__256_64:
+ output->grph.rgb.dcc_controls.dcc_256_64 = 1;
+ break;
+ default:
+ /* Shouldn't get here */
+ ASSERT(0);
+ break;
+ }
+ } else {
+ /* For dual plane cases, need to examine both planes together */
+ if (!hubbub->funcs->dcc_support_swizzle_addr3(input->swizzle_mode_addr3,
+ input->plane0_pitch, plane0_bpe,
+ &segment_order_horz, &segment_order_vert))
+ return false;
+
+ if (!hubbub->funcs->dcc_support_swizzle_addr3(input->swizzle_mode_addr3,
+ input->plane1_pitch, plane1_bpe,
+ &p1_segment_order_horz, &p1_segment_order_vert))
+ return false;
+
+ hubbub401_det_request_size(TO_DCN20_HUBBUB(hubbub)->detile_buf_size, input->format,
+ plane0_height, plane0_width, plane0_bpe,
+ plane1_height, plane1_width, plane1_bpe,
+ &req128_horz_wc, &req128_vert_wc, &p1_req128_horz_wc, &p1_req128_vert_wc);
+
+ /* Determine Plane 0 DCC Controls */
+ if (!req128_horz_wc && !req128_vert_wc) {
+ dcc_control = dcc_control__256_256;
+ } else if (input->scan == SCAN_DIRECTION_HORIZONTAL) {
+ if (!req128_horz_wc)
+ dcc_control = dcc_control__256_256;
+ else if (segment_order_horz == segment_order__contiguous)
+ dcc_control = dcc_control__256_128;
+ else
+ dcc_control = dcc_control__256_64;
+ } else if (input->scan == SCAN_DIRECTION_VERTICAL) {
+ if (!req128_vert_wc)
+ dcc_control = dcc_control__256_256;
+ else if (segment_order_vert == segment_order__contiguous)
+ dcc_control = dcc_control__256_128;
+ else
+ dcc_control = dcc_control__256_64;
+ } else {
+ if ((req128_horz_wc &&
+ segment_order_horz == segment_order__non_contiguous) ||
+ (req128_vert_wc &&
+ segment_order_vert == segment_order__non_contiguous))
+ /* access_dir not known, must use most constraining */
+ dcc_control = dcc_control__256_64;
+ else
+ /* req128 is true for either horz and vert
+ * but segment_order is contiguous
+ */
+ dcc_control = dcc_control__256_128;
+ }
+
+ switch (dcc_control) {
+ case dcc_control__256_256:
+ output->video.luma.dcc_controls.dcc_256_256 = 1;
+ output->video.luma.dcc_controls.dcc_256_128 = 1;
+ output->video.luma.dcc_controls.dcc_256_64 = 1;
+ break;
+ case dcc_control__256_128:
+ output->video.luma.dcc_controls.dcc_256_128 = 1;
+ output->video.luma.dcc_controls.dcc_256_64 = 1;
+ break;
+ case dcc_control__256_64:
+ output->video.luma.dcc_controls.dcc_256_64 = 1;
+ break;
+ default:
+ ASSERT(0);
+ break;
+ }
+
+ /* Determine Plane 1 DCC Controls */
+ if (!p1_req128_horz_wc && !p1_req128_vert_wc) {
+ dcc_control = dcc_control__256_256;
+ } else if (input->scan == SCAN_DIRECTION_HORIZONTAL) {
+ if (!p1_req128_horz_wc)
+ dcc_control = dcc_control__256_256;
+ else if (p1_segment_order_horz == segment_order__contiguous)
+ dcc_control = dcc_control__256_128;
+ else
+ dcc_control = dcc_control__256_64;
+ } else if (input->scan == SCAN_DIRECTION_VERTICAL) {
+ if (!p1_req128_vert_wc)
+ dcc_control = dcc_control__256_256;
+ else if (p1_segment_order_vert == segment_order__contiguous)
+ dcc_control = dcc_control__256_128;
+ else
+ dcc_control = dcc_control__256_64;
+ } else {
+ if ((p1_req128_horz_wc &&
+ p1_segment_order_horz == segment_order__non_contiguous) ||
+ (p1_req128_vert_wc &&
+ p1_segment_order_vert == segment_order__non_contiguous))
+ /* access_dir not known, must use most constraining */
+ dcc_control = dcc_control__256_64;
+ else
+ /* req128 is true for either horz and vert
+ * but segment_order is contiguous
+ */
+ dcc_control = dcc_control__256_128;
+ }
+
+ switch (dcc_control) {
+ case dcc_control__256_256:
+ output->video.chroma.dcc_controls.dcc_256_256 = 1;
+ output->video.chroma.dcc_controls.dcc_256_128 = 1;
+ output->video.chroma.dcc_controls.dcc_256_64 = 1;
+ break;
+ case dcc_control__256_128:
+ output->video.chroma.dcc_controls.dcc_256_128 = 1;
+ output->video.chroma.dcc_controls.dcc_256_64 = 1;
+ break;
+ case dcc_control__256_64:
+ output->video.chroma.dcc_controls.dcc_256_64 = 1;
+ break;
+ default:
+ ASSERT(0);
+ break;
+ }
+ }
+
+ output->capable = true;
+ return true;
+}
static void dcn401_program_det_segments(struct hubbub *hubbub, int hubp_inst, unsigned det_buffer_size_seg)
{
@@ -891,6 +1176,7 @@ static const struct hubbub_funcs hubbub4_01_funcs = {
.init_vm_ctx = hubbub2_init_vm_ctx,
.dcc_support_swizzle_addr3 = hubbub401_dcc_support_swizzle,
.dcc_support_pixel_format_plane0_plane1 = hubbub401_dcc_support_pixel_format,
+ .get_dcc_compression_cap = hubbub401_get_dcc_compression_cap,
.wm_read_state = hubbub401_wm_read_state,
.get_dchub_ref_freq = hubbub2_get_dchub_ref_freq,
.program_watermarks = hubbub401_program_watermarks,
diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.h b/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.h
index d8a57f64a70c..f35f19ba3e18 100644
--- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.h
@@ -180,6 +180,11 @@ void hubbub401_det_request_size(
bool *p0_req128_vert_wc,
bool *p1_req128_horz_wc,
bool *p1_req128_vert_wc);
+bool hubbub401_get_dcc_compression_cap(
+ struct hubbub *hubbub,
+ const struct dc_dcc_surface_param *input,
+ struct dc_surface_dcc_cap *output);
+
void hubbub401_construct(struct dcn20_hubbub *hubbub2,
struct dc_context *ctx,
const struct dcn_hubbub_registers *hubbub_regs,
diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.h b/drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.h
index ecc0a2f37938..18e194507e36 100644
--- a/drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.h
+++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.h
@@ -175,6 +175,8 @@
uint32_t HUBP_3DLUT_ADDRESS_LOW;\
uint32_t HUBP_3DLUT_CONTROL;\
uint32_t HUBP_3DLUT_DLG_PARAM;\
+ uint32_t DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE;\
+ uint32_t DCHUBP_MCACHEID_CONFIG
#define DCN2_HUBP_REG_FIELD_VARIABLE_LIST(type) \
DCN_HUBP_REG_FIELD_BASE_LIST(type); \
@@ -269,6 +271,18 @@
type HUBP_3DLUT_ADDRESS_HIGH;\
type HUBP_3DLUT_ADDRESS_LOW;\
type REFCYC_PER_3DLUT_GROUP;\
+ type VIEWPORT_MCACHE_SPLIT_COORDINATE;\
+ type VIEWPORT_MCACHE_SPLIT_COORDINATE_C;\
+ type MCACHEID_REG_READ_1H_P0;\
+ type MCACHEID_REG_READ_2H_P0;\
+ type MCACHEID_REG_READ_1H_P1;\
+ type MCACHEID_REG_READ_2H_P1;\
+ type MCACHEID_MALL_PREF_1H_P0;\
+ type MCACHEID_MALL_PREF_2H_P0;\
+ type MCACHEID_MALL_PREF_1H_P1;\
+ type MCACHEID_MALL_PREF_2H_P1
+
+
struct dcn_hubp2_registers {
DCN401_HUBP_REG_COMMON_VARIABLE_LIST;
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 6692d57d5cce..eb0da6c6b87c 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
@@ -626,6 +626,26 @@ void hubp401_set_viewport(
SEC_VIEWPORT_Y_START_C, viewport_c->y);
}
+void hubp401_program_mcache_id_and_split_coordinate(
+ struct hubp *hubp,
+ struct dml2_hubp_pipe_mcache_regs *mcache_regs)
+{
+ struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
+
+ REG_SET_8(DCHUBP_MCACHEID_CONFIG, 0,
+ MCACHEID_REG_READ_1H_P0, mcache_regs->main.p0.mcache_id_first,
+ MCACHEID_REG_READ_2H_P0, mcache_regs->main.p0.mcache_id_second,
+ MCACHEID_REG_READ_1H_P1, mcache_regs->main.p1.mcache_id_first,
+ MCACHEID_REG_READ_2H_P1, mcache_regs->main.p1.mcache_id_second,
+ MCACHEID_MALL_PREF_1H_P0, mcache_regs->mall.p0.mcache_id_first,
+ MCACHEID_MALL_PREF_2H_P0, mcache_regs->mall.p0.mcache_id_second,
+ MCACHEID_MALL_PREF_1H_P1, mcache_regs->mall.p1.mcache_id_first,
+ MCACHEID_MALL_PREF_2H_P1, mcache_regs->mall.p1.mcache_id_second);
+
+ REG_SET_2(DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE, 0,
+ VIEWPORT_MCACHE_SPLIT_COORDINATE, mcache_regs->main.p0.split_location,
+ VIEWPORT_MCACHE_SPLIT_COORDINATE_C, mcache_regs->main.p1.split_location);
+}
void hubp401_set_flip_int(struct hubp *hubp)
{
struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
@@ -654,17 +674,26 @@ void hubp401_cursor_set_position(
struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
int x_pos = pos->x - param->recout.x;
int y_pos = pos->y - param->recout.y;
- int x_hotspot = pos->x_hotspot;
- int y_hotspot = pos->y_hotspot;
int rec_x_offset = x_pos - pos->x_hotspot;
int rec_y_offset = y_pos - pos->y_hotspot;
- int cursor_height = (int)hubp->curs_attr.height;
- int cursor_width = (int)hubp->curs_attr.width;
- uint32_t dst_x_offset;
+ int dst_x_offset;
+ int x_pos_viewport = 0;
+ int x_hot_viewport = 0;
uint32_t cur_en = pos->enable ? 1 : 0;
hubp->curs_pos = *pos;
+ /* Recout is zero for pipes if the entire dst_rect is contained
+ * within preceeding ODM slices.
+ */
+ if (param->recout.width) {
+ x_pos_viewport = x_pos * param->viewport.width / param->recout.width;
+ x_hot_viewport = pos->x_hotspot * param->viewport.width / param->recout.width;
+ } else {
+ ASSERT(!cur_en || x_pos == 0);
+ ASSERT(!cur_en || pos->x_hotspot == 0);
+ }
+
/*
* Guard aganst cursor_set_position() from being called with invalid
* attributes
@@ -672,29 +701,13 @@ void hubp401_cursor_set_position(
if (hubp->curs_attr.address.quad_part == 0)
return;
- // Transform cursor width / height and hotspots for offset calculations
- if (param->rotation == ROTATION_ANGLE_90 || param->rotation == ROTATION_ANGLE_270) {
- swap(cursor_height, cursor_width);
- swap(x_hotspot, y_hotspot);
-
- if (param->rotation == ROTATION_ANGLE_90) {
- // hotspot = (-y, x)
- rec_x_offset = x_pos - (cursor_width - x_hotspot);
- rec_y_offset = y_pos - y_hotspot;
- } else if (param->rotation == ROTATION_ANGLE_270) {
- // hotspot = (y, -x)
- rec_x_offset = x_pos - x_hotspot;
- rec_y_offset = y_pos - (cursor_height - y_hotspot);
- }
- } else if (param->rotation == ROTATION_ANGLE_180) {
- // hotspot = (-x, -y)
- if (!param->mirror)
- rec_x_offset = x_pos - (cursor_width - x_hotspot);
-
- rec_y_offset = y_pos - (cursor_height - y_hotspot);
- }
-
- dst_x_offset = (rec_x_offset >= 0) ? rec_x_offset : 0;
+ /* Translate the x position of the cursor from rect
+ * space into viewport space. CURSOR_DST_X_OFFSET
+ * is the offset relative to viewport start position.
+ */
+ dst_x_offset = x_pos_viewport - x_hot_viewport *
+ (1 + hubp->curs_attr.attribute_flags.bits.ENABLE_MAGNIFICATION);
+ dst_x_offset = (dst_x_offset >= 0) ? dst_x_offset : 0;
dst_x_offset *= param->ref_clk_khz;
dst_x_offset /= param->pixel_clk_khz;
@@ -705,18 +718,6 @@ void hubp401_cursor_set_position(
dc_fixpt_from_int(dst_x_offset),
param->h_scale_ratio));
- if (rec_x_offset >= (int)param->recout.width)
- cur_en = 0; /* not visible beyond right edge*/
-
- if (rec_x_offset + cursor_width <= 0)
- cur_en = 0; /* not visible beyond left edge*/
-
- if (rec_y_offset >= (int)param->recout.height)
- cur_en = 0; /* not visible beyond bottom edge*/
-
- if (rec_y_offset + cursor_height <= 0)
- cur_en = 0; /* not visible beyond top edge*/
-
if (cur_en && REG_READ(CURSOR_SURFACE_ADDRESS) == 0)
hubp->funcs->set_cursor_attributes(hubp, &hubp->curs_attr);
@@ -993,6 +994,7 @@ static struct hubp_funcs dcn401_hubp_funcs = {
.phantom_hubp_post_enable = hubp32_phantom_hubp_post_enable,
.hubp_update_mall_sel = hubp401_update_mall_sel,
.hubp_prepare_subvp_buffering = hubp32_prepare_subvp_buffering,
+ .hubp_program_mcache_id_and_split_coordinate = hubp401_program_mcache_id_and_split_coordinate,
.hubp_update_3dlut_fl_bias_scale = hubp401_update_3dlut_fl_bias_scale,
.hubp_program_3dlut_fl_mode = hubp401_program_3dlut_fl_mode,
.hubp_program_3dlut_fl_format = hubp401_program_3dlut_fl_format,
diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.h b/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.h
index e0cec898a2c0..e52fdb5b0cd0 100644
--- a/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.h
+++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.h
@@ -243,6 +243,16 @@
HUBP_SF(CURSOR0_0_HUBP_3DLUT_ADDRESS_HIGH, HUBP_3DLUT_ADDRESS_HIGH, mask_sh),\
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),\
+ HUBP_SF(HUBP0_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE, VIEWPORT_MCACHE_SPLIT_COORDINATE, mask_sh),\
+ HUBP_SF(HUBP0_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE, VIEWPORT_MCACHE_SPLIT_COORDINATE_C, mask_sh),\
+ HUBP_SF(HUBP0_DCHUBP_MCACHEID_CONFIG, MCACHEID_REG_READ_1H_P0, mask_sh),\
+ HUBP_SF(HUBP0_DCHUBP_MCACHEID_CONFIG, MCACHEID_REG_READ_2H_P0, mask_sh),\
+ HUBP_SF(HUBP0_DCHUBP_MCACHEID_CONFIG, MCACHEID_REG_READ_1H_P1, mask_sh),\
+ HUBP_SF(HUBP0_DCHUBP_MCACHEID_CONFIG, MCACHEID_REG_READ_2H_P1, mask_sh),\
+ HUBP_SF(HUBP0_DCHUBP_MCACHEID_CONFIG, MCACHEID_MALL_PREF_1H_P0, mask_sh),\
+ HUBP_SF(HUBP0_DCHUBP_MCACHEID_CONFIG, MCACHEID_MALL_PREF_2H_P0, mask_sh),\
+ HUBP_SF(HUBP0_DCHUBP_MCACHEID_CONFIG, MCACHEID_MALL_PREF_1H_P1, mask_sh),\
+ HUBP_SF(HUBP0_DCHUBP_MCACHEID_CONFIG, MCACHEID_MALL_PREF_2H_P1, mask_sh)
void hubp401_update_mall_sel(struct hubp *hubp, uint32_t mall_sel, bool c_cursor);
@@ -302,7 +312,9 @@ void hubp401_program_surface_config(
void hubp401_set_viewport(struct hubp *hubp,
const struct rect *viewport,
const struct rect *viewport_c);
-
+void hubp401_program_mcache_id_and_split_coordinate(
+ struct hubp *hubp,
+ struct dml2_hubp_pipe_mcache_regs *mcache_regs);
void hubp401_set_flip_int(struct hubp *hubp);
bool hubp401_in_blank(struct hubp *hubp);
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 f489371a3bc6..1f2eb2f727dc 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
@@ -742,12 +742,10 @@ void dce110_edp_wait_for_hpd_ready(
return;
}
- if (link != NULL) {
- if (link->panel_config.pps.extra_t3_ms > 0) {
- int extra_t3_in_ms = link->panel_config.pps.extra_t3_ms;
+ if (link->panel_config.pps.extra_t3_ms > 0) {
+ int extra_t3_in_ms = link->panel_config.pps.extra_t3_ms;
- msleep(extra_t3_in_ms);
- }
+ msleep(extra_t3_in_ms);
}
dal_gpio_open(hpd, GPIO_MODE_INTERRUPT);
@@ -1307,13 +1305,65 @@ static void populate_audio_dp_link_info(
dp_link_info->link_bandwidth_kbps = dc_fixpt_floor(link_bw_kbps);
- /* HW minimum for 128b/132b HBlank is 4 frame symbols.
- * TODO: Plumb the actual programmed HBlank min symbol width to here.
+ /* Calculates hblank_min_symbol_width for 128b/132b
+ * Corresponding HBLANK_MIN_SYMBOL_WIDTH register is calculated as:
+ * floor(h_blank * bits_per_pixel / 128)
*/
- if (dp_link_info->encoding == DP_128b_132b_ENCODING)
- dp_link_info->hblank_min_symbol_width = 4;
- else
+ if (dp_link_info->encoding == DP_128b_132b_ENCODING) {
+ struct dc_crtc_timing *crtc_timing = &pipe_ctx->stream->timing;
+
+ uint32_t h_active = crtc_timing->h_addressable + crtc_timing->h_border_left
+ + crtc_timing->h_border_right;
+ uint32_t h_blank = crtc_timing->h_total - h_active;
+
+ uint32_t bpp;
+
+ if (crtc_timing->flags.DSC) {
+ bpp = crtc_timing->dsc_cfg.bits_per_pixel;
+ } else {
+ /* When the timing is using DSC, dsc_cfg.bits_per_pixel is in 16th bits.
+ * The bpp in this path is scaled to 16th bits so the final calculation
+ * is correct for both cases.
+ */
+ bpp = 16;
+ switch (crtc_timing->display_color_depth) {
+ case COLOR_DEPTH_666:
+ bpp *= 18;
+ break;
+ case COLOR_DEPTH_888:
+ bpp *= 24;
+ break;
+ case COLOR_DEPTH_101010:
+ bpp *= 30;
+ break;
+ case COLOR_DEPTH_121212:
+ bpp *= 36;
+ break;
+ default:
+ bpp = 0;
+ break;
+ }
+
+ switch (crtc_timing->pixel_encoding) {
+ case PIXEL_ENCODING_YCBCR422:
+ bpp = bpp * 2 / 3;
+ break;
+ case PIXEL_ENCODING_YCBCR420:
+ bpp /= 2;
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* Min symbol width = floor(h_blank * (bpp/16) / 128) */
+ dp_link_info->hblank_min_symbol_width = dc_fixpt_floor(
+ dc_fixpt_div(dc_fixpt_from_int(h_blank * bpp),
+ dc_fixpt_from_int(128 / 16)));
+
+ } else {
dp_link_info->hblank_min_symbol_width = 0;
+ }
}
static void build_audio_output(
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 de6ee6bf0a88..e06fc370267b 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
@@ -289,6 +289,7 @@ static void dcn10_log_color_state(struct dc *dc,
{
struct dc_context *dc_ctx = dc->ctx;
struct resource_pool *pool = dc->res_pool;
+ bool is_gamut_remap_available = false;
int i;
DTN_INFO("DPP: IGAM format IGAM mode DGAM mode RGAM mode"
@@ -301,16 +302,15 @@ static void dcn10_log_color_state(struct dc *dc,
struct dcn_dpp_state s = {0};
dpp->funcs->dpp_read_state(dpp, &s);
- dpp->funcs->dpp_get_gamut_remap(dpp, &s.gamut_remap);
+ if (dpp->funcs->dpp_get_gamut_remap) {
+ dpp->funcs->dpp_get_gamut_remap(dpp, &s.gamut_remap);
+ is_gamut_remap_available = true;
+ }
if (!s.is_enabled)
continue;
- DTN_INFO("[%2d]: %11xh %11s %9s %9s"
- " %12s "
- "%010lld %010lld %010lld %010lld "
- "%010lld %010lld %010lld %010lld "
- "%010lld %010lld %010lld %010lld",
+ DTN_INFO("[%2d]: %11xh %11s %9s %9s",
dpp->inst,
s.igam_input_format,
(s.igam_lut_mode == 0) ? "BypassFixed" :
@@ -329,22 +329,27 @@ static void dcn10_log_color_state(struct dc *dc,
((s.rgam_lut_mode == 2) ? "Ycc" :
((s.rgam_lut_mode == 3) ? "RAM" :
((s.rgam_lut_mode == 4) ? "RAM" :
- "Unknown")))),
- (s.gamut_remap.gamut_adjust_type == 0) ? "Bypass" :
- ((s.gamut_remap.gamut_adjust_type == 1) ? "HW" :
- "SW"),
- s.gamut_remap.temperature_matrix[0].value,
- s.gamut_remap.temperature_matrix[1].value,
- s.gamut_remap.temperature_matrix[2].value,
- s.gamut_remap.temperature_matrix[3].value,
- s.gamut_remap.temperature_matrix[4].value,
- s.gamut_remap.temperature_matrix[5].value,
- s.gamut_remap.temperature_matrix[6].value,
- s.gamut_remap.temperature_matrix[7].value,
- s.gamut_remap.temperature_matrix[8].value,
- s.gamut_remap.temperature_matrix[9].value,
- s.gamut_remap.temperature_matrix[10].value,
- s.gamut_remap.temperature_matrix[11].value);
+ "Unknown")))));
+ if (is_gamut_remap_available)
+ DTN_INFO(" %12s "
+ "%010lld %010lld %010lld %010lld "
+ "%010lld %010lld %010lld %010lld "
+ "%010lld %010lld %010lld %010lld",
+ (s.gamut_remap.gamut_adjust_type == 0) ? "Bypass" :
+ ((s.gamut_remap.gamut_adjust_type == 1) ? "HW" : "SW"),
+ s.gamut_remap.temperature_matrix[0].value,
+ s.gamut_remap.temperature_matrix[1].value,
+ s.gamut_remap.temperature_matrix[2].value,
+ s.gamut_remap.temperature_matrix[3].value,
+ s.gamut_remap.temperature_matrix[4].value,
+ s.gamut_remap.temperature_matrix[5].value,
+ s.gamut_remap.temperature_matrix[6].value,
+ s.gamut_remap.temperature_matrix[7].value,
+ s.gamut_remap.temperature_matrix[8].value,
+ s.gamut_remap.temperature_matrix[9].value,
+ s.gamut_remap.temperature_matrix[10].value,
+ s.gamut_remap.temperature_matrix[11].value);
+
DTN_INFO("\n");
}
DTN_INFO("\n");
@@ -1129,26 +1134,9 @@ static bool dcn10_hw_wa_force_recovery(struct dc *dc)
{
struct hubp *hubp ;
unsigned int i;
- bool need_recover = true;
if (!dc->debug.recovery_enabled)
return false;
-
- for (i = 0; i < dc->res_pool->pipe_count; i++) {
- struct pipe_ctx *pipe_ctx =
- &dc->current_state->res_ctx.pipe_ctx[i];
- if (pipe_ctx != NULL) {
- hubp = pipe_ctx->plane_res.hubp;
- if (hubp != NULL && hubp->funcs->hubp_get_underflow_status) {
- if (hubp->funcs->hubp_get_underflow_status(hubp) != 0) {
- /* one pipe underflow, we will reset all the pipes*/
- need_recover = true;
- }
- }
- }
- }
- if (!need_recover)
- return false;
/*
DCHUBP_CNTL:HUBP_BLANK_EN=1
DCHUBBUB_SOFT_RESET:DCHUBBUB_GLOBAL_SOFT_RESET=1
@@ -1255,7 +1243,7 @@ void dcn10_plane_atomic_disconnect(struct dc *dc,
mpc->funcs->remove_mpcc(mpc, mpc_tree_params, mpcc_to_remove);
// Phantom pipes have OTG disabled by default, so MPCC_STATUS will never assert idle,
// so don't wait for MPCC_IDLE in the programming sequence
- if (opp != NULL && dc_state_get_pipe_subvp_type(state, pipe_ctx) != SUBVP_PHANTOM)
+ if (dc_state_get_pipe_subvp_type(state, pipe_ctx) != SUBVP_PHANTOM)
opp->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true;
dc->optimized_required = true;
@@ -2220,7 +2208,7 @@ static int dcn10_align_pixel_clocks(struct dc *dc, int group_size,
grouped_pipes[i]->stream->signal)) {
embedded = i;
master = i;
- phase[i] = embedded_pix_clk_100hz*100;
+ phase[i] = embedded_pix_clk_100hz*(uint64_t)100;
modulo[i] = dp_ref_clk_100hz*100;
} else {
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 0d58c9d439c6..2532ad410cb5 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
@@ -974,8 +974,8 @@ enum dc_status dcn20_enable_stream_timing(
/* TODO enable stream if timing changed */
/* TODO unblank stream if DP */
- if (pipe_ctx->stream && dc_state_get_pipe_subvp_type(context, pipe_ctx) == SUBVP_PHANTOM) {
- if (pipe_ctx->stream_res.tg && pipe_ctx->stream_res.tg->funcs->phantom_crtc_post_enable)
+ if (dc_state_get_pipe_subvp_type(context, pipe_ctx) == SUBVP_PHANTOM) {
+ if (pipe_ctx->stream_res.tg->funcs->phantom_crtc_post_enable)
pipe_ctx->stream_res.tg->funcs->phantom_crtc_post_enable(pipe_ctx->stream_res.tg);
}
@@ -1753,6 +1753,10 @@ static void dcn20_update_dchubp_dpp(
&pipe_ctx->plane_res.scl_data.viewport_c);
viewport_changed = true;
}
+ if (hubp->funcs->hubp_program_mcache_id_and_split_coordinate)
+ hubp->funcs->hubp_program_mcache_id_and_split_coordinate(
+ hubp,
+ &pipe_ctx->mcache_regs);
/* Any updates are handled in dc interface, just need to apply existing for plane enable */
if ((pipe_ctx->update_flags.bits.enable || pipe_ctx->update_flags.bits.opp_changed ||
@@ -1827,8 +1831,7 @@ static void dcn20_update_dchubp_dpp(
if (pipe_ctx->update_flags.bits.enable)
hubp->funcs->set_blank(hubp, false);
/* If the stream paired with this plane is phantom, the plane is also phantom */
- if (pipe_ctx->stream && pipe_mall_type == SUBVP_PHANTOM
- && hubp->funcs->phantom_hubp_post_enable)
+ if (pipe_mall_type == SUBVP_PHANTOM && hubp->funcs->phantom_hubp_post_enable)
hubp->funcs->phantom_hubp_post_enable(hubp);
}
@@ -2051,11 +2054,14 @@ void dcn20_program_front_end_for_ctx(
if (tg->funcs->enable_crtc) {
if (dc->hwss.blank_phantom) {
- int main_pipe_width, main_pipe_height;
+ int main_pipe_width = 0, main_pipe_height = 0;
struct dc_stream_state *phantom_stream = dc_state_get_paired_subvp_stream(dc->current_state, dc->current_state->res_ctx.pipe_ctx[i].stream);
- main_pipe_width = phantom_stream->dst.width;
- main_pipe_height = phantom_stream->dst.height;
+ if (phantom_stream) {
+ main_pipe_width = phantom_stream->dst.width;
+ main_pipe_height = phantom_stream->dst.height;
+ }
+
dc->hwss.blank_phantom(dc, tg, main_pipe_width, main_pipe_height);
}
tg->funcs->enable_crtc(tg);
@@ -2225,6 +2231,29 @@ void dcn20_post_unlock_program_front_end(
}
}
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
+ struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i];
+
+ /* When going from a smaller ODM slice count to larger, we must ensure double
+ * buffer update completes before we return to ensure we don't reduce DISPCLK
+ * before we've transitioned to 2:1 or 4:1
+ */
+ if (resource_is_pipe_type(old_pipe, OTG_MASTER) && resource_is_pipe_type(pipe, OTG_MASTER) &&
+ resource_get_odm_slice_count(old_pipe) < resource_get_odm_slice_count(pipe) &&
+ dc_state_get_pipe_subvp_type(context, pipe) != SUBVP_PHANTOM) {
+ int j = 0;
+ struct timing_generator *tg = pipe->stream_res.tg;
+
+
+ if (tg->funcs->get_double_buffer_pending) {
+ for (j = 0; j < TIMEOUT_FOR_PIPE_ENABLE_US / polling_interval_us
+ && tg->funcs->get_double_buffer_pending(tg); j++)
+ udelay(polling_interval_us);
+ }
+ }
+ }
+
if (dc->res_pool->hubbub->funcs->force_pstate_change_control)
dc->res_pool->hubbub->funcs->force_pstate_change_control(
dc->res_pool->hubbub, false, false);
@@ -2800,6 +2829,11 @@ void dcn20_reset_back_end_for_pipe(
if (i == dc->res_pool->pipe_count)
return;
+/*
+ * In case of a dangling plane, setting this to NULL unconditionally
+ * causes failures during reset hw ctx where, if stream is NULL,
+ * it is expected that the pipe_ctx pointers to pipes and plane are NULL.
+ */
pipe_ctx->stream = NULL;
DC_LOG_DEBUG("Reset back end for pipe %d, tg:%d\n",
pipe_ctx->pipe_idx, pipe_ctx->stream_res.tg->inst);
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_hwseq.c
index 86d871cc74c7..1635e5a552ad 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_hwseq.c
@@ -240,7 +240,7 @@ void dcn201_init_hw(struct dc *dc)
res_pool->ref_clocks.xtalin_clock_inKhz =
dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency;
- if (res_pool->dccg && res_pool->hubbub) {
+ if (res_pool->hubbub) {
(res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg,
dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency,
&res_pool->ref_clocks.dccg_ref_clock_inKhz);
@@ -408,8 +408,7 @@ void dcn201_plane_atomic_disconnect(struct dc *dc,
if (mpcc_removed == false)
return;
- if (opp != NULL)
- opp->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true;
+ opp->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true;
dc->optimized_required = true;
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn21/dcn21_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn21/dcn21_hwseq.c
index 804be977ea47..1ea95f8d4cbc 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn21/dcn21_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn21/dcn21_hwseq.c
@@ -142,7 +142,7 @@ static bool dmub_abm_set_pipe(struct abm *abm, uint32_t otg_inst,
{
union dmub_rb_cmd cmd;
struct dc_context *dc = abm->ctx;
- uint32_t ramping_boundary = 0xFFFF;
+ uint8_t ramping_boundary = 0xFF;
memset(&cmd, 0, sizeof(cmd));
cmd.abm_set_pipe.header.type = DMUB_CMD__ABM;
@@ -183,6 +183,12 @@ void dcn21_set_abm_immediate_disable(struct pipe_ctx *pipe_ctx)
struct panel_cntl *panel_cntl = pipe_ctx->stream->link->panel_cntl;
struct dmcu *dmcu = pipe_ctx->stream->ctx->dc->res_pool->dmcu;
+ // make a short term w/a for an issue that backlight ramping unexpectedly paused in the middle,
+ // will decouple backlight from ABM and redefine DMUB interface, then this w/a could be removed
+ if (pipe_ctx->stream->abm_level == 0 || pipe_ctx->stream->abm_level == ABM_LEVEL_IMMEDIATE_DISABLE) {
+ return;
+ }
+
if (dmcu) {
dce110_set_abm_immediate_disable(pipe_ctx);
return;
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 4c4706153305..eaeeade31ed7 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
@@ -228,8 +228,11 @@ bool dcn30_set_blend_lut(
if (plane_state->blend_tf.type == TF_TYPE_HWPWL)
blend_lut = &plane_state->blend_tf.pwl;
else if (plane_state->blend_tf.type == TF_TYPE_DISTRIBUTED_POINTS) {
- cm3_helper_translate_curve_to_hw_format(
+ result = cm3_helper_translate_curve_to_hw_format(
&plane_state->blend_tf, &dpp_base->regamma_params, false);
+ if (!result)
+ return result;
+
blend_lut = &dpp_base->regamma_params;
}
result = dpp_base->funcs->dpp_program_blnd_lut(dpp_base, blend_lut);
@@ -656,7 +659,7 @@ void dcn30_init_hw(struct dc *dc)
res_pool->ref_clocks.xtalin_clock_inKhz =
dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency;
- if (res_pool->dccg && res_pool->hubbub) {
+ if (res_pool->hubbub) {
(res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg,
dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency,
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 1c8abb417b6e..746c522adf84 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
@@ -132,7 +132,7 @@ void dcn31_init_hw(struct dc *dc)
res_pool->ref_clocks.xtalin_clock_inKhz =
dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency;
- if (res_pool->dccg && res_pool->hubbub) {
+ if (res_pool->hubbub) {
(res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg,
dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency,
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 8e68e05e3b72..388404cdeeaa 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
@@ -379,8 +379,25 @@ void dcn314_resync_fifo_dccg_dio(struct dce_hwseq *hws, struct dc *dc, struct dc
for (i = 0; i < dc->res_pool->pipe_count; i++) {
pipe = &dc->current_state->res_ctx.pipe_ctx[i];
- if (otg_disabled[i])
+ if (otg_disabled[i]) {
+ int opp_inst[MAX_PIPES] = { pipe->stream_res.opp->inst };
+ int opp_cnt = 1;
+ int last_odm_slice_width = resource_get_odm_slice_dst_width(pipe, true);
+ int odm_slice_width = resource_get_odm_slice_dst_width(pipe, false);
+ struct pipe_ctx *odm_pipe;
+
+ for (odm_pipe = pipe->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
+ opp_inst[opp_cnt] = odm_pipe->stream_res.opp->inst;
+ opp_cnt++;
+ }
+ if (opp_cnt > 1)
+ pipe->stream_res.tg->funcs->set_odm_combine(
+ pipe->stream_res.tg,
+ opp_inst, opp_cnt,
+ odm_slice_width,
+ last_odm_slice_width);
pipe->stream_res.tg->funcs->enable_crtc(pipe->stream_res.tg);
+ }
}
}
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 0d27eec724b4..05d8f81daa06 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
@@ -271,58 +271,55 @@ bool dcn32_apply_idle_power_optimizations(struct dc *dc, bool enable)
}
if (enable) {
- if (dc->current_state) {
+ /* 1. Check no memory request case for CAB.
+ * If no memory request case, send CAB_ACTION NO_DF_REQ DMUB message
+ */
+ if (dcn32_check_no_memory_request_for_cab(dc)) {
+ /* Enable no-memory-requests case */
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.cab.header.type = DMUB_CMD__CAB_FOR_SS;
+ cmd.cab.header.sub_type = DMUB_CMD__CAB_NO_DCN_REQ;
+ cmd.cab.header.payload_bytes = sizeof(cmd.cab) - sizeof(cmd.cab.header);
- /* 1. Check no memory request case for CAB.
- * If no memory request case, send CAB_ACTION NO_DF_REQ DMUB message
- */
- if (dcn32_check_no_memory_request_for_cab(dc)) {
- /* Enable no-memory-requests case */
- memset(&cmd, 0, sizeof(cmd));
- cmd.cab.header.type = DMUB_CMD__CAB_FOR_SS;
- cmd.cab.header.sub_type = DMUB_CMD__CAB_NO_DCN_REQ;
- cmd.cab.header.payload_bytes = sizeof(cmd.cab) - sizeof(cmd.cab.header);
+ dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT);
- dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT);
+ return true;
+ }
- return true;
- }
+ /* 2. Check if all surfaces can fit in CAB.
+ * If surfaces can fit into CAB, send CAB_ACTION_ALLOW DMUB message
+ * and configure HUBP's to fetch from MALL
+ */
+ ways = dcn32_calculate_cab_allocation(dc, dc->current_state);
- /* 2. Check if all surfaces can fit in CAB.
- * If surfaces can fit into CAB, send CAB_ACTION_ALLOW DMUB message
- * and configure HUBP's to fetch from MALL
- */
- ways = dcn32_calculate_cab_allocation(dc, dc->current_state);
+ /* MALL not supported with Stereo3D or TMZ surface. If any plane is using stereo,
+ * or TMZ surface, don't try to enter MALL.
+ */
+ for (i = 0; i < dc->current_state->stream_count; i++) {
+ for (j = 0; j < dc->current_state->stream_status[i].plane_count; j++) {
+ plane = dc->current_state->stream_status[i].plane_states[j];
- /* MALL not supported with Stereo3D or TMZ surface. If any plane is using stereo,
- * or TMZ surface, don't try to enter MALL.
- */
- for (i = 0; i < dc->current_state->stream_count; i++) {
- for (j = 0; j < dc->current_state->stream_status[i].plane_count; j++) {
- plane = dc->current_state->stream_status[i].plane_states[j];
-
- if (plane->address.type == PLN_ADDR_TYPE_GRPH_STEREO ||
- plane->address.tmz_surface) {
- mall_ss_unsupported = true;
- break;
- }
- }
- if (mall_ss_unsupported)
+ if (plane->address.type == PLN_ADDR_TYPE_GRPH_STEREO ||
+ plane->address.tmz_surface) {
+ mall_ss_unsupported = true;
break;
+ }
}
- if (ways <= dc->caps.cache_num_ways && !mall_ss_unsupported) {
- memset(&cmd, 0, sizeof(cmd));
- cmd.cab.header.type = DMUB_CMD__CAB_FOR_SS;
- cmd.cab.header.sub_type = DMUB_CMD__CAB_DCN_SS_FIT_IN_CAB;
- cmd.cab.header.payload_bytes = sizeof(cmd.cab) - sizeof(cmd.cab.header);
- cmd.cab.cab_alloc_ways = (uint8_t)ways;
+ if (mall_ss_unsupported)
+ break;
+ }
+ if (ways <= dc->caps.cache_num_ways && !mall_ss_unsupported) {
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.cab.header.type = DMUB_CMD__CAB_FOR_SS;
+ cmd.cab.header.sub_type = DMUB_CMD__CAB_DCN_SS_FIT_IN_CAB;
+ cmd.cab.header.payload_bytes = sizeof(cmd.cab) - sizeof(cmd.cab.header);
+ cmd.cab.cab_alloc_ways = (uint8_t)ways;
- dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT);
-
- return true;
- }
+ dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT);
+ return true;
}
+
return false;
}
@@ -486,11 +483,14 @@ bool dcn32_set_mcm_luts(
if (plane_state->blend_tf.type == TF_TYPE_HWPWL)
lut_params = &plane_state->blend_tf.pwl;
else if (plane_state->blend_tf.type == TF_TYPE_DISTRIBUTED_POINTS) {
- cm3_helper_translate_curve_to_hw_format(&plane_state->blend_tf,
+ result = cm3_helper_translate_curve_to_hw_format(&plane_state->blend_tf,
&dpp_base->regamma_params, false);
+ if (!result)
+ return result;
+
lut_params = &dpp_base->regamma_params;
}
- result = mpc->funcs->program_1dlut(mpc, lut_params, mpcc_id);
+ mpc->funcs->program_1dlut(mpc, lut_params, mpcc_id);
lut_params = NULL;
// Shaper
@@ -504,7 +504,7 @@ bool dcn32_set_mcm_luts(
lut_params = &dpp_base->shaper_params;
}
- result = mpc->funcs->program_shaper(mpc, lut_params, mpcc_id);
+ mpc->funcs->program_shaper(mpc, lut_params, mpcc_id);
// 3D
if (plane_state->lut3d_func.state.bits.initialized == 1)
@@ -806,7 +806,7 @@ void dcn32_init_hw(struct dc *dc)
res_pool->ref_clocks.xtalin_clock_inKhz =
dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency;
- if (res_pool->dccg && res_pool->hubbub) {
+ if (res_pool->hubbub) {
(res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg,
dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency,
&res_pool->ref_clocks.dccg_ref_clock_inKhz);
@@ -1237,9 +1237,28 @@ void dcn32_resync_fifo_dccg_dio(struct dce_hwseq *hws, struct dc *dc, struct dc_
for (i = 0; i < dc->res_pool->pipe_count; i++) {
pipe = &dc->current_state->res_ctx.pipe_ctx[i];
- if (otg_disabled[i])
+ if (otg_disabled[i]) {
+ int opp_inst[MAX_PIPES] = { pipe->stream_res.opp->inst };
+ int opp_cnt = 1;
+ int last_odm_slice_width = resource_get_odm_slice_dst_width(pipe, true);
+ int odm_slice_width = resource_get_odm_slice_dst_width(pipe, false);
+ struct pipe_ctx *odm_pipe;
+
+ for (odm_pipe = pipe->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
+ opp_inst[opp_cnt] = odm_pipe->stream_res.opp->inst;
+ opp_cnt++;
+ }
+ if (opp_cnt > 1)
+ pipe->stream_res.tg->funcs->set_odm_combine(
+ pipe->stream_res.tg,
+ opp_inst, opp_cnt,
+ odm_slice_width,
+ last_odm_slice_width);
pipe->stream_res.tg->funcs->enable_crtc(pipe->stream_res.tg);
+ }
}
+
+ dc_trigger_sync(dc, dc->current_state);
}
void dcn32_unblank_stream(struct pipe_ctx *pipe_ctx,
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 2b3ba5971c69..e4f7078c1026 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
@@ -188,7 +188,7 @@ void dcn35_init_hw(struct dc *dc)
res_pool->ref_clocks.xtalin_clock_inKhz =
dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency;
- if (res_pool->dccg && res_pool->hubbub) {
+ if (res_pool->hubbub) {
(res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg,
dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency,
@@ -1078,6 +1078,19 @@ void dcn35_calc_blocks_to_gate(struct dc *dc, struct dc_state *context,
update_state->pg_pipe_res_update[PG_OPTC][0] = false;
}
+ if (dc->caps.sequential_ono) {
+ for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) {
+ if (!update_state->pg_pipe_res_update[PG_HUBP][i] &&
+ !update_state->pg_pipe_res_update[PG_DPP][i]) {
+ for (j = i - 1; j >= 0; j--) {
+ update_state->pg_pipe_res_update[PG_HUBP][j] = false;
+ update_state->pg_pipe_res_update[PG_DPP][j] = false;
+ }
+
+ break;
+ }
+ }
+ }
}
void dcn35_calc_blocks_to_ungate(struct dc *dc, struct dc_state *context,
@@ -1177,6 +1190,19 @@ void dcn35_calc_blocks_to_ungate(struct dc *dc, struct dc_state *context,
if (hpo_frl_stream_enc_acquired)
update_state->pg_pipe_res_update[PG_HDMISTREAM][0] = true;
+ if (dc->caps.sequential_ono) {
+ for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) {
+ if (update_state->pg_pipe_res_update[PG_HUBP][i] &&
+ update_state->pg_pipe_res_update[PG_DPP][i]) {
+ for (j = i - 1; j >= 0; j--) {
+ update_state->pg_pipe_res_update[PG_HUBP][j] = true;
+ update_state->pg_pipe_res_update[PG_DPP][j] = true;
+ }
+
+ break;
+ }
+ }
+ }
}
/**
@@ -1197,6 +1223,8 @@ void dcn35_calc_blocks_to_ungate(struct dc *dc, struct dc_state *context,
* ONO Region 2, DCPG 24: mpc opp optc dwb
* ONO Region 0, DCPG 22: dccg dio dcio - SKIPPED. will be pwr dwn after lono timer is armed
*
+ * If sequential ONO is specified the order is modified from ONO Region 11 -> ONO Region 0 descending.
+ *
* @dc: Current DC state
* @update_state: update PG sequence states for HW block
*/
@@ -1216,19 +1244,35 @@ void dcn35_hw_block_power_down(struct dc *dc,
pg_cntl->funcs->hpo_pg_control(pg_cntl, false);
}
- for (i = 0; i < dc->res_pool->pipe_count; i++) {
- if (update_state->pg_pipe_res_update[PG_HUBP][i] &&
- update_state->pg_pipe_res_update[PG_DPP][i]) {
- if (pg_cntl->funcs->hubp_dpp_pg_control)
- pg_cntl->funcs->hubp_dpp_pg_control(pg_cntl, i, false);
+ if (!dc->caps.sequential_ono) {
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ if (update_state->pg_pipe_res_update[PG_HUBP][i] &&
+ update_state->pg_pipe_res_update[PG_DPP][i]) {
+ if (pg_cntl->funcs->hubp_dpp_pg_control)
+ pg_cntl->funcs->hubp_dpp_pg_control(pg_cntl, i, false);
+ }
}
- }
- for (i = 0; i < dc->res_pool->res_cap->num_dsc; i++)
- if (update_state->pg_pipe_res_update[PG_DSC][i]) {
- if (pg_cntl->funcs->dsc_pg_control)
- pg_cntl->funcs->dsc_pg_control(pg_cntl, i, false);
+
+ for (i = 0; i < dc->res_pool->res_cap->num_dsc; i++) {
+ if (update_state->pg_pipe_res_update[PG_DSC][i]) {
+ if (pg_cntl->funcs->dsc_pg_control)
+ pg_cntl->funcs->dsc_pg_control(pg_cntl, i, false);
+ }
}
+ } else {
+ for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) {
+ if (update_state->pg_pipe_res_update[PG_DSC][i]) {
+ if (pg_cntl->funcs->dsc_pg_control)
+ pg_cntl->funcs->dsc_pg_control(pg_cntl, i, false);
+ }
+ if (update_state->pg_pipe_res_update[PG_HUBP][i] &&
+ update_state->pg_pipe_res_update[PG_DPP][i]) {
+ if (pg_cntl->funcs->hubp_dpp_pg_control)
+ pg_cntl->funcs->hubp_dpp_pg_control(pg_cntl, i, false);
+ }
+ }
+ }
/*this will need all the clients to unregister optc interruts let dmubfw handle this*/
if (pg_cntl->funcs->plane_otg_pg_control)
@@ -1256,6 +1300,8 @@ void dcn35_hw_block_power_down(struct dc *dc,
* ONO Region 10, DCPG 3: dchubp3, dpp3
* ONO Region 3, DCPG 25: hpo - SKIPPED
*
+ * If sequential ONO is specified the order is modified from ONO Region 0 -> ONO Region 11 ascending.
+ *
* @dc: Current DC state
* @update_state: update PG sequence states for HW block
*/
@@ -1274,11 +1320,13 @@ void dcn35_hw_block_power_up(struct dc *dc,
if (pg_cntl->funcs->plane_otg_pg_control)
pg_cntl->funcs->plane_otg_pg_control(pg_cntl, true);
- for (i = 0; i < dc->res_pool->res_cap->num_dsc; i++)
- if (update_state->pg_pipe_res_update[PG_DSC][i]) {
- if (pg_cntl->funcs->dsc_pg_control)
- pg_cntl->funcs->dsc_pg_control(pg_cntl, i, true);
- }
+ if (!dc->caps.sequential_ono) {
+ for (i = 0; i < dc->res_pool->res_cap->num_dsc; i++)
+ if (update_state->pg_pipe_res_update[PG_DSC][i]) {
+ if (pg_cntl->funcs->dsc_pg_control)
+ pg_cntl->funcs->dsc_pg_control(pg_cntl, i, true);
+ }
+ }
for (i = 0; i < dc->res_pool->pipe_count; i++) {
if (update_state->pg_pipe_res_update[PG_HUBP][i] &&
@@ -1286,6 +1334,13 @@ void dcn35_hw_block_power_up(struct dc *dc,
if (pg_cntl->funcs->hubp_dpp_pg_control)
pg_cntl->funcs->hubp_dpp_pg_control(pg_cntl, i, true);
}
+
+ if (dc->caps.sequential_ono) {
+ if (update_state->pg_pipe_res_update[PG_DSC][i]) {
+ if (pg_cntl->funcs->dsc_pg_control)
+ pg_cntl->funcs->dsc_pg_control(pg_cntl, i, true);
+ }
+ }
}
if (update_state->pg_res_update[PG_HPO]) {
if (pg_cntl->funcs->hpo_pg_control)
@@ -1474,3 +1529,75 @@ void dcn35_set_long_vblank(struct pipe_ctx **pipe_ctx,
}
}
}
+
+static bool should_avoid_empty_tu(struct pipe_ctx *pipe_ctx)
+{
+ /* Calculate average pixel count per TU, return false if under ~2.00 to
+ * avoid empty TUs. This is only required for DPIA tunneling as empty TUs
+ * are legal to generate for native DP links. Assume TU size 64 as there
+ * is currently no scenario where it's reprogrammed from HW default.
+ * MTPs have no such limitation, so this does not affect MST use cases.
+ */
+ unsigned int pix_clk_mhz;
+ unsigned int symclk_mhz;
+ unsigned int avg_pix_per_tu_x1000;
+ unsigned int tu_size_bytes = 64;
+ struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
+ struct dc_link_settings *link_settings = &pipe_ctx->link_config.dp_link_settings;
+ const struct dc *dc = pipe_ctx->stream->link->dc;
+
+ if (pipe_ctx->stream->link->ep_type != DISPLAY_ENDPOINT_USB4_DPIA)
+ return false;
+
+ // Not necessary for MST configurations
+ if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
+ return false;
+
+ pix_clk_mhz = timing->pix_clk_100hz / 10000;
+
+ // If this is true, can't block due to dynamic ODM
+ if (pix_clk_mhz > dc->clk_mgr->bw_params->clk_table.entries[0].dispclk_mhz)
+ return false;
+
+ switch (link_settings->link_rate) {
+ case LINK_RATE_LOW:
+ symclk_mhz = 162;
+ break;
+ case LINK_RATE_HIGH:
+ symclk_mhz = 270;
+ break;
+ case LINK_RATE_HIGH2:
+ symclk_mhz = 540;
+ break;
+ case LINK_RATE_HIGH3:
+ symclk_mhz = 810;
+ break;
+ default:
+ // We shouldn't be tunneling any other rates, something is wrong
+ ASSERT(0);
+ return false;
+ }
+
+ avg_pix_per_tu_x1000 = (1000 * pix_clk_mhz * tu_size_bytes)
+ / (symclk_mhz * link_settings->lane_count);
+
+ // Add small empirically-decided margin to account for potential jitter
+ return (avg_pix_per_tu_x1000 < 2020);
+}
+
+bool dcn35_is_dp_dig_pixel_rate_div_policy(struct pipe_ctx *pipe_ctx)
+{
+ struct dc *dc = pipe_ctx->stream->ctx->dc;
+
+ if (!is_h_timing_divisible_by_2(pipe_ctx->stream))
+ return false;
+
+ if (should_avoid_empty_tu(pipe_ctx))
+ return false;
+
+ if (dc_is_dp_signal(pipe_ctx->stream->signal) && !dc->link_srv->dp_is_128b_132b_signal(pipe_ctx) &&
+ dc->debug.enable_dp_dig_pixel_rate_div_policy)
+ return true;
+
+ return false;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h
index bc05beba5f2c..e27b3609020f 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h
@@ -97,4 +97,6 @@ void dcn35_set_static_screen_control(struct pipe_ctx **pipe_ctx,
void dcn35_set_long_vblank(struct pipe_ctx **pipe_ctx,
int num_pipes, uint32_t v_total_min, uint32_t v_total_max);
+bool dcn35_is_dp_dig_pixel_rate_div_policy(struct pipe_ctx *pipe_ctx);
+
#endif /* __DC_HWSS_DCN35_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c
index 30e6a6398839..428912f37129 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c
@@ -161,7 +161,7 @@ static const struct hwseq_private_funcs dcn35_private_funcs = {
.setup_hpo_hw_control = dcn35_setup_hpo_hw_control,
.calculate_dccg_k1_k2_values = dcn32_calculate_dccg_k1_k2_values,
.resync_fifo_dccg_dio = dcn314_resync_fifo_dccg_dio,
- .is_dp_dig_pixel_rate_div_policy = dcn32_is_dp_dig_pixel_rate_div_policy,
+ .is_dp_dig_pixel_rate_div_policy = dcn35_is_dp_dig_pixel_rate_div_policy,
.dsc_pg_control = dcn35_dsc_pg_control,
.dsc_pg_status = dcn32_dsc_pg_status,
.enable_plane = dcn35_enable_plane,
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 407a45a3ae2c..2c50c0f745a0 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
@@ -57,7 +57,16 @@ static void dcn401_initialize_min_clocks(struct dc *dc)
clocks->socclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].socclk_mhz * 1000;
clocks->dramclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].memclk_mhz * 1000;
clocks->dppclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].dppclk_mhz * 1000;
- clocks->dispclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].dispclk_mhz * 1000;
+ if (dc->debug.disable_boot_optimizations) {
+ clocks->dispclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].dispclk_mhz * 1000;
+ } else {
+ /* 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
+ * freq to ensure that the timing is valid and unchanged.
+ */
+ clocks->dispclk_khz = dc->clk_mgr->funcs->get_dispclk_from_dentist(dc->clk_mgr);
+ }
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;
@@ -250,7 +259,7 @@ void dcn401_init_hw(struct dc *dc)
res_pool->ref_clocks.xtalin_clock_inKhz =
dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency;
- if (res_pool->dccg && res_pool->hubbub) {
+ if (res_pool->hubbub) {
(res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg,
dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency,
&res_pool->ref_clocks.dccg_ref_clock_inKhz);
@@ -304,7 +313,14 @@ void dcn401_init_hw(struct dc *dc)
* everything down.
*/
if (dcb->funcs->is_accelerated_mode(dcb) || !dc->config.seamless_boot_edp_requested) {
- hws->funcs.init_pipes(dc, dc->current_state);
+ /* Disable boot optimizations means power down everything including PHY, DIG,
+ * and OTG (i.e. the boot is not optimized because we do a full power down).
+ */
+ if (dc->hwss.enable_accelerated_mode && dc->debug.disable_boot_optimizations)
+ dc->hwss.enable_accelerated_mode(dc, dc->current_state);
+ else
+ hws->funcs.init_pipes(dc, dc->current_state);
+
if (dc->res_pool->hubbub->funcs->allow_self_refresh_control)
dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub,
!dc->res_pool->hubbub->ctx->dc->debug.disable_stutter);
@@ -392,6 +408,8 @@ void dcn401_init_hw(struct dc *dc)
REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
}
+ dcn401_setup_hpo_hw_control(hws, true);
+
if (!dcb->funcs->is_accelerated_mode(dcb) && dc->res_pool->hubbub->funcs->init_watermarks)
dc->res_pool->hubbub->funcs->init_watermarks(dc->res_pool->hubbub);
@@ -484,7 +502,7 @@ void dcn401_populate_mcm_luts(struct dc *dc,
dcn401_get_mcm_lut_xable_from_pipe_ctx(dc, pipe_ctx, &shaper_xable, &lut3d_xable, &lut1d_xable);
/* 1D LUT */
- if (mcm_luts.lut1d_func) {
+ if (mcm_luts.lut1d_func && lut3d_xable != MCM_LUT_DISABLE) {
memset(&m_lut_params, 0, sizeof(m_lut_params));
if (mcm_luts.lut1d_func->type == TF_TYPE_HWPWL)
m_lut_params.pwl = &mcm_luts.lut1d_func->pwl;
@@ -656,7 +674,7 @@ bool dcn401_set_mcm_luts(struct pipe_ctx *pipe_ctx,
mpc->funcs->set_movable_cm_location(mpc, MPCC_MOVABLE_CM_LOCATION_BEFORE, mpcc_id);
pipe_ctx->plane_state->mcm_location = MPCC_MOVABLE_CM_LOCATION_BEFORE;
// 1D LUT
- if (!plane_state->mcm_lut1d_enable) {
+ if (plane_state->mcm_shaper_3dlut_setting == DC_CM2_SHAPER_3DLUT_SETTING_BYPASS_ALL) {
if (plane_state->blend_tf.type == TF_TYPE_HWPWL)
lut_params = &plane_state->blend_tf.pwl;
else if (plane_state->blend_tf.type == TF_TYPE_DISTRIBUTED_POINTS) {
@@ -798,7 +816,7 @@ enum dc_status dcn401_enable_stream_timing(
unsigned int event_triggers = 0;
int opp_cnt = 1;
int opp_inst[MAX_PIPES] = {0};
- struct pipe_ctx *opp_heads[MAX_PIPES];
+ struct pipe_ctx *opp_heads[MAX_PIPES] = {0};
bool manual_mode;
unsigned int tmds_div = PIXEL_RATE_DIV_NA;
unsigned int unused_div = PIXEL_RATE_DIV_NA;
@@ -900,8 +918,8 @@ enum dc_status dcn401_enable_stream_timing(
/* TODO enable stream if timing changed */
/* TODO unblank stream if DP */
- if (pipe_ctx->stream && dc_state_get_pipe_subvp_type(context, pipe_ctx) == SUBVP_PHANTOM) {
- if (pipe_ctx->stream_res.tg && pipe_ctx->stream_res.tg->funcs->phantom_crtc_post_enable)
+ if (dc_state_get_pipe_subvp_type(context, pipe_ctx) == SUBVP_PHANTOM) {
+ if (pipe_ctx->stream_res.tg->funcs->phantom_crtc_post_enable)
pipe_ctx->stream_res.tg->funcs->phantom_crtc_post_enable(pipe_ctx->stream_res.tg);
}
@@ -1070,6 +1088,17 @@ static bool dcn401_can_pipe_disable_cursor(struct pipe_ctx *pipe_ctx)
return false;
}
+void adjust_hotspot_between_slices_for_2x_magnify(uint32_t cursor_width, struct dc_cursor_position *pos_cpy)
+{
+ if (cursor_width <= 128) {
+ pos_cpy->x_hotspot /= 2;
+ pos_cpy->x_hotspot += 1;
+ } else {
+ pos_cpy->x_hotspot /= 2;
+ pos_cpy->x_hotspot += 2;
+ }
+}
+
void dcn401_set_cursor_position(struct pipe_ctx *pipe_ctx)
{
struct dc_cursor_position pos_cpy = pipe_ctx->stream->cursor_position;
@@ -1083,28 +1112,30 @@ void dcn401_set_cursor_position(struct pipe_ctx *pipe_ctx)
.h_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.horz,
.v_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.vert,
.rotation = pipe_ctx->plane_state->rotation,
- .mirror = pipe_ctx->plane_state->horizontal_mirror
+ .mirror = pipe_ctx->plane_state->horizontal_mirror,
+ .stream = pipe_ctx->stream
};
- bool pipe_split_on = false;
bool odm_combine_on = (pipe_ctx->next_odm_pipe != NULL) ||
(pipe_ctx->prev_odm_pipe != NULL);
int prev_odm_width = 0;
int prev_odm_offset = 0;
- int next_odm_width = 0;
- int next_odm_offset = 0;
+ struct pipe_ctx *prev_odm_pipe = NULL;
+ bool mpc_combine_on = false;
+ int bottom_pipe_x_pos = 0;
int x_pos = pos_cpy.x;
int y_pos = pos_cpy.y;
+ int recout_x_pos = 0;
+ int recout_y_pos = 0;
if ((pipe_ctx->top_pipe != NULL) || (pipe_ctx->bottom_pipe != NULL)) {
if ((pipe_ctx->plane_state->src_rect.width != pipe_ctx->plane_res.scl_data.viewport.width) ||
(pipe_ctx->plane_state->src_rect.height != pipe_ctx->plane_res.scl_data.viewport.height)) {
- pipe_split_on = true;
+ mpc_combine_on = true;
}
}
- /**
- * DCN4 moved cursor composition after Scaler, so in HW it is in
+ /* DCN4 moved cursor composition after Scaler, so in HW it is in
* recout space and for HW Cursor position programming need to
* translate to recout space.
*
@@ -1124,21 +1155,12 @@ void dcn401_set_cursor_position(struct pipe_ctx *pipe_ctx)
* pipe to make sure each pipe enabling cursor on its part of the
* screen.
*/
+ x_pos = pipe_ctx->stream->dst.x + x_pos * pipe_ctx->stream->dst.width /
+ pipe_ctx->stream->src.width;
+ y_pos = pipe_ctx->stream->dst.y + y_pos * pipe_ctx->stream->dst.height /
+ pipe_ctx->stream->src.height;
- if (param.rotation == ROTATION_ANGLE_90 || param.rotation == ROTATION_ANGLE_270) {
- x_pos = pipe_ctx->stream->dst.x + x_pos * pipe_ctx->stream->dst.width /
- pipe_ctx->stream->src.height;
- y_pos = pipe_ctx->stream->dst.y + y_pos * pipe_ctx->stream->dst.height /
- pipe_ctx->stream->src.width;
- } else {
- x_pos = pipe_ctx->stream->dst.x + x_pos * pipe_ctx->stream->dst.width /
- pipe_ctx->stream->src.width;
- y_pos = pipe_ctx->stream->dst.y + y_pos * pipe_ctx->stream->dst.height /
- pipe_ctx->stream->src.height;
- }
-
- /**
- * If the cursor's source viewport is clipped then we need to
+ /* If the cursor's source viewport is clipped then we need to
* translate the cursor to appear in the correct position on
* the screen.
*
@@ -1158,32 +1180,25 @@ void dcn401_set_cursor_position(struct pipe_ctx *pipe_ctx)
* next/prev_odm_offset is to account for scaled modes that have underscan
*/
if (odm_combine_on) {
- struct pipe_ctx *next_odm_pipe = pipe_ctx->next_odm_pipe;
- struct pipe_ctx *prev_odm_pipe = pipe_ctx->prev_odm_pipe;
+ prev_odm_pipe = pipe_ctx->prev_odm_pipe;
- while (next_odm_pipe != NULL) {
- next_odm_width += next_odm_pipe->plane_res.scl_data.recout.width;
- next_odm_offset += next_odm_pipe->plane_res.scl_data.recout.x;
- next_odm_pipe = next_odm_pipe->next_odm_pipe;
- }
while (prev_odm_pipe != NULL) {
prev_odm_width += prev_odm_pipe->plane_res.scl_data.recout.width;
prev_odm_offset += prev_odm_pipe->plane_res.scl_data.recout.x;
prev_odm_pipe = prev_odm_pipe->prev_odm_pipe;
}
- if (param.rotation == ROTATION_ANGLE_0) {
- x_pos -= (prev_odm_width + prev_odm_offset);
- }
+ x_pos -= (prev_odm_width + prev_odm_offset);
}
- /**
- * If the position is negative then we need to add to the hotspot
- * to shift the cursor outside the plane.
+ /* If the position is negative then we need to add to the hotspot
+ * to fix cursor size between ODM slices
*/
if (x_pos < 0) {
pos_cpy.x_hotspot -= x_pos;
+ if (hubp->curs_attr.attribute_flags.bits.ENABLE_MAGNIFICATION)
+ adjust_hotspot_between_slices_for_2x_magnify(hubp->curs_attr.width, &pos_cpy);
x_pos = 0;
}
@@ -1192,149 +1207,45 @@ void dcn401_set_cursor_position(struct pipe_ctx *pipe_ctx)
y_pos = 0;
}
+ /* If the position on bottom MPC pipe is negative then we need to add to the hotspot and
+ * adjust x_pos on bottom pipe to make cursor visible when crossing between MPC slices.
+ */
+ if (mpc_combine_on &&
+ pipe_ctx->top_pipe &&
+ (pipe_ctx == pipe_ctx->top_pipe->bottom_pipe)) {
+
+ bottom_pipe_x_pos = x_pos - pipe_ctx->plane_res.scl_data.recout.x;
+ if (bottom_pipe_x_pos < 0) {
+ x_pos = pipe_ctx->plane_res.scl_data.recout.x;
+ pos_cpy.x_hotspot -= bottom_pipe_x_pos;
+ if (hubp->curs_attr.attribute_flags.bits.ENABLE_MAGNIFICATION)
+ adjust_hotspot_between_slices_for_2x_magnify(hubp->curs_attr.width, &pos_cpy);
+ }
+ }
+
pos_cpy.x = (uint32_t)x_pos;
pos_cpy.y = (uint32_t)y_pos;
if (pos_cpy.enable && dcn401_can_pipe_disable_cursor(pipe_ctx))
pos_cpy.enable = false;
- if (param.rotation == ROTATION_ANGLE_0) {
- int recout_width =
- pipe_ctx->plane_res.scl_data.recout.width;
- int recout_x =
- pipe_ctx->plane_res.scl_data.recout.x;
-
- if (param.mirror) {
- if (pipe_split_on || odm_combine_on) {
- if (pos_cpy.x >= recout_width + recout_x) {
- pos_cpy.x = 2 * recout_width
- - pos_cpy.x + 2 * recout_x;
- } else {
- uint32_t temp_x = pos_cpy.x;
-
- pos_cpy.x = 2 * recout_x - pos_cpy.x;
- if (temp_x >= recout_x +
- (int)hubp->curs_attr.width || pos_cpy.x
- <= (int)hubp->curs_attr.width +
- pipe_ctx->plane_state->src_rect.x) {
- pos_cpy.x = 2 * recout_width - temp_x;
- }
- }
- } else {
- pos_cpy.x = recout_width - pos_cpy.x + 2 * recout_x;
- }
- }
- } else if (param.rotation == ROTATION_ANGLE_90) {
- if (!param.mirror) {
- uint32_t temp_y = pos_cpy.y;
-
- pos_cpy.y = pipe_ctx->plane_res.scl_data.recout.height - pos_cpy.x;
- pos_cpy.x = temp_y - prev_odm_width;
- } else {
- swap(pos_cpy.x, pos_cpy.y);
- }
-
- } else if (param.rotation == ROTATION_ANGLE_270) {
- // Swap axis and mirror vertically
- uint32_t temp_x = pos_cpy.x;
+ x_pos = pos_cpy.x - param.recout.x;
+ y_pos = pos_cpy.y - param.recout.y;
- int recout_height =
- pipe_ctx->plane_res.scl_data.recout.height;
- int recout_y =
- pipe_ctx->plane_res.scl_data.recout.y;
+ recout_x_pos = x_pos - pos_cpy.x_hotspot;
+ recout_y_pos = y_pos - pos_cpy.y_hotspot;
- /**
- * Display groups that are 1xnY, have pos_cpy.x > 2 * recout.height
- * For pipe split cases:
- * - apply offset of recout.y to normalize pos_cpy.x
- * - calculate the pos_cpy.y as before
- * - shift pos_cpy.y back by same offset to get final value
- * - since we iterate through both pipes, use the lower
- * recout.y for offset
- * For non pipe split cases, use the same calculation for
- * pos_cpy.y as the 180 degree rotation case below,
- * but use pos_cpy.x as our input because we are rotating
- * 270 degrees
- */
- if (pipe_split_on || odm_combine_on) {
- int pos_cpy_x_offset;
- int other_pipe_recout_y;
-
- if (pipe_split_on) {
- if (pipe_ctx->bottom_pipe) {
- other_pipe_recout_y =
- pipe_ctx->bottom_pipe->plane_res.scl_data.recout.y;
- } else {
- other_pipe_recout_y =
- pipe_ctx->top_pipe->plane_res.scl_data.recout.y;
- }
- pos_cpy_x_offset = (recout_y > other_pipe_recout_y) ?
- other_pipe_recout_y : recout_y;
- pos_cpy.x -= pos_cpy_x_offset;
- if (pos_cpy.x > recout_height) {
- pos_cpy.x = pos_cpy.x - recout_height;
- pos_cpy.y = recout_height - pos_cpy.x;
- } else {
- pos_cpy.y = 2 * recout_height - pos_cpy.x;
- }
- pos_cpy.y += pos_cpy_x_offset;
+ if (recout_x_pos >= (int)param.recout.width)
+ pos_cpy.enable = false; /* not visible beyond right edge*/
- } else {
- pos_cpy.x = pipe_ctx->plane_res.scl_data.recout.width + next_odm_width + next_odm_offset - pos_cpy.y;
- pos_cpy.y = temp_x;
- }
- } else {
- if (param.mirror) {
- swap(pos_cpy.x, pos_cpy.y);
+ if (recout_y_pos >= (int)param.recout.height)
+ pos_cpy.enable = false; /* not visible beyond bottom edge*/
- pos_cpy.x = pipe_ctx->plane_res.scl_data.recout.width - pos_cpy.x + 2 * pipe_ctx->plane_res.scl_data.recout.x;
- pos_cpy.y = (2 * pipe_ctx->plane_res.scl_data.recout.y) + pipe_ctx->plane_res.scl_data.recout.height - pos_cpy.y;
- } else {
- pos_cpy.x = pipe_ctx->plane_res.scl_data.recout.width - pos_cpy.y;
- pos_cpy.y = temp_x;
- }
- }
- } else if (param.rotation == ROTATION_ANGLE_180) {
- // Mirror horizontally and vertically
- int recout_width =
- pipe_ctx->plane_res.scl_data.recout.width;
- int recout_x =
- pipe_ctx->plane_res.scl_data.recout.x;
-
- if (!param.mirror) {
- if (odm_combine_on) {
- pos_cpy.x = pipe_ctx->plane_res.scl_data.recout.width + next_odm_width - pos_cpy.x;
- } else if (pipe_split_on) {
- if (pos_cpy.x >= recout_width + recout_x) {
- pos_cpy.x = 2 * recout_width
- - pos_cpy.x + 2 * recout_x;
- } else {
- uint32_t temp_x = pos_cpy.x;
-
- pos_cpy.x = 2 * recout_x - pos_cpy.x;
- if (temp_x >= recout_x +
- (int)hubp->curs_attr.width || pos_cpy.x
- <= (int)hubp->curs_attr.width +
- pipe_ctx->plane_state->src_rect.x) {
- pos_cpy.x = temp_x + recout_width;
- }
- }
- } else {
- pos_cpy.x = recout_width - pos_cpy.x + 2 * recout_x;
- }
- }
+ if (recout_x_pos + (int)hubp->curs_attr.width <= 0)
+ pos_cpy.enable = false; /* not visible beyond left edge*/
- /**
- * Display groups that are 1xnY, have pos_cpy.y > recout.height
- * Calculation:
- * delta_from_bottom = recout.y + recout.height - pos_cpy.y
- * pos_cpy.y_new = recout.y + delta_from_bottom
- * Simplify it as:
- * pos_cpy.y = recout.y * 2 + recout.height - pos_cpy.y
- */
- pos_cpy.y = (2 * pipe_ctx->plane_res.scl_data.recout.y) +
- pipe_ctx->plane_res.scl_data.recout.height - pos_cpy.y;
- }
+ if (recout_y_pos + (int)hubp->curs_attr.height <= 0)
+ pos_cpy.enable = false; /* not visible beyond top edge*/
hubp->funcs->set_cursor_position(hubp, &pos_cpy, &param);
dpp->funcs->set_cursor_position(dpp, &pos_cpy, &param, hubp->curs_attr.width, hubp->curs_attr.height);
@@ -1454,6 +1365,31 @@ bool dcn401_apply_idle_power_optimizations(struct dc *dc, bool enable)
return true;
}
+void dcn401_wait_for_dcc_meta_propagation(const struct dc *dc,
+ const struct pipe_ctx *top_pipe)
+{
+ bool is_wait_needed = false;
+ const struct pipe_ctx *pipe_ctx = top_pipe;
+
+ /* check if any surfaces are updating address while using flip immediate and dcc */
+ while (pipe_ctx != NULL) {
+ if (pipe_ctx->plane_state &&
+ pipe_ctx->plane_state->dcc.enable &&
+ pipe_ctx->plane_state->flip_immediate &&
+ pipe_ctx->plane_state->update_flags.bits.addr_update) {
+ is_wait_needed = true;
+ break;
+ }
+
+ /* check next pipe */
+ pipe_ctx = pipe_ctx->bottom_pipe;
+ }
+
+ if (is_wait_needed && dc->debug.dcc_meta_propagation_delay_us > 0) {
+ udelay(dc->debug.dcc_meta_propagation_delay_us);
+ }
+}
+
void dcn401_prepare_bandwidth(struct dc *dc,
struct dc_state *context)
{
@@ -1607,16 +1543,28 @@ static void update_dsc_for_odm_change(struct dc *dc, struct dc_state *context,
struct pipe_ctx *new_pipe;
struct pipe_ctx *old_opp_heads[MAX_PIPES];
struct dccg *dccg = dc->res_pool->dccg;
- struct pipe_ctx *old_otg_master =
- &dc->current_state->res_ctx.pipe_ctx[otg_master->pipe_idx];
- int old_opp_head_count = resource_get_opp_heads_for_otg_master(
- old_otg_master, &dc->current_state->res_ctx,
- old_opp_heads);
+ struct pipe_ctx *old_otg_master;
+ int old_opp_head_count = 0;
+
+ old_otg_master = &dc->current_state->res_ctx.pipe_ctx[otg_master->pipe_idx];
+
+ if (resource_is_pipe_type(old_otg_master, OTG_MASTER)) {
+ old_opp_head_count = resource_get_opp_heads_for_otg_master(old_otg_master,
+ &dc->current_state->res_ctx,
+ old_opp_heads);
+ } else {
+ // DC cannot assume that the current state and the new state
+ // share the same OTG pipe since this is not true when called
+ // in the context of a commit stream not checked. Hence, set
+ // old_otg_master to NULL to skip the DSC configuration.
+ old_otg_master = NULL;
+ }
+
if (otg_master->stream_res.dsc)
dcn32_update_dsc_on_stream(otg_master,
otg_master->stream->timing.flags.DSC);
- if (old_otg_master->stream_res.dsc) {
+ if (old_otg_master && old_otg_master->stream_res.dsc) {
for (i = 0; i < old_opp_head_count; i++) {
old_pipe = old_opp_heads[i];
new_pipe = &context->res_ctx.pipe_ctx[old_pipe->pipe_idx];
@@ -1701,3 +1649,23 @@ void dcn401_unblank_stream(struct pipe_ctx *pipe_ctx,
if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP)
hws->funcs.edp_backlight_control(link, true);
}
+
+void dcn401_hardware_release(struct dc *dc)
+{
+ dc_dmub_srv_fams2_update_config(dc, dc->current_state, false);
+
+ /* If pstate unsupported, or still supported
+ * by firmware, force it supported by dcn
+ */
+ if (dc->current_state) {
+ if ((!dc->clk_mgr->clks.p_state_change_support ||
+ dc->current_state->bw_ctx.bw.dcn.fams2_stream_count > 0) &&
+ dc->res_pool->hubbub->funcs->force_pstate_change_control)
+ dc->res_pool->hubbub->funcs->force_pstate_change_control(
+ dc->res_pool->hubbub, true, true);
+
+ dc->current_state->bw_ctx.bw.dcn.clk.p_state_change_support = true;
+ dc->clk_mgr->funcs->update_clocks(dc->clk_mgr, dc->current_state, true);
+ }
+}
+
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h
index f91159a6e6d4..8e9c1c17aa66 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h
@@ -61,6 +61,8 @@ bool dcn401_apply_idle_power_optimizations(struct dc *dc, bool enable);
struct ips_ono_region_state dcn401_read_ono_state(struct dc *dc,
uint8_t region);
+void dcn401_wait_for_dcc_meta_propagation(const struct dc *dc,
+ const struct pipe_ctx *top_pipe_to_program);
void dcn401_prepare_bandwidth(struct dc *dc,
struct dc_state *context);
@@ -75,7 +77,8 @@ void dcn401_fams2_global_control_lock(struct dc *dc,
void dcn401_fams2_update_config(struct dc *dc, struct dc_state *context, bool enable);
void dcn401_fams2_global_control_lock_fast(union block_sequence_params *params);
void dcn401_unblank_stream(struct pipe_ctx *pipe_ctx, struct dc_link_settings *link_settings);
-
+void dcn401_hardware_release(struct dc *dc);
void dcn401_update_odm(struct dc *dc, struct dc_state *context,
struct pipe_ctx *otg_master);
+void adjust_hotspot_between_slices_for_2x_magnify(uint32_t cursor_width, struct dc_cursor_position *pos_cpy);
#endif /* __DC_HWSS_DCN401_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c
index 8358ba74405f..6a768702c7bd 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c
@@ -79,7 +79,7 @@ static const struct hw_sequencer_funcs dcn401_funcs = {
.does_plane_fit_in_mall = NULL,
.set_backlight_level = dcn21_set_backlight_level,
.set_abm_immediate_disable = dcn21_set_abm_immediate_disable,
- .hardware_release = dcn30_hardware_release,
+ .hardware_release = dcn401_hardware_release,
.set_pipe = dcn21_set_pipe,
.enable_lvds_link_output = dce110_enable_lvds_link_output,
.enable_tmds_link_output = dce110_enable_tmds_link_output,
@@ -94,10 +94,12 @@ static const struct hw_sequencer_funcs dcn401_funcs = {
.update_dsc_pg = dcn32_update_dsc_pg,
.apply_update_flags_for_phantom = dcn32_apply_update_flags_for_phantom,
.blank_phantom = dcn32_blank_phantom,
+ .wait_for_dcc_meta_propagation = dcn401_wait_for_dcc_meta_propagation,
.is_pipe_topology_transition_seamless = dcn32_is_pipe_topology_transition_seamless,
.fams2_global_control_lock = dcn401_fams2_global_control_lock,
.fams2_update_config = dcn401_fams2_update_config,
.fams2_global_control_lock_fast = dcn401_fams2_global_control_lock_fast,
+ .power_down = dce110_power_down,
};
static const struct hwseq_private_funcs dcn401_private_funcs = {
@@ -136,7 +138,6 @@ static const struct hwseq_private_funcs dcn401_private_funcs = {
.program_mall_pipe_config = dcn32_program_mall_pipe_config,
.update_force_pstate = dcn32_update_force_pstate,
.update_mall_sel = dcn32_update_mall_sel,
- .setup_hpo_hw_control = dcn401_setup_hpo_hw_control,
.calculate_dccg_k1_k2_values = NULL,
.apply_single_controller_ctx_to_hw = dce110_apply_single_controller_ctx_to_hw,
.reset_back_end_for_pipe = dcn20_reset_back_end_for_pipe,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
index e9b85884edce..d05be65a2256 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
@@ -141,6 +141,11 @@ struct subvp_save_surf_addr {
uint8_t subvp_index;
};
+struct wait_for_dcc_meta_propagation_params {
+ const struct dc *dc;
+ const struct pipe_ctx *top_pipe_to_program;
+};
+
struct fams2_global_control_lock_fast_params {
struct dc *dc;
bool is_required;
@@ -165,6 +170,7 @@ union block_sequence_params {
struct set_output_csc_params set_output_csc_params;
struct set_ocsc_default_params set_ocsc_default_params;
struct subvp_save_surf_addr subvp_save_surf_addr;
+ struct wait_for_dcc_meta_propagation_params wait_for_dcc_meta_propagation_params;
struct fams2_global_control_lock_fast_params fams2_global_control_lock_fast_params;
};
@@ -186,6 +192,7 @@ enum block_sequence_func {
MPC_SET_OUTPUT_CSC,
MPC_SET_OCSC_DEFAULT,
DMUB_SUBVP_SAVE_SURF_ADDR,
+ HUBP_WAIT_FOR_DCC_META_PROP,
DMUB_FAMS2_GLOBAL_CONTROL_LOCK_FAST,
};
@@ -443,6 +450,8 @@ struct hw_sequencer_funcs {
bool (*is_pipe_topology_transition_seamless)(struct dc *dc,
const struct dc_state *cur_ctx,
const struct dc_state *new_ctx);
+ void (*wait_for_dcc_meta_propagation)(const struct dc *dc,
+ const struct pipe_ctx *top_pipe_to_program);
void (*fams2_global_control_lock)(struct dc *dc,
struct dc_state *context,
bool lock);
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 f58c27ad8b3e..4c8e6436c7e1 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h
@@ -97,6 +97,9 @@ struct resource_funcs {
unsigned int (*calculate_mall_ways_from_bytes)(
const struct dc *dc,
unsigned int total_size_in_mall_bytes);
+ void (*prepare_mcache_programming)(
+ struct dc *dc,
+ struct dc_state *context);
/**
* @populate_dml_pipes - Populate pipe data struct
*
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
index a73cb8f731b3..dd2b2864876c 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
@@ -40,6 +40,10 @@ enum dcc_control {
dcc_control__128_128_xxx,
dcc_control__256_64_64,
dcc_control__256_128_128,
+ dcc_control__256_256,
+ dcc_control__256_128,
+ dcc_control__256_64,
+
};
enum segment_order {
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h
index 9ac7fc717a92..0150f2581ee4 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h
@@ -147,16 +147,28 @@ struct cnv_color_keyer_params {
int color_keyer_blue_high;
};
-/* new for dcn2: set the 8bit alpha values based on the 2 bit alpha
- *ALPHA_2BIT_LUT. ALPHA_2BIT_LUT0 default: 0b00000000
- *ALPHA_2BIT_LUT. ALPHA_2BIT_LUT1 default: 0b01010101
- *ALPHA_2BIT_LUT. ALPHA_2BIT_LUT2 default: 0b10101010
- *ALPHA_2BIT_LUT. ALPHA_2BIT_LUT3 default: 0b11111111
+/**
+ * struct cnv_alpha_2bit_lut - Set the 8bit alpha values based on the 2 bit alpha
*/
struct cnv_alpha_2bit_lut {
+ /**
+ * @lut0: ALPHA_2BIT_LUT. ALPHA_2BIT_LUT0. Default: 0b00000000
+ */
int lut0;
+
+ /**
+ * @lut1: ALPHA_2BIT_LUT. ALPHA_2BIT_LUT1. Default: 0b01010101
+ */
int lut1;
+
+ /**
+ * @lut2: ALPHA_2BIT_LUT. ALPHA_2BIT_LUT2. Default: 0b10101010
+ */
int lut2;
+
+ /**
+ * @lut3: ALPHA_2BIT_LUT. ALPHA_2BIT_LUT3. Default: 0b11111111
+ */
int lut3;
};
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h
index bcd7b22a1627..16580d624278 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h
@@ -257,6 +257,7 @@ struct hubp_funcs {
unsigned int min_dst_y_next_start_optimized);
void (*hubp_wait_pipe_read_start)(struct hubp *hubp);
+ void (*hubp_program_mcache_id_and_split_coordinate)(struct hubp *hubp, struct dml2_hubp_pipe_mcache_regs *mcache_regs);
void (*hubp_update_3dlut_fl_bias_scale)(struct hubp *hubp, uint16_t bias, uint16_t scale);
void (*hubp_program_3dlut_fl_mode)(struct hubp *hubp,
enum hubp_3dlut_fl_mode mode);
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 c80ebb407add..27bba47186e9 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
@@ -44,7 +44,7 @@
*/
#define MAX_PIPES 6
#define MAX_PHANTOM_PIPES (MAX_PIPES / 2)
-#define MAX_LINKS (MAX_PIPES * 2)
+#define MAX_LINKS (MAX_PIPES * 2 +2)
#define MAX_DIG_LINK_ENCODERS 7
#define MAX_DWB_PIPES 1
#define MAX_HPO_DP2_ENCODERS 4
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h
index 40a9b3471208..3a89cc0cffc1 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h
@@ -1039,6 +1039,20 @@ struct mpc_funcs {
*/
void (*program_lut_mode)(struct mpc *mpc, const enum MCM_LUT_ID id, const enum MCM_LUT_XABLE xable,
bool lut_bank_a, int mpcc_id);
+ /**
+ * @program_3dlut_size:
+ *
+ * Program 3D LUT size.
+ *
+ * Parameters:
+ * - [in/out] mpc - MPC context.
+ * - [in] is_17x17x17 - is 3dlut 17x17x17
+ * - [in] mpcc_id
+ *
+ * Return:
+ *
+ * void
+ */
void (*program_3dlut_size)(struct mpc *mpc, bool is_17x17x17, int mpcc_id);
};
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h
index 127fb1a51654..747679cb4944 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h
@@ -205,9 +205,24 @@ struct gamma_coefficients {
struct fixed31_32 user_brightness;
};
+/**
+ * struct pwl_float_data - Fixed point RGB color
+ */
struct pwl_float_data {
+ /**
+ * @r: Component Red.
+ */
struct fixed31_32 r;
+
+ /**
+ * @g: Component Green.
+ */
+
struct fixed31_32 g;
+
+ /**
+ * @b: Component Blue.
+ */
struct fixed31_32 b;
};
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
index cd4826f329c1..0f453452234c 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
@@ -340,6 +340,7 @@ struct timing_generator_funcs {
void (*wait_drr_doublebuffer_pending_clear)(struct timing_generator *tg);
void (*set_long_vtotal)(struct timing_generator *optc, const struct long_vtotal_params *params);
void (*wait_odm_doublebuffer_pending_clear)(struct timing_generator *tg);
+ bool (*get_double_buffer_pending)(struct timing_generator *tg);
};
#endif
diff --git a/drivers/gpu/drm/amd/display/dc/inc/link.h b/drivers/gpu/drm/amd/display/dc/inc/link.h
index 7ab8ba5e23ed..72a8479e1f2d 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/link.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/link.h
@@ -272,7 +272,7 @@ struct link_service {
uint16_t psr_vtotal_idle,
uint16_t psr_vtotal_su);
void (*edp_get_psr_residency)(
- const struct dc_link *link, uint32_t *residency);
+ const struct dc_link *link, uint32_t *residency, enum psr_residency_mode mode);
bool (*edp_get_replay_state)(
const struct dc_link *link, uint64_t *state);
diff --git a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c
index d100edaedbbb..eca3d7ee7e4e 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c
@@ -76,7 +76,7 @@ static const struct irq_source_info *find_irq_source_info(
struct irq_service *irq_service,
enum dc_irq_source source)
{
- if (source >= DAL_IRQ_SOURCES_NUMBER || source < DC_IRQ_SOURCE_INVALID)
+ if (source >= DAL_IRQ_SOURCES_NUMBER)
return NULL;
return &irq_service->info[source];
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 8d1a1cc94a8b..555c1c484cfd 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
@@ -853,7 +853,7 @@ bool dp_set_test_pattern(
CRTC_STATE_VACTIVE);
if (pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_disable) {
- if (pipe_ctx->stream && should_use_dmub_lock(pipe_ctx->stream->link)) {
+ if (should_use_dmub_lock(pipe_ctx->stream->link)) {
union dmub_hw_lock_flags hw_locks = { 0 };
struct dmub_hw_lock_inst_flags inst_flags = { 0 };
diff --git a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.c b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.c
index 50459d7a0f85..b76737b7b9e4 100644
--- a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.c
+++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.c
@@ -26,6 +26,16 @@
#include "core_types.h"
#include "link_enc_cfg.h"
+/**
+ * DOC: overview
+ *
+ * Display Input Output (DIO), is the display input and output unit in DCN. It
+ * includes output encoders to support different display output, like
+ * DisplayPort, HDMI, DVI interface, and others. It also includes the control
+ * and status channels for these interfaces.
+ */
+
+
void set_dio_throttled_vcp_size(struct pipe_ctx *pipe_ctx,
struct fixed31_32 throttled_vcp_size)
{
@@ -254,12 +264,31 @@ static const struct link_hwss dio_link_hwss = {
},
};
+/**
+ * can_use_dio_link_hwss - Check if the link_hwss is accessible
+ *
+ * @link: Reference a link struct containing one or more sinks and the
+ * connective status.
+ * @link_res: Mappable hardware resource used to enable a link.
+ *
+ * Returns:
+ * Return true if the link encoder is accessible from link.
+ */
bool can_use_dio_link_hwss(const struct dc_link *link,
const struct link_resource *link_res)
{
return link->link_enc != NULL;
}
+/**
+ * get_dio_link_hwss - Return link_hwss reference
+ *
+ * This function behaves like a get function to return the link_hwss populated
+ * in the link_hwss_dio.c file.
+ *
+ * Returns:
+ * Return the reference to the filled struct of link_hwss.
+ */
const struct link_hwss *get_dio_link_hwss(void)
{
return &dio_link_hwss;
diff --git a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.h b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.h
index a1f72fe378ee..45f0e091fcb0 100644
--- a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.h
+++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.h
@@ -23,15 +23,6 @@
*
*/
-/**
- * DOC: overview
- *
- * Display Input Output (DIO), is the display input and output unit in DCN. It
- * includes output encoders to support different display output, like
- * DisplayPort, HDMI, DVI interface, and others. It also includes the control
- * and status channels for these interfaces.
- */
-
#ifndef __LINK_HWSS_DIO_H__
#define __LINK_HWSS_DIO_H__
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 5302d2c9c760..116ff37126e7 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
@@ -168,9 +168,9 @@ static void set_hpo_fixed_vs_pe_retimer_dp_link_test_pattern(struct dc_link *lin
link->dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_SET_SOURCE_PATTERN);
- // Give retimer extra time to lock before updating DP_TRAINING_PATTERN_SET to TPS1
- if (tp_params->dp_phy_pattern == DP_TEST_PATTERN_128b_132b_TPS1_TRAINING_MODE)
- msleep(30);
+ // Give retimer extra time to lock before updating DP_TRAINING_PATTERN_SET to TPS1 or phy pattern
+ if (tp_params->dp_phy_pattern != DP_TEST_PATTERN_128b_132b_TPS2_TRAINING_MODE)
+ msleep(50);
}
static void set_hpo_fixed_vs_pe_retimer_dp_lane_settings(struct dc_link *link,
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
index a9ddbe12142f..65607589495f 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
@@ -1976,7 +1976,7 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx)
/* We need to enable stream encoder for TMDS first to apply 1/4 TMDS
* character clock in case that beyond 340MHz.
*/
- if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal))
+ if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal) || dc_is_dvi_signal(pipe_ctx->stream->signal))
link_hwss->setup_stream_encoder(pipe_ctx);
dc->hwss.enable_tmds_link_output(
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_factory.c b/drivers/gpu/drm/amd/display/dc/link/link_factory.c
index 8073fdae9cb1..8246006857b3 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_factory.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_factory.c
@@ -610,14 +610,14 @@ static bool construct_phy(struct dc_link *link,
link->link_enc =
link->dc->res_pool->funcs->link_enc_create(dc_ctx, &enc_init_data);
- DC_LOG_DC("BIOS object table - DP_IS_USB_C: %d", link->link_enc->features.flags.bits.DP_IS_USB_C);
- DC_LOG_DC("BIOS object table - IS_DP2_CAPABLE: %d", link->link_enc->features.flags.bits.IS_DP2_CAPABLE);
-
if (!link->link_enc) {
DC_ERROR("Failed to create link encoder!\n");
goto link_enc_create_fail;
}
+ DC_LOG_DC("BIOS object table - DP_IS_USB_C: %d", link->link_enc->features.flags.bits.DP_IS_USB_C);
+ DC_LOG_DC("BIOS object table - IS_DP2_CAPABLE: %d", link->link_enc->features.flags.bits.IS_DP2_CAPABLE);
+
/* Update link encoder tracking variables. These are used for the dynamic
* assignment of link encoders to streams.
*/
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c
index 964abccebdc6..46bb7a855bc2 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c
@@ -363,10 +363,10 @@ bool dp_is_128b_132b_signal(struct pipe_ctx *pipe_ctx)
bool dp_is_lttpr_present(struct dc_link *link)
{
+ /* Some sink devices report invalid LTTPR revision, so don't validate against that cap */
return (dp_parse_lttpr_repeater_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) != 0 &&
link->dpcd_caps.lttpr_caps.max_lane_count > 0 &&
- link->dpcd_caps.lttpr_caps.max_lane_count <= 4 &&
- link->dpcd_caps.lttpr_caps.revision.raw >= 0x14);
+ link->dpcd_caps.lttpr_caps.max_lane_count <= 4);
}
/* in DP compliance test, DPR-120 may have
@@ -399,7 +399,17 @@ static enum dc_link_rate get_link_rate_from_max_link_bw(
static enum dc_link_rate get_lttpr_max_link_rate(struct dc_link *link)
{
- enum dc_link_rate lttpr_max_link_rate = link->dpcd_caps.lttpr_caps.max_link_rate;
+
+ enum dc_link_rate lttpr_max_link_rate = LINK_RATE_UNKNOWN;
+
+ switch (link->dpcd_caps.lttpr_caps.max_link_rate) {
+ case LINK_RATE_LOW:
+ case LINK_RATE_HIGH:
+ case LINK_RATE_HIGH2:
+ case LINK_RATE_HIGH3:
+ lttpr_max_link_rate = link->dpcd_caps.lttpr_caps.max_link_rate;
+ break;
+ }
if (link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.bits.UHBR20)
lttpr_max_link_rate = LINK_RATE_UHBR20;
@@ -917,21 +927,17 @@ bool link_decide_link_settings(struct dc_stream_state *stream,
memset(link_setting, 0, sizeof(*link_setting));
- /* if preferred is specified through AMDDP, use it, if it's enough
- * to drive the mode
- */
- if (link->preferred_link_setting.lane_count !=
- LANE_COUNT_UNKNOWN &&
- link->preferred_link_setting.link_rate !=
- LINK_RATE_UNKNOWN) {
+ if (dc_is_dp_signal(stream->signal) &&
+ link->preferred_link_setting.lane_count != LANE_COUNT_UNKNOWN &&
+ link->preferred_link_setting.link_rate != LINK_RATE_UNKNOWN) {
+ /* if preferred is specified through AMDDP, use it, if it's enough
+ * to drive the mode
+ */
*link_setting = link->preferred_link_setting;
- return true;
- }
-
- /* MST doesn't perform link training for now
- * TODO: add MST specific link training routine
- */
- if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
+ } else if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
+ /* MST doesn't perform link training for now
+ * TODO: add MST specific link training routine
+ */
decide_mst_link_settings(link, link_setting);
} else if (link->connector_signal == SIGNAL_TYPE_EDP) {
/* enable edp link optimization for DSC eDP case */
@@ -1596,9 +1602,17 @@ static bool retrieve_link_cap(struct dc_link *link)
return false;
}
- if (dp_is_lttpr_present(link))
+ if (dp_is_lttpr_present(link)) {
configure_lttpr_mode_transparent(link);
+ // Echo TOTAL_LTTPR_CNT back downstream
+ core_link_write_dpcd(
+ link,
+ DP_TOTAL_LTTPR_CNT,
+ &link->dpcd_caps.lttpr_caps.phy_repeater_cnt,
+ sizeof(link->dpcd_caps.lttpr_caps.phy_repeater_cnt));
+ }
+
/* Read DP tunneling information. */
status = dpcd_get_tunneling_device_data(link);
@@ -2111,7 +2125,8 @@ struct dc_link_settings dp_get_max_link_cap(struct dc_link *link)
if (cable_max_link_rate < max_link_cap.link_rate)
max_link_cap.link_rate = cable_max_link_rate;
- if (!link->dpcd_caps.cable_id.bits.UHBR13_5_CAPABILITY)
+ if (!link->dpcd_caps.cable_id.bits.UHBR13_5_CAPABILITY &&
+ link->dpcd_caps.cable_id.bits.CABLE_TYPE >= 2)
is_uhbr13_5_supported = false;
}
@@ -2119,15 +2134,19 @@ struct dc_link_settings dp_get_max_link_cap(struct dc_link *link)
* notes: repeaters do not snoop in the DPRX Capabilities addresses (3.6.3).
*/
if (dp_is_lttpr_present(link)) {
- if (link->dpcd_caps.lttpr_caps.max_lane_count < max_link_cap.lane_count)
- max_link_cap.lane_count = link->dpcd_caps.lttpr_caps.max_lane_count;
- lttpr_max_link_rate = get_lttpr_max_link_rate(link);
- if (lttpr_max_link_rate < max_link_cap.link_rate)
- max_link_cap.link_rate = lttpr_max_link_rate;
+ /* Some LTTPR devices do not report valid DPCD revisions, if so, do not take it's link cap into consideration. */
+ if (link->dpcd_caps.lttpr_caps.revision.raw >= DPCD_REV_14) {
+ if (link->dpcd_caps.lttpr_caps.max_lane_count < max_link_cap.lane_count)
+ max_link_cap.lane_count = link->dpcd_caps.lttpr_caps.max_lane_count;
+ lttpr_max_link_rate = get_lttpr_max_link_rate(link);
- if (!link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.bits.UHBR13_5)
- is_uhbr13_5_supported = false;
+ if (lttpr_max_link_rate < max_link_cap.link_rate)
+ max_link_cap.link_rate = lttpr_max_link_rate;
+
+ if (!link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.bits.UHBR13_5)
+ is_uhbr13_5_supported = false;
+ }
DC_LOG_HW_LINK_TRAINING("%s\n Training with LTTPR, max_lane count %d max_link rate %d \n",
__func__,
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c
index 5f087e930cb6..96bf135b6f05 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c
@@ -387,7 +387,6 @@ bool dp_handle_hpd_rx_irq(struct dc_link *link,
union device_service_irq device_service_clear = {0};
enum dc_status result;
bool status = false;
- bool allow_active = false;
if (out_link_loss)
*out_link_loss = false;
@@ -442,6 +441,12 @@ bool dp_handle_hpd_rx_irq(struct dc_link *link,
return false;
}
+ if (handle_hpd_irq_psr_sink(link))
+ /* PSR-related error was detected and handled */
+ return true;
+
+ handle_hpd_irq_replay_sink(link);
+
/* If PSR-related error handled, Main link may be off,
* so do not handle as a normal sink status change interrupt.
*/
@@ -463,8 +468,10 @@ bool dp_handle_hpd_rx_irq(struct dc_link *link,
* If we got sink count changed it means
* Downstream port status changed,
* then DM should call DC to do the detection.
+ * NOTE: Do not handle link loss on eDP since it is internal link
*/
- if (dp_parse_link_loss_status(
+ if ((link->connector_signal != SIGNAL_TYPE_EDP) &&
+ dp_parse_link_loss_status(
link,
&hpd_irq_dpcd_data)) {
/* Connectivity log: link loss */
@@ -473,11 +480,6 @@ bool dp_handle_hpd_rx_irq(struct dc_link *link,
sizeof(hpd_irq_dpcd_data),
"Status: ");
- if (link->psr_settings.psr_feature_enabled)
- edp_set_psr_allow_active(link, &allow_active, true, false, NULL);
- else if (link->replay_settings.replay_allow_active)
- edp_set_replay_allow_active(link, &allow_active, true, false, NULL);
-
if (defer_handling && has_left_work)
*has_left_work = true;
else
@@ -490,14 +492,6 @@ bool dp_handle_hpd_rx_irq(struct dc_link *link,
dp_trace_link_loss_increment(link);
}
- if (*out_link_loss == false) {
- if (handle_hpd_irq_psr_sink(link))
- /* PSR-related error was detected and handled */
- return true;
-
- handle_hpd_irq_replay_sink(link);
- }
-
if (link->type == dc_connection_sst_branch &&
hpd_irq_dpcd_data.bytes.sink_cnt.bits.SINK_COUNT
!= link->dpcd_sink_count)
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 a93dd83cd8c0..988999c44475 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
@@ -329,8 +329,12 @@ static void maximize_lane_settings(const struct link_training_settings *lt_setti
if (max_requested.PRE_EMPHASIS > PRE_EMPHASIS_MAX_LEVEL)
max_requested.PRE_EMPHASIS = PRE_EMPHASIS_MAX_LEVEL;
- if (max_requested.FFE_PRESET.settings.level > DP_FFE_PRESET_MAX_LEVEL)
- max_requested.FFE_PRESET.settings.level = DP_FFE_PRESET_MAX_LEVEL;
+
+ /* Note, we are not checking
+ * if max_requested.FFE_PRESET.settings.level > DP_FFE_PRESET_MAX_LEVEL,
+ * since FFE_PRESET.settings.level is 4 bits and DP_FFE_PRESET_MAX_LEVEL equals 15,
+ * so FFE_PRESET.settings.level will never be greater than 15.
+ */
/* make sure the pre-emphasis matches the voltage swing*/
if (max_requested.PRE_EMPHASIS >
@@ -1659,8 +1663,7 @@ bool perform_link_training_with_retries(
if (status == LINK_TRAINING_ABORT) {
enum dc_connection_type type = dc_connection_none;
- link_detect_connection_type(link, &type);
- if (type == dc_connection_none) {
+ if (link_detect_connection_type(link, &type) && type == dc_connection_none) {
DC_LOG_HW_LINK_TRAINING("%s: Aborting training because sink unplugged\n", __func__);
break;
}
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c
index 89f66d88c3b0..bf820d2b4dc4 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c
@@ -248,9 +248,6 @@ bool edp_backlight_enable_aux(struct dc_link *link, bool enable)
link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
return false;
- if (link->dc->debug.edp_oled_no_backlight_enable && link->dpcd_sink_ext_caps.bits.oled)
- return true;
-
if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_ENABLE,
&backlight_enable, 1) != DC_OK)
return false;
@@ -766,7 +763,7 @@ bool edp_setup_psr(struct dc_link *link,
psr_context->crtcTimingVerticalTotal = stream->timing.v_total;
psr_context->vsync_rate_hz = div64_u64(div64_u64((stream->
- timing.pix_clk_100hz * 100),
+ timing.pix_clk_100hz * (u64)100),
stream->timing.v_total),
stream->timing.h_total);
@@ -853,7 +850,7 @@ bool edp_setup_psr(struct dc_link *link,
}
-void edp_get_psr_residency(const struct dc_link *link, uint32_t *residency)
+void edp_get_psr_residency(const struct dc_link *link, uint32_t *residency, enum psr_residency_mode mode)
{
struct dc *dc = link->ctx->dc;
struct dmub_psr *psr = dc->res_pool->psr;
@@ -864,7 +861,7 @@ void edp_get_psr_residency(const struct dc_link *link, uint32_t *residency)
// PSR residency measurements only supported on DMCUB
if (psr != NULL && link->psr_settings.psr_feature_enabled)
- psr->funcs->psr_get_residency(psr, residency, panel_inst);
+ psr->funcs->psr_get_residency(psr, residency, panel_inst, mode);
else
*residency = 0;
}
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h
index cb6d95cc36e4..8df8ac5bde5b 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h
@@ -51,7 +51,7 @@ bool edp_setup_psr(struct dc_link *link,
struct psr_context *psr_context);
bool edp_set_sink_vtotal_in_psr_active(const struct dc_link *link,
uint16_t psr_vtotal_idle, uint16_t psr_vtotal_su);
-void edp_get_psr_residency(const struct dc_link *link, uint32_t *residency);
+void edp_get_psr_residency(const struct dc_link *link, uint32_t *residency, enum psr_residency_mode mode);
bool edp_set_replay_allow_active(struct dc_link *dc_link, const bool *enable,
bool wait, bool force_static, const unsigned int *power_opts);
bool edp_setup_replay(struct dc_link *link,
diff --git a/drivers/gpu/drm/amd/display/dc/mmhubbub/Makefile b/drivers/gpu/drm/amd/display/dc/mmhubbub/Makefile
new file mode 100644
index 000000000000..505bc0517e08
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/mmhubbub/Makefile
@@ -0,0 +1,45 @@
+#
+# Copyright 2020 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
+#
+#
+
+ifdef CONFIG_DRM_AMD_DC_FP
+###############################################################################
+# DCN32
+###############################################################################
+MMHUBBUB_DCN32 = dcn32_mmhubbub.o
+
+AMD_DAL_MMHUBBUB_DCN32 = $(addprefix $(AMDDALPATH)/dc/mmhubbub/dcn32/,$(MMHUBBUB_DCN32))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_MMHUBBUB_DCN32)
+
+###############################################################################
+# DCN35
+###############################################################################
+MMHUBBUB_DCN35 = dcn35_mmhubbub.o
+
+AMD_DAL_MMHUBBUB_DCN35 = $(addprefix $(AMDDALPATH)/dc/mmhubbub/dcn35/,$(MMHUBBUB_DCN35))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_MMHUBBUB_DCN35)
+
+endif
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mmhubbub.c b/drivers/gpu/drm/amd/display/dc/mmhubbub/dcn32/dcn32_mmhubbub.c
index c3b089ba511a..c3b089ba511a 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mmhubbub.c
+++ b/drivers/gpu/drm/amd/display/dc/mmhubbub/dcn32/dcn32_mmhubbub.c
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mmhubbub.h b/drivers/gpu/drm/amd/display/dc/mmhubbub/dcn32/dcn32_mmhubbub.h
index ef15b4f1f6b9..ef15b4f1f6b9 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mmhubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/mmhubbub/dcn32/dcn32_mmhubbub.h
diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_mmhubbub.c b/drivers/gpu/drm/amd/display/dc/mmhubbub/dcn35/dcn35_mmhubbub.c
index 4317100564a4..4317100564a4 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_mmhubbub.c
+++ b/drivers/gpu/drm/amd/display/dc/mmhubbub/dcn35/dcn35_mmhubbub.c
diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_mmhubbub.h b/drivers/gpu/drm/amd/display/dc/mmhubbub/dcn35/dcn35_mmhubbub.h
index 098e13e07272..098e13e07272 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_mmhubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/mmhubbub/dcn35/dcn35_mmhubbub.h
diff --git a/drivers/gpu/drm/amd/display/dc/mpc/Makefile b/drivers/gpu/drm/amd/display/dc/mpc/Makefile
new file mode 100644
index 000000000000..7f7458c07e2a
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/mpc/Makefile
@@ -0,0 +1,45 @@
+#
+# Copyright 2020 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
+#
+#
+
+ifdef CONFIG_DRM_AMD_DC_FP
+###############################################################################
+# DCN32
+###############################################################################
+MPC_DCN32 = dcn32_mpc.o
+
+AMD_DAL_MPC_DCN32 = $(addprefix $(AMDDALPATH)/dc/mpc/dcn32/,$(MPC_DCN32))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_MPC_DCN32)
+
+###############################################################################
+# DCN401
+###############################################################################
+MPC_DCN401 = dcn401_mpc.o
+
+AMD_DAL_MPC_DCN401 = $(addprefix $(AMDDALPATH)/dc/mpc/dcn401/,$(MPC_DCN401))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_MPC_DCN401)
+
+endif
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c b/drivers/gpu/drm/amd/display/dc/mpc/dcn32/dcn32_mpc.c
index a0e9e9f0441a..a0e9e9f0441a 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c
+++ b/drivers/gpu/drm/amd/display/dc/mpc/dcn32/dcn32_mpc.c
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.h b/drivers/gpu/drm/amd/display/dc/mpc/dcn32/dcn32_mpc.h
index 9622518826c9..9622518826c9 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.h
+++ b/drivers/gpu/drm/amd/display/dc/mpc/dcn32/dcn32_mpc.h
diff --git a/drivers/gpu/drm/amd/display/dc/dcn401/dcn401_mpc.c b/drivers/gpu/drm/amd/display/dc/mpc/dcn401/dcn401_mpc.c
index 37ab5a4eefc7..37ab5a4eefc7 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn401/dcn401_mpc.c
+++ b/drivers/gpu/drm/amd/display/dc/mpc/dcn401/dcn401_mpc.c
diff --git a/drivers/gpu/drm/amd/display/dc/dcn401/dcn401_mpc.h b/drivers/gpu/drm/amd/display/dc/mpc/dcn401/dcn401_mpc.h
index af44054c2477..af44054c2477 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn401/dcn401_mpc.h
+++ b/drivers/gpu/drm/amd/display/dc/mpc/dcn401/dcn401_mpc.h
diff --git a/drivers/gpu/drm/amd/display/dc/opp/Makefile b/drivers/gpu/drm/amd/display/dc/opp/Makefile
new file mode 100644
index 000000000000..fbfb3c3ad819
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/opp/Makefile
@@ -0,0 +1,35 @@
+#
+# Copyright 2020 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
+#
+#
+
+ifdef CONFIG_DRM_AMD_DC_FP
+###############################################################################
+# DCN35
+###############################################################################
+OPP_DCN35 = dcn35_opp.o
+
+AMD_DAL_OPP_DCN35 = $(addprefix $(AMDDALPATH)/dc/opp/dcn35/,$(OPP_DCN35))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_OPP_DCN35)
+endif
diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_opp.c b/drivers/gpu/drm/amd/display/dc/opp/dcn35/dcn35_opp.c
index 3542b51c9aac..3542b51c9aac 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_opp.c
+++ b/drivers/gpu/drm/amd/display/dc/opp/dcn35/dcn35_opp.c
diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_opp.h b/drivers/gpu/drm/amd/display/dc/opp/dcn35/dcn35_opp.h
index a9a413527801..a9a413527801 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_opp.h
+++ b/drivers/gpu/drm/amd/display/dc/opp/dcn35/dcn35_opp.h
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 336488c0574e..94427875bcdd 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
@@ -945,19 +945,10 @@ void optc1_set_drr(
OTG_FORCE_LOCK_ON_EVENT, 0,
OTG_SET_V_TOTAL_MIN_MASK_EN, 0,
OTG_SET_V_TOTAL_MIN_MASK, 0);
-
- // Setup manual flow control for EOF via TRIG_A
- optc->funcs->setup_manual_trigger(optc);
-
- } else {
- REG_UPDATE_4(OTG_V_TOTAL_CONTROL,
- OTG_SET_V_TOTAL_MIN_MASK, 0,
- OTG_V_TOTAL_MIN_SEL, 0,
- OTG_V_TOTAL_MAX_SEL, 0,
- OTG_FORCE_LOCK_ON_EVENT, 0);
-
- optc->funcs->set_vtotal_min_max(optc, 0, 0);
}
+
+ // Setup manual flow control for EOF via TRIG_A
+ optc->funcs->setup_manual_trigger(optc);
}
void optc1_set_vtotal_min_max(struct timing_generator *optc, int vtotal_min, int vtotal_max)
diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h b/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h
index e3e70c1db040..369a13244e5e 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h
@@ -562,7 +562,8 @@ struct dcn_optc_registers {
type OTG_CRC_DATA_FORMAT;\
type OTG_V_TOTAL_LAST_USED_BY_DRR;\
type OTG_DRR_TIMING_DBUF_UPDATE_PENDING;\
- type OTG_H_TIMING_DIV_MODE_DB_UPDATE_PENDING;
+ type OTG_H_TIMING_DIV_MODE_DB_UPDATE_PENDING;\
+ type OPTC_DOUBLE_BUFFER_PENDING;\
#define TG_REG_FIELD_LIST_DCN3_2(type) \
type OTG_H_TIMING_DIV_MODE_MANUAL;
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 43417cff2c9b..b4694985a40a 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
@@ -453,6 +453,16 @@ void optc2_setup_manual_trigger(struct timing_generator *optc)
{
struct optc *optc1 = DCN10TG_FROM_TG(optc);
+ /* Set the min/max selectors unconditionally so that
+ * DMCUB fw may change OTG timings when necessary
+ * TODO: Remove the w/a after fixing the issue in DMCUB firmware
+ */
+ REG_UPDATE_4(OTG_V_TOTAL_CONTROL,
+ OTG_V_TOTAL_MIN_SEL, 1,
+ OTG_V_TOTAL_MAX_SEL, 1,
+ OTG_FORCE_LOCK_ON_EVENT, 0,
+ OTG_SET_V_TOTAL_MIN_MASK, (1 << 1)); /* TRIGA */
+
REG_SET_8(OTG_TRIGA_CNTL, 0,
OTG_TRIGA_SOURCE_SELECT, 21,
OTG_TRIGA_SOURCE_PIPE_SELECT, optc->inst,
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 de83761edce8..6bbbf313b2bb 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
@@ -121,6 +121,17 @@ static bool optc31_enable_crtc(struct timing_generator *optc)
static bool optc31_disable_crtc(struct timing_generator *optc)
{
struct optc *optc1 = DCN10TG_FROM_TG(optc);
+
+ REG_UPDATE_5(OPTC_DATA_SOURCE_SELECT,
+ OPTC_SEG0_SRC_SEL, 0xf,
+ OPTC_SEG1_SRC_SEL, 0xf,
+ OPTC_SEG2_SRC_SEL, 0xf,
+ OPTC_SEG3_SRC_SEL, 0xf,
+ OPTC_NUM_OF_INPUT_SEGMENT, 0);
+
+ REG_UPDATE(OPTC_MEMORY_CONFIG,
+ OPTC_MEM_SEL, 0);
+
/* disable otg request until end of the first line
* in the vertical blank region
*/
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 6c837409df42..00094f0e8470 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
@@ -297,6 +297,18 @@ static void optc32_set_drr(
optc32_setup_manual_trigger(optc);
}
+bool optc32_get_double_buffer_pending(struct timing_generator *optc)
+{
+ struct optc *optc1 = DCN10TG_FROM_TG(optc);
+ uint32_t update_pending = 0;
+
+ REG_GET(OPTC_INPUT_GLOBAL_CONTROL,
+ OPTC_DOUBLE_BUFFER_PENDING,
+ &update_pending);
+
+ return (update_pending == 1);
+}
+
static struct timing_generator_funcs dcn32_tg_funcs = {
.validate_timing = optc1_validate_timing,
.program_timing = optc1_program_timing,
@@ -361,6 +373,7 @@ static struct timing_generator_funcs dcn32_tg_funcs = {
.setup_manual_trigger = optc2_setup_manual_trigger,
.get_hw_timing = optc1_get_hw_timing,
.is_two_pixels_per_container = optc1_is_two_pixels_per_container,
+ .get_double_buffer_pending = optc32_get_double_buffer_pending,
};
void dcn32_timing_generator_init(struct optc *optc1)
diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.h b/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.h
index 0c2c14695561..665d7c52f67c 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.h
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.h
@@ -116,6 +116,7 @@
SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_GATE_DIS, mask_sh),\
SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_OCCURRED_STATUS, mask_sh),\
SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_CLEAR, mask_sh),\
+ SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_DOUBLE_BUFFER_PENDING, mask_sh),\
SF(VTG0_CONTROL, VTG0_ENABLE, mask_sh),\
SF(VTG0_CONTROL, VTG0_FP2, mask_sh),\
SF(VTG0_CONTROL, VTG0_VCOUNT_INIT, mask_sh),\
@@ -184,5 +185,6 @@ void optc32_get_odm_combine_segments(struct timing_generator *tg, int *odm_combi
void optc32_set_odm_bypass(struct timing_generator *optc,
const struct dc_crtc_timing *dc_crtc_timing);
void optc32_wait_odm_doublebuffer_pending_clear(struct timing_generator *tg);
+bool optc32_get_double_buffer_pending(struct timing_generator *optc);
#endif /* __DC_OPTC_DCN32_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn401/dcn401_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn401/dcn401_optc.c
index fd1c8b45c40e..9f5c2efa7560 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn401/dcn401_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn401/dcn401_optc.c
@@ -459,6 +459,7 @@ static struct timing_generator_funcs dcn401_tg_funcs = {
.setup_manual_trigger = optc2_setup_manual_trigger,
.get_hw_timing = optc1_get_hw_timing,
.is_two_pixels_per_container = optc1_is_two_pixels_per_container,
+ .get_double_buffer_pending = optc32_get_double_buffer_pending,
};
void dcn401_timing_generator_init(struct optc *optc1)
diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn401/dcn401_optc.h b/drivers/gpu/drm/amd/display/dc/optc/dcn401/dcn401_optc.h
index 1671fdd5061c..3114ecef332a 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn401/dcn401_optc.h
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn401/dcn401_optc.h
@@ -94,6 +94,7 @@
SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_ON, mask_sh),\
SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_GATE_DIS, mask_sh),\
SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_OCCURRED_STATUS, mask_sh),\
+ SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_DOUBLE_BUFFER_PENDING, mask_sh),\
SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_CLEAR, mask_sh),\
SF(VTG0_CONTROL, VTG0_ENABLE, mask_sh),\
SF(VTG0_CONTROL, VTG0_FP2, mask_sh),\
diff --git a/drivers/gpu/drm/amd/display/dc/pg/Makefile b/drivers/gpu/drm/amd/display/dc/pg/Makefile
new file mode 100644
index 000000000000..ec11d3157a57
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/pg/Makefile
@@ -0,0 +1,35 @@
+#
+# Copyright 2020 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
+#
+#
+
+ifdef CONFIG_DRM_AMD_DC_FP
+###############################################################################
+# DCN35
+###############################################################################
+PG_DCN35 = dcn35_pg_cntl.o
+
+AMD_DAL_PG_DCN35 = $(addprefix $(AMDDALPATH)/dc/pg/dcn35/,$(PG_DCN35))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_PG_DCN35)
+endif
diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_pg_cntl.c b/drivers/gpu/drm/amd/display/dc/pg/dcn35/dcn35_pg_cntl.c
index 53bd0ae4bab5..af21c0a27f86 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_pg_cntl.c
+++ b/drivers/gpu/drm/amd/display/dc/pg/dcn35/dcn35_pg_cntl.c
@@ -359,7 +359,7 @@ void pg_cntl35_mpcc_pg_control(struct pg_cntl *pg_cntl,
if (pg_cntl->ctx->dc->idle_optimizations_allowed)
return;
- if (mpcc_inst >= 0 && mpcc_inst < MAX_PIPES)
+ if (mpcc_inst < MAX_PIPES)
pg_cntl->pg_pipe_res_enable[PG_MPCC][mpcc_inst] = power_on;
}
@@ -369,7 +369,7 @@ void pg_cntl35_opp_pg_control(struct pg_cntl *pg_cntl,
if (pg_cntl->ctx->dc->idle_optimizations_allowed)
return;
- if (opp_inst >= 0 && opp_inst < MAX_PIPES)
+ if (opp_inst < MAX_PIPES)
pg_cntl->pg_pipe_res_enable[PG_OPP][opp_inst] = power_on;
}
@@ -379,7 +379,7 @@ void pg_cntl35_optc_pg_control(struct pg_cntl *pg_cntl,
if (pg_cntl->ctx->dc->idle_optimizations_allowed)
return;
- if (optc_inst >= 0 && optc_inst < MAX_PIPES)
+ if (optc_inst < MAX_PIPES)
pg_cntl->pg_pipe_res_enable[PG_OPTC][optc_inst] = power_on;
}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_pg_cntl.h b/drivers/gpu/drm/amd/display/dc/pg/dcn35/dcn35_pg_cntl.h
index 3de240884d22..3de240884d22 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_pg_cntl.h
+++ b/drivers/gpu/drm/amd/display/dc/pg/dcn35/dcn35_pg_cntl.h
diff --git a/drivers/gpu/drm/amd/display/dc/resource/Makefile b/drivers/gpu/drm/amd/display/dc/resource/Makefile
index abc2405b7167..4860bb2531a1 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/resource/Makefile
@@ -166,7 +166,7 @@ AMD_DISPLAY_FILES += $(AMD_DAL_RESOURCE_DCN316)
###############################################################################
-RESOURCE_DCN32 = dcn32_resource.o
+RESOURCE_DCN32 = dcn32_resource.o dcn32_resource_helpers.o
AMD_DAL_RESOURCE_DCN32 = $(addprefix $(AMDDALPATH)/dc/resource/dcn32/,$(RESOURCE_DCN32))
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 c78675f8be8a..5e7cfa8e8ec9 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
@@ -1612,7 +1612,7 @@ unsigned int dcn20_calc_max_scaled_time(
if (time_per_byte == 0)
time_per_byte = 1;
- small_free_entry = (total_y_free_entry > total_c_free_entry) ? total_c_free_entry : total_y_free_entry;
+ small_free_entry = total_c_free_entry;
max_free_entry = (mode == PACKED_444) ? total_y_free_entry + total_c_free_entry : small_free_entry;
buf_lh_capability = max_free_entry*time_per_byte*32/16; /* there is 4bit fraction */
max_scaled_time = buf_lh_capability - urgent_watermark;
@@ -1666,8 +1666,6 @@ void dcn20_set_mcif_arb_params(
if (dwb_pipe >= MAX_DWB_PIPES)
return;
}
- if (dwb_pipe >= MAX_DWB_PIPES)
- return;
}
}
@@ -2202,10 +2200,11 @@ bool dcn20_get_dcc_compression_cap(const struct dc *dc,
const struct dc_dcc_surface_param *input,
struct dc_surface_dcc_cap *output)
{
- return dc->res_pool->hubbub->funcs->get_dcc_compression_cap(
- dc->res_pool->hubbub,
- input,
- output);
+ if (dc->res_pool->hubbub->funcs->get_dcc_compression_cap)
+ return dc->res_pool->hubbub->funcs->get_dcc_compression_cap(
+ dc->res_pool->hubbub, input, output);
+
+ return false;
}
static void dcn20_destroy_resource_pool(struct resource_pool **pool)
@@ -2630,7 +2629,7 @@ static bool dcn20_resource_construct(
ranges.writer_wm_sets[0].max_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
/* Notify PP Lib/SMU which Watermarks to use for which clock ranges */
- if (pool->base.pp_smu->nv_funcs.set_wm_ranges)
+ if (pool->base.pp_smu && pool->base.pp_smu->nv_funcs.set_wm_ranges)
pool->base.pp_smu->nv_funcs.set_wm_ranges(&pool->base.pp_smu->nv_funcs.pp_smu, &ranges);
}
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 070a4efb308b..131d98025bd4 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
@@ -795,11 +795,13 @@ static struct link_encoder *dcn201_link_encoder_create(
{
struct dcn20_link_encoder *enc20 =
kzalloc(sizeof(struct dcn20_link_encoder), GFP_ATOMIC);
- struct dcn10_link_encoder *enc10 = &enc20->enc10;
+ struct dcn10_link_encoder *enc10;
if (!enc20)
return NULL;
+ enc10 = &enc20->enc10;
+
dcn201_link_encoder_construct(enc20,
enc_init_data,
&link_enc_feature,
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 0cb2cc56d973..5040a4c6ed18 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
@@ -1419,10 +1419,7 @@ void dcn30_set_mcif_arb_params(
if (dwb_pipe >= MAX_DWB_PIPES)
return;
}
- if (dwb_pipe >= MAX_DWB_PIPES)
- return;
}
-
}
static struct dc_cap_funcs cap_funcs = {
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 da73e842c55c..169924d0a839 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
@@ -1695,25 +1695,6 @@ static void dcn314_get_panel_config_defaults(struct dc_panel_config *panel_confi
*panel_config = panel_config_defaults;
}
-static bool filter_modes_for_single_channel_workaround(struct dc *dc,
- struct dc_state *context)
-{
- // Filter 2K@240Hz+8K@24fps above combination timing if memory only has single dimm LPDDR
- if (dc->clk_mgr->bw_params->vram_type == 34 &&
- dc->clk_mgr->bw_params->num_channels < 2 &&
- context->stream_count > 1) {
- int total_phy_pix_clk = 0;
-
- for (int i = 0; i < context->stream_count; i++)
- if (context->res_ctx.pipe_ctx[i].stream)
- total_phy_pix_clk += context->res_ctx.pipe_ctx[i].stream->phy_pix_clk;
-
- if (total_phy_pix_clk >= (1148928+826260)) //2K@240Hz+8K@24fps
- return true;
- }
- return false;
-}
-
bool dcn314_validate_bandwidth(struct dc *dc,
struct dc_state *context,
bool fast_validate)
@@ -1732,9 +1713,6 @@ bool dcn314_validate_bandwidth(struct dc *dc,
if (!pipes)
goto validate_fail;
- if (filter_modes_for_single_channel_workaround(dc, context))
- goto validate_fail;
-
DC_FP_START();
// do not support self refresh only
out = dcn30_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, fast_validate, false);
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 ad40a657e173..3f4b9dba4112 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
@@ -1760,7 +1760,7 @@ static int dcn315_populate_dml_pipes_from_context(
bool split_required = pipe->stream->timing.pix_clk_100hz >= dcn_get_max_non_odm_pix_rate_100hz(&dc->dml.soc)
|| (pipe->plane_state && pipe->plane_state->src_rect.width > 5120);
- if (remaining_det_segs > MIN_RESERVED_DET_SEGS)
+ if (remaining_det_segs > MIN_RESERVED_DET_SEGS && crb_pipes != 0)
pipes[pipe_cnt].pipe.src.det_size_override += (remaining_det_segs - MIN_RESERVED_DET_SEGS) / crb_pipes +
(crb_idx < (remaining_det_segs - MIN_RESERVED_DET_SEGS) % crb_pipes ? 1 : 0);
if (pipes[pipe_cnt].pipe.src.det_size_override > 2 * DCN3_15_MAX_DET_SEGS) {
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 f147c899a95e..969658313fd6 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
@@ -1687,6 +1687,8 @@ static struct dc_stream_state *dcn32_enable_phantom_stream(struct dc *dc,
struct pipe_ctx *ref_pipe = &context->res_ctx.pipe_ctx[dc_pipe_idx];
phantom_stream = dc_state_create_phantom_stream(dc, context, ref_pipe->stream);
+ if (!phantom_stream)
+ return phantom_stream;
/* stream has limited viewport and small timing */
memcpy(&phantom_stream->timing, &ref_pipe->stream->timing, sizeof(phantom_stream->timing));
@@ -2011,11 +2013,9 @@ void dcn32_calculate_wm_and_dlg(struct dc *dc, struct dc_state *context,
static void dcn32_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params)
{
- struct dml2_configuration_options *dml2_opt;
+ struct dml2_configuration_options *dml2_opt = &dc->dml2_tmp;
- dml2_opt = kmemdup(&dc->dml2_options, sizeof(dc->dml2_options), GFP_KERNEL);
- if (!dml2_opt)
- return;
+ memcpy(dml2_opt, &dc->dml2_options, sizeof(dc->dml2_options));
DC_FP_START();
@@ -2030,8 +2030,6 @@ static void dcn32_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw
dml2_reinit(dc, dml2_opt, &dc->current_state->bw_ctx.dml2_dc_power_source);
DC_FP_END();
-
- kfree(dml2_opt);
}
static struct resource_funcs dcn32_res_pool_funcs = {
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource_helpers.c
index d184105ce2b3..d184105ce2b3 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource_helpers.c
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 07ca6f58447d..9a3cc0514a36 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
@@ -1581,11 +1581,9 @@ static struct dc_cap_funcs cap_funcs = {
static void dcn321_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params)
{
- struct dml2_configuration_options *dml2_opt;
+ struct dml2_configuration_options *dml2_opt = &dc->dml2_tmp;
- dml2_opt = kmemdup(&dc->dml2_options, sizeof(dc->dml2_options), GFP_KERNEL);
- if (!dml2_opt)
- return;
+ memcpy(dml2_opt, &dc->dml2_options, sizeof(dc->dml2_options));
DC_FP_START();
@@ -1600,8 +1598,6 @@ static void dcn321_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *b
dml2_reinit(dc, dml2_opt, &dc->current_state->bw_ctx.dml2_dc_power_source);
DC_FP_END();
-
- kfree(dml2_opt);
}
static struct resource_funcs dcn321_res_pool_funcs = {
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 28c459907698..ddf251901fb3 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
@@ -721,7 +721,7 @@ static const struct dc_debug_options debug_defaults_drv = {
.disable_dpp_power_gate = true,
.disable_hubp_power_gate = true,
.disable_optc_power_gate = true, /*should the same as above two*/
- .disable_hpo_power_gate = false, /*dmubfw force domain25 on*/
+ .disable_hpo_power_gate = true, /*dmubfw force domain25 on*/
.disable_clock_gate = false,
.disable_dsc_power_gate = true,
.vsr_support = true,
@@ -758,7 +758,7 @@ static const struct dc_debug_options debug_defaults_drv = {
.symclk32_se = true,
.symclk32_le = true,
.symclk_fe = true,
- .physymclk = true,
+ .physymclk = false,
.dpiasymclk = true,
}
},
@@ -785,6 +785,7 @@ static const struct dc_debug_options debug_defaults_drv = {
.ips2_entry_delay_us = 800,
.disable_dmub_reallow_idle = false,
.static_screen_wait_frames = 2,
+ .disable_timeout = true,
};
static const struct dc_panel_config panel_config_defaults = {
@@ -1891,6 +1892,10 @@ static bool dcn35_resource_construct(
*/
dc->caps.max_disp_clock_khz_at_vmin = 650000;
+ /* Sequential ONO is based on ASIC. */
+ if (dc->ctx->asic_id.hw_internal_rev > 0x10)
+ dc->caps.sequential_ono = true;
+
/* Use pipe context based otg sync logic */
dc->config.use_pipe_ctx_sync_logic = true;
@@ -2147,7 +2152,6 @@ static bool dcn35_resource_construct(
dc->dml2_options.callbacks.can_support_mclk_switch_using_fw_based_vblank_stretch = &dcn30_can_support_mclk_switch_using_fw_based_vblank_stretch;
dc->dml2_options.max_segments_per_hubp = 24;
-
dc->dml2_options.det_segment_size = DCN3_2_DET_SEG_SIZE;/*todo*/
if (dc->config.sdpif_request_limit_words_per_umc == 0)
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 203fd4aaf9f9..4c5e722baa3a 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
@@ -738,7 +738,7 @@ static const struct dc_debug_options debug_defaults_drv = {
.symclk32_se = true,
.symclk32_le = true,
.symclk_fe = true,
- .physymclk = true,
+ .physymclk = false,
.dpiasymclk = true,
}
},
@@ -765,6 +765,7 @@ static const struct dc_debug_options debug_defaults_drv = {
.ips2_entry_delay_us = 800,
.disable_dmub_reallow_idle = false,
.static_screen_wait_frames = 2,
+ .notify_dpia_hr_bw = true,
};
static const struct dc_panel_config panel_config_defaults = {
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 49a8d7048194..a05a2209a44e 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
@@ -731,8 +731,6 @@ static const struct dc_debug_options debug_defaults_drv = {
}
},
.force_cositing = CHROMA_COSITING_TOPLEFT + 1,
- .disable_idle_power_optimizations = true,
- .edp_oled_no_backlight_enable = true,
};
static struct dce_aux *dcn401_aux_engine_create(
@@ -1582,11 +1580,9 @@ static struct dc_cap_funcs cap_funcs = {
static void dcn401_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params)
{
- struct dml2_configuration_options *dml2_opt;
+ struct dml2_configuration_options *dml2_opt = &dc->dml2_tmp;
- dml2_opt = kmemdup(&dc->dml2_options, sizeof(*dml2_opt), GFP_KERNEL);
- if (!dml2_opt)
- return;
+ memcpy(dml2_opt, &dc->dml2_options, sizeof(dc->dml2_options));
DC_FP_START();
@@ -1601,8 +1597,6 @@ static void dcn401_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *b
dml2_reinit(dc, dml2_opt, &dc->current_state->bw_ctx.dml2_dc_power_source);
DC_FP_END();
-
- kfree(dml2_opt);
}
enum dc_status dcn401_patch_unknown_plane_state(struct dc_plane_state *plane_state)
@@ -1623,6 +1617,14 @@ bool dcn401_validate_bandwidth(struct dc *dc,
return out;
}
+void dcn401_prepare_mcache_programming(struct dc *dc,
+ struct dc_state *context)
+{
+ if (dc->debug.using_dml21)
+ dml2_prepare_mcache_programming(dc, context,
+ context->power_source == DC_POWER_SOURCE_DC ? context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2);
+}
+
static void dcn401_build_pipe_pix_clk_params(struct pipe_ctx *pipe_ctx)
{
const struct dc_stream_state *stream = pipe_ctx->stream;
@@ -1705,6 +1707,7 @@ static struct resource_funcs dcn401_res_pool_funcs = {
.patch_unknown_plane_state = dcn401_patch_unknown_plane_state,
.update_soc_for_wm_a = dcn30_update_soc_for_wm_a,
.add_phantom_pipes = dcn32_add_phantom_pipes,
+ .prepare_mcache_programming = dcn401_prepare_mcache_programming,
.build_pipe_pix_clk_params = dcn401_build_pipe_pix_clk_params,
.calculate_mall_ways_from_bytes = dcn32_calculate_mall_ways_from_bytes,
};
@@ -1819,6 +1822,9 @@ static bool dcn401_resource_construct(
dc->caps.extended_aux_timeout_support = true;
dc->caps.dmcub_support = true;
+ if (ASICREV_IS_GC_12_0_1_A0(dc->ctx->asic_id.hw_internal_rev))
+ dc->caps.dcc_plane_width_limit = 7680;
+
/* Color pipeline capabilities */
dc->caps.color.dpp.dcn_arch = 1;
dc->caps.color.dpp.input_lut_shared = 0;
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 c04c8b8f2114..26efeada4f41 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
@@ -26,6 +26,8 @@ bool dcn401_validate_bandwidth(struct dc *dc,
struct dc_state *context,
bool fast_validate);
+void dcn401_prepare_mcache_programming(struct dc *dc, struct dc_state *context);
+
/* Following are definitions for run time init of reg offsets */
/* HUBP */
diff --git a/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c b/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c
index 2836f28fa3af..e3e20cd86af6 100644
--- a/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c
+++ b/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c
@@ -110,21 +110,21 @@ static struct spl_rect calculate_plane_rec_in_timing_active(
struct fixed31_32 temp;
- temp = dc_fixpt_from_fraction(rec_in->x * stream_dst->width,
+ temp = dc_fixpt_from_fraction(rec_in->x * (long long)stream_dst->width,
stream_src->width);
rec_out.x = stream_dst->x + dc_fixpt_round(temp);
temp = dc_fixpt_from_fraction(
- (rec_in->x + rec_in->width) * stream_dst->width,
+ (rec_in->x + rec_in->width) * (long long)stream_dst->width,
stream_src->width);
rec_out.width = stream_dst->x + dc_fixpt_round(temp) - rec_out.x;
- temp = dc_fixpt_from_fraction(rec_in->y * stream_dst->height,
+ temp = dc_fixpt_from_fraction(rec_in->y * (long long)stream_dst->height,
stream_src->height);
rec_out.y = stream_dst->y + dc_fixpt_round(temp);
temp = dc_fixpt_from_fraction(
- (rec_in->y + rec_in->height) * stream_dst->height,
+ (rec_in->y + rec_in->height) * (long long)stream_dst->height,
stream_src->height);
rec_out.height = stream_dst->y + dc_fixpt_round(temp) - rec_out.y;
@@ -170,19 +170,31 @@ static struct spl_rect calculate_odm_slice_in_timing_active(struct spl_in *spl_i
bool is_last_odm_slice = (odm_slice_idx + 1) == odm_slice_count;
int h_active = spl_in->basic_out.output_size.width;
int v_active = spl_in->basic_out.output_size.height;
- int odm_slice_width = h_active / odm_slice_count;
+ int odm_slice_width;
struct spl_rect odm_rec;
- odm_rec.x = odm_slice_width * odm_slice_idx;
- odm_rec.width = is_last_odm_slice ?
- /* last slice width is the reminder of h_active */
- h_active - odm_slice_width * (odm_slice_count - 1) :
- /* odm slice width is the floor of h_active / count */
- odm_slice_width;
- odm_rec.y = 0;
- odm_rec.height = v_active;
+ if (spl_in->basic_out.odm_combine_factor > 0) {
+ odm_slice_width = h_active / odm_slice_count;
+ /*
+ * deprecated, caller must pass in odm slice rect i.e OPP input
+ * rect in timing active for the new interface.
+ */
+ if (spl_in->basic_out.use_two_pixels_per_container && (odm_slice_width % 2))
+ odm_slice_width++;
+
+ odm_rec.x = odm_slice_width * odm_slice_idx;
+ odm_rec.width = is_last_odm_slice ?
+ /* last slice width is the reminder of h_active */
+ h_active - odm_slice_width * (odm_slice_count - 1) :
+ /* odm slice width is the floor of h_active / count */
+ odm_slice_width;
+ odm_rec.y = 0;
+ odm_rec.height = v_active;
+
+ return odm_rec;
+ }
- return odm_rec;
+ return spl_in->basic_out.odm_slice_rect;
}
static void spl_calculate_recout(struct spl_in *spl_in, struct spl_out *spl_out)
diff --git a/drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h b/drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h
index a8f7fccfa16b..201201d3f55b 100644
--- a/drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h
+++ b/drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h
@@ -436,11 +436,13 @@ struct basic_out {
struct spl_size output_size; // Output Size
struct spl_rect dst_rect; // Destination Rect
struct spl_rect src_rect; // Source rect
- int odm_combine_factor; // ODM Combine Factor determine by get_odm_splits
+ int odm_combine_factor; // deprecated
+ struct spl_rect odm_slice_rect; // OPP input rect in timing active
enum spl_view_3d view_format; // TODO: View format Check if it is chroma subsampling
bool always_scale; // Is always scale enabled? Required for getting SCL_MODE
int max_downscale_src_width; // Required to get optimal no of taps
bool alpha_en;
+ bool use_two_pixels_per_container;
};
enum explicit_sharpness {
SHARPNESS_LOW = 0,
diff --git a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h
index cd51c91a822b..6589bb9aea6b 100644
--- a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h
+++ b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h
@@ -137,6 +137,7 @@ enum dmub_notification_type {
DMUB_NOTIFICATION_HPD_IRQ,
DMUB_NOTIFICATION_SET_CONFIG_REPLY,
DMUB_NOTIFICATION_DPIA_NOTIFICATION,
+ DMUB_NOTIFICATION_HPD_SENSE_NOTIFY,
DMUB_NOTIFICATION_MAX
};
@@ -298,6 +299,7 @@ struct dmub_srv_hw_params {
enum dmub_memory_access_type mem_access_type;
enum dmub_ips_disable_type disable_ips;
bool disallow_phy_access;
+ bool disable_sldo_opt;
};
/**
@@ -560,6 +562,7 @@ struct dmub_notification {
* DPIA notification command.
*/
struct dmub_rb_cmd_dpia_notification dpia_notification;
+ struct dmub_rb_cmd_hpd_sense_notify_data hpd_sense_notify;
};
};
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 4db4c5ad5169..5ff0a865705f 100644
--- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
+++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
@@ -208,6 +208,11 @@ union abm_flags {
* @abm_new_frame: Indicates if a new frame update needed for ABM to ramp up into steady
*/
unsigned int abm_new_frame : 1;
+
+ /**
+ * @vb_scaling_enabled: Indicates variBright Scaling Enable
+ */
+ unsigned int vb_scaling_enabled : 1;
} bitfields;
unsigned int u32All;
@@ -558,6 +563,7 @@ union dmub_fw_meta {
//==============================================================================
//< DMUB Trace Buffer>================================================================
//==============================================================================
+#if !defined(TENSILICA) && !defined(DMUB_TRACE_ENTRY_DEFINED)
/**
* dmub_trace_code_t - firmware trace code, 32-bits
*/
@@ -572,6 +578,7 @@ struct dmcub_trace_buf_entry {
uint32_t param0; /**< trace defined parameter 0 */
uint32_t param1; /**< trace defined parameter 1 */
};
+#endif
//==============================================================================
//< DMUB_STATUS>================================================================
@@ -677,7 +684,8 @@ union dmub_fw_boot_options {
uint32_t ips_pg_disable: 1; /* 1 to disable ONO domains power gating*/
uint32_t ips_disable: 3; /* options to disable ips support*/
uint32_t ips_sequential_ono: 1; /**< 1 to enable sequential ONO IPS sequence */
- uint32_t reserved : 8; /**< reserved */
+ uint32_t disable_sldo_opt: 1; /**< 1 to disable SLDO optimizations */
+ uint32_t reserved : 7; /**< reserved */
} bits; /**< boot bits */
uint32_t all; /**< 32-bit access to bits */
};
@@ -1285,6 +1293,10 @@ enum dmub_out_cmd_type {
* Command type used for USB4 DPIA notification
*/
DMUB_OUT_CMD__DPIA_NOTIFICATION = 5,
+ /**
+ * Command type used for HPD redetect notification
+ */
+ DMUB_OUT_CMD__HPD_SENSE_NOTIFY = 6,
};
/* DMUB_CMD__DPIA command sub-types. */
@@ -1829,7 +1841,8 @@ struct dmub_cmd_fams2_global_config {
uint32_t lock_wait_time_us; // time to forecast acquisition of lock
uint32_t num_streams;
union dmub_fams2_global_feature_config features;
- uint8_t pad[3];
+ uint32_t recovery_timeout_us;
+ uint32_t hwfq_flip_programming_delay_us;
};
union dmub_cmd_fams2_config {
@@ -1877,7 +1890,8 @@ struct dmub_rb_cmd_idle_opt_dcn_restore {
*/
struct dmub_dcn_notify_idle_cntl_data {
uint8_t driver_idle;
- uint8_t reserved[59];
+ uint8_t skip_otg_disable;
+ uint8_t reserved[58];
};
/**
@@ -2468,6 +2482,22 @@ struct dmub_rb_cmd_query_hpd_state {
struct dmub_cmd_hpd_state_query_data data;
};
+/**
+ * struct dmub_rb_cmd_hpd_sense_notify - HPD sense notification data.
+ */
+struct dmub_rb_cmd_hpd_sense_notify_data {
+ uint32_t old_hpd_sense_mask; /**< Old HPD sense mask */
+ uint32_t new_hpd_sense_mask; /**< New HPD sense mask */
+};
+
+/**
+ * struct dmub_rb_cmd_hpd_sense_notify - DMUB_OUT_CMD__HPD_SENSE_NOTIFY command.
+ */
+struct dmub_rb_cmd_hpd_sense_notify {
+ struct dmub_cmd_header header; /**< header */
+ struct dmub_rb_cmd_hpd_sense_notify_data data; /**< payload */
+};
+
/*
* Command IDs should be treated as stable ABI.
* Do not reuse or modify IDs.
@@ -2516,6 +2546,18 @@ enum dmub_cmd_psr_type {
DMUB_CMD__SET_PSR_POWER_OPT = 7,
};
+/**
+ * Different PSR residency modes.
+ * Different modes change the definition of PSR residency.
+ */
+enum psr_residency_mode {
+ PSR_RESIDENCY_MODE_PHY = 0,
+ PSR_RESIDENCY_MODE_ALPM,
+ PSR_RESIDENCY_MODE_ENABLEMENT_PERIOD,
+ /* Do not add below. */
+ PSR_RESIDENCY_MODE_LAST_ELEMENT,
+};
+
enum dmub_cmd_fams_type {
DMUB_CMD__FAMS_SETUP_FW_CTRL = 0,
DMUB_CMD__FAMS_DRR_UPDATE = 1,
@@ -2760,9 +2802,9 @@ struct dmub_cmd_psr_copy_settings_data {
*/
uint8_t relock_delay_frame_cnt;
/**
- * Explicit padding to 4 byte boundary.
+ * esd recovery indicate.
*/
- uint8_t pad3;
+ uint8_t esd_recovery;
/**
* DSC Slice height.
*/
@@ -2982,6 +3024,14 @@ struct dmub_cmd_update_dirty_rect_data {
* Currently the support is only for 0 or 1
*/
uint8_t panel_inst;
+ /**
+ * 16-bit value dicated by driver that indicates the coasting vtotal high byte part.
+ */
+ uint16_t coasting_vtotal_high;
+ /**
+ * Explicit padding to 4 byte boundary.
+ */
+ uint8_t pad[2];
};
/**
@@ -3277,6 +3327,7 @@ enum replay_state {
REPLAY_STATE_1 = 0x10,
REPLAY_STATE_1A = 0x11,
REPLAY_STATE_2 = 0x20,
+ REPLAY_STATE_2A = 0x21,
REPLAY_STATE_3 = 0x30,
REPLAY_STATE_3INIT = 0x31,
REPLAY_STATE_4 = 0x40,
@@ -3284,6 +3335,7 @@ enum replay_state {
REPLAY_STATE_4B = 0x42,
REPLAY_STATE_4C = 0x43,
REPLAY_STATE_4D = 0x44,
+ REPLAY_STATE_4E = 0x45,
REPLAY_STATE_4B_LOCKED = 0x4A,
REPLAY_STATE_4C_UNLOCKED = 0x4B,
REPLAY_STATE_5 = 0x50,
@@ -3337,7 +3389,25 @@ enum dmub_cmd_replay_type {
* Set adaptive sync sdp enabled
*/
DMUB_CMD__REPLAY_DISABLED_ADAPTIVE_SYNC_SDP = 8,
+ /**
+ * Set Replay General command.
+ */
+ DMUB_CMD__REPLAY_SET_GENERAL_CMD = 16,
+};
+/**
+ * Replay general command sub-types.
+ */
+enum dmub_cmd_replay_general_subtype {
+ REPLAY_GENERAL_CMD_NOT_SUPPORTED = -1,
+ /**
+ * TODO: For backward compatible, allow new command only.
+ * REPLAY_GENERAL_CMD_SET_TIMING_SYNC_SUPPORTED,
+ * REPLAY_GENERAL_CMD_SET_RESIDENCY_FRAMEUPDATE_TIMER,
+ * REPLAY_GENERAL_CMD_SET_PSEUDO_VTOTAL,
+ */
+ REPLAY_GENERAL_CMD_DISABLED_ADAPTIVE_SYNC_SDP,
+ REPLAY_GENERAL_CMD_DISABLED_DESYNC_ERROR_DETECTION,
};
/**
@@ -3553,6 +3623,26 @@ struct dmub_cmd_replay_disabled_adaptive_sync_sdp_data {
uint8_t pad[2];
};
+struct dmub_cmd_replay_set_general_cmd_data {
+ /**
+ * Panel Instance.
+ * Panel isntance to identify which replay_state to use
+ * Currently the support is only for 0 or 1
+ */
+ uint8_t panel_inst;
+ /**
+ * subtype: replay general cmd sub type
+ */
+ uint8_t subtype;
+
+ uint8_t pad[2];
+ /**
+ * config data with param1 and param2
+ */
+ uint32_t param1;
+
+ uint32_t param2;
+};
/**
* Definition of a DMUB_CMD__SET_REPLAY_POWER_OPT command.
@@ -3671,6 +3761,20 @@ struct dmub_rb_cmd_replay_disabled_adaptive_sync_sdp {
};
/**
+ * Definition of a DMUB_CMD__REPLAY_SET_GENERAL_CMD command.
+ */
+struct dmub_rb_cmd_replay_set_general_cmd {
+ /**
+ * Command header.
+ */
+ struct dmub_cmd_header header;
+ /**
+ * Definition of DMUB_CMD__REPLAY_SET_GENERAL_CMD command.
+ */
+ struct dmub_cmd_replay_set_general_cmd_data data;
+};
+
+/**
* Data passed from driver to FW in DMUB_CMD__REPLAY_SET_RESIDENCY_FRAMEUPDATE_TIMER command.
*/
struct dmub_cmd_replay_frameupdate_timer_data {
@@ -3729,7 +3833,10 @@ union dmub_replay_cmd_set {
* Definition of DMUB_CMD__REPLAY_DISABLED_ADAPTIVE_SYNC_SDP command data.
*/
struct dmub_cmd_replay_disabled_adaptive_sync_sdp_data disabled_adaptive_sync_sdp_data;
-
+ /**
+ * Definition of DMUB_CMD__REPLAY_SET_GENERAL_CMD command data.
+ */
+ struct dmub_cmd_replay_set_general_cmd_data set_general_cmd_data;
};
/**
@@ -3916,6 +4023,11 @@ enum dmub_cmd_abm_type {
* Set ABM Events
*/
DMUB_CMD__ABM_SET_EVENT = 9,
+
+ /**
+ * Get the current ACE curve.
+ */
+ DMUB_CMD__ABM_GET_ACE_CURVE = 10,
};
struct abm_ace_curve {
@@ -4445,6 +4557,55 @@ struct dmub_rb_cmd_abm_query_caps {
};
/**
+ * enum dmub_abm_ace_curve_type - ACE curve type.
+ */
+enum dmub_abm_ace_curve_type {
+ /**
+ * ACE curve as defined by the SW layer.
+ */
+ ABM_ACE_CURVE_TYPE__SW = 0,
+ /**
+ * ACE curve as defined by the SW to HW translation interface layer.
+ */
+ ABM_ACE_CURVE_TYPE__SW_IF = 1,
+};
+
+/**
+ * Definition of a DMUB_CMD__ABM_GET_ACE_CURVE command.
+ */
+struct dmub_rb_cmd_abm_get_ace_curve {
+ /**
+ * Command header.
+ */
+ struct dmub_cmd_header header;
+
+ /**
+ * Address where ACE curve should be copied.
+ */
+ union dmub_addr dest;
+
+ /**
+ * Type of ACE curve being queried.
+ */
+ enum dmub_abm_ace_curve_type ace_type;
+
+ /**
+ * Indirect buffer length.
+ */
+ uint16_t bytes;
+
+ /**
+ * eDP panel instance.
+ */
+ uint8_t panel_inst;
+
+ /**
+ * Explicit padding to 4 byte boundary.
+ */
+ uint8_t pad;
+};
+
+/**
* Definition of a DMUB_CMD__ABM_SAVE_RESTORE command.
*/
struct dmub_rb_cmd_abm_save_restore {
@@ -4477,6 +4638,7 @@ struct dmub_rb_cmd_abm_save_restore {
/**
* Data passed from driver to FW in a DMUB_CMD__ABM_SET_EVENT command.
*/
+
struct dmub_cmd_abm_set_event_data {
/**
@@ -5059,6 +5221,11 @@ union dmub_rb_cmd {
struct dmub_rb_cmd_abm_query_caps abm_query_caps;
/**
+ * Definition of a DMUB_CMD__ABM_GET_ACE_CURVE command.
+ */
+ struct dmub_rb_cmd_abm_get_ace_curve abm_get_ace_curve;
+
+ /**
* Definition of a DMUB_CMD__ABM_SET_EVENT command.
*/
struct dmub_rb_cmd_abm_set_event abm_set_event;
@@ -5170,6 +5337,10 @@ union dmub_rb_cmd {
*/
struct dmub_rb_cmd_replay_disabled_adaptive_sync_sdp replay_disabled_adaptive_sync_sdp;
/**
+ * Definition of a DMUB_CMD__REPLAY_SET_GENERAL_CMD command.
+ */
+ struct dmub_rb_cmd_replay_set_general_cmd replay_set_general_cmd;
+ /**
* Definition of a DMUB_CMD__PSP_ASSR_ENABLE command.
*/
struct dmub_rb_cmd_assr_enable assr_enable;
@@ -5204,6 +5375,10 @@ union dmub_rb_out_cmd {
* DPIA notification command.
*/
struct dmub_rb_cmd_dpia_notification dpia_notification;
+ /**
+ * HPD sense notification command.
+ */
+ struct dmub_rb_cmd_hpd_sense_notify hpd_sense_notify;
};
#pragma pack(pop)
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 7f53074f4e48..916ed022e96b 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c
@@ -424,6 +424,7 @@ void dmub_dcn35_enable_dmub_boot_options(struct dmub_srv *dmub, const struct dmu
boot_options.bits.disable_clk_gate = params->disable_clock_gate;
boot_options.bits.ips_disable = params->disable_ips;
boot_options.bits.ips_sequential_ono = params->ips_sequential_ono;
+ boot_options.bits.disable_sldo_opt = params->disable_sldo_opt;
REG_WRITE(DMCUB_SCRATCH14, boot_options.all);
}
@@ -462,7 +463,7 @@ uint32_t dmub_dcn35_get_current_time(struct dmub_srv *dmub)
void dmub_dcn35_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_diagnostic_data *diag_data)
{
uint32_t is_dmub_enabled, is_soft_reset, is_sec_reset;
- uint32_t is_traceport_enabled, is_cw0_enabled, is_cw6_enabled;
+ uint32_t is_traceport_enabled, is_cw6_enabled;
if (!dmub || !diag_data)
return;
@@ -513,9 +514,6 @@ void dmub_dcn35_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_diagnosti
REG_GET(DMCUB_CNTL, DMCUB_TRACEPORT_EN, &is_traceport_enabled);
diag_data->is_traceport_en = is_traceport_enabled;
- REG_GET(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_ENABLE, &is_cw0_enabled);
- diag_data->is_cw0_enabled = is_cw0_enabled;
-
REG_GET(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE, &is_cw6_enabled);
diag_data->is_cw6_enabled = is_cw6_enabled;
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv_stat.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv_stat.c
index 74189102eaec..cce887cefc01 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv_stat.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv_stat.c
@@ -113,6 +113,12 @@ enum dmub_status dmub_srv_stat_get_notification(struct dmub_srv *dmub,
notify->result = DPIA_BW_ALLOC_CAPS_CHANGED;
}
break;
+ case DMUB_OUT_CMD__HPD_SENSE_NOTIFY:
+ notify->type = DMUB_NOTIFICATION_HPD_SENSE_NOTIFY;
+ dmub_memcpy(&notify->hpd_sense_notify,
+ &cmd.hpd_sense_notify.data,
+ sizeof(cmd.hpd_sense_notify.data));
+ break;
default:
notify->type = DMUB_NOTIFICATION_NO_DATA;
break;
diff --git a/drivers/gpu/drm/amd/display/include/dpcd_defs.h b/drivers/gpu/drm/amd/display/include/dpcd_defs.h
index 914f28e9f224..aee5170f5fb2 100644
--- a/drivers/gpu/drm/amd/display/include/dpcd_defs.h
+++ b/drivers/gpu/drm/amd/display/include/dpcd_defs.h
@@ -177,4 +177,9 @@ enum dpcd_psr_sink_states {
#define DP_SINK_PR_PIXEL_DEVIATION_PER_LINE 0x379
#define DP_SINK_PR_MAX_NUMBER_OF_DEVIATION_LINE 0x37A
+/* Remove once drm_dp_helper.h is updated upstream */
+#ifndef DP_TOTAL_LTTPR_CNT
+#define DP_TOTAL_LTTPR_CNT 0xF000A /* 2.1 */
+#endif
+
#endif /* __DAL_DPCD_DEFS_H__ */
diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
index d09627c15b9c..a40e6590215a 100644
--- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
+++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
@@ -1002,7 +1002,7 @@ void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync,
if (stream->ctx->dc->caps.max_v_total != 0 && stream->timing.h_total != 0) {
min_hardware_refresh_in_uhz = div64_u64((stream->timing.pix_clk_100hz * 100000000ULL),
- (stream->timing.h_total * stream->ctx->dc->caps.max_v_total));
+ (stream->timing.h_total * (long long)stream->ctx->dc->caps.max_v_total));
}
/* Limit minimum refresh rate to what can be supported by hardware */
min_refresh_in_uhz = min_hardware_refresh_in_uhz > in_config->min_refresh_in_uhz ?
diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c
index 182e7532dda8..1e495e884484 100644
--- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c
+++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c
@@ -432,18 +432,18 @@ static enum mod_hdcp_status authenticated_dp(struct mod_hdcp *hdcp,
goto out;
}
- if (status == MOD_HDCP_STATUS_SUCCESS)
- mod_hdcp_execute_and_set(mod_hdcp_read_bstatus,
- &input->bstatus_read, &status,
- hdcp, "bstatus_read");
- if (status == MOD_HDCP_STATUS_SUCCESS)
- mod_hdcp_execute_and_set(check_link_integrity_dp,
- &input->link_integrity_check, &status,
- hdcp, "link_integrity_check");
- if (status == MOD_HDCP_STATUS_SUCCESS)
- mod_hdcp_execute_and_set(check_no_reauthentication_request_dp,
- &input->reauth_request_check, &status,
- hdcp, "reauth_request_check");
+ if (!mod_hdcp_execute_and_set(mod_hdcp_read_bstatus,
+ &input->bstatus_read, &status,
+ hdcp, "bstatus_read"))
+ goto out;
+ if (!mod_hdcp_execute_and_set(check_link_integrity_dp,
+ &input->link_integrity_check, &status,
+ hdcp, "link_integrity_check"))
+ goto out;
+ if (!mod_hdcp_execute_and_set(check_no_reauthentication_request_dp,
+ &input->reauth_request_check, &status,
+ hdcp, "reauth_request_check"))
+ goto out;
out:
return status;
}
diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c
index 1b2df97226a3..7ecf76aea950 100644
--- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c
+++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c
@@ -161,8 +161,7 @@ static enum mod_hdcp_status read(struct mod_hdcp *hdcp,
return MOD_HDCP_STATUS_DDC_FAILURE;
if (is_dp_hdcp(hdcp)) {
- int num_dpcd_addrs = sizeof(hdcp_dpcd_addrs) /
- sizeof(hdcp_dpcd_addrs[0]);
+ int num_dpcd_addrs = ARRAY_SIZE(hdcp_dpcd_addrs);
if (msg_id >= num_dpcd_addrs)
return MOD_HDCP_STATUS_DDC_FAILURE;
@@ -180,8 +179,7 @@ static enum mod_hdcp_status read(struct mod_hdcp *hdcp,
data_offset += cur_size;
}
} else {
- int num_i2c_offsets = sizeof(hdcp_i2c_offsets) /
- sizeof(hdcp_i2c_offsets[0]);
+ int num_i2c_offsets = ARRAY_SIZE(hdcp_i2c_offsets);
if (msg_id >= num_i2c_offsets)
return MOD_HDCP_STATUS_DDC_FAILURE;
@@ -234,8 +232,7 @@ static enum mod_hdcp_status write(struct mod_hdcp *hdcp,
return MOD_HDCP_STATUS_DDC_FAILURE;
if (is_dp_hdcp(hdcp)) {
- int num_dpcd_addrs = sizeof(hdcp_dpcd_addrs) /
- sizeof(hdcp_dpcd_addrs[0]);
+ int num_dpcd_addrs = ARRAY_SIZE(hdcp_dpcd_addrs);
if (msg_id >= num_dpcd_addrs)
return MOD_HDCP_STATUS_DDC_FAILURE;
@@ -254,8 +251,7 @@ static enum mod_hdcp_status write(struct mod_hdcp *hdcp,
data_offset += cur_size;
}
} else {
- int num_i2c_offsets = sizeof(hdcp_i2c_offsets) /
- sizeof(hdcp_i2c_offsets[0]);
+ int num_i2c_offsets = ARRAY_SIZE(hdcp_i2c_offsets);
if (msg_id >= num_i2c_offsets)
return MOD_HDCP_STATUS_DDC_FAILURE;
diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c
index 7c9805705fd3..8c137d7c032e 100644
--- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c
+++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c
@@ -513,9 +513,6 @@ enum mod_hdcp_status mod_hdcp_hdcp2_create_session(struct mod_hdcp *hdcp)
hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.context.mem_context.shared_buf;
memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory));
- if (!display)
- return MOD_HDCP_STATUS_DISPLAY_NOT_FOUND;
-
hdcp_cmd->in_msg.hdcp2_create_session_v2.display_handle = display->index;
if (hdcp->connection.link.adjust.hdcp2.force_type == MOD_HDCP_FORCE_TYPE_0)
diff --git a/drivers/gpu/drm/amd/display/modules/power/power_helpers.c b/drivers/gpu/drm/amd/display/modules/power/power_helpers.c
index 530379508a69..3cd52e7a9c77 100644
--- a/drivers/gpu/drm/amd/display/modules/power/power_helpers.c
+++ b/drivers/gpu/drm/amd/display/modules/power/power_helpers.c
@@ -973,6 +973,20 @@ bool psr_su_set_dsc_slice_height(struct dc *dc, struct dc_link *link,
return true;
}
+void set_replay_defer_update_coasting_vtotal(struct dc_link *link,
+ enum replay_coasting_vtotal_type type,
+ uint32_t vtotal)
+{
+ link->replay_settings.defer_update_coasting_vtotal_table[type] = vtotal;
+}
+
+void update_replay_coasting_vtotal_from_defer(struct dc_link *link,
+ enum replay_coasting_vtotal_type type)
+{
+ link->replay_settings.coasting_vtotal_table[type] =
+ link->replay_settings.defer_update_coasting_vtotal_table[type];
+}
+
void set_replay_coasting_vtotal(struct dc_link *link,
enum replay_coasting_vtotal_type type,
uint32_t vtotal)
diff --git a/drivers/gpu/drm/amd/display/modules/power/power_helpers.h b/drivers/gpu/drm/amd/display/modules/power/power_helpers.h
index ff7e6f3cd6be..cac302e8fa10 100644
--- a/drivers/gpu/drm/amd/display/modules/power/power_helpers.h
+++ b/drivers/gpu/drm/amd/display/modules/power/power_helpers.h
@@ -57,6 +57,11 @@ void init_replay_config(struct dc_link *link, struct replay_config *pr_config);
void set_replay_coasting_vtotal(struct dc_link *link,
enum replay_coasting_vtotal_type type,
uint32_t vtotal);
+void set_replay_defer_update_coasting_vtotal(struct dc_link *link,
+ enum replay_coasting_vtotal_type type,
+ uint32_t vtotal);
+void update_replay_coasting_vtotal_from_defer(struct dc_link *link,
+ enum replay_coasting_vtotal_type type);
void set_replay_ips_full_screen_video_src_vtotal(struct dc_link *link, uint16_t vtotal);
void calculate_replay_link_off_frame_count(struct dc_link *link,
uint16_t vtotal, uint16_t htotal);
diff --git a/drivers/gpu/drm/amd/include/amd_shared.h b/drivers/gpu/drm/amd/include/amd_shared.h
index 36ee9d3d6d9c..f5b725f10a7c 100644
--- a/drivers/gpu/drm/amd/include/amd_shared.h
+++ b/drivers/gpu/drm/amd/include/amd_shared.h
@@ -86,6 +86,7 @@ enum amd_apu_flags {
* @AMD_IP_BLOCK_TYPE_JPEG: JPEG Engine
* @AMD_IP_BLOCK_TYPE_VPE: Video Processing Engine
* @AMD_IP_BLOCK_TYPE_UMSCH_MM: User Mode Schduler for Multimedia
+* @AMD_IP_BLOCK_TYPE_ISP: Image Signal Processor
* @AMD_IP_BLOCK_TYPE_NUM: Total number of IP block types
*/
enum amd_ip_block_type {
@@ -105,6 +106,7 @@ enum amd_ip_block_type {
AMD_IP_BLOCK_TYPE_JPEG,
AMD_IP_BLOCK_TYPE_VPE,
AMD_IP_BLOCK_TYPE_UMSCH_MM,
+ AMD_IP_BLOCK_TYPE_ISP,
AMD_IP_BLOCK_TYPE_NUM,
};
diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_4_1_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_4_1_0_offset.h
index 5dabf0abccce..15e5a65cf492 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_4_1_0_offset.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_4_1_0_offset.h
@@ -1777,6 +1777,8 @@
#define regDCHUBBUB_SDPIF_MEM_PWR_CTRL_BASE_IDX 2
#define regDCHUBBUB_SDPIF_MEM_PWR_STATUS 0x0487
#define regDCHUBBUB_SDPIF_MEM_PWR_STATUS_BASE_IDX 2
+#define regDCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL 0x0488
+#define regDCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL_BASE_IDX 2
// addressBlock: dcn_dcec_dchubbubl_hubbub_ret_path_dispdec
@@ -2089,6 +2091,8 @@
#define regHUBP0_DCSURF_TILING_CONFIG_BASE_IDX 2
#define regHUBP0_DCSURF_PRI_VIEWPORT_START 0x05e9
#define regHUBP0_DCSURF_PRI_VIEWPORT_START_BASE_IDX 2
+#define regHUBP0_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE 0x05ea
+#define regHUBP0_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE_BASE_IDX 2
#define regHUBP0_DCSURF_PRI_VIEWPORT_DIMENSION 0x05eb
#define regHUBP0_DCSURF_PRI_VIEWPORT_DIMENSION_BASE_IDX 2
#define regHUBP0_DCSURF_PRI_VIEWPORT_START_C 0x05ec
@@ -2121,6 +2125,8 @@
#define regHUBP0_DCHUBP_MALL_SUB_VP1_BASE_IDX 2
#define regHUBP0_DCHUBP_MALL_SUB_VP2 0x05fa
#define regHUBP0_DCHUBP_MALL_SUB_VP2_BASE_IDX 2
+#define regHUBP0_DCHUBP_MCACHEID_CONFIG 0x05fb
+#define regHUBP0_DCHUBP_MCACHEID_CONFIG_BASE_IDX 2
#define regHUBP0_HUBPREQ_DEBUG_DB 0x05fc
#define regHUBP0_HUBPREQ_DEBUG_DB_BASE_IDX 2
#define regHUBP0_HUBPREQ_DEBUG 0x05fd
@@ -2378,6 +2384,8 @@
#define regHUBP1_DCSURF_TILING_CONFIG_BASE_IDX 2
#define regHUBP1_DCSURF_PRI_VIEWPORT_START 0x06c5
#define regHUBP1_DCSURF_PRI_VIEWPORT_START_BASE_IDX 2
+#define regHUBP1_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE 0x06c6
+#define regHUBP1_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE_BASE_IDX 2
#define regHUBP1_DCSURF_PRI_VIEWPORT_DIMENSION 0x06c7
#define regHUBP1_DCSURF_PRI_VIEWPORT_DIMENSION_BASE_IDX 2
#define regHUBP1_DCSURF_PRI_VIEWPORT_START_C 0x06c8
@@ -2410,6 +2418,8 @@
#define regHUBP1_DCHUBP_MALL_SUB_VP1_BASE_IDX 2
#define regHUBP1_DCHUBP_MALL_SUB_VP2 0x06d6
#define regHUBP1_DCHUBP_MALL_SUB_VP2_BASE_IDX 2
+#define regHUBP1_DCHUBP_MCACHEID_CONFIG 0x06d7
+#define regHUBP1_DCHUBP_MCACHEID_CONFIG_BASE_IDX 2
#define regHUBP1_HUBPREQ_DEBUG_DB 0x06d8
#define regHUBP1_HUBPREQ_DEBUG_DB_BASE_IDX 2
#define regHUBP1_HUBPREQ_DEBUG 0x06d9
@@ -2667,6 +2677,8 @@
#define regHUBP2_DCSURF_TILING_CONFIG_BASE_IDX 2
#define regHUBP2_DCSURF_PRI_VIEWPORT_START 0x07a1
#define regHUBP2_DCSURF_PRI_VIEWPORT_START_BASE_IDX 2
+#define regHUBP2_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE 0x07a2
+#define regHUBP2_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE_BASE_IDX 2
#define regHUBP2_DCSURF_PRI_VIEWPORT_DIMENSION 0x07a3
#define regHUBP2_DCSURF_PRI_VIEWPORT_DIMENSION_BASE_IDX 2
#define regHUBP2_DCSURF_PRI_VIEWPORT_START_C 0x07a4
@@ -2699,6 +2711,8 @@
#define regHUBP2_DCHUBP_MALL_SUB_VP1_BASE_IDX 2
#define regHUBP2_DCHUBP_MALL_SUB_VP2 0x07b2
#define regHUBP2_DCHUBP_MALL_SUB_VP2_BASE_IDX 2
+#define regHUBP2_DCHUBP_MCACHEID_CONFIG 0x07b3
+#define regHUBP2_DCHUBP_MCACHEID_CONFIG_BASE_IDX 2
#define regHUBP2_HUBPREQ_DEBUG_DB 0x07b4
#define regHUBP2_HUBPREQ_DEBUG_DB_BASE_IDX 2
#define regHUBP2_HUBPREQ_DEBUG 0x07b5
@@ -2957,6 +2971,8 @@
#define regHUBP3_DCSURF_TILING_CONFIG_BASE_IDX 2
#define regHUBP3_DCSURF_PRI_VIEWPORT_START 0x087d
#define regHUBP3_DCSURF_PRI_VIEWPORT_START_BASE_IDX 2
+#define regHUBP3_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE 0x087e
+#define regHUBP3_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE_BASE_IDX 2
#define regHUBP3_DCSURF_PRI_VIEWPORT_DIMENSION 0x087f
#define regHUBP3_DCSURF_PRI_VIEWPORT_DIMENSION_BASE_IDX 2
#define regHUBP3_DCSURF_PRI_VIEWPORT_START_C 0x0880
@@ -2989,6 +3005,8 @@
#define regHUBP3_DCHUBP_MALL_SUB_VP1_BASE_IDX 2
#define regHUBP3_DCHUBP_MALL_SUB_VP2 0x088e
#define regHUBP3_DCHUBP_MALL_SUB_VP2_BASE_IDX 2
+#define regHUBP3_DCHUBP_MCACHEID_CONFIG 0x088f
+#define regHUBP3_DCHUBP_MCACHEID_CONFIG_BASE_IDX 2
#define regHUBP3_HUBPREQ_DEBUG_DB 0x0890
#define regHUBP3_HUBPREQ_DEBUG_DB_BASE_IDX 2
#define regHUBP3_HUBPREQ_DEBUG 0x0891
diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_4_1_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_4_1_0_sh_mask.h
index 0c68f5d818bb..f42a276499cd 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_4_1_0_sh_mask.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_4_1_0_sh_mask.h
@@ -6430,6 +6430,28 @@
//DCHUBBUB_SDPIF_MEM_PWR_STATUS
#define DCHUBBUB_SDPIF_MEM_PWR_STATUS__DCHUBBUB_SDPIF_MEM_PWR_STATE__SHIFT 0x0
#define DCHUBBUB_SDPIF_MEM_PWR_STATUS__DCHUBBUB_SDPIF_MEM_PWR_STATE_MASK 0x00000003L
+//DCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL
+#define DCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL__DCHUBBUB_SDPIF_FLIP_AWAY_MISSING_PIPE0__SHIFT 0x0
+#define DCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL__DCHUBBUB_SDPIF_FLIP_AWAY_MISSING_PIPE1__SHIFT 0x1
+#define DCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL__DCHUBBUB_SDPIF_FLIP_AWAY_MISSING_PIPE2__SHIFT 0x2
+#define DCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL__DCHUBBUB_SDPIF_FLIP_AWAY_MISSING_PIPE3__SHIFT 0x3
+#define DCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL__DCHUBBUB_SDPIF_MCACHEID_INV_ERR_CLEAR_PIPE0__SHIFT 0xc
+#define DCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL__DCHUBBUB_SDPIF_MCACHEID_INV_ERR_CLEAR_PIPE1__SHIFT 0xd
+#define DCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL__DCHUBBUB_SDPIF_MCACHEID_INV_ERR_CLEAR_PIPE2__SHIFT 0xe
+#define DCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL__DCHUBBUB_SDPIF_MCACHEID_INV_ERR_CLEAR_PIPE3__SHIFT 0xf
+#define DCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL__DCHUBBUB_SDPIF_MCACHEID_INV_ERR_ENABLE__SHIFT 0x1c
+#define DCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL__DCHUBBUB_SDPIF_MCACHEID_INV_VREADY_MODE__SHIFT 0x1f
+#define DCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL__DCHUBBUB_SDPIF_FLIP_AWAY_MISSING_PIPE0_MASK 0x00000001L
+#define DCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL__DCHUBBUB_SDPIF_FLIP_AWAY_MISSING_PIPE1_MASK 0x00000002L
+#define DCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL__DCHUBBUB_SDPIF_FLIP_AWAY_MISSING_PIPE2_MASK 0x00000004L
+#define DCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL__DCHUBBUB_SDPIF_FLIP_AWAY_MISSING_PIPE3_MASK 0x00000008L
+#define DCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL__DCHUBBUB_SDPIF_MCACHEID_INV_ERR_CLEAR_PIPE0_MASK 0x00001000L
+#define DCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL__DCHUBBUB_SDPIF_MCACHEID_INV_ERR_CLEAR_PIPE1_MASK 0x00002000L
+#define DCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL__DCHUBBUB_SDPIF_MCACHEID_INV_ERR_CLEAR_PIPE2_MASK 0x00004000L
+#define DCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL__DCHUBBUB_SDPIF_MCACHEID_INV_ERR_CLEAR_PIPE3_MASK 0x00008000L
+#define DCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL__DCHUBBUB_SDPIF_MCACHEID_INV_ERR_ENABLE_MASK 0x10000000L
+#define DCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL__DCHUBBUB_SDPIF_MCACHEID_INV_VREADY_MODE_MASK 0x80000000L
+
// addressBlock: dcn_dcec_dchubbubl_hubbub_ret_path_dispdec
@@ -7084,6 +7106,11 @@
#define HUBP0_DCSURF_PRI_VIEWPORT_START__PRI_VIEWPORT_Y_START__SHIFT 0x10
#define HUBP0_DCSURF_PRI_VIEWPORT_START__PRI_VIEWPORT_X_START_MASK 0x0000FFFFL
#define HUBP0_DCSURF_PRI_VIEWPORT_START__PRI_VIEWPORT_Y_START_MASK 0xFFFF0000L
+//HUBP0_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE
+#define HUBP0_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE__VIEWPORT_MCACHE_SPLIT_COORDINATE__SHIFT 0x0
+#define HUBP0_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE__VIEWPORT_MCACHE_SPLIT_COORDINATE_C__SHIFT 0x10
+#define HUBP0_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE__VIEWPORT_MCACHE_SPLIT_COORDINATE_MASK 0x0000FFFFL
+#define HUBP0_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE__VIEWPORT_MCACHE_SPLIT_COORDINATE_C_MASK 0xFFFF0000L
//HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION
#define HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION__PRI_VIEWPORT_WIDTH__SHIFT 0x0
#define HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION__PRI_VIEWPORT_HEIGHT__SHIFT 0x10
@@ -7244,6 +7271,23 @@
#define HUBP0_DCHUBP_MALL_SUB_VP2__SUB_VP_HEIGHT_NEXT_S1__SHIFT 0xc
#define HUBP0_DCHUBP_MALL_SUB_VP2__SUB_VP_HEIGHT_CURR_S1_MASK 0x00000FFFL
#define HUBP0_DCHUBP_MALL_SUB_VP2__SUB_VP_HEIGHT_NEXT_S1_MASK 0x00FFF000L
+//HUBP0_DCHUBP_MCACHEID_CONFIG
+#define HUBP0_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_1H_P0__SHIFT 0x0
+#define HUBP0_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_2H_P0__SHIFT 0x4
+#define HUBP0_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_1H_P1__SHIFT 0x8
+#define HUBP0_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_2H_P1__SHIFT 0xc
+#define HUBP0_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_1H_P0__SHIFT 0x10
+#define HUBP0_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_2H_P0__SHIFT 0x14
+#define HUBP0_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_1H_P1__SHIFT 0x18
+#define HUBP0_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_2H_P1__SHIFT 0x1c
+#define HUBP0_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_1H_P0_MASK 0x0000000FL
+#define HUBP0_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_2H_P0_MASK 0x000000F0L
+#define HUBP0_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_1H_P1_MASK 0x00000F00L
+#define HUBP0_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_2H_P1_MASK 0x0000F000L
+#define HUBP0_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_1H_P0_MASK 0x000F0000L
+#define HUBP0_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_2H_P0_MASK 0x00F00000L
+#define HUBP0_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_1H_P1_MASK 0x0F000000L
+#define HUBP0_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_2H_P1_MASK 0xF0000000L
//HUBP0_HUBP_MEASURE_WIN_CTRL_DCFCLK
#define HUBP0_HUBP_MEASURE_WIN_CTRL_DCFCLK__HUBP_MEASURE_WIN_EN_DCFCLK__SHIFT 0x0
#define HUBP0_HUBP_MEASURE_WIN_CTRL_DCFCLK__HUBP_MEASURE_WIN_PERIOD_M1_DCFCLK__SHIFT 0x4
@@ -8013,6 +8057,11 @@
#define HUBP1_DCSURF_PRI_VIEWPORT_START__PRI_VIEWPORT_Y_START__SHIFT 0x10
#define HUBP1_DCSURF_PRI_VIEWPORT_START__PRI_VIEWPORT_X_START_MASK 0x0000FFFFL
#define HUBP1_DCSURF_PRI_VIEWPORT_START__PRI_VIEWPORT_Y_START_MASK 0xFFFF0000L
+//HUBP1_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE
+#define HUBP1_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE__VIEWPORT_MCACHE_SPLIT_COORDINATE__SHIFT 0x0
+#define HUBP1_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE__VIEWPORT_MCACHE_SPLIT_COORDINATE_C__SHIFT 0x10
+#define HUBP1_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE__VIEWPORT_MCACHE_SPLIT_COORDINATE_MASK 0x0000FFFFL
+#define HUBP1_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE__VIEWPORT_MCACHE_SPLIT_COORDINATE_C_MASK 0xFFFF0000L
//HUBP1_DCSURF_PRI_VIEWPORT_DIMENSION
#define HUBP1_DCSURF_PRI_VIEWPORT_DIMENSION__PRI_VIEWPORT_WIDTH__SHIFT 0x0
#define HUBP1_DCSURF_PRI_VIEWPORT_DIMENSION__PRI_VIEWPORT_HEIGHT__SHIFT 0x10
@@ -8173,6 +8222,23 @@
#define HUBP1_DCHUBP_MALL_SUB_VP2__SUB_VP_HEIGHT_NEXT_S1__SHIFT 0xc
#define HUBP1_DCHUBP_MALL_SUB_VP2__SUB_VP_HEIGHT_CURR_S1_MASK 0x00000FFFL
#define HUBP1_DCHUBP_MALL_SUB_VP2__SUB_VP_HEIGHT_NEXT_S1_MASK 0x00FFF000L
+//HUBP1_DCHUBP_MCACHEID_CONFIG
+#define HUBP1_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_1H_P0__SHIFT 0x0
+#define HUBP1_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_2H_P0__SHIFT 0x4
+#define HUBP1_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_1H_P1__SHIFT 0x8
+#define HUBP1_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_2H_P1__SHIFT 0xc
+#define HUBP1_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_1H_P0__SHIFT 0x10
+#define HUBP1_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_2H_P0__SHIFT 0x14
+#define HUBP1_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_1H_P1__SHIFT 0x18
+#define HUBP1_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_2H_P1__SHIFT 0x1c
+#define HUBP1_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_1H_P0_MASK 0x0000000FL
+#define HUBP1_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_2H_P0_MASK 0x000000F0L
+#define HUBP1_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_1H_P1_MASK 0x00000F00L
+#define HUBP1_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_2H_P1_MASK 0x0000F000L
+#define HUBP1_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_1H_P0_MASK 0x000F0000L
+#define HUBP1_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_2H_P0_MASK 0x00F00000L
+#define HUBP1_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_1H_P1_MASK 0x0F000000L
+#define HUBP1_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_2H_P1_MASK 0xF0000000L
//HUBP1_HUBP_MEASURE_WIN_CTRL_DCFCLK
#define HUBP1_HUBP_MEASURE_WIN_CTRL_DCFCLK__HUBP_MEASURE_WIN_EN_DCFCLK__SHIFT 0x0
#define HUBP1_HUBP_MEASURE_WIN_CTRL_DCFCLK__HUBP_MEASURE_WIN_PERIOD_M1_DCFCLK__SHIFT 0x4
@@ -8942,6 +9008,11 @@
#define HUBP2_DCSURF_PRI_VIEWPORT_START__PRI_VIEWPORT_Y_START__SHIFT 0x10
#define HUBP2_DCSURF_PRI_VIEWPORT_START__PRI_VIEWPORT_X_START_MASK 0x0000FFFFL
#define HUBP2_DCSURF_PRI_VIEWPORT_START__PRI_VIEWPORT_Y_START_MASK 0xFFFF0000L
+//HUBP2_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE
+#define HUBP2_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE__VIEWPORT_MCACHE_SPLIT_COORDINATE__SHIFT 0x0
+#define HUBP2_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE__VIEWPORT_MCACHE_SPLIT_COORDINATE_C__SHIFT 0x10
+#define HUBP2_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE__VIEWPORT_MCACHE_SPLIT_COORDINATE_MASK 0x0000FFFFL
+#define HUBP2_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE__VIEWPORT_MCACHE_SPLIT_COORDINATE_C_MASK 0xFFFF0000L
//HUBP2_DCSURF_PRI_VIEWPORT_DIMENSION
#define HUBP2_DCSURF_PRI_VIEWPORT_DIMENSION__PRI_VIEWPORT_WIDTH__SHIFT 0x0
#define HUBP2_DCSURF_PRI_VIEWPORT_DIMENSION__PRI_VIEWPORT_HEIGHT__SHIFT 0x10
@@ -9102,6 +9173,23 @@
#define HUBP2_DCHUBP_MALL_SUB_VP2__SUB_VP_HEIGHT_NEXT_S1__SHIFT 0xc
#define HUBP2_DCHUBP_MALL_SUB_VP2__SUB_VP_HEIGHT_CURR_S1_MASK 0x00000FFFL
#define HUBP2_DCHUBP_MALL_SUB_VP2__SUB_VP_HEIGHT_NEXT_S1_MASK 0x00FFF000L
+//HUBP2_DCHUBP_MCACHEID_CONFIG
+#define HUBP2_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_1H_P0__SHIFT 0x0
+#define HUBP2_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_2H_P0__SHIFT 0x4
+#define HUBP2_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_1H_P1__SHIFT 0x8
+#define HUBP2_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_2H_P1__SHIFT 0xc
+#define HUBP2_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_1H_P0__SHIFT 0x10
+#define HUBP2_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_2H_P0__SHIFT 0x14
+#define HUBP2_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_1H_P1__SHIFT 0x18
+#define HUBP2_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_2H_P1__SHIFT 0x1c
+#define HUBP2_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_1H_P0_MASK 0x0000000FL
+#define HUBP2_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_2H_P0_MASK 0x000000F0L
+#define HUBP2_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_1H_P1_MASK 0x00000F00L
+#define HUBP2_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_2H_P1_MASK 0x0000F000L
+#define HUBP2_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_1H_P0_MASK 0x000F0000L
+#define HUBP2_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_2H_P0_MASK 0x00F00000L
+#define HUBP2_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_1H_P1_MASK 0x0F000000L
+#define HUBP2_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_2H_P1_MASK 0xF0000000L
//HUBP2_HUBP_MEASURE_WIN_CTRL_DCFCLK
#define HUBP2_HUBP_MEASURE_WIN_CTRL_DCFCLK__HUBP_MEASURE_WIN_EN_DCFCLK__SHIFT 0x0
#define HUBP2_HUBP_MEASURE_WIN_CTRL_DCFCLK__HUBP_MEASURE_WIN_PERIOD_M1_DCFCLK__SHIFT 0x4
@@ -9871,6 +9959,11 @@
#define HUBP3_DCSURF_PRI_VIEWPORT_START__PRI_VIEWPORT_Y_START__SHIFT 0x10
#define HUBP3_DCSURF_PRI_VIEWPORT_START__PRI_VIEWPORT_X_START_MASK 0x0000FFFFL
#define HUBP3_DCSURF_PRI_VIEWPORT_START__PRI_VIEWPORT_Y_START_MASK 0xFFFF0000L
+//HUBP3_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE
+#define HUBP3_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE__VIEWPORT_MCACHE_SPLIT_COORDINATE__SHIFT 0x0
+#define HUBP3_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE__VIEWPORT_MCACHE_SPLIT_COORDINATE_C__SHIFT 0x10
+#define HUBP3_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE__VIEWPORT_MCACHE_SPLIT_COORDINATE_MASK 0x0000FFFFL
+#define HUBP3_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE__VIEWPORT_MCACHE_SPLIT_COORDINATE_C_MASK 0xFFFF0000L
//HUBP3_DCSURF_PRI_VIEWPORT_DIMENSION
#define HUBP3_DCSURF_PRI_VIEWPORT_DIMENSION__PRI_VIEWPORT_WIDTH__SHIFT 0x0
#define HUBP3_DCSURF_PRI_VIEWPORT_DIMENSION__PRI_VIEWPORT_HEIGHT__SHIFT 0x10
@@ -10031,6 +10124,23 @@
#define HUBP3_DCHUBP_MALL_SUB_VP2__SUB_VP_HEIGHT_NEXT_S1__SHIFT 0xc
#define HUBP3_DCHUBP_MALL_SUB_VP2__SUB_VP_HEIGHT_CURR_S1_MASK 0x00000FFFL
#define HUBP3_DCHUBP_MALL_SUB_VP2__SUB_VP_HEIGHT_NEXT_S1_MASK 0x00FFF000L
+//HUBP3_DCHUBP_MCACHEID_CONFIG
+#define HUBP3_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_1H_P0__SHIFT 0x0
+#define HUBP3_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_2H_P0__SHIFT 0x4
+#define HUBP3_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_1H_P1__SHIFT 0x8
+#define HUBP3_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_2H_P1__SHIFT 0xc
+#define HUBP3_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_1H_P0__SHIFT 0x10
+#define HUBP3_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_2H_P0__SHIFT 0x14
+#define HUBP3_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_1H_P1__SHIFT 0x18
+#define HUBP3_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_2H_P1__SHIFT 0x1c
+#define HUBP3_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_1H_P0_MASK 0x0000000FL
+#define HUBP3_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_2H_P0_MASK 0x000000F0L
+#define HUBP3_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_1H_P1_MASK 0x00000F00L
+#define HUBP3_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_2H_P1_MASK 0x0000F000L
+#define HUBP3_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_1H_P0_MASK 0x000F0000L
+#define HUBP3_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_2H_P0_MASK 0x00F00000L
+#define HUBP3_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_1H_P1_MASK 0x0F000000L
+#define HUBP3_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_2H_P1_MASK 0xF0000000L
//HUBP3_HUBP_MEASURE_WIN_CTRL_DCFCLK
#define HUBP3_HUBP_MEASURE_WIN_CTRL_DCFCLK__HUBP_MEASURE_WIN_EN_DCFCLK__SHIFT 0x0
#define HUBP3_HUBP_MEASURE_WIN_CTRL_DCFCLK__HUBP_MEASURE_WIN_PERIOD_M1_DCFCLK__SHIFT 0x4
diff --git a/drivers/gpu/drm/amd/include/asic_reg/df/df_4_15_offset.h b/drivers/gpu/drm/amd/include/asic_reg/df/df_4_15_offset.h
new file mode 100644
index 000000000000..c2b009752f60
--- /dev/null
+++ b/drivers/gpu/drm/amd/include/asic_reg/df/df_4_15_offset.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2024 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) 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 _df_4_15_OFFSET_HEADER
+#define _df_4_15_OFFSET_HEADER
+
+#define regNCSConfigurationRegister1 0x0901
+#define regNCSConfigurationRegister1_BASE_IDX 4
+
+#endif
diff --git a/drivers/gpu/drm/amd/include/asic_reg/df/df_4_15_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/df/df_4_15_sh_mask.h
new file mode 100644
index 000000000000..9868a9c32795
--- /dev/null
+++ b/drivers/gpu/drm/amd/include/asic_reg/df/df_4_15_sh_mask.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2024 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) 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 _df_4_15_SH_MASK_HEADER
+#define _df_4_15_SH_MASK_HEADER
+
+#define NCSConfigurationRegister1__DisIntAtomicsLclProcessing__SHIFT 0x3
+#define NCSConfigurationRegister1__DisIntAtomicsLclProcessing_MASK 0x0003FFF8L
+
+#endif
diff --git a/drivers/gpu/drm/amd/include/atomfirmware.h b/drivers/gpu/drm/amd/include/atomfirmware.h
index 571691837200..09cbc3afd6d8 100644
--- a/drivers/gpu/drm/amd/include/atomfirmware.h
+++ b/drivers/gpu/drm/amd/include/atomfirmware.h
@@ -734,7 +734,7 @@ struct atom_gpio_pin_lut_v2_1
{
struct atom_common_table_header table_header;
/*the real number of this included in the structure is calcualted by using the (whole structure size - the header size)/size of atom_gpio_pin_lut */
- struct atom_gpio_pin_assignment gpio_pin[8];
+ struct atom_gpio_pin_assignment gpio_pin[];
};
diff --git a/drivers/gpu/drm/amd/include/ivsrcid/isp/irqsrcs_isp_4_1.h b/drivers/gpu/drm/amd/include/ivsrcid/isp/irqsrcs_isp_4_1.h
new file mode 100644
index 000000000000..2ecdfd4f1b03
--- /dev/null
+++ b/drivers/gpu/drm/amd/include/ivsrcid/isp/irqsrcs_isp_4_1.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2024 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 __IRQSRCS_ISP_4_1_H__
+#define __IRQSRCS_ISP_4_1_H__
+
+
+#define ISP_4_1__SRCID__ISP_SEMA_WAIT_FAIL_TIMEOUT 0x12 // Semaphore wait fail timeout
+#define ISP_4_1__SRCID__ISP_SEMA_WAIT_INCOMPLETE_TIMEOUT 0x13 // Semaphore wait incomplete timeout
+#define ISP_4_1__SRCID__ISP_SEMA_SIGNAL_INCOMPLETE_TIMEOUT 0x14 // Semaphore signal incomplete timeout
+#define ISP_4_1__SRCID__ISP_RINGBUFFER_BASE5_CHANGED 0x15 // Ringbuffer base5 address changed
+#define ISP_4_1__SRCID__ISP_RINGBUFFER_WPT5 0x16 // Ringbuffer write point 5 changed
+#define ISP_4_1__SRCID__ISP_RINGBUFFER_BASE6_CHANGED 0x17 // Ringbuffer base6 address changed
+#define ISP_4_1__SRCID__ISP_RINGBUFFER_WPT6 0x18 // Ringbuffer write point 6 changed
+#define ISP_4_1__SRCID__ISP_RINGBUFFER_BASE7_CHANGED 0x19 // Ringbuffer base7 address changed
+#define ISP_4_1__SRCID__ISP_RINGBUFFER_WPT7 0x1A // Ringbuffer write point 7 changed
+#define ISP_4_1__SRCID__ISP_RINGBUFFER_BASE8_CHANGED 0x1B // Ringbuffer base8 address changed
+#define ISP_4_1__SRCID__ISP_RINGBUFFER_WPT8 0x1C // Ringbuffer write point 8 changed
+#define ISP_4_1__SRCID__ISP_RINGBUFFER_BASE9_CHANGED 0x00 // Ringbuffer base9 address changed
+#define ISP_4_1__SRCID__ISP_RINGBUFFER_WPT9 0x01 // Ringbuffer write point 9 changed
+#define ISP_4_1__SRCID__ISP_RINGBUFFER_BASE10_CHANGED 0x02 // Ringbuffer base10 address changed
+#define ISP_4_1__SRCID__ISP_RINGBUFFER_WPT10 0x03 // Ringbuffer write point 10 changed
+#define ISP_4_1__SRCID__ISP_RINGBUFFER_BASE11_CHANGED 0x04 // Ringbuffer base11 address changed
+#define ISP_4_1__SRCID__ISP_RINGBUFFER_WPT11 0x05 // Ringbuffer write point 11 changed
+#define ISP_4_1__SRCID__ISP_RINGBUFFER_BASE12_CHANGED 0x06 // Ringbuffer base12 address changed
+#define ISP_4_1__SRCID__ISP_RINGBUFFER_WPT12 0x07 // Ringbuffer write point 12 changed
+#define ISP_4_1__SRCID__ISP_RINGBUFFER_BASE13_CHANGED 0x08 // Ringbuffer base13 address changed
+#define ISP_4_1__SRCID__ISP_RINGBUFFER_WPT13 0x09 // Ringbuffer write point 13 changed
+#define ISP_4_1__SRCID__ISP_RINGBUFFER_BASE14_CHANGED 0x0A // Ringbuffer base14 address changed
+#define ISP_4_1__SRCID__ISP_RINGBUFFER_WPT14 0x0B // Ringbuffer write point 14 changed
+#define ISP_4_1__SRCID__ISP_RINGBUFFER_BASE15_CHANGED 0x0C // Ringbuffer base15 address changed
+#define ISP_4_1__SRCID__ISP_RINGBUFFER_WPT15 0x0D // Ringbuffer write point 15 changed
+#define ISP_4_1__SRCID__ISP_RINGBUFFER_BASE16_CHANGED 0x0E // Ringbuffer base16 address changed
+#define ISP_4_1__SRCID__ISP_RINGBUFFER_WPT16 0x0F // Ringbuffer write point 16 changed
+#define ISP_4_1__SRCID__ISP_MIPI0 0x29 // MIPI0 interrupt
+#define ISP_4_1__SRCID__ISP_MIPI1 0x2A // MIPI1 interrupt
+#define ISP_4_1__SRCID__ISP_I2C0 0x2B // I2C0 PAD interrupt
+#define ISP_4_1__SRCID__ISP_I2C1 0x2C // I2C1 PAD interrupt
+#define ISP_4_1__SRCID__ISP_FLASH0 0x2D // Flash0 interrupt
+#define ISP_4_1__SRCID__ISP_FLASH1 0x2E // Flash1 interrupt
+#define ISP_4_1__SRCID__ISP_DEBUG 0x2F // Debug information
+
+#endif
diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c
index b3b5e7b74c85..a1b8a82d77cf 100644
--- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c
+++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c
@@ -618,7 +618,7 @@ int amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_versio
const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
int r = 0;
- if (!pp_funcs || !pp_funcs->load_firmware)
+ if (!pp_funcs || !pp_funcs->load_firmware || adev->flags & AMD_IS_APU)
return 0;
mutex_lock(&adev->pm.mutex);
diff --git a/drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c b/drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c
index 6bb42d04b247..e8b6989a40f3 100644
--- a/drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c
+++ b/drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c
@@ -164,6 +164,8 @@ static void sumo_construct_vid_mapping_table(struct amdgpu_device *adev,
for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++) {
if (table[i].ulSupportedSCLK != 0) {
+ if (table[i].usVoltageIndex >= SUMO_MAX_NUMBER_VOLTAGES)
+ continue;
vid_mapping_table->entries[table[i].usVoltageIndex].vid_7bit =
table[i].usVoltageID;
vid_mapping_table->entries[table[i].usVoltageIndex].vid_2bit =
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 f324a8ef8032..a1baa13ab2c2 100644
--- a/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c
+++ b/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c
@@ -7648,7 +7648,6 @@ static int si_dpm_late_init(void *handle)
static int si_dpm_init_microcode(struct amdgpu_device *adev)
{
const char *chip_name;
- char fw_name[30];
int err;
DRM_DEBUG("\n");
@@ -7708,11 +7707,10 @@ static int si_dpm_init_microcode(struct amdgpu_device *adev)
default: BUG();
}
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_smc.bin", chip_name);
- err = amdgpu_ucode_request(adev, &adev->pm.fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->pm.fw, "amdgpu/%s_smc.bin", chip_name);
if (err) {
- DRM_ERROR("si_smc: Failed to load firmware. err = %d\"%s\"\n",
- err, fw_name);
+ DRM_ERROR("si_smc: Failed to load firmware. err = %d\"%s_smc.bin\"\n",
+ err, chip_name);
amdgpu_ucode_release(&adev->pm.fw);
}
return err;
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pptable_v1_0.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pptable_v1_0.h
index 2cf2a7b12623..7711e892c31f 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pptable_v1_0.h
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pptable_v1_0.h
@@ -163,8 +163,8 @@ typedef struct _ATOM_Tonga_State {
typedef struct _ATOM_Tonga_State_Array {
UCHAR ucRevId;
- UCHAR ucNumEntries; /* Number of entries. */
- ATOM_Tonga_State entries[]; /* Dynamically allocate entries. */
+ UCHAR ucNumEntries;
+ ATOM_Tonga_State entries[] __counted_by(ucNumEntries);
} ATOM_Tonga_State_Array;
typedef struct _ATOM_Tonga_MCLK_Dependency_Record {
@@ -178,8 +178,8 @@ typedef struct _ATOM_Tonga_MCLK_Dependency_Record {
typedef struct _ATOM_Tonga_MCLK_Dependency_Table {
UCHAR ucRevId;
- UCHAR ucNumEntries; /* Number of entries. */
- ATOM_Tonga_MCLK_Dependency_Record entries[]; /* Dynamically allocate entries. */
+ UCHAR ucNumEntries;
+ ATOM_Tonga_MCLK_Dependency_Record entries[] __counted_by(ucNumEntries);
} ATOM_Tonga_MCLK_Dependency_Table;
typedef struct _ATOM_Tonga_SCLK_Dependency_Record {
@@ -193,8 +193,8 @@ typedef struct _ATOM_Tonga_SCLK_Dependency_Record {
typedef struct _ATOM_Tonga_SCLK_Dependency_Table {
UCHAR ucRevId;
- UCHAR ucNumEntries; /* Number of entries. */
- ATOM_Tonga_SCLK_Dependency_Record entries[]; /* Dynamically allocate entries. */
+ UCHAR ucNumEntries;
+ ATOM_Tonga_SCLK_Dependency_Record entries[] __counted_by(ucNumEntries);
} ATOM_Tonga_SCLK_Dependency_Table;
typedef struct _ATOM_Polaris_SCLK_Dependency_Record {
@@ -209,8 +209,8 @@ typedef struct _ATOM_Polaris_SCLK_Dependency_Record {
typedef struct _ATOM_Polaris_SCLK_Dependency_Table {
UCHAR ucRevId;
- UCHAR ucNumEntries; /* Number of entries. */
- ATOM_Polaris_SCLK_Dependency_Record entries[]; /* Dynamically allocate entries. */
+ UCHAR ucNumEntries;
+ ATOM_Polaris_SCLK_Dependency_Record entries[] __counted_by(ucNumEntries);
} ATOM_Polaris_SCLK_Dependency_Table;
typedef struct _ATOM_Tonga_PCIE_Record {
@@ -221,8 +221,8 @@ typedef struct _ATOM_Tonga_PCIE_Record {
typedef struct _ATOM_Tonga_PCIE_Table {
UCHAR ucRevId;
- UCHAR ucNumEntries; /* Number of entries. */
- ATOM_Tonga_PCIE_Record entries[]; /* Dynamically allocate entries. */
+ UCHAR ucNumEntries;
+ ATOM_Tonga_PCIE_Record entries[] __counted_by(ucNumEntries);
} ATOM_Tonga_PCIE_Table;
typedef struct _ATOM_Polaris10_PCIE_Record {
@@ -234,8 +234,8 @@ typedef struct _ATOM_Polaris10_PCIE_Record {
typedef struct _ATOM_Polaris10_PCIE_Table {
UCHAR ucRevId;
- UCHAR ucNumEntries; /* Number of entries. */
- ATOM_Polaris10_PCIE_Record entries[]; /* Dynamically allocate entries. */
+ UCHAR ucNumEntries;
+ ATOM_Polaris10_PCIE_Record entries[] __counted_by(ucNumEntries);
} ATOM_Polaris10_PCIE_Table;
@@ -251,8 +251,8 @@ typedef struct _ATOM_Tonga_MM_Dependency_Record {
typedef struct _ATOM_Tonga_MM_Dependency_Table {
UCHAR ucRevId;
- UCHAR ucNumEntries; /* Number of entries. */
- ATOM_Tonga_MM_Dependency_Record entries[]; /* Dynamically allocate entries. */
+ UCHAR ucNumEntries;
+ ATOM_Tonga_MM_Dependency_Record entries[] __counted_by(ucNumEntries);
} ATOM_Tonga_MM_Dependency_Table;
typedef struct _ATOM_Tonga_Voltage_Lookup_Record {
@@ -264,8 +264,8 @@ typedef struct _ATOM_Tonga_Voltage_Lookup_Record {
typedef struct _ATOM_Tonga_Voltage_Lookup_Table {
UCHAR ucRevId;
- UCHAR ucNumEntries; /* Number of entries. */
- ATOM_Tonga_Voltage_Lookup_Record entries[]; /* Dynamically allocate entries. */
+ UCHAR ucNumEntries;
+ ATOM_Tonga_Voltage_Lookup_Record entries[] __counted_by(ucNumEntries);
} ATOM_Tonga_Voltage_Lookup_Table;
typedef struct _ATOM_Tonga_Fan_Table {
@@ -367,7 +367,7 @@ typedef struct _ATOM_Tonga_VCE_State_Record {
typedef struct _ATOM_Tonga_VCE_State_Table {
UCHAR ucRevId;
UCHAR ucNumEntries;
- ATOM_Tonga_VCE_State_Record entries[];
+ ATOM_Tonga_VCE_State_Record entries[] __counted_by(ucNumEntries);
} ATOM_Tonga_VCE_State_Table;
typedef struct _ATOM_Tonga_PowerTune_Table {
@@ -481,7 +481,7 @@ typedef struct _ATOM_Tonga_Hard_Limit_Record {
typedef struct _ATOM_Tonga_Hard_Limit_Table {
UCHAR ucRevId;
UCHAR ucNumEntries;
- ATOM_Tonga_Hard_Limit_Record entries[];
+ ATOM_Tonga_Hard_Limit_Record entries[] __counted_by(ucNumEntries);
} ATOM_Tonga_Hard_Limit_Table;
typedef struct _ATOM_Tonga_GPIO_Table {
diff --git a/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h
index 69928a4a074b..9118fcddbf11 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h
+++ b/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h
@@ -60,7 +60,7 @@ struct vi_dpm_level {
struct vi_dpm_table {
uint32_t count;
- struct vi_dpm_level dpm_level[];
+ struct vi_dpm_level dpm_level[] __counted_by(count);
};
#define PCIE_PERF_REQ_REMOVE_REGISTRY 0
@@ -91,7 +91,7 @@ struct phm_set_power_state_input {
struct phm_clock_array {
uint32_t count;
- uint32_t values[];
+ uint32_t values[] __counted_by(count);
};
struct phm_clock_voltage_dependency_record {
@@ -122,8 +122,8 @@ struct phm_acpclock_voltage_dependency_record {
};
struct phm_clock_voltage_dependency_table {
- uint32_t count; /* Number of entries. */
- struct phm_clock_voltage_dependency_record entries[]; /* Dynamically allocate count entries. */
+ uint32_t count;
+ struct phm_clock_voltage_dependency_record entries[] __counted_by(count);
};
struct phm_phase_shedding_limits_record {
@@ -140,7 +140,7 @@ struct phm_uvd_clock_voltage_dependency_record {
struct phm_uvd_clock_voltage_dependency_table {
uint8_t count;
- struct phm_uvd_clock_voltage_dependency_record entries[];
+ struct phm_uvd_clock_voltage_dependency_record entries[] __counted_by(count);
};
struct phm_acp_clock_voltage_dependency_record {
@@ -150,7 +150,7 @@ struct phm_acp_clock_voltage_dependency_record {
struct phm_acp_clock_voltage_dependency_table {
uint32_t count;
- struct phm_acp_clock_voltage_dependency_record entries[];
+ struct phm_acp_clock_voltage_dependency_record entries[] __counted_by(count);
};
struct phm_vce_clock_voltage_dependency_record {
@@ -160,33 +160,33 @@ struct phm_vce_clock_voltage_dependency_record {
};
struct phm_phase_shedding_limits_table {
- uint32_t count;
- struct phm_phase_shedding_limits_record entries[];
+ uint32_t count;
+ struct phm_phase_shedding_limits_record entries[] __counted_by(count);
};
struct phm_vceclock_voltage_dependency_table {
- uint8_t count; /* Number of entries. */
- struct phm_vceclock_voltage_dependency_record entries[1]; /* Dynamically allocate count entries. */
+ uint8_t count;
+ struct phm_vceclock_voltage_dependency_record entries[] __counted_by(count);
};
struct phm_uvdclock_voltage_dependency_table {
- uint8_t count; /* Number of entries. */
- struct phm_uvdclock_voltage_dependency_record entries[1]; /* Dynamically allocate count entries. */
+ uint8_t count;
+ struct phm_uvdclock_voltage_dependency_record entries[] __counted_by(count);
};
struct phm_samuclock_voltage_dependency_table {
- uint8_t count; /* Number of entries. */
- struct phm_samuclock_voltage_dependency_record entries[1]; /* Dynamically allocate count entries. */
+ uint8_t count;
+ struct phm_samuclock_voltage_dependency_record entries[] __counted_by(count);
};
struct phm_acpclock_voltage_dependency_table {
- uint32_t count; /* Number of entries. */
- struct phm_acpclock_voltage_dependency_record entries[1]; /* Dynamically allocate count entries. */
+ uint32_t count;
+ struct phm_acpclock_voltage_dependency_record entries[] __counted_by(count);
};
struct phm_vce_clock_voltage_dependency_table {
uint8_t count;
- struct phm_vce_clock_voltage_dependency_record entries[];
+ struct phm_vce_clock_voltage_dependency_record entries[] __counted_by(count);
};
@@ -393,7 +393,7 @@ union phm_cac_leakage_record {
struct phm_cac_leakage_table {
uint32_t count;
- union phm_cac_leakage_record entries[];
+ union phm_cac_leakage_record entries[] __counted_by(count);
};
struct phm_samu_clock_voltage_dependency_record {
@@ -404,7 +404,7 @@ struct phm_samu_clock_voltage_dependency_record {
struct phm_samu_clock_voltage_dependency_table {
uint8_t count;
- struct phm_samu_clock_voltage_dependency_record entries[];
+ struct phm_samu_clock_voltage_dependency_record entries[] __counted_by(count);
};
struct phm_cac_tdp_table {
diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
index 6f742d88867d..9d7454b3c314 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
@@ -237,7 +237,6 @@ static int smu_dpm_set_vcn_enable(struct smu_context *smu,
{
struct smu_power_context *smu_power = &smu->smu_power;
struct smu_power_gate *power_gate = &smu_power->power_gate;
- struct amdgpu_device *adev = smu->adev;
int ret = 0;
/*
@@ -253,7 +252,7 @@ static int smu_dpm_set_vcn_enable(struct smu_context *smu,
return 0;
ret = smu->ppt_funcs->dpm_set_vcn_enable(smu, enable);
- if (!ret && !adev->enable_jpeg_test)
+ if (!ret)
atomic_set(&power_gate->vcn_gated, !enable);
return ret;
@@ -325,6 +324,18 @@ static int smu_dpm_set_umsch_mm_enable(struct smu_context *smu,
return ret;
}
+static int smu_set_mall_enable(struct smu_context *smu)
+{
+ int ret = 0;
+
+ if (!smu->ppt_funcs->set_mall_enable)
+ return 0;
+
+ ret = smu->ppt_funcs->set_mall_enable(smu);
+
+ return ret;
+}
+
/**
* smu_dpm_set_power_gate - power gate/ungate the specific IP block
*
@@ -716,6 +727,7 @@ static int smu_set_funcs(struct amdgpu_device *adev)
break;
case IP_VERSION(14, 0, 0):
case IP_VERSION(14, 0, 1):
+ case IP_VERSION(14, 0, 4):
smu_v14_0_0_set_ppt_funcs(smu);
break;
case IP_VERSION(14, 0, 2):
@@ -1743,6 +1755,8 @@ static int smu_start_smc_engine(struct smu_context *smu)
struct amdgpu_device *adev = smu->adev;
int ret = 0;
+ smu->smc_fw_state = SMU_FW_INIT;
+
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) {
if (amdgpu_ip_version(adev, MP1_HWIP, 0) < IP_VERSION(11, 0, 0)) {
if (smu->ppt_funcs->load_microcode) {
@@ -1804,6 +1818,7 @@ static int smu_hw_init(void *handle)
smu_dpm_set_jpeg_enable(smu, true);
smu_dpm_set_vpe_enable(smu, true);
smu_dpm_set_umsch_mm_enable(smu, true);
+ smu_set_mall_enable(smu);
smu_set_gfx_cgpg(smu, true);
}
@@ -1909,20 +1924,12 @@ static int smu_disable_dpms(struct smu_context *smu)
}
/*
- * For SMU 13.0.4/11 and 14.0.0, PMFW will handle the features disablement properly
+ * For GFX11 and subsequent APUs, PMFW will handle the features disablement properly
* for gpu reset and S0i3 cases. Driver involvement is unnecessary.
*/
- if (amdgpu_in_reset(adev) || adev->in_s0ix) {
- switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) {
- case IP_VERSION(13, 0, 4):
- case IP_VERSION(13, 0, 11):
- case IP_VERSION(14, 0, 0):
- case IP_VERSION(14, 0, 1):
- return 0;
- default:
- break;
- }
- }
+ if (IP_VERSION_MAJ(amdgpu_ip_version(adev, GC_HWIP, 0)) >= 11 &&
+ smu->is_apu && (amdgpu_in_reset(adev) || adev->in_s0ix))
+ return 0;
/*
* For gpu reset, runpm and hibernation through BACO,
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 3f94c33df7b7..b44a185d07e8 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
@@ -495,6 +495,12 @@ struct stb_context {
spinlock_t lock;
};
+enum smu_fw_status {
+ SMU_FW_INIT = 0,
+ SMU_FW_RUNTIME,
+ SMU_FW_HANG,
+};
+
#define WORKLOAD_POLICY_MAX 7
/*
@@ -562,6 +568,7 @@ struct smu_context {
uint32_t smc_fw_if_version;
uint32_t smc_fw_version;
uint32_t smc_fw_caps;
+ uint8_t smc_fw_state;
bool uploading_custom_pp_table;
bool dc_controlled_by_gpio;
@@ -1409,6 +1416,11 @@ struct pptable_funcs {
int (*dpm_set_umsch_mm_enable)(struct smu_context *smu, bool enable);
/**
+ * @set_mall_enable: Init MALL power gating control.
+ */
+ int (*set_mall_enable)(struct smu_context *smu);
+
+ /**
* @notify_rlc_state: Notify RLC power state to SMU.
*/
int (*notify_rlc_state)(struct smu_context *smu, bool en);
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v14_0_0_ppsmc.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v14_0_0_ppsmc.h
index c4dc5881d8df..e7f5ef49049f 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v14_0_0_ppsmc.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v14_0_0_ppsmc.h
@@ -106,8 +106,8 @@
#define PPSMC_MSG_DisableLSdma 0x35 ///< Disable LSDMA
#define PPSMC_MSG_SetSoftMaxVpe 0x36 ///<
#define PPSMC_MSG_SetSoftMinVpe 0x37 ///<
-#define PPSMC_MSG_AllocMALLCache 0x38 ///< Allocating MALL Cache
-#define PPSMC_MSG_ReleaseMALLCache 0x39 ///< Releasing MALL Cache
+#define PPSMC_MSG_MALLPowerController 0x38 ///< Set MALL control
+#define PPSMC_MSG_MALLPowerState 0x39 ///< Enter/Exit MALL PG
#define PPSMC_Message_Count 0x3A ///< Total number of PPSMC messages
/** @}*/
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 dff36bd7a17c..ac0dd6b97f8d 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h
@@ -272,8 +272,10 @@
__SMU_DUMMY_MAP(SetSoftMinVpe), \
__SMU_DUMMY_MAP(GetMetricsVersion), \
__SMU_DUMMY_MAP(EnableUCLKShadow), \
- __SMU_DUMMY_MAP(RmaDueToBadPageThreshold),\
- __SMU_DUMMY_MAP(SelectPstatePolicy),
+ __SMU_DUMMY_MAP(RmaDueToBadPageThreshold), \
+ __SMU_DUMMY_MAP(SelectPstatePolicy), \
+ __SMU_DUMMY_MAP(MALLPowerController), \
+ __SMU_DUMMY_MAP(MALLPowerState),
#undef __SMU_DUMMY_MAP
#define __SMU_DUMMY_MAP(type) SMU_MSG_##type
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 cf556f1b5ed1..076620fa3ef5 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
@@ -1389,8 +1389,6 @@ static int navi10_emit_clk_levels(struct smu_context *smu,
case 2:
curve_settings = &od_table->GfxclkFreq3;
break;
- default:
- break;
}
*offset += sysfs_emit_at(buf, *offset, "%d: %uMHz %umV\n",
i, curve_settings[0],
@@ -1594,8 +1592,6 @@ static int navi10_print_clk_levels(struct smu_context *smu,
case 2:
curve_settings = &od_table->GfxclkFreq3;
break;
- default:
- break;
}
size += sysfs_emit_at(buf, size, "%d: %uMHz %umV\n",
i, curve_settings[0],
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 9d5ab2ea643a..16fcd9dcd202 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
@@ -94,7 +94,6 @@ int smu_v11_0_init_microcode(struct smu_context *smu)
{
struct amdgpu_device *adev = smu->adev;
char ucode_prefix[25];
- char fw_name[SMU_FW_NAME_LEN];
int err = 0;
const struct smc_firmware_header_v1_0 *hdr;
const struct common_firmware_header *header;
@@ -106,10 +105,7 @@ int smu_v11_0_init_microcode(struct smu_context *smu)
return 0;
amdgpu_ucode_ip_version_decode(adev, MP1_HWIP, ucode_prefix, sizeof(ucode_prefix));
-
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s.bin", ucode_prefix);
-
- err = amdgpu_ucode_request(adev, &adev->pm.fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->pm.fw, "amdgpu/%s.bin", ucode_prefix);
if (err)
goto out;
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 825786fc849e..2c35eb31475a 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c
@@ -1863,7 +1863,6 @@ static int aldebaran_mode1_reset(struct smu_context *smu)
u32 fatal_err, param;
int ret = 0;
struct amdgpu_device *adev = smu->adev;
- struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
fatal_err = 0;
param = SMU_RESET_MODE_1;
@@ -1876,8 +1875,8 @@ static int aldebaran_mode1_reset(struct smu_context *smu)
} else {
/* fatal error triggered by ras, PMFW supports the flag
from 68.44.0 */
- if ((smu->smc_fw_version >= 0x00442c00) && ras &&
- atomic_read(&ras->in_recovery))
+ if ((smu->smc_fw_version >= 0x00442c00) &&
+ amdgpu_ras_get_fed_status(adev))
fatal_err = 1;
param |= (fatal_err << 16);
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 3a50076e44f0..e17466cc1952 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
@@ -92,7 +92,6 @@ const int pmfw_decoded_link_width[7] = {0, 1, 2, 4, 8, 12, 16};
int smu_v13_0_init_microcode(struct smu_context *smu)
{
struct amdgpu_device *adev = smu->adev;
- char fw_name[30];
char ucode_prefix[15];
int err = 0;
const struct smc_firmware_header_v1_0 *hdr;
@@ -104,10 +103,7 @@ int smu_v13_0_init_microcode(struct smu_context *smu)
return 0;
amdgpu_ucode_ip_version_decode(adev, MP1_HWIP, ucode_prefix, sizeof(ucode_prefix));
-
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s.bin", ucode_prefix);
-
- err = amdgpu_ucode_request(adev, &adev->pm.fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->pm.fw, "amdgpu/%s.bin", ucode_prefix);
if (err)
goto out;
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 6c24e2306383..a887ab945dfa 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
@@ -2786,10 +2786,9 @@ static void smu_v13_0_0_set_mode1_reset_param(struct smu_context *smu,
uint32_t *param)
{
struct amdgpu_device *adev = smu->adev;
- struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
if ((smu->smc_fw_version >= supported_version) &&
- ras && atomic_read(&ras->in_recovery))
+ amdgpu_ras_get_fed_status(adev))
/* Set RAS fatal error reset flag */
*param = 1 << 16;
else
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 6b8decaf6427..78c3f94bb3ff 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
@@ -272,7 +272,6 @@ static int smu_v13_0_6_init_microcode(struct smu_context *smu)
uint32_t p2s_table_id = P2S_TABLE_ID_A;
int ret = 0, i, p2stable_count;
char ucode_prefix[15];
- char fw_name[30];
/* No need to load P2S tables in IOV mode */
if (amdgpu_sriov_vf(adev))
@@ -283,10 +282,7 @@ static int smu_v13_0_6_init_microcode(struct smu_context *smu)
amdgpu_ucode_ip_version_decode(adev, MP1_HWIP, ucode_prefix,
sizeof(ucode_prefix));
-
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s.bin", ucode_prefix);
-
- ret = amdgpu_ucode_request(adev, &adev->pm.fw, fw_name);
+ ret = amdgpu_ucode_request(adev, &adev->pm.fw, "amdgpu/%s.bin", ucode_prefix);
if (ret)
goto out;
@@ -2578,24 +2574,14 @@ failed:
static int smu_v13_0_6_mode1_reset(struct smu_context *smu)
{
struct amdgpu_device *adev = smu->adev;
- struct amdgpu_hive_info *hive = NULL;
- u32 hive_ras_recovery = 0;
- struct amdgpu_ras *ras;
u32 fatal_err, param;
int ret = 0;
- hive = amdgpu_get_xgmi_hive(adev);
- ras = amdgpu_ras_get_context(adev);
fatal_err = 0;
param = SMU_RESET_MODE_1;
- if (hive) {
- hive_ras_recovery = atomic_read(&hive->ras_recovery);
- amdgpu_put_xgmi_hive(hive);
- }
-
/* fatal error triggered by ras, PMFW supports the flag */
- if (ras && (atomic_read(&ras->in_recovery) || hive_ras_recovery))
+ if (amdgpu_ras_get_fed_status(adev))
fatal_err = 1;
param |= (fatal_err << 16);
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 8cce17d1f230..09973615f210 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
@@ -68,7 +68,6 @@ MODULE_FIRMWARE("amdgpu/smu_14_0_3.bin");
int smu_v14_0_init_microcode(struct smu_context *smu)
{
struct amdgpu_device *adev = smu->adev;
- char fw_name[30];
char ucode_prefix[15];
int err = 0;
const struct smc_firmware_header_v1_0 *hdr;
@@ -80,10 +79,7 @@ int smu_v14_0_init_microcode(struct smu_context *smu)
return 0;
amdgpu_ucode_ip_version_decode(adev, MP1_HWIP, ucode_prefix, sizeof(ucode_prefix));
-
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s.bin", ucode_prefix);
-
- err = amdgpu_ucode_request(adev, &adev->pm.fw, fw_name);
+ err = amdgpu_ucode_request(adev, &adev->pm.fw, "amdgpu/%s.bin", ucode_prefix);
if (err)
goto out;
@@ -140,8 +136,7 @@ int smu_v14_0_load_microcode(struct smu_context *smu)
1 & ~MP1_SMN_PUB_CTRL__LX3_RESET_MASK);
for (i = 0; i < adev->usec_timeout; i++) {
- if (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 0) ||
- amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1))
+ if (smu->is_apu)
mp1_fw_flags = RREG32_PCIE(MP1_Public |
(smnMP1_FIRMWARE_FLAGS_14_0_0 & 0xffffffff));
else
@@ -214,8 +209,7 @@ int smu_v14_0_check_fw_status(struct smu_context *smu)
struct amdgpu_device *adev = smu->adev;
uint32_t mp1_fw_flags;
- if (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 0) ||
- amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1))
+ if (smu->is_apu)
mp1_fw_flags = RREG32_PCIE(MP1_Public |
(smnMP1_FIRMWARE_FLAGS_14_0_0 & 0xffffffff));
else
@@ -249,6 +243,7 @@ int smu_v14_0_check_fw_version(struct smu_context *smu)
switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) {
case IP_VERSION(14, 0, 0):
+ case IP_VERSION(14, 0, 4):
smu->smc_driver_if_version = SMU14_DRIVER_IF_VERSION_SMU_V14_0_0;
break;
case IP_VERSION(14, 0, 1):
@@ -763,6 +758,7 @@ int smu_v14_0_gfx_off_control(struct smu_context *smu, bool enable)
case IP_VERSION(14, 0, 1):
case IP_VERSION(14, 0, 2):
case IP_VERSION(14, 0, 3):
+ case IP_VERSION(14, 0, 4):
if (!(adev->pm.pp_feature & PP_GFXOFF_MASK))
return 0;
if (enable)
@@ -870,8 +866,7 @@ static int smu_v14_0_set_irq_state(struct amdgpu_device *adev,
WREG32_SOC15(THM, 0, regTHM_THERMAL_INT_ENA, 0);
/* For MP1 SW irqs */
- if (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 0) ||
- amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1)) {
+ if (smu->is_apu) {
val = RREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_CTRL_mp1_14_0_0);
val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT_CTRL, INT_MASK, 1);
WREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_CTRL_mp1_14_0_0, val);
@@ -904,8 +899,7 @@ static int smu_v14_0_set_irq_state(struct amdgpu_device *adev,
WREG32_SOC15(THM, 0, regTHM_THERMAL_INT_ENA, val);
/* For MP1 SW irqs */
- if (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 0) ||
- amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1)) {
+ if (smu->is_apu) {
val = RREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_mp1_14_0_0);
val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT, ID, 0xFE);
val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT, VALID, 0);
@@ -1498,8 +1492,7 @@ int smu_v14_0_set_vcn_enable(struct smu_context *smu,
if (adev->vcn.harvest_config & (1 << i))
continue;
- if (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 0) ||
- amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1)) {
+ if (smu->is_apu) {
if (i == 0)
ret = smu_cmn_send_smc_msg_with_param(smu, enable ?
SMU_MSG_PowerUpVcn0 : SMU_MSG_PowerDownVcn0,
@@ -1531,8 +1524,7 @@ int smu_v14_0_set_jpeg_enable(struct smu_context *smu,
if (adev->jpeg.harvest_config & (1 << i))
continue;
- if (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 0) ||
- amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1)) {
+ if (smu->is_apu) {
if (i == 0)
ret = smu_cmn_send_smc_msg_with_param(smu, enable ?
SMU_MSG_PowerUpJpeg0 : SMU_MSG_PowerDownJpeg0,
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 e4419e1561ef..8798ebfcea83 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
@@ -52,6 +52,26 @@
#define mmMP1_SMN_C2PMSG_90 0x029a
#define mmMP1_SMN_C2PMSG_90_BASE_IDX 0
+/* MALLPowerController message arguments (Defines for the Cache mode control) */
+#define SMU_MALL_PMFW_CONTROL 0
+#define SMU_MALL_DRIVER_CONTROL 1
+
+/*
+ * MALLPowerState message arguments
+ * (Defines for the Allocate/Release Cache mode if in driver mode)
+ */
+#define SMU_MALL_EXIT_PG 0
+#define SMU_MALL_ENTER_PG 1
+
+#define SMU_MALL_PG_CONFIG_DEFAULT SMU_MALL_PG_CONFIG_DRIVER_CONTROL_ALWAYS_ON
+
+#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
+
+#define SMU_14_0_4_UMD_PSTATE_GFXCLK 938
+#define SMU_14_0_4_UMD_PSTATE_SOCCLK 938
+
#define FEATURE_MASK(feature) (1ULL << feature)
#define SMC_DPM_FEATURE ( \
FEATURE_MASK(FEATURE_CCLK_DPM_BIT) | \
@@ -66,6 +86,12 @@
FEATURE_MASK(FEATURE_GFX_DPM_BIT) | \
FEATURE_MASK(FEATURE_VPE_DPM_BIT))
+enum smu_mall_pg_config {
+ SMU_MALL_PG_CONFIG_PMFW_CONTROL = 0,
+ SMU_MALL_PG_CONFIG_DRIVER_CONTROL_ALWAYS_ON = 1,
+ SMU_MALL_PG_CONFIG_DRIVER_CONTROL_ALWAYS_OFF = 2,
+};
+
static struct cmn2asic_msg_mapping smu_v14_0_0_message_map[SMU_MSG_MAX_COUNT] = {
MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 1),
MSG_MAP(GetSmuVersion, PPSMC_MSG_GetPmfwVersion, 1),
@@ -113,6 +139,8 @@ static struct cmn2asic_msg_mapping smu_v14_0_0_message_map[SMU_MSG_MAX_COUNT] =
MSG_MAP(PowerDownUmsch, PPSMC_MSG_PowerDownUmsch, 1),
MSG_MAP(SetSoftMaxVpe, PPSMC_MSG_SetSoftMaxVpe, 1),
MSG_MAP(SetSoftMinVpe, PPSMC_MSG_SetSoftMinVpe, 1),
+ MSG_MAP(MALLPowerController, PPSMC_MSG_MALLPowerController, 1),
+ MSG_MAP(MALLPowerState, PPSMC_MSG_MALLPowerState, 1),
};
static struct cmn2asic_mapping smu_v14_0_0_feature_mask_map[SMU_FEATURE_COUNT] = {
@@ -702,10 +730,10 @@ static int smu_v14_0_common_get_dpm_freq_by_index(struct smu_context *smu,
uint32_t dpm_level,
uint32_t *freq)
{
- if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 0))
- smu_v14_0_0_get_dpm_freq_by_index(smu, clk_type, dpm_level, freq);
- else if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1))
+ if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1))
smu_v14_0_1_get_dpm_freq_by_index(smu, clk_type, dpm_level, freq);
+ else if (clk_type != SMU_VCLK1 && clk_type != SMU_DCLK1)
+ smu_v14_0_0_get_dpm_freq_by_index(smu, clk_type, dpm_level, freq);
return 0;
}
@@ -797,9 +825,11 @@ static int smu_v14_0_1_get_dpm_ultimate_freq(struct smu_context *smu,
break;
case SMU_MCLK:
case SMU_UCLK:
- case SMU_FCLK:
max_dpm_level = 0;
break;
+ case SMU_FCLK:
+ max_dpm_level = clk_table->NumFclkLevelsEnabled - 1;
+ break;
case SMU_SOCCLK:
max_dpm_level = clk_table->NumSocClkLevelsEnabled - 1;
break;
@@ -834,7 +864,7 @@ static int smu_v14_0_1_get_dpm_ultimate_freq(struct smu_context *smu,
min_dpm_level = clk_table->NumMemPstatesEnabled - 1;
break;
case SMU_FCLK:
- min_dpm_level = clk_table->NumFclkLevelsEnabled - 1;
+ min_dpm_level = 0;
break;
case SMU_SOCCLK:
min_dpm_level = 0;
@@ -915,9 +945,11 @@ static int smu_v14_0_0_get_dpm_ultimate_freq(struct smu_context *smu,
break;
case SMU_MCLK:
case SMU_UCLK:
- case SMU_FCLK:
max_dpm_level = 0;
break;
+ case SMU_FCLK:
+ max_dpm_level = clk_table->NumFclkLevelsEnabled - 1;
+ break;
case SMU_SOCCLK:
max_dpm_level = clk_table->NumSocClkLevelsEnabled - 1;
break;
@@ -948,7 +980,7 @@ static int smu_v14_0_0_get_dpm_ultimate_freq(struct smu_context *smu,
min_dpm_level = clk_table->NumMemPstatesEnabled - 1;
break;
case SMU_FCLK:
- min_dpm_level = clk_table->NumFclkLevelsEnabled - 1;
+ min_dpm_level = 0;
break;
case SMU_SOCCLK:
min_dpm_level = 0;
@@ -978,10 +1010,10 @@ static int smu_v14_0_common_get_dpm_ultimate_freq(struct smu_context *smu,
uint32_t *min,
uint32_t *max)
{
- if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 0))
- smu_v14_0_0_get_dpm_ultimate_freq(smu, clk_type, min, max);
- else if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1))
+ if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1))
smu_v14_0_1_get_dpm_ultimate_freq(smu, clk_type, min, max);
+ else if (clk_type != SMU_VCLK1 && clk_type != SMU_DCLK1)
+ smu_v14_0_0_get_dpm_ultimate_freq(smu, clk_type, min, max);
return 0;
}
@@ -999,9 +1031,15 @@ static int smu_v14_0_0_get_current_clk_freq(struct smu_context *smu,
case SMU_VCLK:
member_type = METRICS_AVERAGE_VCLK;
break;
+ case SMU_VCLK1:
+ member_type = METRICS_AVERAGE_VCLK1;
+ break;
case SMU_DCLK:
member_type = METRICS_AVERAGE_DCLK;
break;
+ case SMU_DCLK1:
+ member_type = METRICS_AVERAGE_DCLK1;
+ break;
case SMU_MCLK:
member_type = METRICS_AVERAGE_UCLK;
break;
@@ -1083,10 +1121,10 @@ static int smu_v14_0_common_get_dpm_level_count(struct smu_context *smu,
enum smu_clk_type clk_type,
uint32_t *count)
{
- if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 0))
- smu_v14_0_0_get_dpm_level_count(smu, clk_type, count);
- else if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1))
+ if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1))
smu_v14_0_1_get_dpm_level_count(smu, clk_type, count);
+ else if (clk_type != SMU_VCLK1 && clk_type != SMU_DCLK1)
+ smu_v14_0_0_get_dpm_level_count(smu, clk_type, count);
return 0;
}
@@ -1229,6 +1267,8 @@ static int smu_v14_0_0_force_clk_levels(struct smu_context *smu,
case SMU_FCLK:
case SMU_VCLK:
case SMU_DCLK:
+ case SMU_VCLK1:
+ case SMU_DCLK1:
ret = smu_v14_0_common_get_dpm_freq_by_index(smu, clk_type, soft_min_level, &min_freq);
if (ret)
break;
@@ -1247,13 +1287,76 @@ static int smu_v14_0_0_force_clk_levels(struct smu_context *smu,
return ret;
}
-static int smu_v14_0_0_set_performance_level(struct smu_context *smu,
+static int smu_v14_0_common_get_dpm_profile_freq(struct smu_context *smu,
+ enum amd_dpm_forced_level level,
+ enum smu_clk_type clk_type,
+ uint32_t *min_clk,
+ uint32_t *max_clk)
+{
+ uint32_t clk_limit = 0;
+ int ret = 0;
+
+ switch (clk_type) {
+ case SMU_GFXCLK:
+ case SMU_SCLK:
+ if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 4))
+ clk_limit = SMU_14_0_4_UMD_PSTATE_GFXCLK;
+ else
+ clk_limit = SMU_14_0_0_UMD_PSTATE_GFXCLK;
+ if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
+ smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_SCLK, NULL, &clk_limit);
+ else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK)
+ smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_SCLK, &clk_limit, NULL);
+ break;
+ case SMU_SOCCLK:
+ if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 4))
+ clk_limit = SMU_14_0_4_UMD_PSTATE_SOCCLK;
+ else
+ clk_limit = SMU_14_0_0_UMD_PSTATE_SOCCLK;
+ if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
+ smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_SOCCLK, NULL, &clk_limit);
+ break;
+ case SMU_FCLK:
+ if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 4))
+ smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_FCLK, NULL, &clk_limit);
+ else
+ clk_limit = SMU_14_0_0_UMD_PSTATE_FCLK;
+ if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
+ smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_FCLK, NULL, &clk_limit);
+ else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK)
+ smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_FCLK, &clk_limit, NULL);
+ break;
+ case SMU_VCLK:
+ smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_VCLK, NULL, &clk_limit);
+ break;
+ case SMU_VCLK1:
+ smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_VCLK1, NULL, &clk_limit);
+ break;
+ case SMU_DCLK:
+ smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_DCLK, NULL, &clk_limit);
+ break;
+ case SMU_DCLK1:
+ smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_DCLK1, NULL, &clk_limit);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ *min_clk = *max_clk = clk_limit;
+ return ret;
+}
+
+static int smu_v14_0_common_set_performance_level(struct smu_context *smu,
enum amd_dpm_forced_level level)
{
struct amdgpu_device *adev = smu->adev;
uint32_t sclk_min = 0, sclk_max = 0;
uint32_t fclk_min = 0, fclk_max = 0;
uint32_t socclk_min = 0, socclk_max = 0;
+ uint32_t vclk_min = 0, vclk_max = 0;
+ uint32_t dclk_min = 0, dclk_max = 0;
+ uint32_t vclk1_min = 0, vclk1_max = 0;
+ uint32_t dclk1_min = 0, dclk1_max = 0;
int ret = 0;
switch (level) {
@@ -1261,28 +1364,54 @@ static int smu_v14_0_0_set_performance_level(struct smu_context *smu,
smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_SCLK, NULL, &sclk_max);
smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_FCLK, NULL, &fclk_max);
smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_SOCCLK, NULL, &socclk_max);
+ smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_VCLK, NULL, &vclk_max);
+ smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_DCLK, NULL, &dclk_max);
+ smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_VCLK1, NULL, &vclk1_max);
+ smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_DCLK1, NULL, &dclk1_max);
sclk_min = sclk_max;
fclk_min = fclk_max;
socclk_min = socclk_max;
+ vclk_min = vclk_max;
+ dclk_min = dclk_max;
+ vclk1_min = vclk1_max;
+ dclk1_min = dclk1_max;
break;
case AMD_DPM_FORCED_LEVEL_LOW:
smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_SCLK, &sclk_min, NULL);
smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_FCLK, &fclk_min, NULL);
smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_SOCCLK, &socclk_min, NULL);
+ smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_VCLK, &vclk_min, NULL);
+ smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_DCLK, &dclk_min, NULL);
+ smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_VCLK1, &vclk1_min, NULL);
+ smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_DCLK1, &dclk1_min, NULL);
sclk_max = sclk_min;
fclk_max = fclk_min;
socclk_max = socclk_min;
+ vclk_max = vclk_min;
+ dclk_max = dclk_min;
+ vclk1_max = vclk1_min;
+ dclk1_max = dclk1_min;
break;
case AMD_DPM_FORCED_LEVEL_AUTO:
smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_SCLK, &sclk_min, &sclk_max);
smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_FCLK, &fclk_min, &fclk_max);
smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_SOCCLK, &socclk_min, &socclk_max);
+ smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_VCLK, &vclk_min, &vclk_max);
+ smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_DCLK, &dclk_min, &dclk_max);
+ smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_VCLK1, &vclk1_min, &vclk1_max);
+ smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_DCLK1, &dclk1_min, &dclk1_max);
break;
case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
- /* Temporarily do nothing since the optimal clocks haven't been provided yet */
+ smu_v14_0_common_get_dpm_profile_freq(smu, level, SMU_SCLK, &sclk_min, &sclk_max);
+ smu_v14_0_common_get_dpm_profile_freq(smu, level, SMU_FCLK, &fclk_min, &fclk_max);
+ smu_v14_0_common_get_dpm_profile_freq(smu, level, SMU_SOCCLK, &socclk_min, &socclk_max);
+ smu_v14_0_common_get_dpm_profile_freq(smu, level, SMU_VCLK, &vclk_min, &vclk_max);
+ smu_v14_0_common_get_dpm_profile_freq(smu, level, SMU_DCLK, &dclk_min, &dclk_max);
+ smu_v14_0_common_get_dpm_profile_freq(smu, level, SMU_VCLK1, &vclk1_min, &vclk1_max);
+ smu_v14_0_common_get_dpm_profile_freq(smu, level, SMU_DCLK1, &dclk1_min, &dclk1_max);
break;
case AMD_DPM_FORCED_LEVEL_MANUAL:
case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT:
@@ -1322,6 +1451,42 @@ static int smu_v14_0_0_set_performance_level(struct smu_context *smu,
return ret;
}
+ if (vclk_min && vclk_max) {
+ ret = smu_v14_0_0_set_soft_freq_limited_range(smu,
+ SMU_VCLK,
+ vclk_min,
+ vclk_max);
+ if (ret)
+ return ret;
+ }
+
+ if (vclk1_min && vclk1_max) {
+ ret = smu_v14_0_0_set_soft_freq_limited_range(smu,
+ SMU_VCLK1,
+ vclk1_min,
+ vclk1_max);
+ if (ret)
+ return ret;
+ }
+
+ if (dclk_min && dclk_max) {
+ ret = smu_v14_0_0_set_soft_freq_limited_range(smu,
+ SMU_DCLK,
+ dclk_min,
+ dclk_max);
+ if (ret)
+ return ret;
+ }
+
+ if (dclk1_min && dclk1_max) {
+ ret = smu_v14_0_0_set_soft_freq_limited_range(smu,
+ SMU_DCLK1,
+ dclk1_min,
+ dclk1_max);
+ if (ret)
+ return ret;
+ }
+
return ret;
}
@@ -1351,10 +1516,10 @@ static int smu_v14_0_0_set_fine_grain_gfx_freq_parameters(struct smu_context *sm
static int smu_v14_0_common_set_fine_grain_gfx_freq_parameters(struct smu_context *smu)
{
- if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 0))
- smu_v14_0_0_set_fine_grain_gfx_freq_parameters(smu);
- else if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1))
+ if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1))
smu_v14_0_1_set_fine_grain_gfx_freq_parameters(smu);
+ else
+ smu_v14_0_0_set_fine_grain_gfx_freq_parameters(smu);
return 0;
}
@@ -1415,14 +1580,65 @@ static int smu_14_0_0_get_dpm_table(struct smu_context *smu, struct dpm_clocks *
static int smu_v14_0_common_get_dpm_table(struct smu_context *smu, struct dpm_clocks *clock_table)
{
- if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 0))
- smu_14_0_0_get_dpm_table(smu, clock_table);
- else if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1))
+ if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1))
smu_14_0_1_get_dpm_table(smu, clock_table);
+ else
+ smu_14_0_0_get_dpm_table(smu, clock_table);
return 0;
}
+static int smu_v14_0_1_init_mall_power_gating(struct smu_context *smu, enum smu_mall_pg_config pg_config)
+{
+ struct amdgpu_device *adev = smu->adev;
+ int ret = 0;
+
+ if (pg_config == SMU_MALL_PG_CONFIG_PMFW_CONTROL) {
+ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_MALLPowerController,
+ SMU_MALL_PMFW_CONTROL, NULL);
+ if (ret) {
+ dev_err(adev->dev, "Init MALL PMFW CONTROL Failure\n");
+ return ret;
+ }
+ } else {
+ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_MALLPowerController,
+ SMU_MALL_DRIVER_CONTROL, NULL);
+ if (ret) {
+ dev_err(adev->dev, "Init MALL Driver CONTROL Failure\n");
+ return ret;
+ }
+
+ if (pg_config == SMU_MALL_PG_CONFIG_DRIVER_CONTROL_ALWAYS_ON) {
+ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_MALLPowerState,
+ SMU_MALL_EXIT_PG, NULL);
+ if (ret) {
+ dev_err(adev->dev, "EXIT MALL PG Failure\n");
+ return ret;
+ }
+ } else if (pg_config == SMU_MALL_PG_CONFIG_DRIVER_CONTROL_ALWAYS_OFF) {
+ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_MALLPowerState,
+ SMU_MALL_ENTER_PG, NULL);
+ if (ret) {
+ dev_err(adev->dev, "Enter MALL PG Failure\n");
+ return ret;
+ }
+ }
+ }
+
+ return ret;
+}
+
+static int smu_v14_0_common_set_mall_enable(struct smu_context *smu)
+{
+ enum smu_mall_pg_config pg_config = SMU_MALL_PG_CONFIG_DEFAULT;
+ int ret = 0;
+
+ if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1))
+ ret = smu_v14_0_1_init_mall_power_gating(smu, pg_config);
+
+ return ret;
+}
+
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,
@@ -1448,12 +1664,13 @@ static const struct pptable_funcs smu_v14_0_0_ppt_funcs = {
.od_edit_dpm_table = smu_v14_0_od_edit_dpm_table,
.print_clk_levels = smu_v14_0_0_print_clk_levels,
.force_clk_levels = smu_v14_0_0_force_clk_levels,
- .set_performance_level = smu_v14_0_0_set_performance_level,
+ .set_performance_level = smu_v14_0_common_set_performance_level,
.set_fine_grain_gfx_freq_parameters = smu_v14_0_common_set_fine_grain_gfx_freq_parameters,
.set_gfx_power_up_by_imu = smu_v14_0_set_gfx_power_up_by_imu,
.dpm_set_vpe_enable = smu_v14_0_0_set_vpe_enable,
.dpm_set_umsch_mm_enable = smu_v14_0_0_set_umsch_mm_enable,
.get_dpm_clock_table = smu_v14_0_common_get_dpm_table,
+ .set_mall_enable = smu_v14_0_common_set_mall_enable,
};
static void smu_v14_0_0_set_smu_mailbox_registers(struct smu_context *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 7179cdacf156..98ea58d792ca 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
@@ -1869,34 +1869,6 @@ static ssize_t smu_v14_0_2_get_ecc_info(struct smu_context *smu,
return ret;
}
-static int smu_v14_0_2_set_vcn_enable(struct smu_context *smu,
- bool enable)
-{
- struct amdgpu_device *adev = smu->adev;
- struct smu_power_gate *power_gate = &smu->smu_power.power_gate;
- int i, ret = 0;
-
- if (!adev->enable_jpeg_test)
- return smu_v14_0_set_vcn_enable(smu, enable);
-
- if (!atomic_read(&power_gate->vcn_gated) || !enable)
- return 0;
-
- for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
- if (adev->vcn.harvest_config & (1 << i))
- continue;
-
- ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn,
- i << 16U, NULL);
- if (ret)
- return ret;
- }
-
- atomic_set(&power_gate->vcn_gated, 0);
-
- return ret;
-}
-
static const struct pptable_funcs smu_v14_0_2_ppt_funcs = {
.get_allowed_feature_mask = smu_v14_0_2_get_allowed_feature_mask,
.set_default_dpm_table = smu_v14_0_2_set_default_dpm_table,
@@ -1919,7 +1891,7 @@ static const struct pptable_funcs smu_v14_0_2_ppt_funcs = {
.system_features_control = smu_v14_0_system_features_control,
.set_allowed_mask = smu_v14_0_set_allowed_mask,
.get_enabled_mask = smu_cmn_get_enabled_mask,
- .dpm_set_vcn_enable = smu_v14_0_2_set_vcn_enable,
+ .dpm_set_vcn_enable = smu_v14_0_set_vcn_enable,
.dpm_set_jpeg_enable = smu_v14_0_set_jpeg_enable,
.get_dpm_ultimate_freq = smu_v14_0_2_get_dpm_ultimate_freq,
.get_vbios_bootup_values = smu_v14_0_get_vbios_bootup_values,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
index 5592fd825aa3..88eefef05fae 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
@@ -315,11 +315,21 @@ int smu_cmn_send_msg_without_waiting(struct smu_context *smu,
if (adev->no_hw_access)
return 0;
- reg = __smu_cmn_poll_stat(smu);
- res = __smu_cmn_reg2errno(smu, reg);
- if (reg == SMU_RESP_NONE ||
- res == -EREMOTEIO)
+ if (smu->smc_fw_state == SMU_FW_HANG) {
+ dev_err(adev->dev, "SMU is in hanged state, failed to send smu message!\n");
+ res = -EREMOTEIO;
goto Out;
+ }
+
+ if (smu->smc_fw_state == SMU_FW_INIT) {
+ smu->smc_fw_state = SMU_FW_RUNTIME;
+ } else {
+ reg = __smu_cmn_poll_stat(smu);
+ res = __smu_cmn_reg2errno(smu, reg);
+ if (reg == SMU_RESP_NONE || res == -EREMOTEIO)
+ goto Out;
+ }
+
__smu_cmn_send_msg(smu, msg_index, param);
res = 0;
Out:
@@ -350,6 +360,9 @@ int smu_cmn_wait_for_response(struct smu_context *smu)
reg = __smu_cmn_poll_stat(smu);
res = __smu_cmn_reg2errno(smu, reg);
+ if (res == -EREMOTEIO)
+ smu->smc_fw_state = SMU_FW_HANG;
+
if (unlikely(smu->adev->pm.smu_debug_mask & SMU_DEBUG_HALT_ON_ERROR) &&
res && (res != -ETIME)) {
amdgpu_device_halt(smu->adev);
@@ -418,6 +431,16 @@ int smu_cmn_send_smc_msg_with_param(struct smu_context *smu,
goto Out;
}
+ if (smu->smc_fw_state == SMU_FW_HANG) {
+ dev_err(adev->dev, "SMU is in hanged state, failed to send smu message!\n");
+ res = -EREMOTEIO;
+ goto Out;
+ } else if (smu->smc_fw_state == SMU_FW_INIT) {
+ /* Ignore initial smu response register value */
+ poll = false;
+ smu->smc_fw_state = SMU_FW_RUNTIME;
+ }
+
if (poll) {
reg = __smu_cmn_poll_stat(smu);
res = __smu_cmn_reg2errno(smu, reg);
@@ -429,8 +452,11 @@ int smu_cmn_send_smc_msg_with_param(struct smu_context *smu,
__smu_cmn_send_msg(smu, (uint16_t) index, param);
reg = __smu_cmn_poll_stat(smu);
res = __smu_cmn_reg2errno(smu, reg);
- if (res != 0)
+ if (res != 0) {
+ if (res == -EREMOTEIO)
+ smu->smc_fw_state = SMU_FW_HANG;
__smu_cmn_reg_print_error(smu, reg, index, param, msg);
+ }
if (read_arg) {
smu_cmn_read_arg(smu, read_arg);
dev_dbg(adev->dev, "smu send message: %s(%d) param: 0x%08x, resp: 0x%08x,\
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
index 2c661f28410e..2ad33559a33a 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
@@ -5,6 +5,7 @@
*
*/
#include <linux/clk.h>
+#include <linux/of.h>
#include <linux/pm_runtime.h>
#include <linux/spinlock.h>
@@ -294,7 +295,6 @@ komeda_crtc_flush_and_wait_for_flip_done(struct komeda_crtc *kcrtc,
struct komeda_dev *mdev = kcrtc->master->mdev;
struct completion *flip_done;
struct completion temp;
- int timeout;
/* if caller doesn't send a flip_done, use a private flip_done */
if (input_flip_done) {
@@ -308,8 +308,7 @@ komeda_crtc_flush_and_wait_for_flip_done(struct komeda_crtc *kcrtc,
mdev->funcs->flush(mdev, kcrtc->master->id, 0);
/* wait the flip take affect.*/
- timeout = wait_for_completion_timeout(flip_done, HZ);
- if (timeout == 0) {
+ if (wait_for_completion_timeout(flip_done, HZ) == 0) {
DRM_ERROR("wait pipe%d flip done timeout\n", kcrtc->master->id);
if (!input_flip_done) {
unsigned long flags;
@@ -610,12 +609,34 @@ get_crtc_primary(struct komeda_kms_dev *kms, struct komeda_crtc *crtc)
return NULL;
}
+static int komeda_attach_bridge(struct device *dev,
+ struct komeda_pipeline *pipe,
+ struct drm_encoder *encoder)
+{
+ struct drm_bridge *bridge;
+ int err;
+
+ bridge = devm_drm_of_get_bridge(dev, pipe->of_node,
+ KOMEDA_OF_PORT_OUTPUT, 0);
+ if (IS_ERR(bridge))
+ return dev_err_probe(dev, PTR_ERR(bridge), "remote bridge not found for pipe: %s\n",
+ of_node_full_name(pipe->of_node));
+
+ err = drm_bridge_attach(encoder, bridge, NULL, 0);
+ if (err)
+ dev_err(dev, "bridge_attach() failed for pipe: %s\n",
+ of_node_full_name(pipe->of_node));
+
+ return err;
+}
+
static int komeda_crtc_add(struct komeda_kms_dev *kms,
struct komeda_crtc *kcrtc)
{
struct drm_crtc *crtc = &kcrtc->base;
struct drm_device *base = &kms->base;
- struct drm_bridge *bridge;
+ struct komeda_pipeline *pipe = kcrtc->master;
+ struct drm_encoder *encoder = &kcrtc->encoder;
int err;
err = drm_crtc_init_with_planes(base, crtc,
@@ -626,27 +647,27 @@ static int komeda_crtc_add(struct komeda_kms_dev *kms,
drm_crtc_helper_add(crtc, &komeda_crtc_helper_funcs);
- crtc->port = kcrtc->master->of_output_port;
+ crtc->port = pipe->of_output_port;
/* Construct an encoder for each pipeline and attach it to the remote
* bridge
*/
kcrtc->encoder.possible_crtcs = drm_crtc_mask(crtc);
- err = drm_simple_encoder_init(base, &kcrtc->encoder,
- DRM_MODE_ENCODER_TMDS);
+ err = drm_simple_encoder_init(base, encoder, DRM_MODE_ENCODER_TMDS);
if (err)
return err;
- bridge = devm_drm_of_get_bridge(base->dev, kcrtc->master->of_node,
- KOMEDA_OF_PORT_OUTPUT, 0);
- if (IS_ERR(bridge))
- return PTR_ERR(bridge);
-
- err = drm_bridge_attach(&kcrtc->encoder, bridge, NULL, 0);
+ if (pipe->of_output_links[0]) {
+ err = komeda_attach_bridge(base->dev, pipe, encoder);
+ if (err)
+ return err;
+ }
drm_crtc_enable_color_mgmt(crtc, 0, true, KOMEDA_COLOR_LUT_SIZE);
- return err;
+ komeda_pipeline_dump(pipe);
+
+ return 0;
}
int komeda_kms_add_crtcs(struct komeda_kms_dev *kms, struct komeda_dev *mdev)
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.c b/drivers/gpu/drm/arm/display/komeda/komeda_dev.c
index 14ee79becacb..5ba62e637a61 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.c
@@ -12,10 +12,8 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/dma-mapping.h>
-#ifdef CONFIG_DEBUG_FS
#include <linux/debugfs.h>
#include <linux/seq_file.h>
-#endif
#include <drm/drm_print.h>
@@ -43,7 +41,6 @@ static int komeda_register_show(struct seq_file *sf, void *x)
DEFINE_SHOW_ATTRIBUTE(komeda_register);
-#ifdef CONFIG_DEBUG_FS
static void komeda_debugfs_init(struct komeda_dev *mdev)
{
if (!debugfs_initialized())
@@ -55,7 +52,6 @@ static void komeda_debugfs_init(struct komeda_dev *mdev)
debugfs_create_x16("err_verbosity", 0664, mdev->debugfs_root,
&mdev->err_verbosity);
}
-#endif
static ssize_t
core_id_show(struct device *dev, struct device_attribute *attr, char *buf)
@@ -265,9 +261,7 @@ struct komeda_dev *komeda_dev_create(struct device *dev)
mdev->err_verbosity = KOMEDA_DEV_PRINT_ERR_EVENTS;
-#ifdef CONFIG_DEBUG_FS
komeda_debugfs_init(mdev);
-#endif
return mdev;
@@ -286,9 +280,7 @@ void komeda_dev_destroy(struct komeda_dev *mdev)
sysfs_remove_group(&dev->kobj, &komeda_sysfs_attr_group);
-#ifdef CONFIG_DEBUG_FS
debugfs_remove_recursive(mdev->debugfs_root);
-#endif
if (mdev->aclk)
clk_prepare_enable(mdev->aclk);
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_drv.c b/drivers/gpu/drm/arm/display/komeda/komeda_drv.c
index cc57ea4e13ae..55c3773befde 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_drv.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_drv.c
@@ -9,7 +9,7 @@
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_dma.h>
#include <drm/drm_module.h>
#include <drm/drm_of.h>
#include "komeda_dev.h"
@@ -59,6 +59,10 @@ static int komeda_platform_probe(struct platform_device *pdev)
struct komeda_drv *mdrv;
int err;
+ err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(40));
+ if (err)
+ return dev_err_probe(dev, err, "DMA mask error\n");
+
mdrv = devm_kzalloc(dev, sizeof(*mdrv), GFP_KERNEL);
if (!mdrv)
return -ENOMEM;
@@ -80,7 +84,7 @@ static int komeda_platform_probe(struct platform_device *pdev)
}
dev_set_drvdata(dev, mdrv);
- drm_fbdev_generic_setup(&mdrv->kms->base, 32);
+ drm_fbdev_dma_setup(&mdrv->kms->base, 32);
return 0;
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.h b/drivers/gpu/drm/arm/display/komeda/komeda_kms.h
index a4048724564d..83e61c4080c2 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.h
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.h
@@ -191,5 +191,6 @@ void komeda_crtc_flush_and_wait_for_flip_done(struct komeda_crtc *kcrtc,
struct komeda_kms_dev *komeda_kms_attach(struct komeda_dev *mdev);
void komeda_kms_detach(struct komeda_kms_dev *kms);
void komeda_kms_shutdown(struct komeda_kms_dev *kms);
+void komeda_pipeline_dump(struct komeda_pipeline *pipe);
#endif /*_KOMEDA_KMS_H_*/
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c
index 00f5864a0495..81e244f0c0ca 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c
@@ -10,6 +10,7 @@
#include <drm/drm_print.h>
#include "komeda_dev.h"
+#include "komeda_kms.h"
#include "komeda_pipeline.h"
/** komeda_pipeline_add - Add a pipeline to &komeda_dev */
@@ -247,7 +248,7 @@ static void komeda_component_dump(struct komeda_component *c)
c->max_active_outputs, c->supported_outputs);
}
-static void komeda_pipeline_dump(struct komeda_pipeline *pipe)
+void komeda_pipeline_dump(struct komeda_pipeline *pipe)
{
struct komeda_component *c;
int id;
@@ -351,7 +352,6 @@ int komeda_assemble_pipelines(struct komeda_dev *mdev)
pipe = mdev->pipelines[i];
komeda_pipeline_assemble(pipe);
- komeda_pipeline_dump(pipe);
}
return 0;
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 f3e744172673..f4e76b46ca32 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c
@@ -259,7 +259,7 @@ komeda_component_get_avail_scaler(struct komeda_component *c,
u32 avail_scalers;
pipe_st = komeda_pipeline_get_state(c->pipeline, state);
- if (!pipe_st)
+ if (IS_ERR_OR_NULL(pipe_st))
return NULL;
avail_scalers = (pipe_st->active_comps & KOMEDA_PIPELINE_SCALERS) ^
diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c
index f8c49ba68e78..aae019e79bda 100644
--- a/drivers/gpu/drm/ast/ast_drv.c
+++ b/drivers/gpu/drm/ast/ast_drv.c
@@ -33,7 +33,7 @@
#include <drm/drm_aperture.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_shmem.h>
#include <drm/drm_gem_shmem_helper.h>
#include <drm/drm_module.h>
#include <drm/drm_probe_helper.h>
@@ -360,7 +360,7 @@ static int ast_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (ret)
return ret;
- drm_fbdev_generic_setup(drm, 32);
+ drm_fbdev_shmem_setup(drm, 32);
return 0;
}
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
index 6695af70768f..dc8f639e82fd 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -45,7 +45,6 @@
#include <drm/drm_managed.h>
#include <drm/drm_panic.h>
#include <drm/drm_probe_helper.h>
-#include <drm/drm_simple_kms_helper.h>
#include "ast_ddc.h"
#include "ast_drv.h"
@@ -304,7 +303,7 @@ static void ast_set_std_reg(struct ast_device *ast,
/* Set SEQ; except Screen Disable field */
ast_set_index_reg(ast, AST_IO_VGASRI, 0x00, 0x03);
- ast_set_index_reg_mask(ast, AST_IO_VGASRI, 0x01, 0xdf, stdtable->seq[0]);
+ ast_set_index_reg_mask(ast, AST_IO_VGASRI, 0x01, 0x20, stdtable->seq[0]);
for (i = 1; i < 4; i++) {
jreg = stdtable->seq[i];
ast_set_index_reg(ast, AST_IO_VGASRI, (i + 1), jreg);
@@ -650,12 +649,12 @@ static void ast_primary_plane_helper_atomic_update(struct drm_plane *plane,
struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
struct drm_framebuffer *old_fb = old_plane_state->fb;
struct ast_plane *ast_plane = to_ast_plane(plane);
+ struct drm_crtc *crtc = plane_state->crtc;
+ struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
struct drm_rect damage;
struct drm_atomic_helper_damage_iter iter;
- if (!old_fb || (fb->format != old_fb->format)) {
- struct drm_crtc *crtc = plane_state->crtc;
- struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+ if (!old_fb || (fb->format != old_fb->format) || crtc_state->mode_changed) {
struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
struct ast_vbios_mode_info *vbios_mode_info = &ast_crtc_state->vbios_mode_info;
@@ -691,15 +690,15 @@ static void ast_primary_plane_helper_atomic_enable(struct drm_plane *plane,
* Therefore only reprogram the address after enabling the plane.
*/
ast_set_start_address_crt1(ast, (u32)ast_plane->offset);
- ast_set_index_reg_mask(ast, AST_IO_VGASRI, 0x1, 0xdf, 0x00);
}
static void ast_primary_plane_helper_atomic_disable(struct drm_plane *plane,
struct drm_atomic_state *state)
{
- struct ast_device *ast = to_ast_device(plane->dev);
-
- ast_set_index_reg_mask(ast, AST_IO_VGASRI, 0x1, 0xdf, 0x20);
+ /*
+ * Keep this empty function to avoid calling
+ * atomic_update when disabling the plane.
+ */
}
static int ast_primary_plane_helper_get_scanout_buffer(struct drm_plane *plane,
@@ -1020,62 +1019,6 @@ static int ast_cursor_plane_init(struct ast_device *ast)
* CRTC
*/
-static void ast_crtc_dpms(struct drm_crtc *crtc, int mode)
-{
- struct ast_device *ast = to_ast_device(crtc->dev);
- u8 ch = AST_DPMS_VSYNC_OFF | AST_DPMS_HSYNC_OFF;
- struct ast_crtc_state *ast_state;
- const struct drm_format_info *format;
- struct ast_vbios_mode_info *vbios_mode_info;
-
- /* TODO: Maybe control display signal generation with
- * Sync Enable (bit CR17.7).
- */
- switch (mode) {
- case DRM_MODE_DPMS_ON:
- ast_set_index_reg_mask(ast, AST_IO_VGASRI, 0x01, 0xdf, 0);
- ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xb6, 0xfc, 0);
- if (ast->tx_chip_types & AST_TX_DP501_BIT)
- ast_set_dp501_video_output(crtc->dev, 1);
-
- if (ast->tx_chip_types & AST_TX_ASTDP_BIT) {
- ast_dp_power_on_off(crtc->dev, AST_DP_POWER_ON);
- ast_wait_for_vretrace(ast);
- ast_dp_set_on_off(crtc->dev, 1);
- }
-
- ast_state = to_ast_crtc_state(crtc->state);
- format = ast_state->format;
-
- if (format) {
- vbios_mode_info = &ast_state->vbios_mode_info;
-
- ast_set_color_reg(ast, format);
- ast_set_vbios_color_reg(ast, format, vbios_mode_info);
- if (crtc->state->gamma_lut)
- ast_crtc_set_gamma(ast, format, crtc->state->gamma_lut->data);
- else
- ast_crtc_set_gamma_linear(ast, format);
- }
- break;
- case DRM_MODE_DPMS_STANDBY:
- case DRM_MODE_DPMS_SUSPEND:
- case DRM_MODE_DPMS_OFF:
- ch = mode;
- if (ast->tx_chip_types & AST_TX_DP501_BIT)
- ast_set_dp501_video_output(crtc->dev, 0);
-
- if (ast->tx_chip_types & AST_TX_ASTDP_BIT) {
- ast_dp_set_on_off(crtc->dev, 0);
- ast_dp_power_on_off(crtc->dev, AST_DP_POWER_OFF);
- }
-
- ast_set_index_reg_mask(ast, AST_IO_VGASRI, 0x01, 0xdf, 0x20);
- ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xb6, 0xfc, ch);
- break;
- }
-}
-
static enum drm_mode_status
ast_crtc_helper_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode)
{
@@ -1148,6 +1091,33 @@ ast_crtc_helper_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode
return status;
}
+static void ast_crtc_helper_mode_set_nofb(struct drm_crtc *crtc)
+{
+ struct drm_device *dev = crtc->dev;
+ struct ast_device *ast = to_ast_device(dev);
+ struct drm_crtc_state *crtc_state = crtc->state;
+ struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
+ struct ast_vbios_mode_info *vbios_mode_info =
+ &ast_crtc_state->vbios_mode_info;
+ struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
+
+ /*
+ * Ensure that no scanout takes place before reprogramming mode
+ * and format registers.
+ *
+ * TODO: Get vblank interrupts working and remove this line.
+ */
+ ast_wait_for_vretrace(ast);
+
+ ast_set_vbios_mode_reg(ast, adjusted_mode, vbios_mode_info);
+ ast_set_index_reg(ast, AST_IO_VGACRI, 0xa1, 0x06);
+ ast_set_std_reg(ast, adjusted_mode, vbios_mode_info);
+ ast_set_crtc_reg(ast, adjusted_mode, vbios_mode_info);
+ ast_set_dclk_reg(ast, adjusted_mode, vbios_mode_info);
+ ast_set_crtthd_reg(ast);
+ ast_set_sync_reg(ast, adjusted_mode, vbios_mode_info);
+}
+
static int ast_crtc_helper_atomic_check(struct drm_crtc *crtc,
struct drm_atomic_state *state)
{
@@ -1207,7 +1177,6 @@ ast_crtc_helper_atomic_flush(struct drm_crtc *crtc,
struct drm_device *dev = crtc->dev;
struct ast_device *ast = to_ast_device(dev);
struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
- struct ast_vbios_mode_info *vbios_mode_info = &ast_crtc_state->vbios_mode_info;
/*
* The gamma LUT has to be reloaded after changing the primary
@@ -1221,40 +1190,27 @@ ast_crtc_helper_atomic_flush(struct drm_crtc *crtc,
else
ast_crtc_set_gamma_linear(ast, ast_crtc_state->format);
}
-
- //Set Aspeed Display-Port
- if (ast->tx_chip_types & AST_TX_ASTDP_BIT)
- ast_dp_set_mode(crtc, vbios_mode_info);
}
static void ast_crtc_helper_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state)
{
- struct drm_device *dev = crtc->dev;
- struct ast_device *ast = to_ast_device(dev);
- struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
- struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
- struct ast_vbios_mode_info *vbios_mode_info =
- &ast_crtc_state->vbios_mode_info;
- struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
-
- ast_set_vbios_mode_reg(ast, adjusted_mode, vbios_mode_info);
- ast_set_index_reg(ast, AST_IO_VGACRI, 0xa1, 0x06);
- ast_set_std_reg(ast, adjusted_mode, vbios_mode_info);
- ast_set_crtc_reg(ast, adjusted_mode, vbios_mode_info);
- ast_set_dclk_reg(ast, adjusted_mode, vbios_mode_info);
- ast_set_crtthd_reg(ast);
- ast_set_sync_reg(ast, adjusted_mode, vbios_mode_info);
+ struct ast_device *ast = to_ast_device(crtc->dev);
- ast_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
+ ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xb6, 0xfc, 0x00);
+ ast_set_index_reg_mask(ast, AST_IO_VGASRI, 0x01, 0xdf, 0x00);
}
static void ast_crtc_helper_atomic_disable(struct drm_crtc *crtc, struct drm_atomic_state *state)
{
struct drm_crtc_state *old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc);
- struct drm_device *dev = crtc->dev;
- struct ast_device *ast = to_ast_device(dev);
+ struct ast_device *ast = to_ast_device(crtc->dev);
+ u8 vgacrb6;
+
+ ast_set_index_reg_mask(ast, AST_IO_VGASRI, 0x01, 0xdf, AST_IO_VGASR1_SD);
- ast_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
+ vgacrb6 = AST_IO_VGACRB6_VSYNC_OFF |
+ AST_IO_VGACRB6_HSYNC_OFF;
+ ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xb6, 0xfc, vgacrb6);
/*
* HW cursors require the underlying primary plane and CRTC to
@@ -1267,16 +1223,11 @@ static void ast_crtc_helper_atomic_disable(struct drm_crtc *crtc, struct drm_ato
* simple pageflips on the planes.
*/
drm_atomic_helper_disable_planes_on_crtc(old_crtc_state, false);
-
- /*
- * Ensure that no scanout takes place before reprogramming mode
- * and format registers.
- */
- ast_wait_for_vretrace(ast);
}
static const struct drm_crtc_helper_funcs ast_crtc_helper_funcs = {
.mode_valid = ast_crtc_helper_mode_valid,
+ .mode_set_nofb = ast_crtc_helper_mode_set_nofb,
.atomic_check = ast_crtc_helper_atomic_check,
.atomic_flush = ast_crtc_helper_atomic_flush,
.atomic_enable = ast_crtc_helper_atomic_enable,
@@ -1359,6 +1310,14 @@ static int ast_crtc_init(struct drm_device *dev)
}
/*
+ * VGA Encoder
+ */
+
+static const struct drm_encoder_funcs ast_vga_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
+/*
* VGA Connector
*/
@@ -1411,7 +1370,8 @@ static int ast_vga_output_init(struct ast_device *ast)
struct drm_connector *connector = &ast->output.vga.connector;
int ret;
- ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_DAC);
+ ret = drm_encoder_init(dev, encoder, &ast_vga_encoder_funcs,
+ DRM_MODE_ENCODER_DAC, NULL);
if (ret)
return ret;
encoder->possible_crtcs = drm_crtc_mask(crtc);
@@ -1428,6 +1388,14 @@ static int ast_vga_output_init(struct ast_device *ast)
}
/*
+ * SIL164 Encoder
+ */
+
+static const struct drm_encoder_funcs ast_sil164_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
+/*
* SIL164 Connector
*/
@@ -1480,7 +1448,8 @@ static int ast_sil164_output_init(struct ast_device *ast)
struct drm_connector *connector = &ast->output.sil164.connector;
int ret;
- ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_TMDS);
+ ret = drm_encoder_init(dev, encoder, &ast_sil164_encoder_funcs,
+ DRM_MODE_ENCODER_TMDS, NULL);
if (ret)
return ret;
encoder->possible_crtcs = drm_crtc_mask(crtc);
@@ -1497,6 +1466,35 @@ static int ast_sil164_output_init(struct ast_device *ast)
}
/*
+ * DP501 Encoder
+ */
+
+static const struct drm_encoder_funcs ast_dp501_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
+static void ast_dp501_encoder_helper_atomic_enable(struct drm_encoder *encoder,
+ struct drm_atomic_state *state)
+{
+ struct drm_device *dev = encoder->dev;
+
+ ast_set_dp501_video_output(dev, 1);
+}
+
+static void ast_dp501_encoder_helper_atomic_disable(struct drm_encoder *encoder,
+ struct drm_atomic_state *state)
+{
+ struct drm_device *dev = encoder->dev;
+
+ ast_set_dp501_video_output(dev, 0);
+}
+
+static const struct drm_encoder_helper_funcs ast_dp501_encoder_helper_funcs = {
+ .atomic_enable = ast_dp501_encoder_helper_atomic_enable,
+ .atomic_disable = ast_dp501_encoder_helper_atomic_disable,
+};
+
+/*
* DP501 Connector
*/
@@ -1578,9 +1576,12 @@ static int ast_dp501_output_init(struct ast_device *ast)
struct drm_connector *connector = &ast->output.dp501.connector;
int ret;
- ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_TMDS);
+ ret = drm_encoder_init(dev, encoder, &ast_dp501_encoder_funcs,
+ DRM_MODE_ENCODER_TMDS, NULL);
if (ret)
return ret;
+ drm_encoder_helper_add(encoder, &ast_dp501_encoder_helper_funcs);
+
encoder->possible_crtcs = drm_crtc_mask(crtc);
ret = ast_dp501_connector_init(dev, connector);
@@ -1595,6 +1596,51 @@ static int ast_dp501_output_init(struct ast_device *ast)
}
/*
+ * ASPEED Display-Port Encoder
+ */
+
+static const struct drm_encoder_funcs ast_astdp_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
+static void ast_astdp_encoder_helper_atomic_mode_set(struct drm_encoder *encoder,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state)
+{
+ struct drm_crtc *crtc = crtc_state->crtc;
+ struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
+ struct ast_vbios_mode_info *vbios_mode_info = &ast_crtc_state->vbios_mode_info;
+
+ ast_dp_set_mode(crtc, vbios_mode_info);
+}
+
+static void ast_astdp_encoder_helper_atomic_enable(struct drm_encoder *encoder,
+ struct drm_atomic_state *state)
+{
+ struct drm_device *dev = encoder->dev;
+ struct ast_device *ast = to_ast_device(dev);
+
+ ast_dp_power_on_off(dev, AST_DP_POWER_ON);
+ ast_wait_for_vretrace(ast);
+ ast_dp_set_on_off(dev, 1);
+}
+
+static void ast_astdp_encoder_helper_atomic_disable(struct drm_encoder *encoder,
+ struct drm_atomic_state *state)
+{
+ struct drm_device *dev = encoder->dev;
+
+ ast_dp_set_on_off(dev, 0);
+ ast_dp_power_on_off(dev, AST_DP_POWER_OFF);
+}
+
+static const struct drm_encoder_helper_funcs ast_astdp_encoder_helper_funcs = {
+ .atomic_mode_set = ast_astdp_encoder_helper_atomic_mode_set,
+ .atomic_enable = ast_astdp_encoder_helper_atomic_enable,
+ .atomic_disable = ast_astdp_encoder_helper_atomic_disable,
+};
+
+/*
* ASPEED Display-Port Connector
*/
@@ -1688,9 +1734,12 @@ static int ast_astdp_output_init(struct ast_device *ast)
struct drm_connector *connector = &ast->output.astdp.connector;
int ret;
- ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_TMDS);
+ ret = drm_encoder_init(dev, encoder, &ast_astdp_encoder_funcs,
+ DRM_MODE_ENCODER_TMDS, NULL);
if (ret)
return ret;
+ drm_encoder_helper_add(encoder, &ast_astdp_encoder_helper_funcs);
+
encoder->possible_crtcs = drm_crtc_mask(crtc);
ret = ast_astdp_connector_init(dev, connector);
@@ -1816,7 +1865,7 @@ static void ast_mode_config_helper_atomic_commit_tail(struct drm_atomic_state *s
* the I/O-register lock. Released in atomic_flush().
*/
mutex_lock(&ast->modeset_lock);
- drm_atomic_helper_commit_tail_rpm(state);
+ drm_atomic_helper_commit_tail(state);
mutex_unlock(&ast->modeset_lock);
}
diff --git a/drivers/gpu/drm/ast/ast_reg.h b/drivers/gpu/drm/ast/ast_reg.h
index 62dddbf3fe56..75671d345057 100644
--- a/drivers/gpu/drm/ast/ast_reg.h
+++ b/drivers/gpu/drm/ast/ast_reg.h
@@ -22,6 +22,7 @@
#define AST_IO_VGAER_VGA_ENABLE BIT(0)
#define AST_IO_VGASRI (0x44)
+#define AST_IO_VGASR1_SD BIT(5)
#define AST_IO_VGADRR (0x47)
#define AST_IO_VGADWR (0x48)
#define AST_IO_VGAPDR (0x49)
@@ -31,6 +32,8 @@
#define AST_IO_VGACR80_PASSWORD (0xa8)
#define AST_IO_VGACRA1_VGAIO_DISABLED BIT(1)
#define AST_IO_VGACRA1_MMIO_ENABLED BIT(2)
+#define AST_IO_VGACRB6_HSYNC_OFF BIT(0)
+#define AST_IO_VGACRB6_VSYNC_OFF BIT(1)
#define AST_IO_VGACRCB_HWC_16BPP BIT(0) /* set: ARGB4444, cleared: 2bpp palette */
#define AST_IO_VGACRCB_HWC_ENABLED BIT(1)
@@ -76,13 +79,6 @@
#define ASTDP_HOST_EDID_READ_DONE_MASK GENMASK(0, 0)
/*
- * CRB8[b1]: Enable VSYNC off
- * CRB8[b0]: Enable HSYNC off
- */
-#define AST_DPMS_VSYNC_OFF BIT(1)
-#define AST_DPMS_HSYNC_OFF BIT(0)
-
-/*
* CRDF[b4]: Mirror of AST_DP_VIDEO_ENABLE
* Precondition: A. ~AST_DP_PHY_SLEEP &&
* B. DP_HPD &&
diff --git a/drivers/gpu/drm/atmel-hlcdc/Kconfig b/drivers/gpu/drm/atmel-hlcdc/Kconfig
index 3bdbab3a6333..945f3aa7bb24 100644
--- a/drivers/gpu/drm/atmel-hlcdc/Kconfig
+++ b/drivers/gpu/drm/atmel-hlcdc/Kconfig
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
config DRM_ATMEL_HLCDC
tristate "DRM Support for ATMEL HLCDC Display Controller"
- depends on DRM && OF && COMMON_CLK && MFD_ATMEL_HLCDC && ARM
+ depends on DRM && OF && COMMON_CLK && ((MFD_ATMEL_HLCDC && ARM) || COMPILE_TEST)
select DRM_GEM_DMA_HELPER
select DRM_KMS_HELPER
select DRM_PANEL
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
index cc5cf4c2faf7..0f7ffb3ced20 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
@@ -30,10 +30,12 @@
*
* @base: base CRTC state
* @output_mode: RGBXXX output mode
+ * @dpi: output DPI mode
*/
struct atmel_hlcdc_crtc_state {
struct drm_crtc_state base;
unsigned int output_mode;
+ u8 dpi;
};
static inline struct atmel_hlcdc_crtc_state *
@@ -164,18 +166,24 @@ static void atmel_hlcdc_crtc_mode_set_nofb(struct drm_crtc *c)
state = drm_crtc_state_to_atmel_hlcdc_crtc_state(c->state);
cfg = state->output_mode << 8;
- if (adj->flags & DRM_MODE_FLAG_NVSYNC)
- cfg |= ATMEL_HLCDC_VSPOL;
+ if (!crtc->dc->desc->is_xlcdc) {
+ if (adj->flags & DRM_MODE_FLAG_NVSYNC)
+ cfg |= ATMEL_HLCDC_VSPOL;
- if (adj->flags & DRM_MODE_FLAG_NHSYNC)
- cfg |= ATMEL_HLCDC_HSPOL;
+ if (adj->flags & DRM_MODE_FLAG_NHSYNC)
+ cfg |= ATMEL_HLCDC_HSPOL;
+ } else {
+ cfg |= state->dpi << 11;
+ }
regmap_update_bits(regmap, ATMEL_HLCDC_CFG(5),
ATMEL_HLCDC_HSPOL | ATMEL_HLCDC_VSPOL |
ATMEL_HLCDC_VSPDLYS | ATMEL_HLCDC_VSPDLYE |
ATMEL_HLCDC_DISPPOL | ATMEL_HLCDC_DISPDLY |
ATMEL_HLCDC_VSPSU | ATMEL_HLCDC_VSPHO |
- ATMEL_HLCDC_GUARDTIME_MASK | ATMEL_HLCDC_MODE_MASK,
+ ATMEL_HLCDC_GUARDTIME_MASK |
+ (crtc->dc->desc->is_xlcdc ? ATMEL_XLCDC_MODE_MASK |
+ ATMEL_XLCDC_DPI : ATMEL_HLCDC_MODE_MASK),
cfg);
clk_disable_unprepare(crtc->dc->hlcdc->sys_clk);
@@ -202,20 +210,37 @@ static void atmel_hlcdc_crtc_atomic_disable(struct drm_crtc *c,
pm_runtime_get_sync(dev->dev);
+ if (crtc->dc->desc->is_xlcdc) {
+ regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_XLCDC_CM);
+ if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status,
+ !(status & ATMEL_XLCDC_CM),
+ 10, 1000))
+ dev_warn(dev->dev, "Atmel LCDC status register CMSTS timeout\n");
+
+ regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_XLCDC_SD);
+ if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status,
+ status & ATMEL_XLCDC_SD,
+ 10, 1000))
+ dev_warn(dev->dev, "Atmel LCDC status register SDSTS timeout\n");
+ }
+
regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_HLCDC_DISP);
- while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) &&
- (status & ATMEL_HLCDC_DISP))
- cpu_relax();
+ if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status,
+ !(status & ATMEL_HLCDC_DISP),
+ 10, 1000))
+ dev_warn(dev->dev, "Atmel LCDC status register DISPSTS timeout\n");
regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_HLCDC_SYNC);
- while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) &&
- (status & ATMEL_HLCDC_SYNC))
- cpu_relax();
+ if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status,
+ !(status & ATMEL_HLCDC_SYNC),
+ 10, 1000))
+ dev_warn(dev->dev, "Atmel LCDC status register LCDSTS timeout\n");
regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_HLCDC_PIXEL_CLK);
- while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) &&
- (status & ATMEL_HLCDC_PIXEL_CLK))
- cpu_relax();
+ if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status,
+ !(status & ATMEL_HLCDC_PIXEL_CLK),
+ 10, 1000))
+ dev_warn(dev->dev, "Atmel LCDC status register CLKSTS timeout\n");
clk_disable_unprepare(crtc->dc->hlcdc->sys_clk);
pinctrl_pm_select_sleep_state(dev->dev);
@@ -241,30 +266,95 @@ static void atmel_hlcdc_crtc_atomic_enable(struct drm_crtc *c,
clk_prepare_enable(crtc->dc->hlcdc->sys_clk);
regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_HLCDC_PIXEL_CLK);
- while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) &&
- !(status & ATMEL_HLCDC_PIXEL_CLK))
- cpu_relax();
-
+ if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status,
+ status & ATMEL_HLCDC_PIXEL_CLK,
+ 10, 1000))
+ dev_warn(dev->dev, "Atmel LCDC status register CLKSTS timeout\n");
regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_HLCDC_SYNC);
- while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) &&
- !(status & ATMEL_HLCDC_SYNC))
- cpu_relax();
+ if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status,
+ status & ATMEL_HLCDC_SYNC,
+ 10, 1000))
+ dev_warn(dev->dev, "Atmel LCDC status register LCDSTS timeout\n");
regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_HLCDC_DISP);
- while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) &&
- !(status & ATMEL_HLCDC_DISP))
- cpu_relax();
+ if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status,
+ status & ATMEL_HLCDC_DISP,
+ 10, 1000))
+ dev_warn(dev->dev, "Atmel LCDC status register DISPSTS timeout\n");
+
+ if (crtc->dc->desc->is_xlcdc) {
+ regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_XLCDC_CM);
+ if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status,
+ status & ATMEL_XLCDC_CM,
+ 10, 1000))
+ dev_warn(dev->dev, "Atmel LCDC status register CMSTS timeout\n");
+
+ regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_XLCDC_SD);
+ if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status,
+ !(status & ATMEL_XLCDC_SD),
+ 10, 1000))
+ dev_warn(dev->dev, "Atmel LCDC status register SDSTS timeout\n");
+ }
pm_runtime_put_sync(dev->dev);
}
-#define ATMEL_HLCDC_RGB444_OUTPUT BIT(0)
-#define ATMEL_HLCDC_RGB565_OUTPUT BIT(1)
-#define ATMEL_HLCDC_RGB666_OUTPUT BIT(2)
-#define ATMEL_HLCDC_RGB888_OUTPUT BIT(3)
-#define ATMEL_HLCDC_OUTPUT_MODE_MASK GENMASK(3, 0)
+#define ATMEL_HLCDC_RGB444_OUTPUT BIT(0)
+#define ATMEL_HLCDC_RGB565_OUTPUT BIT(1)
+#define ATMEL_HLCDC_RGB666_OUTPUT BIT(2)
+#define ATMEL_HLCDC_RGB888_OUTPUT BIT(3)
+#define ATMEL_HLCDC_DPI_RGB565C1_OUTPUT BIT(4)
+#define ATMEL_HLCDC_DPI_RGB565C2_OUTPUT BIT(5)
+#define ATMEL_HLCDC_DPI_RGB565C3_OUTPUT BIT(6)
+#define ATMEL_HLCDC_DPI_RGB666C1_OUTPUT BIT(7)
+#define ATMEL_HLCDC_DPI_RGB666C2_OUTPUT BIT(8)
+#define ATMEL_HLCDC_DPI_RGB888_OUTPUT BIT(9)
+#define ATMEL_HLCDC_OUTPUT_MODE_MASK GENMASK(3, 0)
+#define ATMEL_XLCDC_OUTPUT_MODE_MASK GENMASK(9, 0)
+
+static int atmel_xlcdc_connector_output_dsi(struct drm_encoder *encoder,
+ struct drm_display_info *info)
+{
+ int j;
+ unsigned int supported_fmts = 0;
+
+ switch (atmel_hlcdc_encoder_get_bus_fmt(encoder)) {
+ case 0:
+ break;
+ case MEDIA_BUS_FMT_RGB565_1X16:
+ return ATMEL_HLCDC_DPI_RGB565C1_OUTPUT;
+ case MEDIA_BUS_FMT_RGB666_1X18:
+ return ATMEL_HLCDC_DPI_RGB666C1_OUTPUT;
+ case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
+ return ATMEL_HLCDC_DPI_RGB666C2_OUTPUT;
+ case MEDIA_BUS_FMT_RGB888_1X24:
+ return ATMEL_HLCDC_DPI_RGB888_OUTPUT;
+ default:
+ return -EINVAL;
+ }
+
+ for (j = 0; j < info->num_bus_formats; j++) {
+ switch (info->bus_formats[j]) {
+ case MEDIA_BUS_FMT_RGB565_1X16:
+ supported_fmts |= ATMEL_HLCDC_DPI_RGB565C1_OUTPUT;
+ break;
+ case MEDIA_BUS_FMT_RGB666_1X18:
+ supported_fmts |= ATMEL_HLCDC_DPI_RGB666C1_OUTPUT;
+ break;
+ case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
+ supported_fmts |= ATMEL_HLCDC_DPI_RGB666C2_OUTPUT;
+ break;
+ case MEDIA_BUS_FMT_RGB888_1X24:
+ supported_fmts |= ATMEL_HLCDC_DPI_RGB888_OUTPUT;
+ break;
+ default:
+ break;
+ }
+ }
+ return supported_fmts;
+}
static int atmel_hlcdc_connector_output_mode(struct drm_connector_state *state)
{
@@ -277,6 +367,13 @@ static int atmel_hlcdc_connector_output_mode(struct drm_connector_state *state)
encoder = state->best_encoder;
if (!encoder)
encoder = connector->encoder;
+ /*
+ * atmel-hlcdc to support DSI formats with DSI video pipeline
+ * when DRM_MODE_ENCODER_DSI type is set by
+ * connector driver component.
+ */
+ if (encoder->encoder_type == DRM_MODE_ENCODER_DSI)
+ return atmel_xlcdc_connector_output_dsi(encoder, info);
switch (atmel_hlcdc_encoder_get_bus_fmt(encoder)) {
case 0:
@@ -317,7 +414,7 @@ static int atmel_hlcdc_connector_output_mode(struct drm_connector_state *state)
static int atmel_hlcdc_crtc_select_output_mode(struct drm_crtc_state *state)
{
- unsigned int output_fmts = ATMEL_HLCDC_OUTPUT_MODE_MASK;
+ unsigned int output_fmts;
struct atmel_hlcdc_crtc_state *hstate;
struct drm_connector_state *cstate;
struct drm_connector *connector;
@@ -325,6 +422,8 @@ static int atmel_hlcdc_crtc_select_output_mode(struct drm_crtc_state *state)
int i;
crtc = drm_crtc_to_atmel_hlcdc_crtc(state->crtc);
+ output_fmts = crtc->dc->desc->is_xlcdc ? ATMEL_XLCDC_OUTPUT_MODE_MASK :
+ ATMEL_HLCDC_OUTPUT_MODE_MASK;
for_each_new_connector_in_state(state->state, connector, cstate, i) {
unsigned int supported_fmts = 0;
@@ -345,7 +444,15 @@ static int atmel_hlcdc_crtc_select_output_mode(struct drm_crtc_state *state)
hstate = drm_crtc_state_to_atmel_hlcdc_crtc_state(state);
hstate->output_mode = fls(output_fmts) - 1;
-
+ if (crtc->dc->desc->is_xlcdc) {
+ /* check if MIPI DPI bit needs to be set */
+ if (fls(output_fmts) > 3) {
+ hstate->output_mode -= 4;
+ hstate->dpi = 1;
+ } else {
+ hstate->dpi = 0;
+ }
+ }
return 0;
}
@@ -449,6 +556,7 @@ static struct drm_crtc_state *
atmel_hlcdc_crtc_duplicate_state(struct drm_crtc *crtc)
{
struct atmel_hlcdc_crtc_state *state, *cur;
+ struct atmel_hlcdc_crtc *c = drm_crtc_to_atmel_hlcdc_crtc(crtc);
if (WARN_ON(!crtc->state))
return NULL;
@@ -460,6 +568,8 @@ atmel_hlcdc_crtc_duplicate_state(struct drm_crtc *crtc)
cur = drm_crtc_state_to_atmel_hlcdc_crtc_state(crtc->state);
state->output_mode = cur->output_mode;
+ if (c->dc->desc->is_xlcdc)
+ state->dpi = cur->dpi;
return &state->base;
}
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
index 84c54e8622d1..9ce429f889ca 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
@@ -58,6 +58,7 @@ static const struct atmel_hlcdc_dc_desc atmel_hlcdc_dc_at91sam9n12 = {
.conflicting_output_formats = true,
.nlayers = ARRAY_SIZE(atmel_hlcdc_at91sam9n12_layers),
.layers = atmel_hlcdc_at91sam9n12_layers,
+ .ops = &atmel_hlcdc_ops,
};
static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = {
@@ -151,6 +152,7 @@ static const struct atmel_hlcdc_dc_desc atmel_hlcdc_dc_at91sam9x5 = {
.conflicting_output_formats = true,
.nlayers = ARRAY_SIZE(atmel_hlcdc_at91sam9x5_layers),
.layers = atmel_hlcdc_at91sam9x5_layers,
+ .ops = &atmel_hlcdc_ops,
};
static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = {
@@ -269,6 +271,7 @@ static const struct atmel_hlcdc_dc_desc atmel_hlcdc_dc_sama5d3 = {
.conflicting_output_formats = true,
.nlayers = ARRAY_SIZE(atmel_hlcdc_sama5d3_layers),
.layers = atmel_hlcdc_sama5d3_layers,
+ .ops = &atmel_hlcdc_ops,
};
static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d4_layers[] = {
@@ -364,6 +367,7 @@ static const struct atmel_hlcdc_dc_desc atmel_hlcdc_dc_sama5d4 = {
.max_hpw = 0x3ff,
.nlayers = ARRAY_SIZE(atmel_hlcdc_sama5d4_layers),
.layers = atmel_hlcdc_sama5d4_layers,
+ .ops = &atmel_hlcdc_ops,
};
static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sam9x60_layers[] = {
@@ -460,6 +464,103 @@ static const struct atmel_hlcdc_dc_desc atmel_hlcdc_dc_sam9x60 = {
.fixed_clksrc = true,
.nlayers = ARRAY_SIZE(atmel_hlcdc_sam9x60_layers),
.layers = atmel_hlcdc_sam9x60_layers,
+ .ops = &atmel_hlcdc_ops,
+};
+
+static const struct atmel_hlcdc_layer_desc atmel_xlcdc_sam9x75_layers[] = {
+ {
+ .name = "base",
+ .formats = &atmel_hlcdc_plane_rgb_formats,
+ .regs_offset = 0x60,
+ .id = 0,
+ .type = ATMEL_HLCDC_BASE_LAYER,
+ .cfgs_offset = 0x1c,
+ .layout = {
+ .xstride = { 2 },
+ .default_color = 3,
+ .general_config = 4,
+ .disc_pos = 5,
+ .disc_size = 6,
+ },
+ .clut_offset = 0x700,
+ },
+ {
+ .name = "overlay1",
+ .formats = &atmel_hlcdc_plane_rgb_formats,
+ .regs_offset = 0x160,
+ .id = 1,
+ .type = ATMEL_HLCDC_OVERLAY_LAYER,
+ .cfgs_offset = 0x1c,
+ .layout = {
+ .pos = 2,
+ .size = 3,
+ .xstride = { 4 },
+ .pstride = { 5 },
+ .default_color = 6,
+ .chroma_key = 7,
+ .chroma_key_mask = 8,
+ .general_config = 9,
+ },
+ .clut_offset = 0xb00,
+ },
+ {
+ .name = "overlay2",
+ .formats = &atmel_hlcdc_plane_rgb_formats,
+ .regs_offset = 0x260,
+ .id = 2,
+ .type = ATMEL_HLCDC_OVERLAY_LAYER,
+ .cfgs_offset = 0x1c,
+ .layout = {
+ .pos = 2,
+ .size = 3,
+ .xstride = { 4 },
+ .pstride = { 5 },
+ .default_color = 6,
+ .chroma_key = 7,
+ .chroma_key_mask = 8,
+ .general_config = 9,
+ },
+ .clut_offset = 0xf00,
+ },
+ {
+ .name = "high-end-overlay",
+ .formats = &atmel_hlcdc_plane_rgb_and_yuv_formats,
+ .regs_offset = 0x360,
+ .id = 3,
+ .type = ATMEL_HLCDC_OVERLAY_LAYER,
+ .cfgs_offset = 0x30,
+ .layout = {
+ .pos = 2,
+ .size = 3,
+ .memsize = 4,
+ .xstride = { 5, 7 },
+ .pstride = { 6, 8 },
+ .default_color = 9,
+ .chroma_key = 10,
+ .chroma_key_mask = 11,
+ .general_config = 12,
+ .csc = 16,
+ .scaler_config = 23,
+ .vxs_config = 30,
+ .hxs_config = 31,
+ },
+ .clut_offset = 0x1300,
+ },
+};
+
+static const struct atmel_hlcdc_dc_desc atmel_xlcdc_dc_sam9x75 = {
+ .min_width = 0,
+ .min_height = 0,
+ .max_width = 2048,
+ .max_height = 2048,
+ .max_spw = 0x3ff,
+ .max_vpw = 0x3ff,
+ .max_hpw = 0x3ff,
+ .fixed_clksrc = true,
+ .is_xlcdc = true,
+ .nlayers = ARRAY_SIZE(atmel_xlcdc_sam9x75_layers),
+ .layers = atmel_xlcdc_sam9x75_layers,
+ .ops = &atmel_xlcdc_ops,
};
static const struct of_device_id atmel_hlcdc_of_match[] = {
@@ -487,6 +588,10 @@ static const struct of_device_id atmel_hlcdc_of_match[] = {
.compatible = "microchip,sam9x60-hlcdc",
.data = &atmel_hlcdc_dc_sam9x60,
},
+ {
+ .compatible = "microchip,sam9x75-xlcdc",
+ .data = &atmel_xlcdc_dc_sam9x75,
+ },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, atmel_hlcdc_of_match);
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
index 5b5c774e0edf..e1a0bb24b511 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
@@ -15,6 +15,7 @@
#include <drm/drm_plane.h>
+/* LCD controller common registers */
#define ATMEL_HLCDC_LAYER_CHER 0x0
#define ATMEL_HLCDC_LAYER_CHDR 0x4
#define ATMEL_HLCDC_LAYER_CHSR 0x8
@@ -128,6 +129,47 @@
#define ATMEL_HLCDC_MAX_LAYERS 6
+/* XLCDC controller specific registers */
+#define ATMEL_XLCDC_LAYER_ENR 0x10
+#define ATMEL_XLCDC_LAYER_EN BIT(0)
+
+#define ATMEL_XLCDC_LAYER_IER 0x0
+#define ATMEL_XLCDC_LAYER_IDR 0x4
+#define ATMEL_XLCDC_LAYER_ISR 0xc
+#define ATMEL_XLCDC_LAYER_OVR_IRQ(p) BIT(2 + (8 * (p)))
+
+#define ATMEL_XLCDC_LAYER_PLANE_ADDR(p) (((p) * 0x4) + 0x18)
+
+#define ATMEL_XLCDC_LAYER_DMA_CFG 0
+
+#define ATMEL_XLCDC_LAYER_DMA BIT(0)
+#define ATMEL_XLCDC_LAYER_REP BIT(1)
+#define ATMEL_XLCDC_LAYER_DISCEN BIT(4)
+
+#define ATMEL_XLCDC_LAYER_SFACTC_A0_MULT_AS (4 << 6)
+#define ATMEL_XLCDC_LAYER_SFACTA_ONE BIT(9)
+#define ATMEL_XLCDC_LAYER_DFACTC_M_A0_MULT_AS (6 << 11)
+#define ATMEL_XLCDC_LAYER_DFACTA_ONE BIT(14)
+
+#define ATMEL_XLCDC_LAYER_A0_SHIFT 16
+#define ATMEL_XLCDC_LAYER_A0(x) \
+ ((x) << ATMEL_XLCDC_LAYER_A0_SHIFT)
+
+#define ATMEL_XLCDC_LAYER_VSCALER_LUMA_ENABLE BIT(0)
+#define ATMEL_XLCDC_LAYER_VSCALER_CHROMA_ENABLE BIT(1)
+#define ATMEL_XLCDC_LAYER_HSCALER_LUMA_ENABLE BIT(4)
+#define ATMEL_XLCDC_LAYER_HSCALER_CHROMA_ENABLE BIT(5)
+
+#define ATMEL_XLCDC_LAYER_VXSYCFG_ONE BIT(0)
+#define ATMEL_XLCDC_LAYER_VXSYTAP2_ENABLE BIT(4)
+#define ATMEL_XLCDC_LAYER_VXSCCFG_ONE BIT(16)
+#define ATMEL_XLCDC_LAYER_VXSCTAP2_ENABLE BIT(20)
+
+#define ATMEL_XLCDC_LAYER_HXSYCFG_ONE BIT(0)
+#define ATMEL_XLCDC_LAYER_HXSYTAP2_ENABLE BIT(4)
+#define ATMEL_XLCDC_LAYER_HXSCCFG_ONE BIT(16)
+#define ATMEL_XLCDC_LAYER_HXSCTAP2_ENABLE BIT(20)
+
/**
* Atmel HLCDC Layer registers layout structure
*
@@ -156,6 +198,8 @@
* @disc_pos: discard area position register
* @disc_size: discard area size register
* @csc: color space conversion register
+ * @vxs_config: vertical scalar filter taps control register
+ * @hxs_config: horizontal scalar filter taps control register
*/
struct atmel_hlcdc_layer_cfg_layout {
int xstride[ATMEL_HLCDC_LAYER_MAX_PLANES];
@@ -175,6 +219,8 @@ struct atmel_hlcdc_layer_cfg_layout {
int disc_pos;
int disc_size;
int csc;
+ int vxs_config;
+ int hxs_config;
};
/**
@@ -289,6 +335,64 @@ atmel_hlcdc_layer_to_plane(struct atmel_hlcdc_layer *layer)
}
/**
+ * struct atmel_hlcdc_dc - Atmel HLCDC Display Controller.
+ * @desc: HLCDC Display Controller description
+ * @dscrpool: DMA coherent pool used to allocate DMA descriptors
+ * @hlcdc: pointer to the atmel_hlcdc structure provided by the MFD device
+ * @crtc: CRTC provided by the display controller
+ * @layers: active HLCDC layers
+ * @suspend: used to store the HLCDC state when entering suspend
+ * @suspend.imr: used to read/write LCDC Interrupt Mask Register
+ * @suspend.state: Atomic commit structure
+ */
+struct atmel_hlcdc_dc {
+ const struct atmel_hlcdc_dc_desc *desc;
+ struct dma_pool *dscrpool;
+ struct atmel_hlcdc *hlcdc;
+ struct drm_crtc *crtc;
+ struct atmel_hlcdc_layer *layers[ATMEL_HLCDC_MAX_LAYERS];
+ struct {
+ u32 imr;
+ struct drm_atomic_state *state;
+ } suspend;
+};
+
+struct atmel_hlcdc_plane_state;
+
+/**
+ * struct atmel_lcdc_dc_ops - describes atmel_lcdc ops group
+ * to differentiate HLCDC and XLCDC IP code support
+ * @plane_setup_scaler: update the vertical and horizontal scaling factors
+ * @update_lcdc_buffers: update the each LCDC layers DMA registers
+ * @lcdc_atomic_disable: disable LCDC interrupts and layers
+ * @lcdc_update_general_settings: update each LCDC layers general
+ * configuration register
+ * @lcdc_atomic_update: enable the LCDC layers and interrupts
+ * @lcdc_csc_init: update the color space conversion co-efficient of
+ * High-end overlay register
+ * @lcdc_irq_dbg: to raise alert incase of interrupt overrun in any LCDC layer
+ */
+struct atmel_lcdc_dc_ops {
+ void (*plane_setup_scaler)(struct atmel_hlcdc_plane *plane,
+ struct atmel_hlcdc_plane_state *state);
+ void (*lcdc_update_buffers)(struct atmel_hlcdc_plane *plane,
+ struct atmel_hlcdc_plane_state *state,
+ u32 sr, int i);
+ void (*lcdc_atomic_disable)(struct atmel_hlcdc_plane *plane);
+ void (*lcdc_update_general_settings)(struct atmel_hlcdc_plane *plane,
+ struct atmel_hlcdc_plane_state *state);
+ void (*lcdc_atomic_update)(struct atmel_hlcdc_plane *plane,
+ struct atmel_hlcdc_dc *dc);
+ void (*lcdc_csc_init)(struct atmel_hlcdc_plane *plane,
+ const struct atmel_hlcdc_layer_desc *desc);
+ void (*lcdc_irq_dbg)(struct atmel_hlcdc_plane *plane,
+ const struct atmel_hlcdc_layer_desc *desc);
+};
+
+extern const struct atmel_lcdc_dc_ops atmel_hlcdc_ops;
+extern const struct atmel_lcdc_dc_ops atmel_xlcdc_ops;
+
+/**
* Atmel HLCDC Display Controller description structure.
*
* This structure describes the HLCDC IP capabilities and depends on the
@@ -304,8 +408,10 @@ atmel_hlcdc_layer_to_plane(struct atmel_hlcdc_layer *layer)
* @conflicting_output_formats: true if RGBXXX output formats conflict with
* each other.
* @fixed_clksrc: true if clock source is fixed
+ * @is_xlcdc: true if XLCDC IP is supported
* @layers: a layer description table describing available layers
* @nlayers: layer description table size
+ * @ops: atmel lcdc dc ops
*/
struct atmel_hlcdc_dc_desc {
int min_width;
@@ -317,32 +423,10 @@ struct atmel_hlcdc_dc_desc {
int max_hpw;
bool conflicting_output_formats;
bool fixed_clksrc;
+ bool is_xlcdc;
const struct atmel_hlcdc_layer_desc *layers;
int nlayers;
-};
-
-/**
- * Atmel HLCDC Display Controller.
- *
- * @desc: HLCDC Display Controller description
- * @dscrpool: DMA coherent pool used to allocate DMA descriptors
- * @hlcdc: pointer to the atmel_hlcdc structure provided by the MFD device
- * @fbdev: framebuffer device attached to the Display Controller
- * @crtc: CRTC provided by the display controller
- * @planes: instantiated planes
- * @layers: active HLCDC layers
- * @suspend: used to store the HLCDC state when entering suspend
- */
-struct atmel_hlcdc_dc {
- const struct atmel_hlcdc_dc_desc *desc;
- struct dma_pool *dscrpool;
- struct atmel_hlcdc *hlcdc;
- struct drm_crtc *crtc;
- struct atmel_hlcdc_layer *layers[ATMEL_HLCDC_MAX_LAYERS];
- struct {
- u32 imr;
- struct drm_atomic_state *state;
- } suspend;
+ const struct atmel_lcdc_dc_ops *ops;
};
extern struct atmel_hlcdc_formats atmel_hlcdc_plane_rgb_formats;
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
index daa508504f47..4a7ba0918eca 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
@@ -282,8 +282,9 @@ atmel_hlcdc_plane_scaler_set_phicoeff(struct atmel_hlcdc_plane *plane,
coeff_tab[i]);
}
-static void atmel_hlcdc_plane_setup_scaler(struct atmel_hlcdc_plane *plane,
- struct atmel_hlcdc_plane_state *state)
+static
+void atmel_hlcdc_plane_setup_scaler(struct atmel_hlcdc_plane *plane,
+ struct atmel_hlcdc_plane_state *state)
{
const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc;
u32 xfactor, yfactor;
@@ -330,11 +331,61 @@ static void atmel_hlcdc_plane_setup_scaler(struct atmel_hlcdc_plane *plane,
yfactor));
}
+static
+void atmel_xlcdc_plane_setup_scaler(struct atmel_hlcdc_plane *plane,
+ struct atmel_hlcdc_plane_state *state)
+{
+ const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc;
+ u32 xfactor, yfactor;
+
+ if (!desc->layout.scaler_config)
+ return;
+
+ if (state->crtc_w == state->src_w && state->crtc_h == state->src_h) {
+ atmel_hlcdc_layer_write_cfg(&plane->layer,
+ desc->layout.scaler_config, 0);
+ return;
+ }
+
+ /* xfactor = round[(2^20 * XMEMSIZE)/XSIZE)] */
+ xfactor = (u32)(((1 << 20) * state->src_w) / state->crtc_w);
+
+ /* yfactor = round[(2^20 * YMEMSIZE)/YSIZE)] */
+ yfactor = (u32)(((1 << 20) * state->src_h) / state->crtc_h);
+
+ atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.scaler_config,
+ ATMEL_XLCDC_LAYER_VSCALER_LUMA_ENABLE |
+ ATMEL_XLCDC_LAYER_VSCALER_CHROMA_ENABLE |
+ ATMEL_XLCDC_LAYER_HSCALER_LUMA_ENABLE |
+ ATMEL_XLCDC_LAYER_HSCALER_CHROMA_ENABLE);
+
+ atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.scaler_config + 1,
+ yfactor);
+ atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.scaler_config + 3,
+ xfactor);
+
+ /*
+ * With YCbCr 4:2:2 and YCbYcr 4:2:0 window resampling, configuration
+ * register LCDC_HEOCFG25.VXSCFACT and LCDC_HEOCFG27.HXSCFACT is half
+ * the value of yfactor and xfactor.
+ */
+ if (state->base.fb->format->format == DRM_FORMAT_YUV420) {
+ yfactor /= 2;
+ xfactor /= 2;
+ }
+
+ atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.scaler_config + 2,
+ yfactor);
+ atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.scaler_config + 4,
+ xfactor);
+}
+
static void
atmel_hlcdc_plane_update_pos_and_size(struct atmel_hlcdc_plane *plane,
struct atmel_hlcdc_plane_state *state)
{
const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc;
+ struct atmel_hlcdc_dc *dc = plane->base.dev->dev_private;
if (desc->layout.size)
atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.size,
@@ -352,12 +403,12 @@ atmel_hlcdc_plane_update_pos_and_size(struct atmel_hlcdc_plane *plane,
ATMEL_HLCDC_LAYER_POS(state->crtc_x,
state->crtc_y));
- atmel_hlcdc_plane_setup_scaler(plane, state);
+ dc->desc->ops->plane_setup_scaler(plane, state);
}
-static void
-atmel_hlcdc_plane_update_general_settings(struct atmel_hlcdc_plane *plane,
- struct atmel_hlcdc_plane_state *state)
+static
+void atmel_hlcdc_plane_update_general_settings(struct atmel_hlcdc_plane *plane,
+ struct atmel_hlcdc_plane_state *state)
{
unsigned int cfg = ATMEL_HLCDC_LAYER_DMA_BLEN_INCR16 | state->ahb_id;
const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc;
@@ -393,6 +444,40 @@ atmel_hlcdc_plane_update_general_settings(struct atmel_hlcdc_plane *plane,
cfg);
}
+static
+void atmel_xlcdc_plane_update_general_settings(struct atmel_hlcdc_plane *plane,
+ struct atmel_hlcdc_plane_state *state)
+{
+ const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc;
+ const struct drm_format_info *format = state->base.fb->format;
+ unsigned int cfg;
+
+ atmel_hlcdc_layer_write_cfg(&plane->layer, ATMEL_XLCDC_LAYER_DMA_CFG,
+ ATMEL_HLCDC_LAYER_DMA_BLEN_INCR16 | state->ahb_id);
+
+ cfg = ATMEL_XLCDC_LAYER_DMA | ATMEL_XLCDC_LAYER_REP;
+
+ if (plane->base.type != DRM_PLANE_TYPE_PRIMARY) {
+ /*
+ * Alpha Blending bits specific to SAM9X7 SoC
+ */
+ cfg |= ATMEL_XLCDC_LAYER_SFACTC_A0_MULT_AS |
+ ATMEL_XLCDC_LAYER_SFACTA_ONE |
+ ATMEL_XLCDC_LAYER_DFACTC_M_A0_MULT_AS |
+ ATMEL_XLCDC_LAYER_DFACTA_ONE;
+ if (format->has_alpha)
+ cfg |= ATMEL_XLCDC_LAYER_A0(0xff);
+ else
+ cfg |= ATMEL_XLCDC_LAYER_A0(state->base.alpha);
+ }
+
+ if (state->disc_h && state->disc_w)
+ cfg |= ATMEL_XLCDC_LAYER_DISCEN;
+
+ atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.general_config,
+ cfg);
+}
+
static void atmel_hlcdc_plane_update_format(struct atmel_hlcdc_plane *plane,
struct atmel_hlcdc_plane_state *state)
{
@@ -437,36 +522,55 @@ static void atmel_hlcdc_plane_update_clut(struct atmel_hlcdc_plane *plane,
}
}
+static void atmel_hlcdc_update_buffers(struct atmel_hlcdc_plane *plane,
+ struct atmel_hlcdc_plane_state *state,
+ u32 sr, int i)
+{
+ atmel_hlcdc_layer_write_reg(&plane->layer,
+ ATMEL_HLCDC_LAYER_PLANE_HEAD(i),
+ state->dscrs[i]->self);
+
+ if (sr & ATMEL_HLCDC_LAYER_EN)
+ return;
+
+ atmel_hlcdc_layer_write_reg(&plane->layer,
+ ATMEL_HLCDC_LAYER_PLANE_ADDR(i),
+ state->dscrs[i]->addr);
+ atmel_hlcdc_layer_write_reg(&plane->layer,
+ ATMEL_HLCDC_LAYER_PLANE_CTRL(i),
+ state->dscrs[i]->ctrl);
+ atmel_hlcdc_layer_write_reg(&plane->layer,
+ ATMEL_HLCDC_LAYER_PLANE_NEXT(i),
+ state->dscrs[i]->self);
+}
+
+static void atmel_xlcdc_update_buffers(struct atmel_hlcdc_plane *plane,
+ struct atmel_hlcdc_plane_state *state,
+ u32 sr, int i)
+{
+ atmel_hlcdc_layer_write_reg(&plane->layer,
+ ATMEL_XLCDC_LAYER_PLANE_ADDR(i),
+ state->dscrs[i]->addr);
+}
+
static void atmel_hlcdc_plane_update_buffers(struct atmel_hlcdc_plane *plane,
- struct atmel_hlcdc_plane_state *state)
+ struct atmel_hlcdc_plane_state *state)
{
const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc;
+ struct atmel_hlcdc_dc *dc = plane->base.dev->dev_private;
struct drm_framebuffer *fb = state->base.fb;
u32 sr;
int i;
- sr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_CHSR);
+ if (!dc->desc->is_xlcdc)
+ sr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_CHSR);
for (i = 0; i < state->nplanes; i++) {
struct drm_gem_dma_object *gem = drm_fb_dma_get_gem_obj(fb, i);
state->dscrs[i]->addr = gem->dma_addr + state->offsets[i];
- atmel_hlcdc_layer_write_reg(&plane->layer,
- ATMEL_HLCDC_LAYER_PLANE_HEAD(i),
- state->dscrs[i]->self);
-
- if (!(sr & ATMEL_HLCDC_LAYER_EN)) {
- atmel_hlcdc_layer_write_reg(&plane->layer,
- ATMEL_HLCDC_LAYER_PLANE_ADDR(i),
- state->dscrs[i]->addr);
- atmel_hlcdc_layer_write_reg(&plane->layer,
- ATMEL_HLCDC_LAYER_PLANE_CTRL(i),
- state->dscrs[i]->ctrl);
- atmel_hlcdc_layer_write_reg(&plane->layer,
- ATMEL_HLCDC_LAYER_PLANE_NEXT(i),
- state->dscrs[i]->self);
- }
+ dc->desc->ops->lcdc_update_buffers(plane, state, sr, i);
if (desc->layout.xstride[i])
atmel_hlcdc_layer_write_cfg(&plane->layer,
@@ -712,11 +816,8 @@ static int atmel_hlcdc_plane_atomic_check(struct drm_plane *p,
return 0;
}
-static void atmel_hlcdc_plane_atomic_disable(struct drm_plane *p,
- struct drm_atomic_state *state)
+static void atmel_hlcdc_atomic_disable(struct atmel_hlcdc_plane *plane)
{
- struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p);
-
/* Disable interrupts */
atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_HLCDC_LAYER_IDR,
0xffffffff);
@@ -731,6 +832,70 @@ static void atmel_hlcdc_plane_atomic_disable(struct drm_plane *p,
atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_ISR);
}
+static void atmel_xlcdc_atomic_disable(struct atmel_hlcdc_plane *plane)
+{
+ /* Disable interrupts */
+ atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_XLCDC_LAYER_IDR,
+ 0xffffffff);
+
+ /* Disable the layer */
+ atmel_hlcdc_layer_write_reg(&plane->layer,
+ ATMEL_XLCDC_LAYER_ENR, 0);
+
+ /* Clear all pending interrupts */
+ atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_XLCDC_LAYER_ISR);
+}
+
+static void atmel_hlcdc_plane_atomic_disable(struct drm_plane *p,
+ struct drm_atomic_state *state)
+{
+ struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p);
+ struct atmel_hlcdc_dc *dc = plane->base.dev->dev_private;
+
+ dc->desc->ops->lcdc_atomic_disable(plane);
+}
+
+static void atmel_hlcdc_atomic_update(struct atmel_hlcdc_plane *plane,
+ struct atmel_hlcdc_dc *dc)
+{
+ u32 sr;
+
+ /* Enable the overrun interrupts. */
+ atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_HLCDC_LAYER_IER,
+ ATMEL_HLCDC_LAYER_OVR_IRQ(0) |
+ ATMEL_HLCDC_LAYER_OVR_IRQ(1) |
+ ATMEL_HLCDC_LAYER_OVR_IRQ(2));
+
+ /* Apply the new config at the next SOF event. */
+ sr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_CHSR);
+ atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_HLCDC_LAYER_CHER,
+ ATMEL_HLCDC_LAYER_UPDATE |
+ (sr & ATMEL_HLCDC_LAYER_EN ?
+ ATMEL_HLCDC_LAYER_A2Q : ATMEL_HLCDC_LAYER_EN));
+}
+
+static void atmel_xlcdc_atomic_update(struct atmel_hlcdc_plane *plane,
+ struct atmel_hlcdc_dc *dc)
+{
+ /* Enable the overrun interrupts. */
+ atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_XLCDC_LAYER_IER,
+ ATMEL_XLCDC_LAYER_OVR_IRQ(0) |
+ ATMEL_XLCDC_LAYER_OVR_IRQ(1) |
+ ATMEL_XLCDC_LAYER_OVR_IRQ(2));
+
+ atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_XLCDC_LAYER_ENR,
+ ATMEL_XLCDC_LAYER_EN);
+
+ /*
+ * Updating XLCDC_xxxCFGx, XLCDC_xxxFBA and XLCDC_xxxEN,
+ * (where xxx indicates each layer) requires writing one to the
+ * Update Attribute field for each layer in LCDC_ATTRE register for SAM9X7.
+ */
+ regmap_write(dc->hlcdc->regmap, ATMEL_XLCDC_ATTRE, ATMEL_XLCDC_BASE_UPDATE |
+ ATMEL_XLCDC_OVR1_UPDATE | ATMEL_XLCDC_OVR3_UPDATE |
+ ATMEL_XLCDC_HEO_UPDATE);
+}
+
static void atmel_hlcdc_plane_atomic_update(struct drm_plane *p,
struct drm_atomic_state *state)
{
@@ -739,7 +904,7 @@ static void atmel_hlcdc_plane_atomic_update(struct drm_plane *p,
struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p);
struct atmel_hlcdc_plane_state *hstate =
drm_plane_state_to_atmel_hlcdc_plane_state(new_s);
- u32 sr;
+ struct atmel_hlcdc_dc *dc = p->dev->dev_private;
if (!new_s->crtc || !new_s->fb)
return;
@@ -750,29 +915,83 @@ static void atmel_hlcdc_plane_atomic_update(struct drm_plane *p,
}
atmel_hlcdc_plane_update_pos_and_size(plane, hstate);
- atmel_hlcdc_plane_update_general_settings(plane, hstate);
+ dc->desc->ops->lcdc_update_general_settings(plane, hstate);
atmel_hlcdc_plane_update_format(plane, hstate);
atmel_hlcdc_plane_update_clut(plane, hstate);
atmel_hlcdc_plane_update_buffers(plane, hstate);
atmel_hlcdc_plane_update_disc_area(plane, hstate);
- /* Enable the overrun interrupts. */
- atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_HLCDC_LAYER_IER,
- ATMEL_HLCDC_LAYER_OVR_IRQ(0) |
- ATMEL_HLCDC_LAYER_OVR_IRQ(1) |
- ATMEL_HLCDC_LAYER_OVR_IRQ(2));
+ dc->desc->ops->lcdc_atomic_update(plane, dc);
+}
- /* Apply the new config at the next SOF event. */
- sr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_CHSR);
- atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_HLCDC_LAYER_CHER,
- ATMEL_HLCDC_LAYER_UPDATE |
- (sr & ATMEL_HLCDC_LAYER_EN ?
- ATMEL_HLCDC_LAYER_A2Q : ATMEL_HLCDC_LAYER_EN));
+static void atmel_hlcdc_csc_init(struct atmel_hlcdc_plane *plane,
+ const struct atmel_hlcdc_layer_desc *desc)
+{
+ /*
+ * TODO: declare a "yuv-to-rgb-conv-factors" property to let
+ * userspace modify these factors (using a BLOB property ?).
+ */
+ static const u32 hlcdc_csc_coeffs[] = {
+ 0x4c900091,
+ 0x7a5f5090,
+ 0x40040890
+ };
+
+ for (int i = 0; i < ARRAY_SIZE(hlcdc_csc_coeffs); i++) {
+ atmel_hlcdc_layer_write_cfg(&plane->layer,
+ desc->layout.csc + i,
+ hlcdc_csc_coeffs[i]);
+ }
+}
+
+static void atmel_xlcdc_csc_init(struct atmel_hlcdc_plane *plane,
+ const struct atmel_hlcdc_layer_desc *desc)
+{
+ /*
+ * yuv-to-rgb-conv-factors are now defined from LCDC_HEOCFG16 to
+ * LCDC_HEOCFG21 registers in SAM9X7.
+ */
+ static const u32 xlcdc_csc_coeffs[] = {
+ 0x00000488,
+ 0x00000648,
+ 0x1EA00480,
+ 0x00001D28,
+ 0x08100480,
+ 0x00000000,
+ 0x00000007
+ };
+
+ for (int i = 0; i < ARRAY_SIZE(xlcdc_csc_coeffs); i++) {
+ atmel_hlcdc_layer_write_cfg(&plane->layer,
+ desc->layout.csc + i,
+ xlcdc_csc_coeffs[i]);
+ }
+
+ if (desc->layout.vxs_config && desc->layout.hxs_config) {
+ /*
+ * Updating vxs.config and hxs.config fixes the
+ * Green Color Issue in SAM9X7 EGT Video Player App
+ */
+ atmel_hlcdc_layer_write_cfg(&plane->layer,
+ desc->layout.vxs_config,
+ ATMEL_XLCDC_LAYER_VXSYCFG_ONE |
+ ATMEL_XLCDC_LAYER_VXSYTAP2_ENABLE |
+ ATMEL_XLCDC_LAYER_VXSCCFG_ONE |
+ ATMEL_XLCDC_LAYER_VXSCTAP2_ENABLE);
+
+ atmel_hlcdc_layer_write_cfg(&plane->layer,
+ desc->layout.hxs_config,
+ ATMEL_XLCDC_LAYER_HXSYCFG_ONE |
+ ATMEL_XLCDC_LAYER_HXSYTAP2_ENABLE |
+ ATMEL_XLCDC_LAYER_HXSCCFG_ONE |
+ ATMEL_XLCDC_LAYER_HXSCTAP2_ENABLE);
+ }
}
static int atmel_hlcdc_plane_init_properties(struct atmel_hlcdc_plane *plane)
{
const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc;
+ struct atmel_hlcdc_dc *dc = plane->base.dev->dev_private;
if (desc->type == ATMEL_HLCDC_OVERLAY_LAYER ||
desc->type == ATMEL_HLCDC_CURSOR_LAYER) {
@@ -796,31 +1015,16 @@ static int atmel_hlcdc_plane_init_properties(struct atmel_hlcdc_plane *plane)
return ret;
}
- if (desc->layout.csc) {
- /*
- * TODO: decare a "yuv-to-rgb-conv-factors" property to let
- * userspace modify these factors (using a BLOB property ?).
- */
- atmel_hlcdc_layer_write_cfg(&plane->layer,
- desc->layout.csc,
- 0x4c900091);
- atmel_hlcdc_layer_write_cfg(&plane->layer,
- desc->layout.csc + 1,
- 0x7a5f5090);
- atmel_hlcdc_layer_write_cfg(&plane->layer,
- desc->layout.csc + 2,
- 0x40040890);
- }
+ if (desc->layout.csc)
+ dc->desc->ops->lcdc_csc_init(plane, desc);
return 0;
}
-void atmel_hlcdc_plane_irq(struct atmel_hlcdc_plane *plane)
+static void atmel_hlcdc_irq_dbg(struct atmel_hlcdc_plane *plane,
+ const struct atmel_hlcdc_layer_desc *desc)
{
- const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc;
- u32 isr;
-
- isr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_ISR);
+ u32 isr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_ISR);
/*
* There's not much we can do in case of overrun except informing
@@ -834,6 +1038,51 @@ void atmel_hlcdc_plane_irq(struct atmel_hlcdc_plane *plane)
desc->name);
}
+static void atmel_xlcdc_irq_dbg(struct atmel_hlcdc_plane *plane,
+ const struct atmel_hlcdc_layer_desc *desc)
+{
+ u32 isr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_XLCDC_LAYER_ISR);
+
+ /*
+ * There's not much we can do in case of overrun except informing
+ * the user. However, we are in interrupt context here, hence the
+ * use of dev_dbg().
+ */
+ if (isr &
+ (ATMEL_XLCDC_LAYER_OVR_IRQ(0) | ATMEL_XLCDC_LAYER_OVR_IRQ(1) |
+ ATMEL_XLCDC_LAYER_OVR_IRQ(2)))
+ dev_dbg(plane->base.dev->dev, "overrun on plane %s\n",
+ desc->name);
+}
+
+void atmel_hlcdc_plane_irq(struct atmel_hlcdc_plane *plane)
+{
+ const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc;
+ struct atmel_hlcdc_dc *dc = plane->base.dev->dev_private;
+
+ dc->desc->ops->lcdc_irq_dbg(plane, desc);
+}
+
+const struct atmel_lcdc_dc_ops atmel_hlcdc_ops = {
+ .plane_setup_scaler = atmel_hlcdc_plane_setup_scaler,
+ .lcdc_update_buffers = atmel_hlcdc_update_buffers,
+ .lcdc_atomic_disable = atmel_hlcdc_atomic_disable,
+ .lcdc_update_general_settings = atmel_hlcdc_plane_update_general_settings,
+ .lcdc_atomic_update = atmel_hlcdc_atomic_update,
+ .lcdc_csc_init = atmel_hlcdc_csc_init,
+ .lcdc_irq_dbg = atmel_hlcdc_irq_dbg,
+};
+
+const struct atmel_lcdc_dc_ops atmel_xlcdc_ops = {
+ .plane_setup_scaler = atmel_xlcdc_plane_setup_scaler,
+ .lcdc_update_buffers = atmel_xlcdc_update_buffers,
+ .lcdc_atomic_disable = atmel_xlcdc_atomic_disable,
+ .lcdc_update_general_settings = atmel_xlcdc_plane_update_general_settings,
+ .lcdc_atomic_update = atmel_xlcdc_atomic_update,
+ .lcdc_csc_init = atmel_xlcdc_csc_init,
+ .lcdc_irq_dbg = atmel_xlcdc_irq_dbg,
+};
+
static const struct drm_plane_helper_funcs atmel_hlcdc_layer_plane_helper_funcs = {
.atomic_check = atmel_hlcdc_plane_atomic_check,
.atomic_update = atmel_hlcdc_plane_atomic_update,
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511.h b/drivers/gpu/drm/bridge/adv7511/adv7511.h
index ea271f62b214..ec0b7f3d889c 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511.h
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511.h
@@ -401,7 +401,7 @@ struct adv7511 {
#ifdef CONFIG_DRM_I2C_ADV7511_CEC
int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511);
-void adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1);
+int adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1);
#else
static inline int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511)
{
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c b/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c
index 44451a9658a3..2e9c88a2b5ed 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c
@@ -119,7 +119,7 @@ static void adv7511_cec_rx(struct adv7511 *adv7511, int rx_buf)
cec_received_msg(adv7511->cec_adap, &msg);
}
-void adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1)
+int adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1)
{
unsigned int offset = adv7511->info->reg_cec_offset;
const u32 irq_tx_mask = ADV7511_INT1_CEC_TX_READY |
@@ -131,16 +131,19 @@ void adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1)
unsigned int rx_status;
int rx_order[3] = { -1, -1, -1 };
int i;
+ int irq_status = IRQ_NONE;
- if (irq1 & irq_tx_mask)
+ if (irq1 & irq_tx_mask) {
adv_cec_tx_raw_status(adv7511, irq1);
+ irq_status = IRQ_HANDLED;
+ }
if (!(irq1 & irq_rx_mask))
- return;
+ return irq_status;
if (regmap_read(adv7511->regmap_cec,
ADV7511_REG_CEC_RX_STATUS + offset, &rx_status))
- return;
+ return irq_status;
/*
* ADV7511_REG_CEC_RX_STATUS[5:0] contains the reception order of RX
@@ -172,6 +175,8 @@ void adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1)
adv7511_cec_rx(adv7511, rx_buf);
}
+
+ return IRQ_HANDLED;
}
static int adv7511_cec_adap_enable(struct cec_adapter *adap, bool enable)
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
index 66ccb61e2a66..eb5919b38263 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
@@ -469,6 +469,8 @@ static int adv7511_irq_process(struct adv7511 *adv7511, bool process_hpd)
{
unsigned int irq0, irq1;
int ret;
+ int cec_status = IRQ_NONE;
+ int irq_status = IRQ_NONE;
ret = regmap_read(adv7511->regmap, ADV7511_REG_INT(0), &irq0);
if (ret < 0)
@@ -478,29 +480,31 @@ static int adv7511_irq_process(struct adv7511 *adv7511, bool process_hpd)
if (ret < 0)
return ret;
- /* If there is no IRQ to handle, exit indicating no IRQ data */
- if (!(irq0 & (ADV7511_INT0_HPD | ADV7511_INT0_EDID_READY)) &&
- !(irq1 & ADV7511_INT1_DDC_ERROR))
- return -ENODATA;
-
regmap_write(adv7511->regmap, ADV7511_REG_INT(0), irq0);
regmap_write(adv7511->regmap, ADV7511_REG_INT(1), irq1);
- if (process_hpd && irq0 & ADV7511_INT0_HPD && adv7511->bridge.encoder)
+ if (process_hpd && irq0 & ADV7511_INT0_HPD && adv7511->bridge.encoder) {
schedule_work(&adv7511->hpd_work);
+ irq_status = IRQ_HANDLED;
+ }
if (irq0 & ADV7511_INT0_EDID_READY || irq1 & ADV7511_INT1_DDC_ERROR) {
adv7511->edid_read = true;
if (adv7511->i2c_main->irq)
wake_up_all(&adv7511->wq);
+ irq_status = IRQ_HANDLED;
}
#ifdef CONFIG_DRM_I2C_ADV7511_CEC
- adv7511_cec_irq_process(adv7511, irq1);
+ cec_status = adv7511_cec_irq_process(adv7511, irq1);
#endif
- return 0;
+ /* If there is no IRQ to handle, exit indicating no IRQ data */
+ if (irq_status == IRQ_HANDLED || cec_status == IRQ_HANDLED)
+ return IRQ_HANDLED;
+
+ return IRQ_NONE;
}
static irqreturn_t adv7511_irq_handler(int irq, void *devid)
@@ -509,7 +513,7 @@ static irqreturn_t adv7511_irq_handler(int irq, void *devid)
int ret;
ret = adv7511_irq_process(adv7511, true);
- return ret < 0 ? IRQ_NONE : IRQ_HANDLED;
+ return ret < 0 ? IRQ_NONE : ret;
}
/* -----------------------------------------------------------------------------
@@ -877,11 +881,6 @@ static int adv7511_connector_init(struct adv7511 *adv)
struct drm_bridge *bridge = &adv->bridge;
int ret;
- if (!bridge->encoder) {
- DRM_ERROR("Parent encoder object not found");
- return -ENODEV;
- }
-
if (adv->i2c_main->irq)
adv->connector.polled = DRM_CONNECTOR_POLL_HPD;
else
diff --git a/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c b/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c
index c9e35731e6a1..b754947e3e00 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c
@@ -47,7 +47,7 @@ struct anx6345 {
struct drm_dp_aux aux;
struct drm_bridge bridge;
struct i2c_client *client;
- struct edid *edid;
+ const struct drm_edid *drm_edid;
struct drm_connector connector;
struct drm_panel *panel;
struct regulator *dvdd12;
@@ -458,7 +458,7 @@ static int anx6345_get_modes(struct drm_connector *connector)
mutex_lock(&anx6345->lock);
- if (!anx6345->edid) {
+ if (!anx6345->drm_edid) {
if (!anx6345->powered) {
anx6345_poweron(anx6345);
power_off = true;
@@ -470,19 +470,18 @@ static int anx6345_get_modes(struct drm_connector *connector)
goto unlock;
}
- anx6345->edid = drm_get_edid(connector, &anx6345->aux.ddc);
- if (!anx6345->edid)
+ anx6345->drm_edid = drm_edid_read_ddc(connector, &anx6345->aux.ddc);
+ if (!anx6345->drm_edid)
DRM_ERROR("Failed to read EDID from panel\n");
- err = drm_connector_update_edid_property(connector,
- anx6345->edid);
+ err = drm_edid_connector_update(connector, anx6345->drm_edid);
if (err) {
DRM_ERROR("Failed to update EDID property: %d\n", err);
goto unlock;
}
}
- num_modes += drm_add_edid_modes(connector, anx6345->edid);
+ num_modes += drm_edid_connector_add_modes(connector);
/* Driver currently supports only 6bpc */
connector->display_info.bpc = 6;
@@ -528,11 +527,6 @@ static int anx6345_bridge_attach(struct drm_bridge *bridge,
return -EINVAL;
}
- if (!bridge->encoder) {
- DRM_ERROR("Parent encoder object not found");
- return -ENODEV;
- }
-
/* Register aux channel */
anx6345->aux.name = "DP-AUX";
anx6345->aux.dev = &anx6345->client->dev;
@@ -793,7 +787,7 @@ static void anx6345_i2c_remove(struct i2c_client *client)
unregister_i2c_dummy_clients(anx6345);
- kfree(anx6345->edid);
+ drm_edid_free(anx6345->drm_edid);
mutex_destroy(&anx6345->lock);
}
diff --git a/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c b/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c
index 5748a8581af4..f74694bb9c50 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c
@@ -67,7 +67,7 @@ struct anx78xx {
struct drm_dp_aux aux;
struct drm_bridge bridge;
struct i2c_client *client;
- struct edid *edid;
+ const struct drm_edid *drm_edid;
struct drm_connector connector;
struct anx78xx_platform_data pdata;
struct mutex lock;
@@ -830,8 +830,8 @@ static int anx78xx_get_modes(struct drm_connector *connector)
if (WARN_ON(!anx78xx->powered))
return 0;
- if (anx78xx->edid)
- return drm_add_edid_modes(connector, anx78xx->edid);
+ if (anx78xx->drm_edid)
+ return drm_edid_connector_add_modes(connector);
mutex_lock(&anx78xx->lock);
@@ -841,20 +841,21 @@ static int anx78xx_get_modes(struct drm_connector *connector)
goto unlock;
}
- anx78xx->edid = drm_get_edid(connector, &anx78xx->aux.ddc);
- if (!anx78xx->edid) {
+ anx78xx->drm_edid = drm_edid_read_ddc(connector, &anx78xx->aux.ddc);
+
+ err = drm_edid_connector_update(connector, anx78xx->drm_edid);
+
+ if (!anx78xx->drm_edid) {
DRM_ERROR("Failed to read EDID\n");
goto unlock;
}
- err = drm_connector_update_edid_property(connector,
- anx78xx->edid);
if (err) {
DRM_ERROR("Failed to update EDID property: %d\n", err);
goto unlock;
}
- num_modes = drm_add_edid_modes(connector, anx78xx->edid);
+ num_modes = drm_edid_connector_add_modes(connector);
unlock:
mutex_unlock(&anx78xx->lock);
@@ -897,11 +898,6 @@ static int anx78xx_bridge_attach(struct drm_bridge *bridge,
return -EINVAL;
}
- if (!bridge->encoder) {
- DRM_ERROR("Parent encoder object not found");
- return -ENODEV;
- }
-
/* Register aux channel */
anx78xx->aux.name = "DP-AUX";
anx78xx->aux.dev = &anx78xx->client->dev;
@@ -1091,8 +1087,8 @@ static bool anx78xx_handle_common_int_4(struct anx78xx *anx78xx, u8 irq)
event = true;
anx78xx_poweroff(anx78xx);
/* Free cached EDID */
- kfree(anx78xx->edid);
- anx78xx->edid = NULL;
+ drm_edid_free(anx78xx->drm_edid);
+ anx78xx->drm_edid = NULL;
} else if (irq & SP_HPD_PLUG) {
DRM_DEBUG_KMS("IRQ: Hot plug detect - cable plug\n");
event = true;
@@ -1363,7 +1359,7 @@ static void anx78xx_i2c_remove(struct i2c_client *client)
unregister_i2c_dummy_clients(anx78xx);
- kfree(anx78xx->edid);
+ drm_edid_free(anx78xx->drm_edid);
}
static const struct of_device_id anx78xx_match_table[] = {
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index df9370e0ff23..ddf1e4424ffd 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -41,10 +41,8 @@ struct bridge_init {
struct device_node *node;
};
-static int analogix_dp_init_dp(struct analogix_dp_device *dp)
+static void analogix_dp_init_dp(struct analogix_dp_device *dp)
{
- int ret;
-
analogix_dp_reset(dp);
analogix_dp_swreset(dp);
@@ -56,13 +54,9 @@ static int analogix_dp_init_dp(struct analogix_dp_device *dp)
analogix_dp_enable_sw_function(dp);
analogix_dp_config_interrupt(dp);
- ret = analogix_dp_init_analog_func(dp);
- if (ret)
- return ret;
analogix_dp_init_hpd(dp);
analogix_dp_init_aux(dp);
- return 0;
}
static int analogix_dp_detect_hpd(struct analogix_dp_device *dp)
@@ -234,32 +228,10 @@ static int analogix_dp_training_pattern_dis(struct analogix_dp_device *dp)
return ret < 0 ? ret : 0;
}
-static void
-analogix_dp_set_lane_lane_pre_emphasis(struct analogix_dp_device *dp,
- int pre_emphasis, int lane)
-{
- switch (lane) {
- case 0:
- analogix_dp_set_lane0_pre_emphasis(dp, pre_emphasis);
- break;
- case 1:
- analogix_dp_set_lane1_pre_emphasis(dp, pre_emphasis);
- break;
-
- case 2:
- analogix_dp_set_lane2_pre_emphasis(dp, pre_emphasis);
- break;
-
- case 3:
- analogix_dp_set_lane3_pre_emphasis(dp, pre_emphasis);
- break;
- }
-}
-
static int analogix_dp_link_start(struct analogix_dp_device *dp)
{
u8 buf[4];
- int lane, lane_count, pll_tries, retval;
+ int lane, lane_count, retval;
lane_count = dp->link_train.lane_count;
@@ -271,6 +243,16 @@ static int analogix_dp_link_start(struct analogix_dp_device *dp)
/* Set link rate and count as you want to establish*/
analogix_dp_set_link_bandwidth(dp, dp->link_train.link_rate);
+ retval = analogix_dp_wait_pll_locked(dp);
+ if (retval) {
+ DRM_DEV_ERROR(dp->dev, "Wait for pll lock failed %d\n", retval);
+ return retval;
+ }
+ /*
+ * MACRO_RST must be applied after the PLL_LOCK to avoid
+ * the DP inter pair skew issue for at least 10 us
+ */
+ analogix_dp_reset_macro(dp);
analogix_dp_set_lane_count(dp, dp->link_train.lane_count);
/* Setup RX configuration */
@@ -286,22 +268,12 @@ static int analogix_dp_link_start(struct analogix_dp_device *dp)
return retval;
}
- /* Set TX pre-emphasis to minimum */
+ /* Set TX voltage-swing and pre-emphasis to minimum */
for (lane = 0; lane < lane_count; lane++)
- analogix_dp_set_lane_lane_pre_emphasis(dp,
- PRE_EMPHASIS_LEVEL_0, lane);
-
- /* Wait for PLL lock */
- pll_tries = 0;
- while (analogix_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
- if (pll_tries == DP_TIMEOUT_LOOP_COUNT) {
- dev_err(dp->dev, "Wait for PLL lock timed out\n");
- return -ETIMEDOUT;
- }
-
- pll_tries++;
- usleep_range(90, 120);
- }
+ dp->link_train.training_lane[lane] =
+ DP_TRAIN_VOLTAGE_SWING_LEVEL_0 |
+ DP_TRAIN_PRE_EMPH_LEVEL_0;
+ analogix_dp_set_lane_link_training(dp);
/* Set training pattern 1 */
analogix_dp_set_training_pattern(dp, TRAINING_PTN1);
@@ -384,54 +356,6 @@ static unsigned char analogix_dp_get_adjust_request_pre_emphasis(
return ((link_value >> shift) & 0xc) >> 2;
}
-static void analogix_dp_set_lane_link_training(struct analogix_dp_device *dp,
- u8 training_lane_set, int lane)
-{
- switch (lane) {
- case 0:
- analogix_dp_set_lane0_link_training(dp, training_lane_set);
- break;
- case 1:
- analogix_dp_set_lane1_link_training(dp, training_lane_set);
- break;
-
- case 2:
- analogix_dp_set_lane2_link_training(dp, training_lane_set);
- break;
-
- case 3:
- analogix_dp_set_lane3_link_training(dp, training_lane_set);
- break;
- }
-}
-
-static unsigned int
-analogix_dp_get_lane_link_training(struct analogix_dp_device *dp,
- int lane)
-{
- u32 reg;
-
- switch (lane) {
- case 0:
- reg = analogix_dp_get_lane0_link_training(dp);
- break;
- case 1:
- reg = analogix_dp_get_lane1_link_training(dp);
- break;
- case 2:
- reg = analogix_dp_get_lane2_link_training(dp);
- break;
- case 3:
- reg = analogix_dp_get_lane3_link_training(dp);
- break;
- default:
- WARN_ON(1);
- return 0;
- }
-
- return reg;
-}
-
static void analogix_dp_reduce_link_rate(struct analogix_dp_device *dp)
{
analogix_dp_training_pattern_dis(dp);
@@ -478,11 +402,6 @@ static int analogix_dp_process_clock_recovery(struct analogix_dp_device *dp)
if (retval < 0)
return retval;
- retval = drm_dp_dpcd_read(&dp->aux, DP_ADJUST_REQUEST_LANE0_1,
- adjust_request, 2);
- if (retval < 0)
- return retval;
-
if (analogix_dp_clock_recovery_ok(link_status, lane_count) == 0) {
/* set training pattern 2 for EQ */
analogix_dp_set_training_pattern(dp, TRAINING_PTN2);
@@ -495,38 +414,37 @@ static int analogix_dp_process_clock_recovery(struct analogix_dp_device *dp)
dev_dbg(dp->dev, "Link Training Clock Recovery success\n");
dp->link_train.lt_state = EQUALIZER_TRAINING;
- } else {
- 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);
-
- if (DPCD_VOLTAGE_SWING_GET(training_lane) ==
- voltage_swing &&
- DPCD_PRE_EMPHASIS_GET(training_lane) ==
- pre_emphasis)
- dp->link_train.cr_loop[lane]++;
-
- if (dp->link_train.cr_loop[lane] == MAX_CR_LOOP ||
- voltage_swing == VOLTAGE_LEVEL_3 ||
- pre_emphasis == PRE_EMPHASIS_LEVEL_3) {
- dev_err(dp->dev, "CR Max reached (%d,%d,%d)\n",
- dp->link_train.cr_loop[lane],
- voltage_swing, pre_emphasis);
- analogix_dp_reduce_link_rate(dp);
- return -EIO;
- }
+
+ 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);
+
+ if (DPCD_VOLTAGE_SWING_GET(training_lane) == voltage_swing &&
+ DPCD_PRE_EMPHASIS_GET(training_lane) == pre_emphasis)
+ dp->link_train.cr_loop[lane]++;
+
+ if (dp->link_train.cr_loop[lane] == MAX_CR_LOOP ||
+ voltage_swing == VOLTAGE_LEVEL_3 ||
+ pre_emphasis == PRE_EMPHASIS_LEVEL_3) {
+ dev_err(dp->dev, "CR Max reached (%d,%d,%d)\n",
+ dp->link_train.cr_loop[lane],
+ voltage_swing, pre_emphasis);
+ analogix_dp_reduce_link_rate(dp);
+ return -EIO;
}
}
analogix_dp_get_adjust_training_lane(dp, adjust_request);
-
- for (lane = 0; lane < lane_count; lane++)
- analogix_dp_set_lane_link_training(dp,
- dp->link_train.training_lane[lane], lane);
+ analogix_dp_set_lane_link_training(dp);
retval = drm_dp_dpcd_write(&dp->aux, DP_TRAINING_LANE0_SET,
dp->link_train.training_lane, lane_count);
@@ -538,7 +456,7 @@ static int analogix_dp_process_clock_recovery(struct analogix_dp_device *dp)
static int analogix_dp_process_equalizer_training(struct analogix_dp_device *dp)
{
- int lane, lane_count, retval;
+ int lane_count, retval;
u32 reg;
u8 link_align, link_status[2], adjust_request[2];
@@ -598,9 +516,7 @@ static int analogix_dp_process_equalizer_training(struct analogix_dp_device *dp)
return -EIO;
}
- for (lane = 0; lane < lane_count; lane++)
- analogix_dp_set_lane_link_training(dp,
- dp->link_train.training_lane[lane], lane);
+ analogix_dp_set_lane_link_training(dp);
retval = drm_dp_dpcd_write(&dp->aux, DP_TRAINING_LANE0_SET,
dp->link_train.training_lane, lane_count);
@@ -644,12 +560,6 @@ static int analogix_dp_full_link_train(struct analogix_dp_device *dp,
int retval = 0;
bool training_finished = false;
- /*
- * MACRO_RST must be applied after the PLL_LOCK to avoid
- * the DP inter pair skew issue for at least 10 us
- */
- analogix_dp_reset_macro(dp);
-
/* Initialize by reading RX's DPCD */
analogix_dp_get_max_rx_bandwidth(dp, &dp->link_train.link_rate);
analogix_dp_get_max_rx_lane_count(dp, &dp->link_train.lane_count);
@@ -712,28 +622,24 @@ 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 i, ret;
+ int ret;
u8 link_align, link_status[2];
- enum pll_status status;
-
- analogix_dp_reset_macro(dp);
analogix_dp_set_link_bandwidth(dp, dp->link_train.link_rate);
- analogix_dp_set_lane_count(dp, dp->link_train.lane_count);
-
- for (i = 0; i < dp->link_train.lane_count; i++) {
- analogix_dp_set_lane_link_training(dp,
- dp->link_train.training_lane[i], i);
- }
-
- ret = readx_poll_timeout(analogix_dp_get_pll_lock_status, dp, status,
- status != PLL_UNLOCKED, 120,
- 120 * DP_TIMEOUT_LOOP_COUNT);
+ ret = analogix_dp_wait_pll_locked(dp);
if (ret) {
DRM_DEV_ERROR(dp->dev, "Wait for pll lock failed %d\n", ret);
return ret;
}
+ /*
+ * MACRO_RST must be applied after the PLL_LOCK to avoid
+ * the DP inter pair skew issue for at least 10 us
+ */
+ analogix_dp_reset_macro(dp);
+ analogix_dp_set_lane_count(dp, dp->link_train.lane_count);
+ analogix_dp_set_lane_link_training(dp);
+
/* source Set training pattern 1 */
analogix_dp_set_training_pattern(dp, TRAINING_PTN1);
/* From DP spec, pattern must be on-screen for a minimum 500us */
@@ -803,11 +709,6 @@ static int analogix_dp_config_video(struct analogix_dp_device *dp)
analogix_dp_set_video_color_format(dp);
- if (analogix_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
- dev_err(dp->dev, "PLL is not locked yet.\n");
- return -EINVAL;
- }
-
for (;;) {
timeout_loop++;
if (analogix_dp_is_slave_video_stream_clock_on(dp) == 0)
@@ -1108,7 +1009,7 @@ out:
static int analogix_dp_get_modes(struct drm_connector *connector)
{
struct analogix_dp_device *dp = to_dp(connector);
- struct edid *edid;
+ const struct drm_edid *drm_edid;
int ret, num_modes = 0;
if (dp->plat_data->panel) {
@@ -1120,12 +1021,13 @@ static int analogix_dp_get_modes(struct drm_connector *connector)
return 0;
}
- edid = drm_get_edid(connector, &dp->aux.ddc);
- if (edid) {
- drm_connector_update_edid_property(&dp->connector,
- edid);
- num_modes += drm_add_edid_modes(&dp->connector, edid);
- kfree(edid);
+ drm_edid = drm_edid_read_ddc(connector, &dp->aux.ddc);
+
+ drm_edid_connector_update(&dp->connector, drm_edid);
+
+ if (drm_edid) {
+ num_modes += drm_edid_connector_add_modes(&dp->connector);
+ drm_edid_free(drm_edid);
}
ret = analogix_dp_prepare_panel(dp, false, false);
@@ -1228,11 +1130,6 @@ static int analogix_dp_bridge_attach(struct drm_bridge *bridge,
return -EINVAL;
}
- if (!bridge->encoder) {
- DRM_ERROR("Parent encoder object not found");
- return -ENODEV;
- }
-
if (!dp->plat_data->skip_connector) {
connector = &dp->connector;
connector->polled = DRM_CONNECTOR_POLL_HPD;
@@ -1335,20 +1232,9 @@ static int analogix_dp_set_bridge(struct analogix_dp_device *dp)
pm_runtime_get_sync(dp->dev);
- ret = clk_prepare_enable(dp->clock);
- if (ret < 0) {
- DRM_ERROR("Failed to prepare_enable the clock clk [%d]\n", ret);
- goto out_dp_clk_pre;
- }
-
- if (dp->plat_data->power_on_start)
- dp->plat_data->power_on_start(dp->plat_data);
-
- phy_power_on(dp->phy);
-
- ret = analogix_dp_init_dp(dp);
+ ret = analogix_dp_init_analog_func(dp);
if (ret)
- goto out_dp_init;
+ return ret;
/*
* According to DP spec v1.3 chap 3.5.1.2 Link Training,
@@ -1367,18 +1253,10 @@ static int analogix_dp_set_bridge(struct analogix_dp_device *dp)
goto out_dp_init;
}
- if (dp->plat_data->power_on_end)
- dp->plat_data->power_on_end(dp->plat_data);
-
enable_irq(dp->irq);
return 0;
out_dp_init:
- phy_power_off(dp->phy);
- if (dp->plat_data->power_off)
- dp->plat_data->power_off(dp->plat_data);
- clk_disable_unprepare(dp->clock);
-out_dp_clk_pre:
pm_runtime_put_sync(dp->dev);
return ret;
@@ -1441,13 +1319,7 @@ static void analogix_dp_bridge_disable(struct drm_bridge *bridge)
disable_irq(dp->irq);
- if (dp->plat_data->power_off)
- dp->plat_data->power_off(dp->plat_data);
-
analogix_dp_set_analog_power_down(dp, POWER_ALL, 1);
- phy_power_off(dp->phy);
-
- clk_disable_unprepare(dp->clock);
pm_runtime_put_sync(dp->dev);
@@ -1738,8 +1610,6 @@ analogix_dp_probe(struct device *dev, struct analogix_dp_plat_data *plat_data)
return ERR_CAST(dp->clock);
}
- clk_prepare_enable(dp->clock);
-
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
dp->reg_base = devm_ioremap_resource(&pdev->dev, res);
@@ -1801,6 +1671,40 @@ err_disable_clk:
}
EXPORT_SYMBOL_GPL(analogix_dp_probe);
+int analogix_dp_suspend(struct analogix_dp_device *dp)
+{
+ phy_power_off(dp->phy);
+
+ if (dp->plat_data->power_off)
+ dp->plat_data->power_off(dp->plat_data);
+
+ clk_disable_unprepare(dp->clock);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(analogix_dp_suspend);
+
+int analogix_dp_resume(struct analogix_dp_device *dp)
+{
+ int ret;
+
+ ret = clk_prepare_enable(dp->clock);
+ if (ret < 0) {
+ DRM_ERROR("Failed to prepare_enable the clock clk [%d]\n", ret);
+ return ret;
+ }
+
+ if (dp->plat_data->power_on)
+ dp->plat_data->power_on(dp->plat_data);
+
+ phy_power_on(dp->phy);
+
+ analogix_dp_init_dp(dp);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(analogix_dp_resume);
+
int analogix_dp_bind(struct analogix_dp_device *dp, struct drm_device *drm_dev)
{
int ret;
@@ -1808,31 +1712,44 @@ int analogix_dp_bind(struct analogix_dp_device *dp, struct drm_device *drm_dev)
dp->drm_dev = drm_dev;
dp->encoder = dp->plat_data->encoder;
+ if (IS_ENABLED(CONFIG_PM)) {
+ pm_runtime_use_autosuspend(dp->dev);
+ pm_runtime_set_autosuspend_delay(dp->dev, 100);
+ pm_runtime_enable(dp->dev);
+ } else {
+ ret = analogix_dp_resume(dp);
+ if (ret)
+ return ret;
+ }
+
dp->aux.name = "DP-AUX";
dp->aux.transfer = analogix_dpaux_transfer;
dp->aux.dev = dp->dev;
dp->aux.drm_dev = drm_dev;
ret = drm_dp_aux_register(&dp->aux);
- if (ret)
- return ret;
-
- pm_runtime_use_autosuspend(dp->dev);
- pm_runtime_set_autosuspend_delay(dp->dev, 100);
- pm_runtime_enable(dp->dev);
+ if (ret) {
+ DRM_ERROR("failed to register AUX (%d)\n", ret);
+ goto err_disable_pm_runtime;
+ }
ret = analogix_dp_create_bridge(drm_dev, dp);
if (ret) {
DRM_ERROR("failed to create bridge (%d)\n", ret);
- goto err_disable_pm_runtime;
+ goto err_unregister_aux;
}
return 0;
-err_disable_pm_runtime:
- pm_runtime_dont_use_autosuspend(dp->dev);
- pm_runtime_disable(dp->dev);
+err_unregister_aux:
drm_dp_aux_unregister(&dp->aux);
+err_disable_pm_runtime:
+ if (IS_ENABLED(CONFIG_PM)) {
+ pm_runtime_dont_use_autosuspend(dp->dev);
+ pm_runtime_disable(dp->dev);
+ } else {
+ analogix_dp_suspend(dp);
+ }
return ret;
}
@@ -1849,39 +1766,15 @@ void analogix_dp_unbind(struct analogix_dp_device *dp)
}
drm_dp_aux_unregister(&dp->aux);
- pm_runtime_dont_use_autosuspend(dp->dev);
- pm_runtime_disable(dp->dev);
-}
-EXPORT_SYMBOL_GPL(analogix_dp_unbind);
-void analogix_dp_remove(struct analogix_dp_device *dp)
-{
- clk_disable_unprepare(dp->clock);
-}
-EXPORT_SYMBOL_GPL(analogix_dp_remove);
-
-#ifdef CONFIG_PM
-int analogix_dp_suspend(struct analogix_dp_device *dp)
-{
- clk_disable_unprepare(dp->clock);
- return 0;
-}
-EXPORT_SYMBOL_GPL(analogix_dp_suspend);
-
-int analogix_dp_resume(struct analogix_dp_device *dp)
-{
- int ret;
-
- ret = clk_prepare_enable(dp->clock);
- if (ret < 0) {
- DRM_ERROR("Failed to prepare_enable the clock clk [%d]\n", ret);
- return ret;
+ if (IS_ENABLED(CONFIG_PM)) {
+ pm_runtime_dont_use_autosuspend(dp->dev);
+ pm_runtime_disable(dp->dev);
+ } else {
+ analogix_dp_suspend(dp);
}
-
- return 0;
}
-EXPORT_SYMBOL_GPL(analogix_dp_resume);
-#endif
+EXPORT_SYMBOL_GPL(analogix_dp_unbind);
int analogix_dp_start_crc(struct drm_connector *connector)
{
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
index 433f2d7efa0c..774d11574b09 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
@@ -95,11 +95,6 @@ enum dynamic_range {
CEA
};
-enum pll_status {
- PLL_UNLOCKED,
- PLL_LOCKED
-};
-
enum clock_recovery_m_value_type {
CALCULATED_M,
REGISTER_M
@@ -191,7 +186,7 @@ void analogix_dp_swreset(struct analogix_dp_device *dp);
void analogix_dp_config_interrupt(struct analogix_dp_device *dp);
void analogix_dp_mute_hpd_interrupt(struct analogix_dp_device *dp);
void analogix_dp_unmute_hpd_interrupt(struct analogix_dp_device *dp);
-enum pll_status analogix_dp_get_pll_lock_status(struct analogix_dp_device *dp);
+int analogix_dp_wait_pll_locked(struct analogix_dp_device *dp);
void analogix_dp_set_pll_power_down(struct analogix_dp_device *dp, bool enable);
void analogix_dp_set_analog_power_down(struct analogix_dp_device *dp,
enum analog_power_block block,
@@ -213,26 +208,8 @@ void analogix_dp_enable_enhanced_mode(struct analogix_dp_device *dp,
bool enable);
void analogix_dp_set_training_pattern(struct analogix_dp_device *dp,
enum pattern_set pattern);
-void analogix_dp_set_lane0_pre_emphasis(struct analogix_dp_device *dp,
- u32 level);
-void analogix_dp_set_lane1_pre_emphasis(struct analogix_dp_device *dp,
- u32 level);
-void analogix_dp_set_lane2_pre_emphasis(struct analogix_dp_device *dp,
- u32 level);
-void analogix_dp_set_lane3_pre_emphasis(struct analogix_dp_device *dp,
- u32 level);
-void analogix_dp_set_lane0_link_training(struct analogix_dp_device *dp,
- u32 training_lane);
-void analogix_dp_set_lane1_link_training(struct analogix_dp_device *dp,
- u32 training_lane);
-void analogix_dp_set_lane2_link_training(struct analogix_dp_device *dp,
- u32 training_lane);
-void analogix_dp_set_lane3_link_training(struct analogix_dp_device *dp,
- u32 training_lane);
-u32 analogix_dp_get_lane0_link_training(struct analogix_dp_device *dp);
-u32 analogix_dp_get_lane1_link_training(struct analogix_dp_device *dp);
-u32 analogix_dp_get_lane2_link_training(struct analogix_dp_device *dp);
-u32 analogix_dp_get_lane3_link_training(struct analogix_dp_device *dp);
+void analogix_dp_set_lane_link_training(struct analogix_dp_device *dp);
+u32 analogix_dp_get_lane_link_training(struct analogix_dp_device *dp, u8 lane);
void analogix_dp_reset_macro(struct analogix_dp_device *dp);
void analogix_dp_init_video(struct analogix_dp_device *dp);
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
index 6a4f20fccf84..3afc73c858c4 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
@@ -217,15 +217,13 @@ void analogix_dp_unmute_hpd_interrupt(struct analogix_dp_device *dp)
writel(reg, dp->reg_base + ANALOGIX_DP_INT_STA_MASK);
}
-enum pll_status analogix_dp_get_pll_lock_status(struct analogix_dp_device *dp)
+int analogix_dp_wait_pll_locked(struct analogix_dp_device *dp)
{
- u32 reg;
+ u32 val;
- reg = readl(dp->reg_base + ANALOGIX_DP_DEBUG_CTL);
- if (reg & PLL_LOCK)
- return PLL_LOCKED;
- else
- return PLL_UNLOCKED;
+ return readl_poll_timeout(dp->reg_base + ANALOGIX_DP_DEBUG_CTL, val,
+ val & PLL_LOCK, 120,
+ 120 * DP_TIMEOUT_LOOP_COUNT);
}
void analogix_dp_set_pll_power_down(struct analogix_dp_device *dp, bool enable)
@@ -356,7 +354,6 @@ void analogix_dp_set_analog_power_down(struct analogix_dp_device *dp,
int analogix_dp_init_analog_func(struct analogix_dp_device *dp)
{
u32 reg;
- int timeout_loop = 0;
analogix_dp_set_analog_power_down(dp, POWER_ALL, 0);
@@ -368,18 +365,7 @@ int analogix_dp_init_analog_func(struct analogix_dp_device *dp)
writel(reg, dp->reg_base + ANALOGIX_DP_DEBUG_CTL);
/* Power up PLL */
- if (analogix_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
- analogix_dp_set_pll_power_down(dp, 0);
-
- while (analogix_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
- timeout_loop++;
- if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
- dev_err(dp->dev, "failed to get pll lock status\n");
- return -ETIMEDOUT;
- }
- usleep_range(10, 20);
- }
- }
+ analogix_dp_set_pll_power_down(dp, 0);
/* Enable Serdes FIFO function and Link symbol clock domain module */
reg = readl(dp->reg_base + ANALOGIX_DP_FUNC_EN_2);
@@ -557,6 +543,20 @@ void analogix_dp_get_lane_count(struct analogix_dp_device *dp, u32 *count)
*count = reg;
}
+void analogix_dp_set_lane_link_training(struct analogix_dp_device *dp)
+{
+ u8 lane;
+
+ for (lane = 0; lane < dp->link_train.lane_count; lane++)
+ writel(dp->link_train.training_lane[lane],
+ dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL + 4 * lane);
+}
+
+u32 analogix_dp_get_lane_link_training(struct analogix_dp_device *dp, u8 lane)
+{
+ return readl(dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL + 4 * lane);
+}
+
void analogix_dp_enable_enhanced_mode(struct analogix_dp_device *dp,
bool enable)
{
@@ -606,106 +606,6 @@ void analogix_dp_set_training_pattern(struct analogix_dp_device *dp,
}
}
-void analogix_dp_set_lane0_pre_emphasis(struct analogix_dp_device *dp,
- u32 level)
-{
- u32 reg;
-
- reg = readl(dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL);
- reg &= ~PRE_EMPHASIS_SET_MASK;
- reg |= level << PRE_EMPHASIS_SET_SHIFT;
- writel(reg, dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL);
-}
-
-void analogix_dp_set_lane1_pre_emphasis(struct analogix_dp_device *dp,
- u32 level)
-{
- u32 reg;
-
- reg = readl(dp->reg_base + ANALOGIX_DP_LN1_LINK_TRAINING_CTL);
- reg &= ~PRE_EMPHASIS_SET_MASK;
- reg |= level << PRE_EMPHASIS_SET_SHIFT;
- writel(reg, dp->reg_base + ANALOGIX_DP_LN1_LINK_TRAINING_CTL);
-}
-
-void analogix_dp_set_lane2_pre_emphasis(struct analogix_dp_device *dp,
- u32 level)
-{
- u32 reg;
-
- reg = readl(dp->reg_base + ANALOGIX_DP_LN2_LINK_TRAINING_CTL);
- reg &= ~PRE_EMPHASIS_SET_MASK;
- reg |= level << PRE_EMPHASIS_SET_SHIFT;
- writel(reg, dp->reg_base + ANALOGIX_DP_LN2_LINK_TRAINING_CTL);
-}
-
-void analogix_dp_set_lane3_pre_emphasis(struct analogix_dp_device *dp,
- u32 level)
-{
- u32 reg;
-
- reg = readl(dp->reg_base + ANALOGIX_DP_LN3_LINK_TRAINING_CTL);
- reg &= ~PRE_EMPHASIS_SET_MASK;
- reg |= level << PRE_EMPHASIS_SET_SHIFT;
- writel(reg, dp->reg_base + ANALOGIX_DP_LN3_LINK_TRAINING_CTL);
-}
-
-void analogix_dp_set_lane0_link_training(struct analogix_dp_device *dp,
- u32 training_lane)
-{
- u32 reg;
-
- reg = training_lane;
- writel(reg, dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL);
-}
-
-void analogix_dp_set_lane1_link_training(struct analogix_dp_device *dp,
- u32 training_lane)
-{
- u32 reg;
-
- reg = training_lane;
- writel(reg, dp->reg_base + ANALOGIX_DP_LN1_LINK_TRAINING_CTL);
-}
-
-void analogix_dp_set_lane2_link_training(struct analogix_dp_device *dp,
- u32 training_lane)
-{
- u32 reg;
-
- reg = training_lane;
- writel(reg, dp->reg_base + ANALOGIX_DP_LN2_LINK_TRAINING_CTL);
-}
-
-void analogix_dp_set_lane3_link_training(struct analogix_dp_device *dp,
- u32 training_lane)
-{
- u32 reg;
-
- reg = training_lane;
- writel(reg, dp->reg_base + ANALOGIX_DP_LN3_LINK_TRAINING_CTL);
-}
-
-u32 analogix_dp_get_lane0_link_training(struct analogix_dp_device *dp)
-{
- return readl(dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL);
-}
-
-u32 analogix_dp_get_lane1_link_training(struct analogix_dp_device *dp)
-{
- return readl(dp->reg_base + ANALOGIX_DP_LN1_LINK_TRAINING_CTL);
-}
-
-u32 analogix_dp_get_lane2_link_training(struct analogix_dp_device *dp)
-{
- return readl(dp->reg_base + ANALOGIX_DP_LN2_LINK_TRAINING_CTL);
-}
-
-u32 analogix_dp_get_lane3_link_training(struct analogix_dp_device *dp)
-{
- return readl(dp->reg_base + ANALOGIX_DP_LN3_LINK_TRAINING_CTL);
-}
-
void analogix_dp_reset_macro(struct analogix_dp_device *dp)
{
u32 reg;
@@ -1024,10 +924,8 @@ ssize_t analogix_dp_transfer(struct analogix_dp_device *dp,
struct drm_dp_aux_msg *msg)
{
u32 reg;
- u32 status_reg;
u8 *buffer = msg->buffer;
unsigned int i;
- int num_transferred = 0;
int ret;
/* Buffer size of AUX CH is 16 bytes */
@@ -1079,7 +977,6 @@ ssize_t analogix_dp_transfer(struct analogix_dp_device *dp,
reg = buffer[i];
writel(reg, dp->reg_base + ANALOGIX_DP_BUF_DATA_0 +
4 * i);
- num_transferred++;
}
}
@@ -1113,12 +1010,17 @@ ssize_t analogix_dp_transfer(struct analogix_dp_device *dp,
/* Clear interrupt source for AUX CH access error */
reg = readl(dp->reg_base + ANALOGIX_DP_INT_STA);
- status_reg = readl(dp->reg_base + ANALOGIX_DP_AUX_CH_STA);
- if ((reg & AUX_ERR) || (status_reg & AUX_STATUS_MASK)) {
+ if ((reg & AUX_ERR)) {
+ u32 aux_status = readl(dp->reg_base + ANALOGIX_DP_AUX_CH_STA) &
+ AUX_STATUS_MASK;
+
writel(AUX_ERR, dp->reg_base + ANALOGIX_DP_INT_STA);
+ if (aux_status == AUX_STATUS_TIMEOUT_ERROR)
+ return -ETIMEDOUT;
+
dev_warn(dp->dev, "AUX CH error happened: %#x (%d)\n",
- status_reg & AUX_STATUS_MASK, !!(reg & AUX_ERR));
+ aux_status, !!(reg & AUX_ERR));
goto aux_error;
}
@@ -1127,7 +1029,6 @@ ssize_t analogix_dp_transfer(struct analogix_dp_device *dp,
reg = readl(dp->reg_base + ANALOGIX_DP_BUF_DATA_0 +
4 * i);
buffer[i] = (unsigned char)reg;
- num_transferred++;
}
}
@@ -1144,7 +1045,7 @@ ssize_t analogix_dp_transfer(struct analogix_dp_device *dp,
(msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_NATIVE_READ)
msg->reply = DP_AUX_NATIVE_REPLY_ACK;
- return num_transferred > 0 ? num_transferred : -EBUSY;
+ return msg->size;
aux_error:
/* if aux err happen, reset aux */
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h
index e284ee8da58b..12735139046c 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h
@@ -361,6 +361,15 @@
/* ANALOGIX_DP_AUX_CH_STA */
#define AUX_BUSY (0x1 << 4)
#define AUX_STATUS_MASK (0xf << 0)
+#define AUX_STATUS_OK (0x0 << 0)
+#define AUX_STATUS_NACK_ERROR (0x1 << 0)
+#define AUX_STATUS_TIMEOUT_ERROR (0x2 << 0)
+#define AUX_STATUS_UNKNOWN_ERROR (0x3 << 0)
+#define AUX_STATUS_MUCH_DEFER_ERROR (0x4 << 0)
+#define AUX_STATUS_TX_SHORT_ERROR (0x5 << 0)
+#define AUX_STATUS_RX_SHORT_ERROR (0x6 << 0)
+#define AUX_STATUS_NACK_WITHOUT_M_ERROR (0x7 << 0)
+#define AUX_STATUS_I2C_NACK_ERROR (0x8 << 0)
/* ANALOGIX_DP_AUX_CH_DEFER_CTL */
#define DEFER_CTRL_EN (0x1 << 7)
diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
index 59e9ad349969..88e4aa5830f3 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.c
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
@@ -464,9 +464,11 @@ static int anx7625_odfc_config(struct anx7625_data *ctx,
*/
static int anx7625_set_k_value(struct anx7625_data *ctx)
{
- struct edid *edid = (struct edid *)ctx->slimport_edid_p.edid_raw_data;
+ struct drm_edid_product_id id;
- if (edid->mfg_id[0] == IVO_MID0 && edid->mfg_id[1] == IVO_MID1)
+ drm_edid_get_product_id(ctx->cached_drm_edid, &id);
+
+ if (be16_to_cpu(id.manufacturer_name) == IVO_MID)
return anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
MIPI_DIGITAL_ADJ_1, 0x3B);
@@ -1526,7 +1528,8 @@ static int anx7625_wait_hpd_asserted(struct drm_dp_aux *aux,
static void anx7625_remove_edid(struct anx7625_data *ctx)
{
- ctx->slimport_edid_p.edid_block_num = -1;
+ drm_edid_free(ctx->cached_drm_edid);
+ ctx->cached_drm_edid = NULL;
}
static void anx7625_dp_adjust_swing(struct anx7625_data *ctx)
@@ -1787,27 +1790,32 @@ static ssize_t anx7625_aux_transfer(struct drm_dp_aux *aux,
static const struct drm_edid *anx7625_edid_read(struct anx7625_data *ctx)
{
struct device *dev = ctx->dev;
- struct s_edid_data *p_edid = &ctx->slimport_edid_p;
+ u8 *edid_buf;
int edid_num;
- if (ctx->slimport_edid_p.edid_block_num > 0)
+ if (ctx->cached_drm_edid)
goto out;
+ edid_buf = kmalloc(FOUR_BLOCK_SIZE, GFP_KERNEL);
+ if (!edid_buf)
+ return NULL;
+
pm_runtime_get_sync(dev);
_anx7625_hpd_polling(ctx, 5000 * 100);
- edid_num = sp_tx_edid_read(ctx, p_edid->edid_raw_data);
+ edid_num = sp_tx_edid_read(ctx, edid_buf);
pm_runtime_put_sync(dev);
if (edid_num < 1) {
DRM_DEV_ERROR(dev, "Fail to read EDID: %d\n", edid_num);
+ kfree(edid_buf);
return NULL;
}
- p_edid->edid_block_num = edid_num;
+ ctx->cached_drm_edid = drm_edid_alloc(edid_buf, FOUR_BLOCK_SIZE);
+ kfree(edid_buf);
out:
- return drm_edid_alloc(ctx->slimport_edid_p.edid_raw_data,
- FOUR_BLOCK_SIZE);
+ return drm_edid_dup(ctx->cached_drm_edid);
}
static enum drm_connector_status anx7625_sink_detect(struct anx7625_data *ctx)
@@ -2193,11 +2201,6 @@ static int anx7625_bridge_attach(struct drm_bridge *bridge,
if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR))
return -EINVAL;
- if (!bridge->encoder) {
- DRM_DEV_ERROR(dev, "Parent encoder object not found");
- return -ENODEV;
- }
-
ctx->aux.drm_dev = bridge->dev;
err = drm_dp_aux_register(&ctx->aux);
if (err) {
@@ -2435,11 +2438,6 @@ static void anx7625_bridge_atomic_enable(struct drm_bridge *bridge,
dev_dbg(dev, "drm atomic enable\n");
- if (!bridge->encoder) {
- dev_err(dev, "Parent encoder object not found");
- return;
- }
-
connector = drm_atomic_get_new_connector_for_encoder(state->base.state,
bridge->encoder);
if (!connector)
diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h
index 39ed35d33836..eb5580f1ab2f 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.h
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.h
@@ -286,8 +286,7 @@
#define MIPI_LANE_CTRL_10 0x0F
#define MIPI_DIGITAL_ADJ_1 0x1B
-#define IVO_MID0 0x26
-#define IVO_MID1 0xCF
+#define IVO_MID 0x26CF
#define MIPI_PLL_M_NUM_23_16 0x1E
#define MIPI_PLL_M_NUM_15_8 0x1F
@@ -417,11 +416,6 @@ enum audio_wd_len {
#define EDID_TRY_CNT 3
#define SUPPORT_PIXEL_CLOCK 300000
-struct s_edid_data {
- int edid_block_num;
- u8 edid_raw_data[FOUR_BLOCK_SIZE];
-};
-
/***************** Display End *****************/
#define MAX_LANES_SUPPORT 4
@@ -466,7 +460,7 @@ struct anx7625_data {
struct anx7625_i2c_client i2c;
struct i2c_client *last_client;
struct timer_list hdcp_timer;
- struct s_edid_data slimport_edid_p;
+ const struct drm_edid *cached_drm_edid;
struct device *codec_dev;
hdmi_codec_plugged_cb plugged_cb;
struct work_struct work;
diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
index 8a91ef0ae065..dee640ab1d3a 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
@@ -1697,11 +1697,6 @@ static int cdns_mhdp_connector_init(struct cdns_mhdp_device *mhdp)
struct drm_bridge *bridge = &mhdp->bridge;
int ret;
- if (!bridge->encoder) {
- dev_err(mhdp->dev, "Parent encoder object not found");
- return -ENODEV;
- }
-
conn->polled = DRM_CONNECTOR_POLL_HPD;
ret = drm_connector_init(bridge->dev, conn, &cdns_mhdp_conn_funcs,
diff --git a/drivers/gpu/drm/bridge/imx/imx-ldb-helper.c b/drivers/gpu/drm/bridge/imx/imx-ldb-helper.c
index 6967325cd8ee..9b5bebbe357d 100644
--- a/drivers/gpu/drm/bridge/imx/imx-ldb-helper.c
+++ b/drivers/gpu/drm/bridge/imx/imx-ldb-helper.c
@@ -116,11 +116,6 @@ int ldb_bridge_attach_helper(struct drm_bridge *bridge,
return -EINVAL;
}
- if (!bridge->encoder) {
- DRM_DEV_ERROR(ldb->dev, "missing encoder\n");
- return -ENODEV;
- }
-
return drm_bridge_attach(bridge->encoder,
ldb_ch->next_bridge, bridge,
DRM_BRIDGE_ATTACH_NO_CONNECTOR);
diff --git a/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-combiner.c b/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-combiner.c
index d0868a6ac6c9..e6dbbdc87ce2 100644
--- a/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-combiner.c
+++ b/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-combiner.c
@@ -119,11 +119,6 @@ static int imx8qxp_pc_bridge_attach(struct drm_bridge *bridge,
return -EINVAL;
}
- if (!bridge->encoder) {
- DRM_DEV_ERROR(pc->dev, "missing encoder\n");
- return -ENODEV;
- }
-
return drm_bridge_attach(bridge->encoder,
ch->next_bridge, bridge,
DRM_BRIDGE_ATTACH_NO_CONNECTOR);
diff --git a/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-link.c b/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-link.c
index ed8b7a4e0e11..1d11cc1df43c 100644
--- a/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-link.c
+++ b/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-link.c
@@ -138,11 +138,6 @@ static int imx8qxp_pixel_link_bridge_attach(struct drm_bridge *bridge,
return -EINVAL;
}
- if (!bridge->encoder) {
- DRM_DEV_ERROR(pl->dev, "missing encoder\n");
- return -ENODEV;
- }
-
return drm_bridge_attach(bridge->encoder,
pl->next_bridge, bridge,
DRM_BRIDGE_ATTACH_NO_CONNECTOR);
diff --git a/drivers/gpu/drm/bridge/imx/imx8qxp-pxl2dpi.c b/drivers/gpu/drm/bridge/imx/imx8qxp-pxl2dpi.c
index 4a886cb808ca..fb7cf4369bb8 100644
--- a/drivers/gpu/drm/bridge/imx/imx8qxp-pxl2dpi.c
+++ b/drivers/gpu/drm/bridge/imx/imx8qxp-pxl2dpi.c
@@ -58,11 +58,6 @@ static int imx8qxp_pxl2dpi_bridge_attach(struct drm_bridge *bridge,
return -EINVAL;
}
- if (!bridge->encoder) {
- DRM_DEV_ERROR(p2d->dev, "missing encoder\n");
- return -ENODEV;
- }
-
return drm_bridge_attach(bridge->encoder,
p2d->next_bridge, bridge,
DRM_BRIDGE_ATTACH_NO_CONNECTOR);
diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c
index 3f68c82888c2..1e1c06fdf206 100644
--- a/drivers/gpu/drm/bridge/ite-it6505.c
+++ b/drivers/gpu/drm/bridge/ite-it6505.c
@@ -1307,9 +1307,15 @@ static void it6505_video_reset(struct it6505 *it6505)
it6505_link_reset_step_train(it6505);
it6505_set_bits(it6505, REG_DATA_MUTE_CTRL, EN_VID_MUTE, EN_VID_MUTE);
it6505_set_bits(it6505, REG_INFOFRAME_CTRL, EN_VID_CTRL_PKT, 0x00);
- it6505_set_bits(it6505, REG_RESET_CTRL, VIDEO_RESET, VIDEO_RESET);
+
+ it6505_set_bits(it6505, REG_VID_BUS_CTRL1, TX_FIFO_RESET, TX_FIFO_RESET);
+ it6505_set_bits(it6505, REG_VID_BUS_CTRL1, TX_FIFO_RESET, 0x00);
+
it6505_set_bits(it6505, REG_501_FIFO_CTRL, RST_501_FIFO, RST_501_FIFO);
it6505_set_bits(it6505, REG_501_FIFO_CTRL, RST_501_FIFO, 0x00);
+
+ it6505_set_bits(it6505, REG_RESET_CTRL, VIDEO_RESET, VIDEO_RESET);
+ usleep_range(1000, 2000);
it6505_set_bits(it6505, REG_RESET_CTRL, VIDEO_RESET, 0x00);
}
@@ -2245,12 +2251,11 @@ static void it6505_link_training_work(struct work_struct *work)
if (ret) {
it6505->auto_train_retry = AUTO_TRAIN_RETRY;
it6505_link_train_ok(it6505);
- return;
} else {
it6505->auto_train_retry--;
+ it6505_dump(it6505);
}
- it6505_dump(it6505);
}
static void it6505_plugged_status_to_codec(struct it6505 *it6505)
@@ -2471,31 +2476,53 @@ static void it6505_irq_link_train_fail(struct it6505 *it6505)
schedule_work(&it6505->link_works);
}
-static void it6505_irq_video_fifo_error(struct it6505 *it6505)
+static bool it6505_test_bit(unsigned int bit, const unsigned int *addr)
{
- struct device *dev = it6505->dev;
-
- DRM_DEV_DEBUG_DRIVER(dev, "video fifo overflow interrupt");
- it6505->auto_train_retry = AUTO_TRAIN_RETRY;
- flush_work(&it6505->link_works);
- it6505_stop_hdcp(it6505);
- it6505_video_reset(it6505);
+ return 1 & (addr[bit / BITS_PER_BYTE] >> (bit % BITS_PER_BYTE));
}
-static void it6505_irq_io_latch_fifo_overflow(struct it6505 *it6505)
+static void it6505_irq_video_handler(struct it6505 *it6505, const int *int_status)
{
struct device *dev = it6505->dev;
+ int reg_0d, reg_int03;
- DRM_DEV_DEBUG_DRIVER(dev, "IO latch fifo overflow interrupt");
- it6505->auto_train_retry = AUTO_TRAIN_RETRY;
- flush_work(&it6505->link_works);
- it6505_stop_hdcp(it6505);
- it6505_video_reset(it6505);
-}
+ /*
+ * When video SCDT change with video not stable,
+ * Or video FIFO error, need video reset
+ */
-static bool it6505_test_bit(unsigned int bit, const unsigned int *addr)
-{
- return 1 & (addr[bit / BITS_PER_BYTE] >> (bit % BITS_PER_BYTE));
+ if ((!it6505_get_video_status(it6505) &&
+ (it6505_test_bit(INT_SCDT_CHANGE, (unsigned int *)int_status))) ||
+ (it6505_test_bit(BIT_INT_IO_FIFO_OVERFLOW,
+ (unsigned int *)int_status)) ||
+ (it6505_test_bit(BIT_INT_VID_FIFO_ERROR,
+ (unsigned int *)int_status))) {
+ it6505->auto_train_retry = AUTO_TRAIN_RETRY;
+ flush_work(&it6505->link_works);
+ it6505_stop_hdcp(it6505);
+ it6505_video_reset(it6505);
+
+ usleep_range(10000, 11000);
+
+ /*
+ * Clear FIFO error IRQ to prevent fifo error -> reset loop
+ * HW will trigger SCDT change IRQ again when video stable
+ */
+
+ reg_int03 = it6505_read(it6505, INT_STATUS_03);
+ reg_0d = it6505_read(it6505, REG_SYSTEM_STS);
+
+ reg_int03 &= (BIT(INT_VID_FIFO_ERROR) | BIT(INT_IO_LATCH_FIFO_OVERFLOW));
+ it6505_write(it6505, INT_STATUS_03, reg_int03);
+
+ DRM_DEV_DEBUG_DRIVER(dev, "reg08 = 0x%02x", reg_int03);
+ DRM_DEV_DEBUG_DRIVER(dev, "reg0D = 0x%02x", reg_0d);
+
+ return;
+ }
+
+ if (it6505_test_bit(INT_SCDT_CHANGE, (unsigned int *)int_status))
+ it6505_irq_scdt(it6505);
}
static irqreturn_t it6505_int_threaded_handler(int unused, void *data)
@@ -2508,15 +2535,12 @@ static irqreturn_t it6505_int_threaded_handler(int unused, void *data)
} irq_vec[] = {
{ BIT_INT_HPD, it6505_irq_hpd },
{ BIT_INT_HPD_IRQ, it6505_irq_hpd_irq },
- { BIT_INT_SCDT, it6505_irq_scdt },
{ BIT_INT_HDCP_FAIL, it6505_irq_hdcp_fail },
{ BIT_INT_HDCP_DONE, it6505_irq_hdcp_done },
{ BIT_INT_AUX_CMD_FAIL, it6505_irq_aux_cmd_fail },
{ BIT_INT_HDCP_KSV_CHECK, it6505_irq_hdcp_ksv_check },
{ BIT_INT_AUDIO_FIFO_ERROR, it6505_irq_audio_fifo_error },
{ BIT_INT_LINK_TRAIN_FAIL, it6505_irq_link_train_fail },
- { BIT_INT_VID_FIFO_ERROR, it6505_irq_video_fifo_error },
- { BIT_INT_IO_FIFO_OVERFLOW, it6505_irq_io_latch_fifo_overflow },
};
int int_status[3], i;
@@ -2546,6 +2570,7 @@ static irqreturn_t it6505_int_threaded_handler(int unused, void *data)
if (it6505_test_bit(irq_vec[i].bit, (unsigned int *)int_status))
irq_vec[i].handler(it6505);
}
+ it6505_irq_video_handler(it6505, (unsigned int *)int_status);
}
pm_runtime_put_sync(dev);
@@ -2590,7 +2615,7 @@ static int it6505_poweron(struct it6505 *it6505)
gpiod_set_value_cansleep(pdata->gpiod_reset, 0);
usleep_range(1000, 2000);
gpiod_set_value_cansleep(pdata->gpiod_reset, 1);
- usleep_range(10000, 20000);
+ usleep_range(25000, 35000);
}
it6505->powered = true;
@@ -2882,11 +2907,6 @@ static int it6505_bridge_attach(struct drm_bridge *bridge,
return -EINVAL;
}
- if (!bridge->encoder) {
- dev_err(dev, "Parent encoder object not found");
- return -ENODEV;
- }
-
/* Register aux channel */
it6505->aux.drm_dev = bridge->dev;
diff --git a/drivers/gpu/drm/bridge/lontium-lt9611.c b/drivers/gpu/drm/bridge/lontium-lt9611.c
index b99fe87ec738..73983f9b50cb 100644
--- a/drivers/gpu/drm/bridge/lontium-lt9611.c
+++ b/drivers/gpu/drm/bridge/lontium-lt9611.c
@@ -1195,4 +1195,5 @@ static struct i2c_driver lt9611_driver = {
};
module_i2c_driver(lt9611_driver);
+MODULE_DESCRIPTION("Lontium LT9611 DSI/HDMI bridge driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
index ab702471f3ab..4e802b54a1cb 100644
--- a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
+++ b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
@@ -337,11 +337,6 @@ static int lt9611uxc_connector_init(struct drm_bridge *bridge, struct lt9611uxc
{
int ret;
- if (!bridge->encoder) {
- DRM_ERROR("Parent encoder object not found");
- return -ENODEV;
- }
-
lt9611uxc->connector.polled = DRM_CONNECTOR_POLL_HPD;
drm_connector_helper_add(&lt9611uxc->connector,
@@ -1021,6 +1016,7 @@ static struct i2c_driver lt9611uxc_driver = {
module_i2c_driver(lt9611uxc_driver);
MODULE_AUTHOR("Dmitry Baryshkov <dmitry.baryshkov@linaro.org>");
+MODULE_DESCRIPTION("Lontium LT9611UXC DSI/HDMI bridge driver");
MODULE_LICENSE("GPL v2");
MODULE_FIRMWARE(FW_FILE);
diff --git a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
index 4480523244e4..37f1acf5c0f8 100644
--- a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
+++ b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
@@ -165,11 +165,6 @@ static int ge_b850v3_lvds_create_connector(struct drm_bridge *bridge)
struct drm_connector *connector = &ge_b850v3_lvds_ptr->connector;
int ret;
- if (!bridge->encoder) {
- DRM_ERROR("Parent encoder object not found");
- return -ENODEV;
- }
-
connector->polled = DRM_CONNECTOR_POLL_HPD;
drm_connector_helper_add(connector,
diff --git a/drivers/gpu/drm/bridge/nxp-ptn3460.c b/drivers/gpu/drm/bridge/nxp-ptn3460.c
index ed93fd4c3265..e77aab965fcf 100644
--- a/drivers/gpu/drm/bridge/nxp-ptn3460.c
+++ b/drivers/gpu/drm/bridge/nxp-ptn3460.c
@@ -229,11 +229,6 @@ static int ptn3460_bridge_attach(struct drm_bridge *bridge,
if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
return 0;
- if (!bridge->encoder) {
- DRM_ERROR("Parent encoder object not found");
- return -ENODEV;
- }
-
ptn_bridge->connector.polled = DRM_CONNECTOR_POLL_HPD;
ret = drm_connector_init(bridge->dev, &ptn_bridge->connector,
&ptn3460_connector_funcs, DRM_MODE_CONNECTOR_LVDS);
diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c
index 32506524d9a2..6e88339dec0f 100644
--- a/drivers/gpu/drm/bridge/panel.c
+++ b/drivers/gpu/drm/bridge/panel.c
@@ -67,11 +67,6 @@ static int panel_bridge_attach(struct drm_bridge *bridge,
if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
return 0;
- if (!bridge->encoder) {
- DRM_ERROR("Missing encoder\n");
- return -ENODEV;
- }
-
drm_connector_helper_add(connector,
&panel_bridge_connector_helper_funcs);
@@ -360,9 +355,12 @@ EXPORT_SYMBOL(drm_panel_bridge_set_orientation);
static void devm_drm_panel_bridge_release(struct device *dev, void *res)
{
- struct drm_bridge **bridge = res;
+ struct drm_bridge *bridge = *(struct drm_bridge **)res;
+
+ if (!bridge)
+ return;
- drm_panel_bridge_remove(*bridge);
+ drm_bridge_remove(bridge);
}
/**
diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c
index 95fedc68b0ae..e7e53a9e42af 100644
--- a/drivers/gpu/drm/bridge/samsung-dsim.c
+++ b/drivers/gpu/drm/bridge/samsung-dsim.c
@@ -574,8 +574,8 @@ static unsigned long samsung_dsim_pll_find_pms(struct samsung_dsim *dsi,
u16 _m, best_m;
u8 _s, best_s;
- p_min = DIV_ROUND_UP(fin, (12 * MHZ));
- p_max = fin / (6 * MHZ);
+ p_min = DIV_ROUND_UP(fin, (driver_data->pll_fin_max * MHZ));
+ p_max = fin / (driver_data->pll_fin_min * MHZ);
for (_p = p_min; _p <= p_max; ++_p) {
for (_s = 0; _s <= 5; ++_s) {
@@ -1606,6 +1606,27 @@ static int samsung_dsim_atomic_check(struct drm_bridge *bridge,
adjusted_mode->flags |= (DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC);
}
+ /*
+ * When using video sync pulses, the HFP, HBP, and HSA are divided between
+ * the available lanes if there is more than one lane. For certain
+ * timings and lane configurations, the HFP may not be evenly divisible.
+ * If the HFP is rounded down, it ends up being too small which can cause
+ * some monitors to not sync properly. In these instances, adjust htotal
+ * and hsync to round the HFP up, and recalculate the htotal. Through trial
+ * and error, it appears that the HBP and HSA do not appearto need the same
+ * correction that HFP does.
+ */
+ if (dsi->lanes > 1) {
+ int hfp = adjusted_mode->hsync_start - adjusted_mode->hdisplay;
+ int remainder = hfp % dsi->lanes;
+
+ if (remainder) {
+ adjusted_mode->hsync_start += remainder;
+ adjusted_mode->hsync_end += remainder;
+ adjusted_mode->htotal += remainder;
+ }
+ }
+
return 0;
}
diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c
index 2fbeda9025bf..7f91b0db161e 100644
--- a/drivers/gpu/drm/bridge/sii902x.c
+++ b/drivers/gpu/drm/bridge/sii902x.c
@@ -163,6 +163,14 @@
#define SII902X_AUDIO_PORT_INDEX 3
+/*
+ * The maximum resolution supported by the HDMI bridge is 1080p@60Hz
+ * and 1920x1200 requiring a pixel clock of 165MHz and the minimum
+ * resolution supported is 480p@60Hz requiring a pixel clock of 25MHz
+ */
+#define SII902X_MIN_PIXEL_CLOCK_KHZ 25000
+#define SII902X_MAX_PIXEL_CLOCK_KHZ 165000
+
struct sii902x {
struct i2c_client *i2c;
struct regmap *regmap;
@@ -310,20 +318,12 @@ static int sii902x_get_modes(struct drm_connector *connector)
return num;
}
-static enum drm_mode_status sii902x_mode_valid(struct drm_connector *connector,
- struct drm_display_mode *mode)
-{
- /* TODO: check mode */
-
- return MODE_OK;
-}
-
static const struct drm_connector_helper_funcs sii902x_connector_helper_funcs = {
.get_modes = sii902x_get_modes,
- .mode_valid = sii902x_mode_valid,
};
-static void sii902x_bridge_disable(struct drm_bridge *bridge)
+static void sii902x_bridge_atomic_disable(struct drm_bridge *bridge,
+ struct drm_bridge_state *old_bridge_state)
{
struct sii902x *sii902x = bridge_to_sii902x(bridge);
@@ -336,7 +336,8 @@ static void sii902x_bridge_disable(struct drm_bridge *bridge)
mutex_unlock(&sii902x->mutex);
}
-static void sii902x_bridge_enable(struct drm_bridge *bridge)
+static void sii902x_bridge_atomic_enable(struct drm_bridge *bridge,
+ struct drm_bridge_state *old_bridge_state)
{
struct sii902x *sii902x = bridge_to_sii902x(bridge);
@@ -495,6 +496,10 @@ static int sii902x_bridge_atomic_check(struct drm_bridge *bridge,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
{
+ if (crtc_state->mode.clock < SII902X_MIN_PIXEL_CLOCK_KHZ ||
+ crtc_state->mode.clock > SII902X_MAX_PIXEL_CLOCK_KHZ)
+ return -EINVAL;
+
/*
* There might be flags negotiation supported in future but
* set the bus flags in atomic_check statically for now.
@@ -504,11 +509,25 @@ static int sii902x_bridge_atomic_check(struct drm_bridge *bridge,
return 0;
}
+static enum drm_mode_status
+sii902x_bridge_mode_valid(struct drm_bridge *bridge,
+ const struct drm_display_info *info,
+ const struct drm_display_mode *mode)
+{
+ if (mode->clock < SII902X_MIN_PIXEL_CLOCK_KHZ)
+ return MODE_CLOCK_LOW;
+
+ if (mode->clock > SII902X_MAX_PIXEL_CLOCK_KHZ)
+ return MODE_CLOCK_HIGH;
+
+ return MODE_OK;
+}
+
static const struct drm_bridge_funcs sii902x_bridge_funcs = {
.attach = sii902x_bridge_attach,
.mode_set = sii902x_bridge_mode_set,
- .disable = sii902x_bridge_disable,
- .enable = sii902x_bridge_enable,
+ .atomic_disable = sii902x_bridge_atomic_disable,
+ .atomic_enable = sii902x_bridge_atomic_enable,
.detect = sii902x_bridge_detect,
.edid_read = sii902x_bridge_edid_read,
.atomic_reset = drm_atomic_helper_bridge_reset,
@@ -516,6 +535,7 @@ static const struct drm_bridge_funcs sii902x_bridge_funcs = {
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
.atomic_get_input_bus_fmts = sii902x_bridge_atomic_get_input_bus_fmts,
.atomic_check = sii902x_bridge_atomic_check,
+ .mode_valid = sii902x_bridge_mode_valid,
};
static int sii902x_mute(struct sii902x *sii902x, bool mute)
diff --git a/drivers/gpu/drm/bridge/sii9234.c b/drivers/gpu/drm/bridge/sii9234.c
index d8373d918324..0c74cdc07032 100644
--- a/drivers/gpu/drm/bridge/sii9234.c
+++ b/drivers/gpu/drm/bridge/sii9234.c
@@ -961,4 +961,5 @@ static struct i2c_driver sii9234_driver = {
};
module_i2c_driver(sii9234_driver);
+MODULE_DESCRIPTION("Silicon Image SII9234 HDMI/MHL bridge driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/bridge/sil-sii8620.c b/drivers/gpu/drm/bridge/sil-sii8620.c
index 599164e3877d..6bb755e9f0a5 100644
--- a/drivers/gpu/drm/bridge/sil-sii8620.c
+++ b/drivers/gpu/drm/bridge/sil-sii8620.c
@@ -2384,4 +2384,5 @@ static struct i2c_driver sii8620_driver = {
};
module_i2c_driver(sii8620_driver);
+MODULE_DESCRIPTION("Silicon Image SiI8620 HDMI/MHL bridge driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/bridge/simple-bridge.c b/drivers/gpu/drm/bridge/simple-bridge.c
index 5813a2c4fc5e..ab0b0e36e97a 100644
--- a/drivers/gpu/drm/bridge/simple-bridge.c
+++ b/drivers/gpu/drm/bridge/simple-bridge.c
@@ -116,11 +116,6 @@ static int simple_bridge_attach(struct drm_bridge *bridge,
if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
return 0;
- if (!bridge->encoder) {
- DRM_ERROR("Missing encoder\n");
- return -ENODEV;
- }
-
drm_connector_helper_add(&sbridge->connector,
&simple_bridge_con_helper_funcs);
ret = drm_connector_init_with_ddc(bridge->dev, &sbridge->connector,
@@ -175,7 +170,6 @@ static int simple_bridge_probe(struct platform_device *pdev)
sbridge = devm_kzalloc(&pdev->dev, sizeof(*sbridge), GFP_KERNEL);
if (!sbridge)
return -ENOMEM;
- platform_set_drvdata(pdev, sbridge);
sbridge->info = of_device_get_match_data(&pdev->dev);
@@ -213,16 +207,7 @@ static int simple_bridge_probe(struct platform_device *pdev)
sbridge->bridge.of_node = pdev->dev.of_node;
sbridge->bridge.timings = sbridge->info->timings;
- drm_bridge_add(&sbridge->bridge);
-
- return 0;
-}
-
-static void simple_bridge_remove(struct platform_device *pdev)
-{
- struct simple_bridge *sbridge = platform_get_drvdata(pdev);
-
- drm_bridge_remove(&sbridge->bridge);
+ return devm_drm_bridge_add(&pdev->dev, &sbridge->bridge);
}
/*
@@ -299,7 +284,6 @@ MODULE_DEVICE_TABLE(of, simple_bridge_match);
static struct platform_driver simple_bridge_driver = {
.probe = simple_bridge_probe,
- .remove_new = simple_bridge_remove,
.driver = {
.name = "simple-bridge",
.of_match_table = simple_bridge_match,
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
index 824fb3c65742..c4e9d96933dc 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
@@ -1071,11 +1071,6 @@ static int dw_mipi_dsi_bridge_attach(struct drm_bridge *bridge,
{
struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
- if (!bridge->encoder) {
- DRM_ERROR("Parent encoder object not found\n");
- return -ENODEV;
- }
-
/* Set the encoder type as caller does not know it */
bridge->encoder->encoder_type = DRM_MODE_ENCODER_DSI;
diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c
index 166f9a3e9622..b8b7a227addf 100644
--- a/drivers/gpu/drm/bridge/tc358767.c
+++ b/drivers/gpu/drm/bridge/tc358767.c
@@ -577,9 +577,9 @@ static int tc_pllupdate(struct tc_data *tc, unsigned int pllctrl)
return 0;
}
-static int tc_pxl_pll_en(struct tc_data *tc, u32 refclk, u32 pixelclock)
+static int tc_pxl_pll_calc(struct tc_data *tc, u32 refclk, u32 pixelclock,
+ int *out_best_pixelclock, u32 *out_pxl_pllparam)
{
- int ret;
int i_pre, best_pre = 1;
int i_post, best_post = 1;
int div, best_div = 1;
@@ -658,8 +658,7 @@ static int tc_pxl_pll_en(struct tc_data *tc, u32 refclk, u32 pixelclock)
return -EINVAL;
}
- dev_dbg(tc->dev, "PLL: got %d, delta %d\n", best_pixelclock,
- best_delta);
+ dev_dbg(tc->dev, "PLL: got %d, delta %d\n", best_pixelclock, best_delta);
dev_dbg(tc->dev, "PLL: %d / %d / %d * %d / %d\n", refclk,
ext_div[best_pre], best_div, best_mul, ext_div[best_post]);
@@ -672,11 +671,6 @@ static int tc_pxl_pll_en(struct tc_data *tc, u32 refclk, u32 pixelclock)
if (best_mul == 128)
best_mul = 0;
- /* Power up PLL and switch to bypass */
- ret = regmap_write(tc->regmap, PXL_PLLCTRL, PLLBYP | PLLEN);
- if (ret)
- return ret;
-
pxl_pllparam = vco_hi << 24; /* For PLL VCO >= 300 MHz = 1 */
pxl_pllparam |= ext_div[best_pre] << 20; /* External Pre-divider */
pxl_pllparam |= ext_div[best_post] << 16; /* External Post-divider */
@@ -684,6 +678,29 @@ static int tc_pxl_pll_en(struct tc_data *tc, u32 refclk, u32 pixelclock)
pxl_pllparam |= best_div << 8; /* Divider for PLL RefClk */
pxl_pllparam |= best_mul; /* Multiplier for PLL */
+ if (out_best_pixelclock)
+ *out_best_pixelclock = best_pixelclock;
+
+ if (out_pxl_pllparam)
+ *out_pxl_pllparam = pxl_pllparam;
+
+ return 0;
+}
+
+static int tc_pxl_pll_en(struct tc_data *tc, u32 refclk, u32 pixelclock)
+{
+ u32 pxl_pllparam = 0;
+ int ret;
+
+ ret = tc_pxl_pll_calc(tc, refclk, pixelclock, NULL, &pxl_pllparam);
+ if (ret)
+ return ret;
+
+ /* Power up PLL and switch to bypass */
+ ret = regmap_write(tc->regmap, PXL_PLLCTRL, PLLBYP | PLLEN);
+ if (ret)
+ return ret;
+
ret = regmap_write(tc->regmap, PXL_PLLPARAM, pxl_pllparam);
if (ret)
return ret;
@@ -721,7 +738,7 @@ static int tc_stream_clock_calc(struct tc_data *tc)
static int tc_set_syspllparam(struct tc_data *tc)
{
unsigned long rate;
- u32 pllparam = SYSCLK_SEL_LSCLK | LSCLK_DIV_2;
+ u32 pllparam = SYSCLK_SEL_LSCLK | LSCLK_DIV_1;
rate = clk_get_rate(tc->refclk);
switch (rate) {
@@ -885,7 +902,6 @@ static int tc_set_common_video_mode(struct tc_data *tc,
upper_margin, lower_margin, vsync_len);
dev_dbg(tc->dev, "total: %dx%d\n", mode->htotal, mode->vtotal);
-
/*
* LCD Ctl Frame Size
* datasheet is not clear of vsdelay in case of DPI
@@ -894,7 +910,7 @@ static int tc_set_common_video_mode(struct tc_data *tc,
*/
ret = regmap_write(tc->regmap, VPCTRL0,
FIELD_PREP(VSDELAY, right_margin + 10) |
- OPXLFMT_RGB888 | FRMSYNC_DISABLED | MSF_DISABLED);
+ OPXLFMT_RGB888 | FRMSYNC_ENABLED | MSF_DISABLED);
if (ret)
return ret;
@@ -1340,10 +1356,10 @@ static int tc_dsi_rx_enable(struct tc_data *tc)
u32 value;
int ret;
- regmap_write(tc->regmap, PPI_D0S_CLRSIPOCOUNT, 25);
- regmap_write(tc->regmap, PPI_D1S_CLRSIPOCOUNT, 25);
- regmap_write(tc->regmap, PPI_D2S_CLRSIPOCOUNT, 25);
- regmap_write(tc->regmap, PPI_D3S_CLRSIPOCOUNT, 25);
+ regmap_write(tc->regmap, PPI_D0S_CLRSIPOCOUNT, 5);
+ regmap_write(tc->regmap, PPI_D1S_CLRSIPOCOUNT, 5);
+ regmap_write(tc->regmap, PPI_D2S_CLRSIPOCOUNT, 5);
+ regmap_write(tc->regmap, PPI_D3S_CLRSIPOCOUNT, 5);
regmap_write(tc->regmap, PPI_D0S_ATMR, 0);
regmap_write(tc->regmap, PPI_D1S_ATMR, 0);
regmap_write(tc->regmap, PPI_TX_RX_TA, TTA_GET | TTA_SURE);
@@ -1589,6 +1605,18 @@ static int tc_dpi_atomic_check(struct drm_bridge *bridge,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
{
+ struct tc_data *tc = bridge_to_tc(bridge);
+ int adjusted_clock = 0;
+ int ret;
+
+ ret = tc_pxl_pll_calc(tc, clk_get_rate(tc->refclk),
+ crtc_state->mode.clock * 1000,
+ &adjusted_clock, NULL);
+ if (ret)
+ return ret;
+
+ crtc_state->adjusted_mode.clock = adjusted_clock / 1000;
+
/* DSI->DPI interface clock limitation: upto 100 MHz */
if (crtc_state->adjusted_mode.clock > 100000)
return -EINVAL;
@@ -1601,6 +1629,18 @@ static int tc_edp_atomic_check(struct drm_bridge *bridge,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
{
+ struct tc_data *tc = bridge_to_tc(bridge);
+ int adjusted_clock = 0;
+ int ret;
+
+ ret = tc_pxl_pll_calc(tc, clk_get_rate(tc->refclk),
+ crtc_state->mode.clock * 1000,
+ &adjusted_clock, NULL);
+ if (ret)
+ return ret;
+
+ crtc_state->adjusted_mode.clock = adjusted_clock / 1000;
+
/* DPI->(e)DP interface clock limitation: upto 154 MHz */
if (crtc_state->adjusted_mode.clock > 154000)
return -EINVAL;
@@ -1629,7 +1669,7 @@ tc_edp_mode_valid(struct drm_bridge *bridge,
u32 req, avail;
u32 bits_per_pixel = 24;
- /* DPI interface clock limitation: upto 154 MHz */
+ /* DPI->(e)DP interface clock limitation: up to 154 MHz */
if (mode->clock > 154000)
return MODE_CLOCK_HIGH;
@@ -1803,6 +1843,7 @@ static void tc_edp_bridge_detach(struct drm_bridge *bridge)
}
#define MAX_INPUT_SEL_FORMATS 1
+#define MAX_OUTPUT_SEL_FORMATS 1
static u32 *
tc_dpi_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
@@ -1828,6 +1869,28 @@ tc_dpi_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
return input_fmts;
}
+static u32 *
+tc_edp_atomic_get_output_bus_fmts(struct drm_bridge *bridge,
+ struct drm_bridge_state *bridge_state,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state,
+ unsigned int *num_output_fmts)
+{
+ u32 *output_fmts;
+
+ *num_output_fmts = 0;
+
+ output_fmts = kcalloc(MAX_OUTPUT_SEL_FORMATS, sizeof(*output_fmts),
+ GFP_KERNEL);
+ if (!output_fmts)
+ return NULL;
+
+ output_fmts[0] = MEDIA_BUS_FMT_RGB888_1X24;
+ *num_output_fmts = 1;
+
+ return output_fmts;
+}
+
static const struct drm_bridge_funcs tc_dpi_bridge_funcs = {
.attach = tc_dpi_bridge_attach,
.mode_valid = tc_dpi_mode_valid,
@@ -1854,6 +1917,8 @@ static const struct drm_bridge_funcs tc_edp_bridge_funcs = {
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
.atomic_reset = drm_atomic_helper_bridge_reset,
+ .atomic_get_input_bus_fmts = drm_atomic_helper_bridge_propagate_bus_fmt,
+ .atomic_get_output_bus_fmts = tc_edp_atomic_get_output_bus_fmts,
};
static bool tc_readable_reg(struct device *dev, unsigned int reg)
@@ -2135,7 +2200,7 @@ static irqreturn_t tc_irq_handler(int irq, void *arg)
dev_err(tc->dev, "syserr %x\n", stat);
}
- if (tc->hpd_pin >= 0 && tc->bridge.dev) {
+ if (tc->hpd_pin >= 0 && tc->bridge.dev && tc->aux.drm_dev) {
/*
* H is triggered when the GPIO goes high.
*
diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c b/drivers/gpu/drm/bridge/ti-tfp410.c
index c7bef5c23927..b1b1e4d5a24a 100644
--- a/drivers/gpu/drm/bridge/ti-tfp410.c
+++ b/drivers/gpu/drm/bridge/ti-tfp410.c
@@ -133,11 +133,6 @@ static int tfp410_attach(struct drm_bridge *bridge,
if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
return 0;
- if (!bridge->encoder) {
- dev_err(dvi->dev, "Missing encoder\n");
- return -ENODEV;
- }
-
if (dvi->next_bridge->ops & DRM_BRIDGE_OP_DETECT)
dvi->connector.polled = DRM_CONNECTOR_POLL_HPD;
else
diff --git a/drivers/gpu/drm/ci/build-igt.sh b/drivers/gpu/drm/ci/build-igt.sh
index 500fa4f5c30a..eddb5f782a5e 100644
--- a/drivers/gpu/drm/ci/build-igt.sh
+++ b/drivers/gpu/drm/ci/build-igt.sh
@@ -3,6 +3,30 @@
set -ex
+function generate_testlist {
+ set +x
+ while read -r line; do
+ if [ "$line" = "TESTLIST" ] || [ "$line" = "END TESTLIST" ]; then
+ continue
+ fi
+
+ tests=$(echo "$line" | tr ' ' '\n')
+
+ for test in $tests; do
+ output=$(/igt/libexec/igt-gpu-tools/"$test" --list-subtests || true)
+
+ if [ -z "$output" ]; then
+ echo "$test"
+ else
+ echo "$output" | while read -r subtest; do
+ echo "$test@$subtest"
+ done
+ fi
+ done
+ done < /igt/libexec/igt-gpu-tools/test-list.txt > /igt/libexec/igt-gpu-tools/ci-testlist.txt
+ set -x
+}
+
git clone https://gitlab.freedesktop.org/drm/igt-gpu-tools.git --single-branch --no-checkout
cd igt-gpu-tools
git checkout $IGT_VERSION
@@ -21,15 +45,30 @@ MESON_OPTIONS="-Doverlay=disabled \
-Dlibunwind=enabled \
-Dprefix=/igt"
+if [[ "$KERNEL_ARCH" = "arm64" ]] || [[ "$KERNEL_ARCH" = "arm" ]]; then
+ MESON_OPTIONS="$MESON_OPTIONS -Dxe_driver=disabled"
+fi
+
mkdir -p /igt
meson build $MESON_OPTIONS $EXTRA_MESON_ARGS
ninja -C build -j${FDO_CI_CONCURRENT:-4} || ninja -C build -j 1
ninja -C build install
+if [[ "$KERNEL_ARCH" = "arm64" ]]; then
+ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/igt/lib/aarch64-linux-gnu
+elif [[ "$KERNEL_ARCH" = "arm" ]]; then
+ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/igt/lib
+else
+ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/igt/lib64
+fi
+
+echo "Generating ci-testlist.txt"
+generate_testlist
+
mkdir -p artifacts/
tar -cf artifacts/igt.tar /igt
# Pass needed files to the test stage
S3_ARTIFACT_NAME="igt.tar.gz"
gzip -c artifacts/igt.tar > ${S3_ARTIFACT_NAME}
-ci-fairy s3cp --token-file "${CI_JOB_JWT_FILE}" ${S3_ARTIFACT_NAME} https://${PIPELINE_ARTIFACTS_BASE}/${KERNEL_ARCH}/${S3_ARTIFACT_NAME}
+ci-fairy s3cp --token-file "${S3_JWT_FILE}" ${S3_ARTIFACT_NAME} https://${PIPELINE_ARTIFACTS_BASE}/${KERNEL_ARCH}/${S3_ARTIFACT_NAME}
diff --git a/drivers/gpu/drm/ci/build.sh b/drivers/gpu/drm/ci/build.sh
index 106f2d40d222..5a3bdcffae32 100644
--- a/drivers/gpu/drm/ci/build.sh
+++ b/drivers/gpu/drm/ci/build.sh
@@ -12,6 +12,9 @@ rm -rf .git/rebase-apply
apt-get update
apt-get install -y libssl-dev
+# for msm header validation
+apt-get install -y python3-lxml
+
if [[ "$KERNEL_ARCH" = "arm64" ]]; then
GCC_ARCH="aarch64-linux-gnu"
DEBIAN_ARCH="arm64"
@@ -128,6 +131,7 @@ fi
# Pass needed files to the test stage
mkdir -p install
cp -rfv .gitlab-ci/* install/.
+cp -rfv ci/* install/.
cp -rfv install/common install/ci-common
cp -rfv drivers/gpu/drm/ci/* install/.
@@ -141,21 +145,21 @@ if [[ "$UPLOAD_TO_MINIO" = "1" ]]; then
FILES_TO_UPLOAD="$FILES_TO_UPLOAD $(basename -a $DEVICE_TREES)"
fi
+ ls -l "${S3_JWT_FILE}"
for f in $FILES_TO_UPLOAD; do
- ci-fairy s3cp --token-file "${CI_JOB_JWT_FILE}" /lava-files/$f \
+ ci-fairy s3cp --token-file "${S3_JWT_FILE}" /lava-files/$f \
https://${PIPELINE_ARTIFACTS_BASE}/${DEBIAN_ARCH}/$f
done
S3_ARTIFACT_NAME="kernel-files.tar.zst"
tar --zstd -cf $S3_ARTIFACT_NAME install
- ci-fairy s3cp --token-file "${CI_JOB_JWT_FILE}" ${S3_ARTIFACT_NAME} https://${PIPELINE_ARTIFACTS_BASE}/${DEBIAN_ARCH}/${S3_ARTIFACT_NAME}
+ ci-fairy s3cp --token-file "${S3_JWT_FILE}" ${S3_ARTIFACT_NAME} https://${PIPELINE_ARTIFACTS_BASE}/${DEBIAN_ARCH}/${S3_ARTIFACT_NAME}
echo "Download vmlinux.xz from https://${PIPELINE_ARTIFACTS_BASE}/${DEBIAN_ARCH}/vmlinux.xz"
fi
mkdir -p artifacts/install/lib
mv install/* artifacts/install/.
-rm -rf artifacts/install/modules
ln -s common artifacts/install/ci-common
cp .config artifacts/${CI_JOB_NAME}_config
diff --git a/drivers/gpu/drm/ci/build.yml b/drivers/gpu/drm/ci/build.yml
index 17ab38304885..9c198239033d 100644
--- a/drivers/gpu/drm/ci/build.yml
+++ b/drivers/gpu/drm/ci/build.yml
@@ -106,6 +106,7 @@ build-nodebugfs:arm64:
extends: .build:arm64
variables:
DISABLE_KCONFIGS: "DEBUG_FS"
+ ENABLE_KCONFIGS: "EXPERT DRM_MSM_VALIDATE_XML"
build:x86_64:
extends: .build:x86_64
diff --git a/drivers/gpu/drm/ci/container.yml b/drivers/gpu/drm/ci/container.yml
index 9764e7921a4f..d6edf3635b23 100644
--- a/drivers/gpu/drm/ci/container.yml
+++ b/drivers/gpu/drm/ci/container.yml
@@ -36,15 +36,15 @@ debian/android_build:
rules:
- when: never
-debian/x86_64_test-android:
+.debian/x86_64_test-android:
rules:
- when: never
-windows_build_vs2019:
+windows_build_msvc:
rules:
- when: never
-windows_test_vs2019:
+windows_test_msvc:
rules:
- when: never
@@ -56,10 +56,6 @@ rustfmt:
rules:
- when: never
-windows_vs2019:
- rules:
- - when: never
-
-clang-format:
+windows_msvc:
rules:
- when: never \ No newline at end of file
diff --git a/drivers/gpu/drm/ci/gitlab-ci.yml b/drivers/gpu/drm/ci/gitlab-ci.yml
index 084e3ff8e3f4..80fb0f57ae46 100644
--- a/drivers/gpu/drm/ci/gitlab-ci.yml
+++ b/drivers/gpu/drm/ci/gitlab-ci.yml
@@ -1,11 +1,11 @@
variables:
DRM_CI_PROJECT_PATH: &drm-ci-project-path mesa/mesa
- DRM_CI_COMMIT_SHA: &drm-ci-commit-sha 9d162de9a05155e1c4041857a5848842749164cf
+ DRM_CI_COMMIT_SHA: &drm-ci-commit-sha e2b9c5a9e3e4f9b532067af8022eaef8d6fc6c00
UPSTREAM_REPO: git://anongit.freedesktop.org/drm/drm
TARGET_BRANCH: drm-next
- IGT_VERSION: d2af13d9f5be5ce23d996e4afd3e45990f5ab977
+ IGT_VERSION: 0df7b9b97f9da0e364f5ee30fe331004b8c86b56
DEQP_RUNNER_GIT_URL: https://gitlab.freedesktop.org/anholt/deqp-runner.git
DEQP_RUNNER_GIT_TAG: v0.15.0
@@ -19,33 +19,47 @@ variables:
bash download-git-cache.sh
rm download-git-cache.sh
set +o xtrace
+ S3_JWT_FILE: /s3_jwt
S3_HOST: s3.freedesktop.org
+ # This bucket is used to fetch the kernel image
+ S3_KERNEL_BUCKET: mesa-rootfs
+ # Bucket for git cache
+ S3_GITCACHE_BUCKET: git-cache
+ # Bucket for the pipeline artifacts pushed to S3
+ S3_ARTIFACTS_BUCKET: artifacts
# per-pipeline artifact storage on MinIO
- PIPELINE_ARTIFACTS_BASE: ${S3_HOST}/artifacts/${CI_PROJECT_PATH}/${CI_PIPELINE_ID}
+ PIPELINE_ARTIFACTS_BASE: ${S3_HOST}/${S3_ARTIFACTS_BUCKET}/${CI_PROJECT_PATH}/${CI_PIPELINE_ID}
# per-job artifact storage on MinIO
JOB_ARTIFACTS_BASE: ${PIPELINE_ARTIFACTS_BASE}/${CI_JOB_ID}
# default kernel for rootfs before injecting the current kernel tree
KERNEL_REPO: "gfx-ci/linux"
- KERNEL_TAG: "v6.6.4-for-mesa-ci-e4f4c500f7fb"
- KERNEL_IMAGE_BASE: https://${S3_HOST}/mesa-lava/${KERNEL_REPO}/${KERNEL_TAG}
+ KERNEL_TAG: "v6.6.21-mesa-f8ea"
+ KERNEL_IMAGE_BASE: https://${S3_HOST}/${S3_KERNEL_BUCKET}/${KERNEL_REPO}/${KERNEL_TAG}
+ PKG_REPO_REV: "3cc12a2a"
LAVA_TAGS: subset-1-gfx
LAVA_JOB_PRIORITY: 30
+ 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"
default:
+ id_tokens:
+ S3_JWT:
+ aud: https://s3.freedesktop.org
before_script:
- export SCRIPTS_DIR=$(mktemp -d)
- curl -L -s --retry 4 -f --retry-all-errors --retry-delay 60 -O --output-dir "${SCRIPTS_DIR}" "${DRM_CI_PROJECT_URL}/-/raw/${DRM_CI_COMMIT_SHA}/.gitlab-ci/setup-test-env.sh"
- source ${SCRIPTS_DIR}/setup-test-env.sh
- echo -e "\e[0Ksection_start:$(date +%s):unset_env_vars_section[collapsed=true]\r\e[0KUnsetting vulnerable environment variables"
- - export CI_JOB_JWT_FILE="${CI_JOB_JWT_FILE:-$(mktemp)}"
- - echo -n "${CI_JOB_JWT}" > "${CI_JOB_JWT_FILE}"
- - unset CI_JOB_JWT
+ - echo -n "${S3_JWT}" > "${S3_JWT_FILE}"
+ - unset CI_JOB_JWT S3_JWT
- echo -e "\e[0Ksection_end:$(date +%s):unset_env_vars_section\r\e[0K"
- echo -e "\e[0Ksection_start:$(date +%s):drm_ci_download_section[collapsed=true]\r\e[0KDownloading mesa from $DRM_CI_PROJECT_URL/-/archive/$DRM_CI_COMMIT_SHA/mesa-$DRM_CI_COMMIT_SHA.tar.gz"
- cd $CI_PROJECT_DIR
- curl --output - $DRM_CI_PROJECT_URL/-/archive/$DRM_CI_COMMIT_SHA/mesa-$DRM_CI_COMMIT_SHA.tar.gz | tar -xz
- mv mesa-$DRM_CI_COMMIT_SHA/.gitlab-ci* .
+ - mv mesa-$DRM_CI_COMMIT_SHA/bin/ci .
- rm -rf mesa-$DRM_CI_COMMIT_SHA/
- echo -e "\e[0Ksection_end:$(date +%s):drm_ci_download_section\r\e[0K"
@@ -53,9 +67,9 @@ default:
- >
set +x
- test -e "${CI_JOB_JWT_FILE}" &&
- export CI_JOB_JWT="$(<${CI_JOB_JWT_FILE})" &&
- rm "${CI_JOB_JWT_FILE}"
+ test -e "${S3_JWT_FILE}" &&
+ export S3_JWT="$(<${S3_JWT_FILE})" &&
+ rm "${S3_JWT_FILE}"
include:
- project: 'freedesktop/ci-templates'
@@ -87,6 +101,7 @@ include:
- '/src/intel/ci/gitlab-ci-inc.yml'
- '/src/freedreno/ci/gitlab-ci-inc.yml'
- '/src/amd/ci/gitlab-ci-inc.yml'
+ - '/src/virtio/ci/gitlab-ci-inc.yml'
- drivers/gpu/drm/ci/image-tags.yml
- drivers/gpu/drm/ci/container.yml
- drivers/gpu/drm/ci/static-checks.yml
@@ -98,6 +113,7 @@ include:
stages:
- sanity
- container
+ - code-validation
- git-archive
- build
- amdgpu
@@ -107,7 +123,7 @@ stages:
- msm
- rockchip
- virtio-gpu
- - lint
+ - software-driver
# YAML anchors for rule conditions
# --------------------------------
@@ -218,14 +234,15 @@ make git archive:
script:
# Remove drm-ci files we just added
- rm -rf .gitlab-ci.*
+ - rm -rf ci
# Compactify the .git directory
- git gc --aggressive
# compress the current folder
- tar -cvzf ../$CI_PROJECT_NAME.tar.gz .
- # login with the JWT token file
- - ci-fairy s3cp --token-file "${CI_JOB_JWT_FILE}" ../$CI_PROJECT_NAME.tar.gz https://$S3_HOST/git-cache/$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME/$CI_PROJECT_NAME.tar.gz
+ # Use id_tokens for JWT auth
+ - ci-fairy s3cp --token-file "${S3_JWT_FILE}" ../$CI_PROJECT_NAME.tar.gz https://$S3_HOST/${S3_GITCACHE_BUCKET}/$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME/$CI_PROJECT_NAME.tar.gz
# Sanity checks of MR settings and commit logs
@@ -262,4 +279,4 @@ sanity:
# Jobs that need to pass before spending hardware resources on further testing
.required-for-hardware-jobs:
- needs: [] \ No newline at end of file
+ needs: []
diff --git a/drivers/gpu/drm/ci/igt_runner.sh b/drivers/gpu/drm/ci/igt_runner.sh
index f1a08b9b146f..79f41d7da772 100755
--- a/drivers/gpu/drm/ci/igt_runner.sh
+++ b/drivers/gpu/drm/ci/igt_runner.sh
@@ -30,10 +30,10 @@ case "$DRIVER_NAME" in
export IGT_FORCE_DRIVER="panfrost"
fi
;;
- amdgpu)
+ amdgpu|vkms)
# Cannot use HWCI_KERNEL_MODULES as at that point we don't have the module in /lib
- mv /install/modules/lib/modules/* /lib/modules/.
- modprobe amdgpu
+ mv /install/modules/lib/modules/* /lib/modules/. || true
+ modprobe --first-time $DRIVER_NAME
;;
esac
@@ -59,25 +59,26 @@ fi
curl -L --retry 4 -f --retry-all-errors --retry-delay 60 -s ${FDO_HTTP_CACHE_URI:-}$PIPELINE_ARTIFACTS_BASE/$ARCH/igt.tar.gz | tar --zstd -v -x -C /
+TESTLIST="/igt/libexec/igt-gpu-tools/ci-testlist.txt"
# If the job is parallel at the gitab job level, take the corresponding fraction
# of the caselist.
if [ -n "$CI_NODE_INDEX" ]; then
- sed -ni $CI_NODE_INDEX~$CI_NODE_TOTAL"p" /install/testlist.txt
+ sed -ni $CI_NODE_INDEX~$CI_NODE_TOTAL"p" $TESTLIST
fi
# core_getversion checks if the driver is loaded and probed correctly
# so run it in all shards
-if ! grep -q "core_getversion" /install/testlist.txt; then
+if ! grep -q "core_getversion" $TESTLIST; then
# Add the line to the file
- echo "core_getversion" >> /install/testlist.txt
+ echo "core_getversion" >> $TESTLIST
fi
set +e
igt-runner \
run \
--igt-folder /igt/libexec/igt-gpu-tools \
- --caselist /install/testlist.txt \
+ --caselist $TESTLIST \
--output /results \
$IGT_SKIPS \
$IGT_FLAKES \
diff --git a/drivers/gpu/drm/ci/image-tags.yml b/drivers/gpu/drm/ci/image-tags.yml
index 7ab4f2514da8..13eda37bdf05 100644
--- a/drivers/gpu/drm/ci/image-tags.yml
+++ b/drivers/gpu/drm/ci/image-tags.yml
@@ -1,10 +1,10 @@
variables:
- CONTAINER_TAG: "2023-10-11-mesa-uprev"
+ CONTAINER_TAG: "2024-05-09-mesa-uprev"
DEBIAN_X86_64_BUILD_BASE_IMAGE: "debian/x86_64_build-base"
DEBIAN_BASE_TAG: "${CONTAINER_TAG}"
DEBIAN_X86_64_BUILD_IMAGE_PATH: "debian/x86_64_build"
- DEBIAN_BUILD_TAG: "2023-10-08-config"
+ DEBIAN_BUILD_TAG: "2024-06-10-vkms"
KERNEL_ROOTFS_TAG: "2023-10-06-amd"
diff --git a/drivers/gpu/drm/ci/lava-submit.sh b/drivers/gpu/drm/ci/lava-submit.sh
index 3d39b0c916a8..0707fa706a48 100755
--- a/drivers/gpu/drm/ci/lava-submit.sh
+++ b/drivers/gpu/drm/ci/lava-submit.sh
@@ -27,7 +27,7 @@ KERNEL_IMAGE_BASE="https://${BASE_SYSTEM_HOST_PATH}" \
section_end variables
tar zcf job-rootfs-overlay.tar.gz -C results/job-rootfs-overlay/ .
-ci-fairy s3cp --token-file "${CI_JOB_JWT_FILE}" job-rootfs-overlay.tar.gz "https://${JOB_ROOTFS_OVERLAY_PATH}"
+ci-fairy s3cp --token-file "${S3_JWT_FILE}" job-rootfs-overlay.tar.gz "https://${JOB_ROOTFS_OVERLAY_PATH}"
touch results/lava.log
tail -f results/lava.log &
@@ -45,7 +45,7 @@ PYTHONPATH=artifacts/ artifacts/lava/lava_job_submitter.py \
--ci-project-dir "${CI_PROJECT_DIR}" \
--device-type "${DEVICE_TYPE}" \
--dtb-filename "${DTB}" \
- --jwt-file "${CI_JOB_JWT_FILE}" \
+ --jwt-file "${S3_JWT_FILE}" \
--kernel-image-name "${KERNEL_IMAGE_NAME}" \
--kernel-image-type "${KERNEL_IMAGE_TYPE}" \
--boot-method "${BOOT_METHOD}" \
diff --git a/drivers/gpu/drm/ci/test.yml b/drivers/gpu/drm/ci/test.yml
index 8bc63912fddb..ee908b66aad2 100644
--- a/drivers/gpu/drm/ci/test.yml
+++ b/drivers/gpu/drm/ci/test.yml
@@ -24,6 +24,7 @@
variables:
HWCI_TEST_SCRIPT: "/install/igt_runner.sh"
DEBIAN_ARCH: "armhf"
+ FARM: collabora
dependencies:
- testing:arm32
needs:
@@ -39,6 +40,7 @@
variables:
HWCI_TEST_SCRIPT: "/install/igt_runner.sh"
DEBIAN_ARCH: "arm64"
+ FARM: collabora
dependencies:
- testing:arm64
needs:
@@ -54,6 +56,7 @@
variables:
HWCI_TEST_SCRIPT: "/install/igt_runner.sh"
DEBIAN_ARCH: "amd64"
+ FARM: collabora
dependencies:
- testing:x86_64
needs:
@@ -74,6 +77,7 @@
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/arm64_test
- job: testing:arm64
@@ -116,8 +120,9 @@ msm:apq8016:
- .baremetal-igt-arm64
stage: msm
variables:
+ DEVICE_TYPE: apq8016-sbc-usb-host
DRIVER_NAME: msm
- BM_DTB: https://${PIPELINE_ARTIFACTS_BASE}/arm64/apq8016-sbc-usb-host.dtb
+ BM_DTB: https://${PIPELINE_ARTIFACTS_BASE}/arm64/${DEVICE_TYPE}.dtb
GPU_VERSION: apq8016
# disabling unused clocks congests with the MDSS runtime PM trying to
# disable those clocks and causes boot to fail.
@@ -132,9 +137,10 @@ msm:apq8096:
- .baremetal-igt-arm64
stage: msm
variables:
+ DEVICE_TYPE: apq8096-db820c
DRIVER_NAME: msm
BM_KERNEL_EXTRA_ARGS: maxcpus=2
- BM_DTB: https://${PIPELINE_ARTIFACTS_BASE}/arm64/apq8096-db820c.dtb
+ BM_DTB: https://${PIPELINE_ARTIFACTS_BASE}/arm64/${DEVICE_TYPE}.dtb
GPU_VERSION: apq8096
RUNNER_TAG: google-freedreno-db820c
script:
@@ -146,6 +152,7 @@ msm:sdm845:
stage: msm
parallel: 6
variables:
+ DEVICE_TYPE: sdm845-cheza-r3
DRIVER_NAME: msm
BM_KERNEL: https://${PIPELINE_ARTIFACTS_BASE}/arm64/cheza-kernel
GPU_VERSION: sdm845
@@ -184,6 +191,7 @@ rockchip:rk3399:
extends:
- .lava-igt:x86_64
stage: i915
+ timeout: "1h30m"
variables:
DRIVER_NAME: i915
DTB: ""
@@ -194,7 +202,6 @@ i915:apl:
extends:
- .i915
parallel: 3
- timeout: "1h30m"
variables:
DEVICE_TYPE: asus-C523NA-A20057-coral
GPU_VERSION: apl
@@ -204,7 +211,6 @@ i915:glk:
extends:
- .i915
parallel: 2
- timeout: "1h30m"
variables:
DEVICE_TYPE: hp-x360-12b-ca0010nr-n4020-octopus
GPU_VERSION: glk
@@ -214,7 +220,6 @@ i915:amly:
extends:
- .i915
parallel: 2
- timeout: "1h30m"
variables:
DEVICE_TYPE: asus-C433TA-AJ0005-rammus
GPU_VERSION: amly
@@ -233,7 +238,6 @@ i915:whl:
extends:
- .i915
parallel: 2
- timeout: "1h30m"
variables:
DEVICE_TYPE: dell-latitude-5400-8665U-sarien
GPU_VERSION: whl
@@ -243,7 +247,6 @@ i915:cml:
extends:
- .i915
parallel: 2
- timeout: "1h30m"
variables:
DEVICE_TYPE: asus-C436FA-Flip-hatch
GPU_VERSION: cml
@@ -335,7 +338,7 @@ meson:g12b:
RUNNER_TAG: mesa-ci-x86-64-lava-meson-g12b-a311d-khadas-vim3
virtio_gpu:none:
- stage: virtio-gpu
+ stage: software-driver
variables:
CROSVM_GALLIUM_DRIVER: llvmpipe
DRIVER_NAME: virtio_gpu
@@ -355,3 +358,25 @@ virtio_gpu:none:
- debian/x86_64_test-gl
- testing:x86_64
- igt:x86_64
+
+vkms:none:
+ stage: software-driver
+ variables:
+ DRIVER_NAME: vkms
+ GPU_VERSION: none
+ extends:
+ - .test-gl
+ - .test-rules
+ tags:
+ - kvm
+ script:
+ - ln -sf $CI_PROJECT_DIR/install /install
+ - mv install/bzImage /lava-files/bzImage
+ - mkdir -p /lib/modules
+ - mkdir -p $CI_PROJECT_DIR/results
+ - ln -sf $CI_PROJECT_DIR/results /results
+ - ./install/crosvm-runner.sh ./install/igt_runner.sh
+ needs:
+ - debian/x86_64_test-gl
+ - testing:x86_64
+ - igt:x86_64
diff --git a/drivers/gpu/drm/ci/testlist.txt b/drivers/gpu/drm/ci/testlist.txt
deleted file mode 100644
index 3377f002f8c5..000000000000
--- a/drivers/gpu/drm/ci/testlist.txt
+++ /dev/null
@@ -1,2761 +0,0 @@
-core_auth@getclient-simple
-core_auth@getclient-master-drop
-core_auth@basic-auth
-core_auth@many-magics
-core_getclient
-core_getstats
-core_getversion
-core_setmaster_vs_auth
-drm_read@invalid-buffer
-drm_read@fault-buffer
-drm_read@empty-block
-drm_read@empty-nonblock
-drm_read@short-buffer-block
-drm_read@short-buffer-nonblock
-drm_read@short-buffer-wakeup
-gem_eio@throttle
-gem_eio@create
-gem_eio@create-ext
-gem_eio@context-create
-gem_eio@execbuf
-gem_eio@banned
-gem_eio@suspend
-gem_eio@hibernate
-gem_eio@in-flight-external
-gem_eio@in-flight-suspend
-gem_eio@reset-stress
-gem_eio@unwedge-stress
-gem_eio@wait-immediate
-gem_eio@wait-wedge-immediate
-gem_eio@in-flight-immediate
-gem_eio@in-flight-contexts-immediate
-gem_eio@in-flight-internal-immediate
-gem_eio@wait-1us
-gem_eio@wait-wedge-1us
-gem_eio@in-flight-1us
-gem_eio@in-flight-contexts-1us
-gem_eio@in-flight-internal-1us
-gem_eio@wait-10ms
-gem_eio@wait-wedge-10ms
-gem_eio@in-flight-10ms
-gem_eio@in-flight-contexts-10ms
-gem_eio@in-flight-internal-10ms
-gem_eio@kms
-kms_3d
-kms_addfb_basic@unused-handle
-kms_addfb_basic@unused-pitches
-kms_addfb_basic@unused-offsets
-kms_addfb_basic@unused-modifier
-kms_addfb_basic@clobberred-modifier
-kms_addfb_basic@invalid-smem-bo-on-discrete
-kms_addfb_basic@legacy-format
-kms_addfb_basic@no-handle
-kms_addfb_basic@basic
-kms_addfb_basic@bad-pitch-0
-kms_addfb_basic@bad-pitch-32
-kms_addfb_basic@bad-pitch-63
-kms_addfb_basic@bad-pitch-128
-kms_addfb_basic@bad-pitch-256
-kms_addfb_basic@bad-pitch-1024
-kms_addfb_basic@bad-pitch-999
-kms_addfb_basic@bad-pitch-65536
-kms_addfb_basic@invalid-get-prop-any
-kms_addfb_basic@invalid-get-prop
-kms_addfb_basic@invalid-set-prop-any
-kms_addfb_basic@invalid-set-prop
-kms_addfb_basic@master-rmfb
-kms_addfb_basic@addfb25-modifier-no-flag
-kms_addfb_basic@addfb25-bad-modifier
-kms_addfb_basic@addfb25-x-tiled-mismatch-legacy
-kms_addfb_basic@addfb25-x-tiled-legacy
-kms_addfb_basic@addfb25-framebuffer-vs-set-tiling
-kms_addfb_basic@basic-x-tiled-legacy
-kms_addfb_basic@framebuffer-vs-set-tiling
-kms_addfb_basic@tile-pitch-mismatch
-kms_addfb_basic@basic-y-tiled-legacy
-kms_addfb_basic@size-max
-kms_addfb_basic@too-wide
-kms_addfb_basic@too-high
-kms_addfb_basic@bo-too-small
-kms_addfb_basic@small-bo
-kms_addfb_basic@bo-too-small-due-to-tiling
-kms_addfb_basic@addfb25-y-tiled-legacy
-kms_addfb_basic@addfb25-yf-tiled-legacy
-kms_addfb_basic@addfb25-y-tiled-small-legacy
-kms_addfb_basic@addfb25-4-tiled
-kms_async_flips@async-flip-with-page-flip-events
-kms_async_flips@alternate-sync-async-flip
-kms_async_flips@test-time-stamp
-kms_async_flips@test-cursor
-kms_async_flips@invalid-async-flip
-kms_async_flips@crc
-kms_atomic@plane-overlay-legacy
-kms_atomic@plane-primary-legacy
-kms_atomic@plane-primary-overlay-mutable-zpos
-kms_atomic@plane-immutable-zpos
-kms_atomic@test-only
-kms_atomic@plane-cursor-legacy
-kms_atomic@plane-invalid-params
-kms_atomic@plane-invalid-params-fence
-kms_atomic@crtc-invalid-params
-kms_atomic@crtc-invalid-params-fence
-kms_atomic@atomic-invalid-params
-kms_atomic@atomic-plane-damage
-kms_atomic_interruptible@legacy-setmode
-kms_atomic_interruptible@atomic-setmode
-kms_atomic_interruptible@legacy-dpms
-kms_atomic_interruptible@legacy-pageflip
-kms_atomic_interruptible@legacy-cursor
-kms_atomic_interruptible@universal-setplane-primary
-kms_atomic_interruptible@universal-setplane-cursor
-kms_atomic_transition@plane-primary-toggle-with-vblank-wait
-kms_atomic_transition@plane-all-transition
-kms_atomic_transition@plane-all-transition-fencing
-kms_atomic_transition@plane-all-transition-nonblocking
-kms_atomic_transition@plane-all-transition-nonblocking-fencing
-kms_atomic_transition@plane-use-after-nonblocking-unbind
-kms_atomic_transition@plane-use-after-nonblocking-unbind-fencing
-kms_atomic_transition@plane-all-modeset-transition
-kms_atomic_transition@plane-all-modeset-transition-fencing
-kms_atomic_transition@plane-all-modeset-transition-internal-panels
-kms_atomic_transition@plane-all-modeset-transition-fencing-internal-panels
-kms_atomic_transition@plane-toggle-modeset-transition
-kms_atomic_transition@modeset-transition
-kms_atomic_transition@modeset-transition-fencing
-kms_atomic_transition@modeset-transition-nonblocking
-kms_atomic_transition@modeset-transition-nonblocking-fencing
-kms_big_fb@x-tiled-addfb-size-overflow
-kms_big_fb@y-tiled-addfb-size-overflow
-kms_big_fb@yf-tiled-addfb-size-overflow
-kms_big_fb@4-tiled-addfb-size-overflow
-kms_big_fb@x-tiled-addfb-size-offset-overflow
-kms_big_fb@y-tiled-addfb-size-offset-overflow
-kms_big_fb@yf-tiled-addfb-size-offset-overflow
-kms_big_fb@4-tiled-addfb-size-offset-overflow
-kms_big_fb@linear-addfb
-kms_big_fb@x-tiled-addfb
-kms_big_fb@y-tiled-addfb
-kms_big_fb@yf-tiled-addfb
-kms_big_fb@4-tiled-addfb
-kms_big_fb@linear-8bpp-rotate-0
-kms_big_fb@linear-8bpp-rotate-90
-kms_big_fb@linear-8bpp-rotate-180
-kms_big_fb@linear-8bpp-rotate-270
-kms_big_fb@linear-16bpp-rotate-0
-kms_big_fb@linear-16bpp-rotate-90
-kms_big_fb@linear-16bpp-rotate-180
-kms_big_fb@linear-16bpp-rotate-270
-kms_big_fb@linear-32bpp-rotate-0
-kms_big_fb@linear-32bpp-rotate-90
-kms_big_fb@linear-32bpp-rotate-180
-kms_big_fb@linear-32bpp-rotate-270
-kms_big_fb@linear-64bpp-rotate-0
-kms_big_fb@linear-64bpp-rotate-90
-kms_big_fb@linear-64bpp-rotate-180
-kms_big_fb@linear-64bpp-rotate-270
-kms_big_fb@x-tiled-8bpp-rotate-0
-kms_big_fb@x-tiled-8bpp-rotate-90
-kms_big_fb@x-tiled-8bpp-rotate-180
-kms_big_fb@x-tiled-8bpp-rotate-270
-kms_big_fb@x-tiled-16bpp-rotate-0
-kms_big_fb@x-tiled-16bpp-rotate-90
-kms_big_fb@x-tiled-16bpp-rotate-180
-kms_big_fb@x-tiled-16bpp-rotate-270
-kms_big_fb@x-tiled-32bpp-rotate-0
-kms_big_fb@x-tiled-32bpp-rotate-90
-kms_big_fb@x-tiled-32bpp-rotate-180
-kms_big_fb@x-tiled-32bpp-rotate-270
-kms_big_fb@x-tiled-64bpp-rotate-0
-kms_big_fb@x-tiled-64bpp-rotate-90
-kms_big_fb@x-tiled-64bpp-rotate-180
-kms_big_fb@x-tiled-64bpp-rotate-270
-kms_big_fb@y-tiled-8bpp-rotate-0
-kms_big_fb@y-tiled-8bpp-rotate-90
-kms_big_fb@y-tiled-8bpp-rotate-180
-kms_big_fb@y-tiled-8bpp-rotate-270
-kms_big_fb@y-tiled-16bpp-rotate-0
-kms_big_fb@y-tiled-16bpp-rotate-90
-kms_big_fb@y-tiled-16bpp-rotate-180
-kms_big_fb@y-tiled-16bpp-rotate-270
-kms_big_fb@y-tiled-32bpp-rotate-0
-kms_big_fb@y-tiled-32bpp-rotate-90
-kms_big_fb@y-tiled-32bpp-rotate-180
-kms_big_fb@y-tiled-32bpp-rotate-270
-kms_big_fb@y-tiled-64bpp-rotate-0
-kms_big_fb@y-tiled-64bpp-rotate-90
-kms_big_fb@y-tiled-64bpp-rotate-180
-kms_big_fb@y-tiled-64bpp-rotate-270
-kms_big_fb@yf-tiled-8bpp-rotate-0
-kms_big_fb@yf-tiled-8bpp-rotate-90
-kms_big_fb@yf-tiled-8bpp-rotate-180
-kms_big_fb@yf-tiled-8bpp-rotate-270
-kms_big_fb@yf-tiled-16bpp-rotate-0
-kms_big_fb@yf-tiled-16bpp-rotate-90
-kms_big_fb@yf-tiled-16bpp-rotate-180
-kms_big_fb@yf-tiled-16bpp-rotate-270
-kms_big_fb@yf-tiled-32bpp-rotate-0
-kms_big_fb@yf-tiled-32bpp-rotate-90
-kms_big_fb@yf-tiled-32bpp-rotate-180
-kms_big_fb@yf-tiled-32bpp-rotate-270
-kms_big_fb@yf-tiled-64bpp-rotate-0
-kms_big_fb@yf-tiled-64bpp-rotate-90
-kms_big_fb@yf-tiled-64bpp-rotate-180
-kms_big_fb@yf-tiled-64bpp-rotate-270
-kms_big_fb@4-tiled-8bpp-rotate-0
-kms_big_fb@4-tiled-8bpp-rotate-90
-kms_big_fb@4-tiled-8bpp-rotate-180
-kms_big_fb@4-tiled-8bpp-rotate-270
-kms_big_fb@4-tiled-16bpp-rotate-0
-kms_big_fb@4-tiled-16bpp-rotate-90
-kms_big_fb@4-tiled-16bpp-rotate-180
-kms_big_fb@4-tiled-16bpp-rotate-270
-kms_big_fb@4-tiled-32bpp-rotate-0
-kms_big_fb@4-tiled-32bpp-rotate-90
-kms_big_fb@4-tiled-32bpp-rotate-180
-kms_big_fb@4-tiled-32bpp-rotate-270
-kms_big_fb@4-tiled-64bpp-rotate-0
-kms_big_fb@4-tiled-64bpp-rotate-90
-kms_big_fb@4-tiled-64bpp-rotate-180
-kms_big_fb@4-tiled-64bpp-rotate-270
-kms_big_fb@linear-max-hw-stride-32bpp-rotate-0
-kms_big_fb@linear-max-hw-stride-32bpp-rotate-180
-kms_big_fb@linear-max-hw-stride-64bpp-rotate-0
-kms_big_fb@linear-max-hw-stride-64bpp-rotate-180
-kms_big_fb@x-tiled-max-hw-stride-32bpp-rotate-0
-kms_big_fb@x-tiled-max-hw-stride-32bpp-rotate-0-async-flip
-kms_big_fb@x-tiled-max-hw-stride-32bpp-rotate-180
-kms_big_fb@x-tiled-max-hw-stride-32bpp-rotate-180-async-flip
-kms_big_fb@x-tiled-max-hw-stride-64bpp-rotate-0
-kms_big_fb@x-tiled-max-hw-stride-64bpp-rotate-0-async-flip
-kms_big_fb@x-tiled-max-hw-stride-64bpp-rotate-180
-kms_big_fb@x-tiled-max-hw-stride-64bpp-rotate-180-async-flip
-kms_big_fb@x-tiled-max-hw-stride-32bpp-rotate-0-hflip
-kms_big_fb@x-tiled-max-hw-stride-32bpp-rotate-0-hflip-async-flip
-kms_big_fb@x-tiled-max-hw-stride-32bpp-rotate-180-hflip
-kms_big_fb@x-tiled-max-hw-stride-32bpp-rotate-180-hflip-async-flip
-kms_big_fb@x-tiled-max-hw-stride-64bpp-rotate-0-hflip
-kms_big_fb@x-tiled-max-hw-stride-64bpp-rotate-0-hflip-async-flip
-kms_big_fb@x-tiled-max-hw-stride-64bpp-rotate-180-hflip
-kms_big_fb@x-tiled-max-hw-stride-64bpp-rotate-180-hflip-async-flip
-kms_big_fb@y-tiled-max-hw-stride-32bpp-rotate-0
-kms_big_fb@y-tiled-max-hw-stride-32bpp-rotate-0-async-flip
-kms_big_fb@y-tiled-max-hw-stride-32bpp-rotate-180
-kms_big_fb@y-tiled-max-hw-stride-32bpp-rotate-180-async-flip
-kms_big_fb@y-tiled-max-hw-stride-64bpp-rotate-0
-kms_big_fb@y-tiled-max-hw-stride-64bpp-rotate-0-async-flip
-kms_big_fb@y-tiled-max-hw-stride-64bpp-rotate-180
-kms_big_fb@y-tiled-max-hw-stride-64bpp-rotate-180-async-flip
-kms_big_fb@y-tiled-max-hw-stride-32bpp-rotate-0-hflip
-kms_big_fb@y-tiled-max-hw-stride-32bpp-rotate-0-hflip-async-flip
-kms_big_fb@y-tiled-max-hw-stride-32bpp-rotate-180-hflip
-kms_big_fb@y-tiled-max-hw-stride-32bpp-rotate-180-hflip-async-flip
-kms_big_fb@y-tiled-max-hw-stride-64bpp-rotate-0-hflip
-kms_big_fb@y-tiled-max-hw-stride-64bpp-rotate-0-hflip-async-flip
-kms_big_fb@y-tiled-max-hw-stride-64bpp-rotate-180-hflip
-kms_big_fb@y-tiled-max-hw-stride-64bpp-rotate-180-hflip-async-flip
-kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-0
-kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-0-async-flip
-kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-180
-kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-180-async-flip
-kms_big_fb@yf-tiled-max-hw-stride-64bpp-rotate-0
-kms_big_fb@yf-tiled-max-hw-stride-64bpp-rotate-0-async-flip
-kms_big_fb@yf-tiled-max-hw-stride-64bpp-rotate-180
-kms_big_fb@yf-tiled-max-hw-stride-64bpp-rotate-180-async-flip
-kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-0-hflip
-kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-0-hflip-async-flip
-kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-180-hflip
-kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-180-hflip-async-flip
-kms_big_fb@yf-tiled-max-hw-stride-64bpp-rotate-0-hflip
-kms_big_fb@yf-tiled-max-hw-stride-64bpp-rotate-0-hflip-async-flip
-kms_big_fb@yf-tiled-max-hw-stride-64bpp-rotate-180-hflip
-kms_big_fb@yf-tiled-max-hw-stride-64bpp-rotate-180-hflip-async-flip
-kms_big_fb@4-tiled-max-hw-stride-32bpp-rotate-0
-kms_big_fb@4-tiled-max-hw-stride-32bpp-rotate-0-async-flip
-kms_big_fb@4-tiled-max-hw-stride-32bpp-rotate-180
-kms_big_fb@4-tiled-max-hw-stride-32bpp-rotate-180-async-flip
-kms_big_fb@4-tiled-max-hw-stride-64bpp-rotate-0
-kms_big_fb@4-tiled-max-hw-stride-64bpp-rotate-0-async-flip
-kms_big_fb@4-tiled-max-hw-stride-64bpp-rotate-180
-kms_big_fb@4-tiled-max-hw-stride-64bpp-rotate-180-async-flip
-kms_big_fb@4-tiled-max-hw-stride-32bpp-rotate-0-hflip
-kms_big_fb@4-tiled-max-hw-stride-32bpp-rotate-0-hflip-async-flip
-kms_big_fb@4-tiled-max-hw-stride-32bpp-rotate-180-hflip
-kms_big_fb@4-tiled-max-hw-stride-32bpp-rotate-180-hflip-async-flip
-kms_big_fb@4-tiled-max-hw-stride-64bpp-rotate-0-hflip
-kms_big_fb@4-tiled-max-hw-stride-64bpp-rotate-0-hflip-async-flip
-kms_big_fb@4-tiled-max-hw-stride-64bpp-rotate-180-hflip
-kms_big_fb@4-tiled-max-hw-stride-64bpp-rotate-180-hflip-async-flip
-kms_big_joiner@basic
-kms_big_joiner@invalid-modeset
-kms_big_joiner@2x-modeset
-kms_busy@basic
-kms_busy@basic-hang
-kms_busy@extended-pageflip-modeset-hang-oldfb
-kms_busy@extended-pageflip-hang-oldfb
-kms_busy@extended-pageflip-hang-newfb
-kms_busy@extended-modeset-hang-oldfb
-kms_busy@extended-modeset-hang-newfb
-kms_busy@extended-modeset-hang-oldfb-with-reset
-kms_busy@extended-modeset-hang-newfb-with-reset
-kms_bw@linear-tiling-1-displays-1920x1080p
-kms_bw@linear-tiling-1-displays-2560x1440p
-kms_bw@linear-tiling-1-displays-3840x2160p
-kms_bw@linear-tiling-2-displays-1920x1080p
-kms_bw@linear-tiling-2-displays-2560x1440p
-kms_bw@linear-tiling-2-displays-3840x2160p
-kms_bw@linear-tiling-3-displays-1920x1080p
-kms_bw@linear-tiling-3-displays-2560x1440p
-kms_bw@linear-tiling-3-displays-3840x2160p
-kms_bw@linear-tiling-4-displays-1920x1080p
-kms_bw@linear-tiling-4-displays-2560x1440p
-kms_bw@linear-tiling-4-displays-3840x2160p
-kms_bw@linear-tiling-5-displays-1920x1080p
-kms_bw@linear-tiling-5-displays-2560x1440p
-kms_bw@linear-tiling-5-displays-3840x2160p
-kms_bw@linear-tiling-6-displays-1920x1080p
-kms_bw@linear-tiling-6-displays-2560x1440p
-kms_bw@linear-tiling-6-displays-3840x2160p
-kms_bw@linear-tiling-7-displays-1920x1080p
-kms_bw@linear-tiling-7-displays-2560x1440p
-kms_bw@linear-tiling-7-displays-3840x2160p
-kms_bw@linear-tiling-8-displays-1920x1080p
-kms_bw@linear-tiling-8-displays-2560x1440p
-kms_bw@linear-tiling-8-displays-3840x2160p
-kms_ccs@pipe-A-bad-pixel-format-y-tiled-ccs
-kms_ccs@pipe-A-bad-pixel-format-yf-tiled-ccs
-kms_ccs@pipe-A-bad-pixel-format-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-A-bad-pixel-format-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-A-bad-pixel-format-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-A-bad-pixel-format-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-A-bad-pixel-format-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-A-bad-pixel-format-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-A-bad-pixel-format-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-A-bad-pixel-format-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-A-bad-pixel-format-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-A-bad-rotation-90-y-tiled-ccs
-kms_ccs@pipe-A-bad-rotation-90-yf-tiled-ccs
-kms_ccs@pipe-A-bad-rotation-90-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-A-bad-rotation-90-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-A-bad-rotation-90-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-A-bad-rotation-90-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-A-bad-rotation-90-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-A-bad-rotation-90-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-A-bad-rotation-90-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-A-bad-rotation-90-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-A-bad-rotation-90-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-A-crc-primary-basic-y-tiled-ccs
-kms_ccs@pipe-A-crc-primary-basic-yf-tiled-ccs
-kms_ccs@pipe-A-crc-primary-basic-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-A-crc-primary-basic-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-A-crc-primary-basic-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-A-crc-primary-basic-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-A-crc-primary-basic-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-A-crc-primary-basic-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-A-crc-primary-basic-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-A-crc-primary-basic-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-A-crc-primary-basic-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-A-crc-primary-rotation-180-y-tiled-ccs
-kms_ccs@pipe-A-crc-primary-rotation-180-yf-tiled-ccs
-kms_ccs@pipe-A-crc-primary-rotation-180-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-A-crc-primary-rotation-180-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-A-crc-primary-rotation-180-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-A-crc-primary-rotation-180-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-A-crc-primary-rotation-180-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-A-crc-primary-rotation-180-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-A-crc-primary-rotation-180-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-A-crc-primary-rotation-180-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-A-crc-primary-rotation-180-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-A-random-ccs-data-y-tiled-ccs
-kms_ccs@pipe-A-random-ccs-data-yf-tiled-ccs
-kms_ccs@pipe-A-random-ccs-data-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-A-random-ccs-data-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-A-random-ccs-data-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-A-random-ccs-data-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-A-random-ccs-data-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-A-random-ccs-data-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-A-random-ccs-data-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-A-random-ccs-data-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-A-random-ccs-data-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-A-missing-ccs-buffer-y-tiled-ccs
-kms_ccs@pipe-A-missing-ccs-buffer-yf-tiled-ccs
-kms_ccs@pipe-A-missing-ccs-buffer-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-A-missing-ccs-buffer-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-A-missing-ccs-buffer-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-A-missing-ccs-buffer-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-A-missing-ccs-buffer-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-A-missing-ccs-buffer-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-A-ccs-on-another-bo-y-tiled-ccs
-kms_ccs@pipe-A-ccs-on-another-bo-yf-tiled-ccs
-kms_ccs@pipe-A-ccs-on-another-bo-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-A-ccs-on-another-bo-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-A-ccs-on-another-bo-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-A-ccs-on-another-bo-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-A-ccs-on-another-bo-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-A-ccs-on-another-bo-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-A-bad-aux-stride-y-tiled-ccs
-kms_ccs@pipe-A-bad-aux-stride-yf-tiled-ccs
-kms_ccs@pipe-A-bad-aux-stride-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-A-bad-aux-stride-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-A-bad-aux-stride-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-A-bad-aux-stride-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-A-bad-aux-stride-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-A-bad-aux-stride-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-A-crc-sprite-planes-basic-y-tiled-ccs
-kms_ccs@pipe-A-crc-sprite-planes-basic-yf-tiled-ccs
-kms_ccs@pipe-A-crc-sprite-planes-basic-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-A-crc-sprite-planes-basic-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-A-crc-sprite-planes-basic-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-A-crc-sprite-planes-basic-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-A-crc-sprite-planes-basic-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-A-crc-sprite-planes-basic-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-A-crc-sprite-planes-basic-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-A-crc-sprite-planes-basic-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-A-crc-sprite-planes-basic-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-B-bad-pixel-format-y-tiled-ccs
-kms_ccs@pipe-B-bad-pixel-format-yf-tiled-ccs
-kms_ccs@pipe-B-bad-pixel-format-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-B-bad-pixel-format-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-B-bad-pixel-format-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-B-bad-pixel-format-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-B-bad-pixel-format-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-B-bad-pixel-format-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-B-bad-pixel-format-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-B-bad-pixel-format-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-B-bad-pixel-format-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-B-bad-rotation-90-y-tiled-ccs
-kms_ccs@pipe-B-bad-rotation-90-yf-tiled-ccs
-kms_ccs@pipe-B-bad-rotation-90-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-B-bad-rotation-90-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-B-bad-rotation-90-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-B-bad-rotation-90-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-B-bad-rotation-90-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-B-bad-rotation-90-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-B-bad-rotation-90-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-B-bad-rotation-90-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-B-bad-rotation-90-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-B-crc-primary-basic-y-tiled-ccs
-kms_ccs@pipe-B-crc-primary-basic-yf-tiled-ccs
-kms_ccs@pipe-B-crc-primary-basic-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-B-crc-primary-basic-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-B-crc-primary-basic-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-B-crc-primary-basic-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-B-crc-primary-basic-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-B-crc-primary-basic-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-B-crc-primary-basic-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-B-crc-primary-basic-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-B-crc-primary-basic-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-B-crc-primary-rotation-180-y-tiled-ccs
-kms_ccs@pipe-B-crc-primary-rotation-180-yf-tiled-ccs
-kms_ccs@pipe-B-crc-primary-rotation-180-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-B-crc-primary-rotation-180-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-B-crc-primary-rotation-180-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-B-crc-primary-rotation-180-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-B-crc-primary-rotation-180-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-B-crc-primary-rotation-180-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-B-crc-primary-rotation-180-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-B-crc-primary-rotation-180-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-B-crc-primary-rotation-180-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-B-random-ccs-data-y-tiled-ccs
-kms_ccs@pipe-B-random-ccs-data-yf-tiled-ccs
-kms_ccs@pipe-B-random-ccs-data-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-B-random-ccs-data-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-B-random-ccs-data-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-B-random-ccs-data-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-B-random-ccs-data-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-B-random-ccs-data-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-B-random-ccs-data-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-B-random-ccs-data-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-B-random-ccs-data-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-B-missing-ccs-buffer-y-tiled-ccs
-kms_ccs@pipe-B-missing-ccs-buffer-yf-tiled-ccs
-kms_ccs@pipe-B-missing-ccs-buffer-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-B-missing-ccs-buffer-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-B-missing-ccs-buffer-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-B-missing-ccs-buffer-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-B-missing-ccs-buffer-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-B-missing-ccs-buffer-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-B-ccs-on-another-bo-y-tiled-ccs
-kms_ccs@pipe-B-ccs-on-another-bo-yf-tiled-ccs
-kms_ccs@pipe-B-ccs-on-another-bo-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-B-ccs-on-another-bo-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-B-ccs-on-another-bo-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-B-ccs-on-another-bo-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-B-ccs-on-another-bo-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-B-ccs-on-another-bo-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-B-bad-aux-stride-y-tiled-ccs
-kms_ccs@pipe-B-bad-aux-stride-yf-tiled-ccs
-kms_ccs@pipe-B-bad-aux-stride-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-B-bad-aux-stride-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-B-bad-aux-stride-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-B-bad-aux-stride-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-B-bad-aux-stride-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-B-bad-aux-stride-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-B-crc-sprite-planes-basic-y-tiled-ccs
-kms_ccs@pipe-B-crc-sprite-planes-basic-yf-tiled-ccs
-kms_ccs@pipe-B-crc-sprite-planes-basic-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-B-crc-sprite-planes-basic-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-B-crc-sprite-planes-basic-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-B-crc-sprite-planes-basic-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-B-crc-sprite-planes-basic-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-B-crc-sprite-planes-basic-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-B-crc-sprite-planes-basic-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-B-crc-sprite-planes-basic-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-B-crc-sprite-planes-basic-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-C-bad-pixel-format-y-tiled-ccs
-kms_ccs@pipe-C-bad-pixel-format-yf-tiled-ccs
-kms_ccs@pipe-C-bad-pixel-format-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-C-bad-pixel-format-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-C-bad-pixel-format-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-C-bad-pixel-format-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-C-bad-pixel-format-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-C-bad-pixel-format-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-C-bad-pixel-format-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-C-bad-pixel-format-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-C-bad-pixel-format-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-C-bad-rotation-90-y-tiled-ccs
-kms_ccs@pipe-C-bad-rotation-90-yf-tiled-ccs
-kms_ccs@pipe-C-bad-rotation-90-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-C-bad-rotation-90-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-C-bad-rotation-90-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-C-bad-rotation-90-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-C-bad-rotation-90-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-C-bad-rotation-90-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-C-bad-rotation-90-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-C-bad-rotation-90-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-C-bad-rotation-90-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-C-crc-primary-basic-y-tiled-ccs
-kms_ccs@pipe-C-crc-primary-basic-yf-tiled-ccs
-kms_ccs@pipe-C-crc-primary-basic-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-C-crc-primary-basic-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-C-crc-primary-basic-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-C-crc-primary-basic-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-C-crc-primary-basic-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-C-crc-primary-basic-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-C-crc-primary-basic-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-C-crc-primary-basic-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-C-crc-primary-basic-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-C-crc-primary-rotation-180-y-tiled-ccs
-kms_ccs@pipe-C-crc-primary-rotation-180-yf-tiled-ccs
-kms_ccs@pipe-C-crc-primary-rotation-180-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-C-crc-primary-rotation-180-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-C-crc-primary-rotation-180-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-C-crc-primary-rotation-180-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-C-crc-primary-rotation-180-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-C-crc-primary-rotation-180-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-C-crc-primary-rotation-180-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-C-crc-primary-rotation-180-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-C-crc-primary-rotation-180-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-C-random-ccs-data-y-tiled-ccs
-kms_ccs@pipe-C-random-ccs-data-yf-tiled-ccs
-kms_ccs@pipe-C-random-ccs-data-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-C-random-ccs-data-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-C-random-ccs-data-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-C-random-ccs-data-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-C-random-ccs-data-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-C-random-ccs-data-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-C-random-ccs-data-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-C-random-ccs-data-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-C-random-ccs-data-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-C-missing-ccs-buffer-y-tiled-ccs
-kms_ccs@pipe-C-missing-ccs-buffer-yf-tiled-ccs
-kms_ccs@pipe-C-missing-ccs-buffer-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-C-missing-ccs-buffer-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-C-missing-ccs-buffer-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-C-missing-ccs-buffer-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-C-missing-ccs-buffer-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-C-missing-ccs-buffer-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-C-ccs-on-another-bo-y-tiled-ccs
-kms_ccs@pipe-C-ccs-on-another-bo-yf-tiled-ccs
-kms_ccs@pipe-C-ccs-on-another-bo-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-C-ccs-on-another-bo-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-C-ccs-on-another-bo-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-C-ccs-on-another-bo-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-C-ccs-on-another-bo-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-C-ccs-on-another-bo-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-C-bad-aux-stride-y-tiled-ccs
-kms_ccs@pipe-C-bad-aux-stride-yf-tiled-ccs
-kms_ccs@pipe-C-bad-aux-stride-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-C-bad-aux-stride-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-C-bad-aux-stride-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-C-bad-aux-stride-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-C-bad-aux-stride-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-C-bad-aux-stride-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-C-crc-sprite-planes-basic-y-tiled-ccs
-kms_ccs@pipe-C-crc-sprite-planes-basic-yf-tiled-ccs
-kms_ccs@pipe-C-crc-sprite-planes-basic-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-C-crc-sprite-planes-basic-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-C-crc-sprite-planes-basic-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-C-crc-sprite-planes-basic-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-C-crc-sprite-planes-basic-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-C-crc-sprite-planes-basic-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-C-crc-sprite-planes-basic-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-C-crc-sprite-planes-basic-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-C-crc-sprite-planes-basic-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-D-bad-pixel-format-y-tiled-ccs
-kms_ccs@pipe-D-bad-pixel-format-yf-tiled-ccs
-kms_ccs@pipe-D-bad-pixel-format-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-D-bad-pixel-format-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-D-bad-pixel-format-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-D-bad-pixel-format-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-D-bad-pixel-format-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-D-bad-pixel-format-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-D-bad-pixel-format-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-D-bad-pixel-format-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-D-bad-pixel-format-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-D-bad-rotation-90-y-tiled-ccs
-kms_ccs@pipe-D-bad-rotation-90-yf-tiled-ccs
-kms_ccs@pipe-D-bad-rotation-90-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-D-bad-rotation-90-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-D-bad-rotation-90-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-D-bad-rotation-90-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-D-bad-rotation-90-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-D-bad-rotation-90-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-D-bad-rotation-90-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-D-bad-rotation-90-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-D-bad-rotation-90-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-D-crc-primary-basic-y-tiled-ccs
-kms_ccs@pipe-D-crc-primary-basic-yf-tiled-ccs
-kms_ccs@pipe-D-crc-primary-basic-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-D-crc-primary-basic-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-D-crc-primary-basic-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-D-crc-primary-basic-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-D-crc-primary-basic-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-D-crc-primary-basic-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-D-crc-primary-basic-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-D-crc-primary-basic-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-D-crc-primary-basic-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-D-crc-primary-rotation-180-y-tiled-ccs
-kms_ccs@pipe-D-crc-primary-rotation-180-yf-tiled-ccs
-kms_ccs@pipe-D-crc-primary-rotation-180-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-D-crc-primary-rotation-180-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-D-crc-primary-rotation-180-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-D-crc-primary-rotation-180-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-D-crc-primary-rotation-180-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-D-crc-primary-rotation-180-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-D-crc-primary-rotation-180-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-D-crc-primary-rotation-180-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-D-crc-primary-rotation-180-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-D-random-ccs-data-y-tiled-ccs
-kms_ccs@pipe-D-random-ccs-data-yf-tiled-ccs
-kms_ccs@pipe-D-random-ccs-data-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-D-random-ccs-data-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-D-random-ccs-data-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-D-random-ccs-data-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-D-random-ccs-data-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-D-random-ccs-data-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-D-random-ccs-data-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-D-random-ccs-data-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-D-random-ccs-data-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-D-missing-ccs-buffer-y-tiled-ccs
-kms_ccs@pipe-D-missing-ccs-buffer-yf-tiled-ccs
-kms_ccs@pipe-D-missing-ccs-buffer-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-D-missing-ccs-buffer-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-D-missing-ccs-buffer-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-D-missing-ccs-buffer-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-D-missing-ccs-buffer-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-D-missing-ccs-buffer-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-D-ccs-on-another-bo-y-tiled-ccs
-kms_ccs@pipe-D-ccs-on-another-bo-yf-tiled-ccs
-kms_ccs@pipe-D-ccs-on-another-bo-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-D-ccs-on-another-bo-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-D-ccs-on-another-bo-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-D-ccs-on-another-bo-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-D-ccs-on-another-bo-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-D-ccs-on-another-bo-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-D-bad-aux-stride-y-tiled-ccs
-kms_ccs@pipe-D-bad-aux-stride-yf-tiled-ccs
-kms_ccs@pipe-D-bad-aux-stride-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-D-bad-aux-stride-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-D-bad-aux-stride-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-D-bad-aux-stride-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-D-bad-aux-stride-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-D-bad-aux-stride-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-D-crc-sprite-planes-basic-y-tiled-ccs
-kms_ccs@pipe-D-crc-sprite-planes-basic-yf-tiled-ccs
-kms_ccs@pipe-D-crc-sprite-planes-basic-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-D-crc-sprite-planes-basic-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-D-crc-sprite-planes-basic-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-D-crc-sprite-planes-basic-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-D-crc-sprite-planes-basic-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-D-crc-sprite-planes-basic-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-D-crc-sprite-planes-basic-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-D-crc-sprite-planes-basic-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-D-crc-sprite-planes-basic-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-E-bad-pixel-format-y-tiled-ccs
-kms_ccs@pipe-E-bad-pixel-format-yf-tiled-ccs
-kms_ccs@pipe-E-bad-pixel-format-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-E-bad-pixel-format-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-E-bad-pixel-format-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-E-bad-pixel-format-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-E-bad-pixel-format-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-E-bad-pixel-format-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-E-bad-pixel-format-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-E-bad-pixel-format-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-E-bad-pixel-format-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-E-bad-rotation-90-y-tiled-ccs
-kms_ccs@pipe-E-bad-rotation-90-yf-tiled-ccs
-kms_ccs@pipe-E-bad-rotation-90-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-E-bad-rotation-90-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-E-bad-rotation-90-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-E-bad-rotation-90-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-E-bad-rotation-90-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-E-bad-rotation-90-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-E-bad-rotation-90-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-E-bad-rotation-90-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-E-bad-rotation-90-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-E-crc-primary-basic-y-tiled-ccs
-kms_ccs@pipe-E-crc-primary-basic-yf-tiled-ccs
-kms_ccs@pipe-E-crc-primary-basic-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-E-crc-primary-basic-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-E-crc-primary-basic-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-E-crc-primary-basic-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-E-crc-primary-basic-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-E-crc-primary-basic-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-E-crc-primary-basic-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-E-crc-primary-basic-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-E-crc-primary-basic-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-E-crc-primary-rotation-180-y-tiled-ccs
-kms_ccs@pipe-E-crc-primary-rotation-180-yf-tiled-ccs
-kms_ccs@pipe-E-crc-primary-rotation-180-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-E-crc-primary-rotation-180-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-E-crc-primary-rotation-180-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-E-crc-primary-rotation-180-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-E-crc-primary-rotation-180-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-E-crc-primary-rotation-180-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-E-crc-primary-rotation-180-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-E-crc-primary-rotation-180-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-E-crc-primary-rotation-180-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-E-random-ccs-data-y-tiled-ccs
-kms_ccs@pipe-E-random-ccs-data-yf-tiled-ccs
-kms_ccs@pipe-E-random-ccs-data-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-E-random-ccs-data-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-E-random-ccs-data-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-E-random-ccs-data-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-E-random-ccs-data-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-E-random-ccs-data-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-E-random-ccs-data-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-E-random-ccs-data-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-E-random-ccs-data-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-E-missing-ccs-buffer-y-tiled-ccs
-kms_ccs@pipe-E-missing-ccs-buffer-yf-tiled-ccs
-kms_ccs@pipe-E-missing-ccs-buffer-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-E-missing-ccs-buffer-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-E-missing-ccs-buffer-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-E-missing-ccs-buffer-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-E-missing-ccs-buffer-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-E-missing-ccs-buffer-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-E-ccs-on-another-bo-y-tiled-ccs
-kms_ccs@pipe-E-ccs-on-another-bo-yf-tiled-ccs
-kms_ccs@pipe-E-ccs-on-another-bo-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-E-ccs-on-another-bo-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-E-ccs-on-another-bo-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-E-ccs-on-another-bo-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-E-ccs-on-another-bo-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-E-ccs-on-another-bo-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-E-bad-aux-stride-y-tiled-ccs
-kms_ccs@pipe-E-bad-aux-stride-yf-tiled-ccs
-kms_ccs@pipe-E-bad-aux-stride-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-E-bad-aux-stride-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-E-bad-aux-stride-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-E-bad-aux-stride-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-E-bad-aux-stride-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-E-bad-aux-stride-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-E-crc-sprite-planes-basic-y-tiled-ccs
-kms_ccs@pipe-E-crc-sprite-planes-basic-yf-tiled-ccs
-kms_ccs@pipe-E-crc-sprite-planes-basic-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-E-crc-sprite-planes-basic-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-E-crc-sprite-planes-basic-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-E-crc-sprite-planes-basic-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-E-crc-sprite-planes-basic-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-E-crc-sprite-planes-basic-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-E-crc-sprite-planes-basic-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-E-crc-sprite-planes-basic-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-E-crc-sprite-planes-basic-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-F-bad-pixel-format-y-tiled-ccs
-kms_ccs@pipe-F-bad-pixel-format-yf-tiled-ccs
-kms_ccs@pipe-F-bad-pixel-format-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-F-bad-pixel-format-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-F-bad-pixel-format-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-F-bad-pixel-format-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-F-bad-pixel-format-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-F-bad-pixel-format-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-F-bad-pixel-format-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-F-bad-pixel-format-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-F-bad-pixel-format-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-F-bad-rotation-90-y-tiled-ccs
-kms_ccs@pipe-F-bad-rotation-90-yf-tiled-ccs
-kms_ccs@pipe-F-bad-rotation-90-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-F-bad-rotation-90-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-F-bad-rotation-90-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-F-bad-rotation-90-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-F-bad-rotation-90-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-F-bad-rotation-90-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-F-bad-rotation-90-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-F-bad-rotation-90-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-F-bad-rotation-90-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-F-crc-primary-basic-y-tiled-ccs
-kms_ccs@pipe-F-crc-primary-basic-yf-tiled-ccs
-kms_ccs@pipe-F-crc-primary-basic-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-F-crc-primary-basic-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-F-crc-primary-basic-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-F-crc-primary-basic-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-F-crc-primary-basic-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-F-crc-primary-basic-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-F-crc-primary-basic-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-F-crc-primary-basic-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-F-crc-primary-basic-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-F-crc-primary-rotation-180-y-tiled-ccs
-kms_ccs@pipe-F-crc-primary-rotation-180-yf-tiled-ccs
-kms_ccs@pipe-F-crc-primary-rotation-180-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-F-crc-primary-rotation-180-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-F-crc-primary-rotation-180-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-F-crc-primary-rotation-180-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-F-crc-primary-rotation-180-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-F-crc-primary-rotation-180-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-F-crc-primary-rotation-180-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-F-crc-primary-rotation-180-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-F-crc-primary-rotation-180-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-F-random-ccs-data-y-tiled-ccs
-kms_ccs@pipe-F-random-ccs-data-yf-tiled-ccs
-kms_ccs@pipe-F-random-ccs-data-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-F-random-ccs-data-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-F-random-ccs-data-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-F-random-ccs-data-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-F-random-ccs-data-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-F-random-ccs-data-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-F-random-ccs-data-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-F-random-ccs-data-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-F-random-ccs-data-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-F-missing-ccs-buffer-y-tiled-ccs
-kms_ccs@pipe-F-missing-ccs-buffer-yf-tiled-ccs
-kms_ccs@pipe-F-missing-ccs-buffer-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-F-missing-ccs-buffer-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-F-missing-ccs-buffer-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-F-missing-ccs-buffer-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-F-missing-ccs-buffer-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-F-missing-ccs-buffer-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-F-ccs-on-another-bo-y-tiled-ccs
-kms_ccs@pipe-F-ccs-on-another-bo-yf-tiled-ccs
-kms_ccs@pipe-F-ccs-on-another-bo-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-F-ccs-on-another-bo-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-F-ccs-on-another-bo-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-F-ccs-on-another-bo-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-F-ccs-on-another-bo-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-F-ccs-on-another-bo-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-F-bad-aux-stride-y-tiled-ccs
-kms_ccs@pipe-F-bad-aux-stride-yf-tiled-ccs
-kms_ccs@pipe-F-bad-aux-stride-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-F-bad-aux-stride-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-F-bad-aux-stride-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-F-bad-aux-stride-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-F-bad-aux-stride-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-F-bad-aux-stride-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-F-crc-sprite-planes-basic-y-tiled-ccs
-kms_ccs@pipe-F-crc-sprite-planes-basic-yf-tiled-ccs
-kms_ccs@pipe-F-crc-sprite-planes-basic-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-F-crc-sprite-planes-basic-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-F-crc-sprite-planes-basic-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-F-crc-sprite-planes-basic-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-F-crc-sprite-planes-basic-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-F-crc-sprite-planes-basic-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-F-crc-sprite-planes-basic-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-F-crc-sprite-planes-basic-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-F-crc-sprite-planes-basic-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-G-bad-pixel-format-y-tiled-ccs
-kms_ccs@pipe-G-bad-pixel-format-yf-tiled-ccs
-kms_ccs@pipe-G-bad-pixel-format-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-G-bad-pixel-format-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-G-bad-pixel-format-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-G-bad-pixel-format-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-G-bad-pixel-format-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-G-bad-pixel-format-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-G-bad-pixel-format-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-G-bad-pixel-format-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-G-bad-pixel-format-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-G-bad-rotation-90-y-tiled-ccs
-kms_ccs@pipe-G-bad-rotation-90-yf-tiled-ccs
-kms_ccs@pipe-G-bad-rotation-90-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-G-bad-rotation-90-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-G-bad-rotation-90-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-G-bad-rotation-90-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-G-bad-rotation-90-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-G-bad-rotation-90-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-G-bad-rotation-90-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-G-bad-rotation-90-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-G-bad-rotation-90-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-G-crc-primary-basic-y-tiled-ccs
-kms_ccs@pipe-G-crc-primary-basic-yf-tiled-ccs
-kms_ccs@pipe-G-crc-primary-basic-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-G-crc-primary-basic-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-G-crc-primary-basic-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-G-crc-primary-basic-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-G-crc-primary-basic-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-G-crc-primary-basic-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-G-crc-primary-basic-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-G-crc-primary-basic-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-G-crc-primary-basic-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-G-crc-primary-rotation-180-y-tiled-ccs
-kms_ccs@pipe-G-crc-primary-rotation-180-yf-tiled-ccs
-kms_ccs@pipe-G-crc-primary-rotation-180-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-G-crc-primary-rotation-180-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-G-crc-primary-rotation-180-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-G-crc-primary-rotation-180-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-G-crc-primary-rotation-180-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-G-crc-primary-rotation-180-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-G-crc-primary-rotation-180-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-G-crc-primary-rotation-180-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-G-crc-primary-rotation-180-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-G-random-ccs-data-y-tiled-ccs
-kms_ccs@pipe-G-random-ccs-data-yf-tiled-ccs
-kms_ccs@pipe-G-random-ccs-data-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-G-random-ccs-data-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-G-random-ccs-data-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-G-random-ccs-data-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-G-random-ccs-data-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-G-random-ccs-data-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-G-random-ccs-data-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-G-random-ccs-data-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-G-random-ccs-data-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-G-missing-ccs-buffer-y-tiled-ccs
-kms_ccs@pipe-G-missing-ccs-buffer-yf-tiled-ccs
-kms_ccs@pipe-G-missing-ccs-buffer-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-G-missing-ccs-buffer-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-G-missing-ccs-buffer-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-G-missing-ccs-buffer-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-G-missing-ccs-buffer-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-G-missing-ccs-buffer-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-G-ccs-on-another-bo-y-tiled-ccs
-kms_ccs@pipe-G-ccs-on-another-bo-yf-tiled-ccs
-kms_ccs@pipe-G-ccs-on-another-bo-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-G-ccs-on-another-bo-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-G-ccs-on-another-bo-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-G-ccs-on-another-bo-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-G-ccs-on-another-bo-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-G-ccs-on-another-bo-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-G-bad-aux-stride-y-tiled-ccs
-kms_ccs@pipe-G-bad-aux-stride-yf-tiled-ccs
-kms_ccs@pipe-G-bad-aux-stride-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-G-bad-aux-stride-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-G-bad-aux-stride-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-G-bad-aux-stride-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-G-bad-aux-stride-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-G-bad-aux-stride-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-G-crc-sprite-planes-basic-y-tiled-ccs
-kms_ccs@pipe-G-crc-sprite-planes-basic-yf-tiled-ccs
-kms_ccs@pipe-G-crc-sprite-planes-basic-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-G-crc-sprite-planes-basic-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-G-crc-sprite-planes-basic-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-G-crc-sprite-planes-basic-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-G-crc-sprite-planes-basic-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-G-crc-sprite-planes-basic-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-G-crc-sprite-planes-basic-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-G-crc-sprite-planes-basic-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-G-crc-sprite-planes-basic-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-H-bad-pixel-format-y-tiled-ccs
-kms_ccs@pipe-H-bad-pixel-format-yf-tiled-ccs
-kms_ccs@pipe-H-bad-pixel-format-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-H-bad-pixel-format-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-H-bad-pixel-format-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-H-bad-pixel-format-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-H-bad-pixel-format-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-H-bad-pixel-format-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-H-bad-pixel-format-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-H-bad-pixel-format-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-H-bad-pixel-format-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-H-bad-rotation-90-y-tiled-ccs
-kms_ccs@pipe-H-bad-rotation-90-yf-tiled-ccs
-kms_ccs@pipe-H-bad-rotation-90-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-H-bad-rotation-90-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-H-bad-rotation-90-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-H-bad-rotation-90-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-H-bad-rotation-90-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-H-bad-rotation-90-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-H-bad-rotation-90-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-H-bad-rotation-90-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-H-bad-rotation-90-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-H-crc-primary-basic-y-tiled-ccs
-kms_ccs@pipe-H-crc-primary-basic-yf-tiled-ccs
-kms_ccs@pipe-H-crc-primary-basic-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-H-crc-primary-basic-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-H-crc-primary-basic-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-H-crc-primary-basic-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-H-crc-primary-basic-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-H-crc-primary-basic-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-H-crc-primary-basic-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-H-crc-primary-basic-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-H-crc-primary-basic-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-H-crc-primary-rotation-180-y-tiled-ccs
-kms_ccs@pipe-H-crc-primary-rotation-180-yf-tiled-ccs
-kms_ccs@pipe-H-crc-primary-rotation-180-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-H-crc-primary-rotation-180-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-H-crc-primary-rotation-180-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-H-crc-primary-rotation-180-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-H-crc-primary-rotation-180-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-H-crc-primary-rotation-180-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-H-crc-primary-rotation-180-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-H-crc-primary-rotation-180-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-H-crc-primary-rotation-180-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-H-random-ccs-data-y-tiled-ccs
-kms_ccs@pipe-H-random-ccs-data-yf-tiled-ccs
-kms_ccs@pipe-H-random-ccs-data-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-H-random-ccs-data-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-H-random-ccs-data-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-H-random-ccs-data-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-H-random-ccs-data-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-H-random-ccs-data-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-H-random-ccs-data-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-H-random-ccs-data-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-H-random-ccs-data-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-H-missing-ccs-buffer-y-tiled-ccs
-kms_ccs@pipe-H-missing-ccs-buffer-yf-tiled-ccs
-kms_ccs@pipe-H-missing-ccs-buffer-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-H-missing-ccs-buffer-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-H-missing-ccs-buffer-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-H-missing-ccs-buffer-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-H-missing-ccs-buffer-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-H-missing-ccs-buffer-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-H-ccs-on-another-bo-y-tiled-ccs
-kms_ccs@pipe-H-ccs-on-another-bo-yf-tiled-ccs
-kms_ccs@pipe-H-ccs-on-another-bo-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-H-ccs-on-another-bo-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-H-ccs-on-another-bo-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-H-ccs-on-another-bo-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-H-ccs-on-another-bo-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-H-ccs-on-another-bo-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-H-bad-aux-stride-y-tiled-ccs
-kms_ccs@pipe-H-bad-aux-stride-yf-tiled-ccs
-kms_ccs@pipe-H-bad-aux-stride-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-H-bad-aux-stride-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-H-bad-aux-stride-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-H-bad-aux-stride-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-H-bad-aux-stride-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-H-bad-aux-stride-4-tiled-mtl-rc-ccs-cc
-kms_ccs@pipe-H-crc-sprite-planes-basic-y-tiled-ccs
-kms_ccs@pipe-H-crc-sprite-planes-basic-yf-tiled-ccs
-kms_ccs@pipe-H-crc-sprite-planes-basic-y-tiled-gen12-rc-ccs
-kms_ccs@pipe-H-crc-sprite-planes-basic-y-tiled-gen12-rc-ccs-cc
-kms_ccs@pipe-H-crc-sprite-planes-basic-y-tiled-gen12-mc-ccs
-kms_ccs@pipe-H-crc-sprite-planes-basic-4-tiled-dg2-rc-ccs
-kms_ccs@pipe-H-crc-sprite-planes-basic-4-tiled-dg2-mc-ccs
-kms_ccs@pipe-H-crc-sprite-planes-basic-4-tiled-dg2-rc-ccs-cc
-kms_ccs@pipe-H-crc-sprite-planes-basic-4-tiled-mtl-rc-ccs
-kms_ccs@pipe-H-crc-sprite-planes-basic-4-tiled-mtl-mc-ccs
-kms_ccs@pipe-H-crc-sprite-planes-basic-4-tiled-mtl-rc-ccs-cc
-kms_cdclk@plane-scaling
-kms_cdclk@mode-transition
-kms_cdclk@mode-transition-all-outputs
-kms_color@degamma
-kms_color@gamma
-kms_color@legacy-gamma
-kms_color@legacy-gamma-reset
-kms_color@ctm-red-to-blue
-kms_color@ctm-green-to-red
-kms_color@ctm-blue-to-red
-kms_color@ctm-max
-kms_color@ctm-negative
-kms_color@ctm-0-25
-kms_color@ctm-0-50
-kms_color@ctm-0-75
-kms_color@ctm-signed
-kms_color@deep-color
-kms_color@invalid-gamma-lut-sizes
-kms_color@invalid-degamma-lut-sizes
-kms_color@invalid-ctm-matrix-sizes
-kms_concurrent@multi-plane-atomic-lowres
-kms_content_protection@legacy
-kms_content_protection@atomic
-kms_content_protection@atomic-dpms
-kms_content_protection@lic
-kms_content_protection@type1
-kms_content_protection@mei-interface
-kms_content_protection@content-type-change
-kms_content_protection@uevent
-kms_content_protection@srm
-kms_content_protection@dp-mst-type-0
-kms_content_protection@dp-mst-lic-type-0
-kms_content_protection@dp-mst-type-1
-kms_content_protection@dp-mst-lic-type-1
-kms_cursor_crc@cursor-size-change
-kms_cursor_crc@cursor-alpha-opaque
-kms_cursor_crc@cursor-alpha-transparent
-kms_cursor_crc@cursor-dpms
-kms_cursor_crc@cursor-suspend
-kms_cursor_crc@cursor-onscreen-32x32
-kms_cursor_crc@cursor-offscreen-32x32
-kms_cursor_crc@cursor-sliding-32x32
-kms_cursor_crc@cursor-random-32x32
-kms_cursor_crc@cursor-rapid-movement-32x32
-kms_cursor_crc@cursor-onscreen-32x10
-kms_cursor_crc@cursor-offscreen-32x10
-kms_cursor_crc@cursor-sliding-32x10
-kms_cursor_crc@cursor-random-32x10
-kms_cursor_crc@cursor-rapid-movement-32x10
-kms_cursor_crc@cursor-onscreen-64x64
-kms_cursor_crc@cursor-offscreen-64x64
-kms_cursor_crc@cursor-sliding-64x64
-kms_cursor_crc@cursor-random-64x64
-kms_cursor_crc@cursor-rapid-movement-64x64
-kms_cursor_crc@cursor-onscreen-64x21
-kms_cursor_crc@cursor-offscreen-64x21
-kms_cursor_crc@cursor-sliding-64x21
-kms_cursor_crc@cursor-random-64x21
-kms_cursor_crc@cursor-rapid-movement-64x21
-kms_cursor_crc@cursor-onscreen-128x128
-kms_cursor_crc@cursor-offscreen-128x128
-kms_cursor_crc@cursor-sliding-128x128
-kms_cursor_crc@cursor-random-128x128
-kms_cursor_crc@cursor-rapid-movement-128x128
-kms_cursor_crc@cursor-onscreen-128x42
-kms_cursor_crc@cursor-offscreen-128x42
-kms_cursor_crc@cursor-sliding-128x42
-kms_cursor_crc@cursor-random-128x42
-kms_cursor_crc@cursor-rapid-movement-128x42
-kms_cursor_crc@cursor-onscreen-256x256
-kms_cursor_crc@cursor-offscreen-256x256
-kms_cursor_crc@cursor-sliding-256x256
-kms_cursor_crc@cursor-random-256x256
-kms_cursor_crc@cursor-rapid-movement-256x256
-kms_cursor_crc@cursor-onscreen-256x85
-kms_cursor_crc@cursor-offscreen-256x85
-kms_cursor_crc@cursor-sliding-256x85
-kms_cursor_crc@cursor-random-256x85
-kms_cursor_crc@cursor-rapid-movement-256x85
-kms_cursor_crc@cursor-onscreen-512x512
-kms_cursor_crc@cursor-offscreen-512x512
-kms_cursor_crc@cursor-sliding-512x512
-kms_cursor_crc@cursor-random-512x512
-kms_cursor_crc@cursor-rapid-movement-512x512
-kms_cursor_crc@cursor-onscreen-512x170
-kms_cursor_crc@cursor-offscreen-512x170
-kms_cursor_crc@cursor-sliding-512x170
-kms_cursor_crc@cursor-random-512x170
-kms_cursor_crc@cursor-rapid-movement-512x170
-kms_cursor_crc@cursor-onscreen-max-size
-kms_cursor_crc@cursor-offscreen-max-size
-kms_cursor_crc@cursor-sliding-max-size
-kms_cursor_crc@cursor-random-max-size
-kms_cursor_crc@cursor-rapid-movement-max-size
-kms_cursor_legacy@single-bo
-kms_cursor_legacy@single-move
-kms_cursor_legacy@forked-bo
-kms_cursor_legacy@forked-move
-kms_cursor_legacy@torture-bo
-kms_cursor_legacy@torture-move
-kms_cursor_legacy@nonblocking-modeset-vs-cursor-atomic
-kms_cursor_legacy@long-nonblocking-modeset-vs-cursor-atomic
-kms_cursor_legacy@2x-flip-vs-cursor-legacy
-kms_cursor_legacy@2x-flip-vs-cursor-atomic
-kms_cursor_legacy@2x-long-flip-vs-cursor-legacy
-kms_cursor_legacy@2x-long-flip-vs-cursor-atomic
-kms_cursor_legacy@2x-nonblocking-modeset-vs-cursor-atomic
-kms_cursor_legacy@2x-long-nonblocking-modeset-vs-cursor-atomic
-kms_cursor_legacy@2x-cursor-vs-flip-legacy
-kms_cursor_legacy@2x-long-cursor-vs-flip-legacy
-kms_cursor_legacy@2x-cursor-vs-flip-atomic
-kms_cursor_legacy@2x-long-cursor-vs-flip-atomic
-kms_cursor_legacy@flip-vs-cursor-crc-legacy
-kms_cursor_legacy@flip-vs-cursor-crc-atomic
-kms_cursor_legacy@flip-vs-cursor-busy-crc-legacy
-kms_cursor_legacy@flip-vs-cursor-busy-crc-atomic
-kms_cursor_legacy@basic-flip-before-cursor-legacy
-kms_cursor_legacy@basic-busy-flip-before-cursor-legacy
-kms_cursor_legacy@basic-flip-after-cursor-legacy
-kms_cursor_legacy@basic-flip-before-cursor-varying-size
-kms_cursor_legacy@basic-busy-flip-before-cursor-varying-size
-kms_cursor_legacy@basic-flip-after-cursor-varying-size
-kms_cursor_legacy@short-flip-before-cursor-toggle
-kms_cursor_legacy@short-busy-flip-before-cursor-toggle
-kms_cursor_legacy@short-flip-after-cursor-toggle
-kms_cursor_legacy@basic-flip-before-cursor-atomic
-kms_cursor_legacy@basic-busy-flip-before-cursor-atomic
-kms_cursor_legacy@basic-flip-after-cursor-atomic
-kms_cursor_legacy@short-flip-before-cursor-atomic-transitions
-kms_cursor_legacy@short-busy-flip-before-cursor-atomic-transitions
-kms_cursor_legacy@short-flip-after-cursor-atomic-transitions
-kms_cursor_legacy@short-flip-before-cursor-atomic-transitions-varying-size
-kms_cursor_legacy@short-busy-flip-before-cursor-atomic-transitions-varying-size
-kms_cursor_legacy@short-flip-after-cursor-atomic-transitions-varying-size
-kms_cursor_legacy@cursor-vs-flip-legacy
-kms_cursor_legacy@flip-vs-cursor-legacy
-kms_cursor_legacy@cursorA-vs-flipA-legacy
-kms_cursor_legacy@cursorA-vs-flipB-legacy
-kms_cursor_legacy@cursorB-vs-flipA-legacy
-kms_cursor_legacy@cursorB-vs-flipB-legacy
-kms_cursor_legacy@cursor-vs-flip-varying-size
-kms_cursor_legacy@flip-vs-cursor-varying-size
-kms_cursor_legacy@cursorA-vs-flipA-varying-size
-kms_cursor_legacy@cursorA-vs-flipB-varying-size
-kms_cursor_legacy@cursorB-vs-flipA-varying-size
-kms_cursor_legacy@cursorB-vs-flipB-varying-size
-kms_cursor_legacy@cursor-vs-flip-toggle
-kms_cursor_legacy@flip-vs-cursor-toggle
-kms_cursor_legacy@cursorA-vs-flipA-toggle
-kms_cursor_legacy@cursorA-vs-flipB-toggle
-kms_cursor_legacy@cursorB-vs-flipA-toggle
-kms_cursor_legacy@cursorB-vs-flipB-toggle
-kms_cursor_legacy@cursor-vs-flip-atomic
-kms_cursor_legacy@flip-vs-cursor-atomic
-kms_cursor_legacy@cursorA-vs-flipA-atomic
-kms_cursor_legacy@cursorA-vs-flipB-atomic
-kms_cursor_legacy@cursorB-vs-flipA-atomic
-kms_cursor_legacy@cursorB-vs-flipB-atomic
-kms_cursor_legacy@cursor-vs-flip-atomic-transitions
-kms_cursor_legacy@flip-vs-cursor-atomic-transitions
-kms_cursor_legacy@cursorA-vs-flipA-atomic-transitions
-kms_cursor_legacy@cursorA-vs-flipB-atomic-transitions
-kms_cursor_legacy@cursorB-vs-flipA-atomic-transitions
-kms_cursor_legacy@cursorB-vs-flipB-atomic-transitions
-kms_cursor_legacy@cursor-vs-flip-atomic-transitions-varying-size
-kms_cursor_legacy@flip-vs-cursor-atomic-transitions-varying-size
-kms_cursor_legacy@cursorA-vs-flipA-atomic-transitions-varying-size
-kms_cursor_legacy@cursorA-vs-flipB-atomic-transitions-varying-size
-kms_cursor_legacy@cursorB-vs-flipA-atomic-transitions-varying-size
-kms_cursor_legacy@cursorB-vs-flipB-atomic-transitions-varying-size
-kms_dither@fb-8bpc-vs-panel-6bpc
-kms_dither@fb-8bpc-vs-panel-8bpc
-kms_dp_aux_dev
-kms_tiled_display@basic-test-pattern
-kms_tiled_display@basic-test-pattern-with-chamelium
-kms_draw_crc@draw-method-mmap-cpu
-kms_draw_crc@draw-method-mmap-gtt
-kms_draw_crc@draw-method-mmap-wc
-kms_draw_crc@draw-method-pwrite
-kms_draw_crc@draw-method-blt
-kms_draw_crc@draw-method-render
-kms_draw_crc@fill-fb
-kms_dsc@dsc-basic
-kms_dsc@dsc-with-formats
-kms_dsc@dsc-with-bpc
-kms_dsc@dsc-with-bpc-formats
-kms_dsc@dsc-with-output-formats
-kms_fbcon_fbt@fbc
-kms_fbcon_fbt@psr
-kms_fbcon_fbt@fbc-suspend
-kms_fbcon_fbt@psr-suspend
-kms_fence_pin_leak
-kms_flip@nonblocking-read
-kms_flip@wf_vblank-ts-check
-kms_flip@2x-wf_vblank-ts-check
-kms_flip@blocking-wf_vblank
-kms_flip@2x-blocking-wf_vblank
-kms_flip@absolute-wf_vblank
-kms_flip@2x-absolute-wf_vblank
-kms_flip@blocking-absolute-wf_vblank
-kms_flip@2x-blocking-absolute-wf_vblank
-kms_flip@basic-plain-flip
-kms_flip@2x-plain-flip
-kms_flip@busy-flip
-kms_flip@2x-busy-flip
-kms_flip@flip-vs-fences
-kms_flip@2x-flip-vs-fences
-kms_flip@plain-flip-ts-check
-kms_flip@2x-plain-flip-ts-check
-kms_flip@plain-flip-fb-recreate
-kms_flip@2x-plain-flip-fb-recreate
-kms_flip@flip-vs-rmfb
-kms_flip@2x-flip-vs-rmfb
-kms_flip@basic-flip-vs-dpms
-kms_flip@2x-flip-vs-dpms
-kms_flip@flip-vs-panning
-kms_flip@2x-flip-vs-panning
-kms_flip@basic-flip-vs-modeset
-kms_flip@2x-flip-vs-modeset
-kms_flip@flip-vs-expired-vblank
-kms_flip@2x-flip-vs-expired-vblank
-kms_flip@flip-vs-absolute-wf_vblank
-kms_flip@2x-flip-vs-absolute-wf_vblank
-kms_flip@basic-flip-vs-wf_vblank
-kms_flip@2x-flip-vs-wf_vblank
-kms_flip@flip-vs-blocking-wf-vblank
-kms_flip@2x-flip-vs-blocking-wf-vblank
-kms_flip@flip-vs-modeset-vs-hang
-kms_flip@2x-flip-vs-modeset-vs-hang
-kms_flip@flip-vs-panning-vs-hang
-kms_flip@2x-flip-vs-panning-vs-hang
-kms_flip@flip-vs-dpms-off-vs-modeset
-kms_flip@2x-flip-vs-dpms-off-vs-modeset
-kms_flip@single-buffer-flip-vs-dpms-off-vs-modeset
-kms_flip@2x-single-buffer-flip-vs-dpms-off-vs-modeset
-kms_flip@dpms-off-confusion
-kms_flip@nonexisting-fb
-kms_flip@2x-nonexisting-fb
-kms_flip@dpms-vs-vblank-race
-kms_flip@2x-dpms-vs-vblank-race
-kms_flip@modeset-vs-vblank-race
-kms_flip@2x-modeset-vs-vblank-race
-kms_flip@bo-too-big
-kms_flip@flip-vs-suspend
-kms_flip@2x-flip-vs-suspend
-kms_flip@wf_vblank-ts-check-interruptible
-kms_flip@2x-wf_vblank-ts-check-interruptible
-kms_flip@absolute-wf_vblank-interruptible
-kms_flip@2x-absolute-wf_vblank-interruptible
-kms_flip@blocking-absolute-wf_vblank-interruptible
-kms_flip@2x-blocking-absolute-wf_vblank-interruptible
-kms_flip@plain-flip-interruptible
-kms_flip@2x-plain-flip-interruptible
-kms_flip@flip-vs-fences-interruptible
-kms_flip@2x-flip-vs-fences-interruptible
-kms_flip@plain-flip-ts-check-interruptible
-kms_flip@2x-plain-flip-ts-check-interruptible
-kms_flip@plain-flip-fb-recreate-interruptible
-kms_flip@2x-plain-flip-fb-recreate-interruptible
-kms_flip@flip-vs-rmfb-interruptible
-kms_flip@2x-flip-vs-rmfb-interruptible
-kms_flip@flip-vs-panning-interruptible
-kms_flip@2x-flip-vs-panning-interruptible
-kms_flip@flip-vs-expired-vblank-interruptible
-kms_flip@2x-flip-vs-expired-vblank-interruptible
-kms_flip@flip-vs-absolute-wf_vblank-interruptible
-kms_flip@2x-flip-vs-absolute-wf_vblank-interruptible
-kms_flip@flip-vs-wf_vblank-interruptible
-kms_flip@2x-flip-vs-wf_vblank-interruptible
-kms_flip@flip-vs-dpms-off-vs-modeset-interruptible
-kms_flip@2x-flip-vs-dpms-off-vs-modeset-interruptible
-kms_flip@single-buffer-flip-vs-dpms-off-vs-modeset-interruptible
-kms_flip@2x-single-buffer-flip-vs-dpms-off-vs-modeset-interruptible
-kms_flip@dpms-off-confusion-interruptible
-kms_flip@nonexisting-fb-interruptible
-kms_flip@2x-nonexisting-fb-interruptible
-kms_flip@dpms-vs-vblank-race-interruptible
-kms_flip@2x-dpms-vs-vblank-race-interruptible
-kms_flip@modeset-vs-vblank-race-interruptible
-kms_flip@2x-modeset-vs-vblank-race-interruptible
-kms_flip@bo-too-big-interruptible
-kms_flip@flip-vs-suspend-interruptible
-kms_flip@2x-flip-vs-suspend-interruptible
-kms_flip_event_leak@basic
-kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-downscaling
-kms_flip_scaled_crc@flip-32bpp-yftile-to-64bpp-yftile-downscaling
-kms_flip_scaled_crc@flip-32bpp-xtile-to-64bpp-xtile-downscaling
-kms_flip_scaled_crc@flip-32bpp-4tile-to-64bpp-4tile-downscaling
-kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-downscaling
-kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-downscaling
-kms_flip_scaled_crc@flip-64bpp-yftile-to-32bpp-yftile-downscaling
-kms_flip_scaled_crc@flip-64bpp-xtile-to-32bpp-xtile-downscaling
-kms_flip_scaled_crc@flip-64bpp-4tile-to-32bpp-4tile-downscaling
-kms_flip_scaled_crc@flip-64bpp-linear-to-32bpp-linear-downscaling
-kms_flip_scaled_crc@flip-64bpp-ytile-to-16bpp-ytile-downscaling
-kms_flip_scaled_crc@flip-64bpp-yftile-to-16bpp-yftile-downscaling
-kms_flip_scaled_crc@flip-64bpp-xtile-to-16bpp-xtile-downscaling
-kms_flip_scaled_crc@flip-64bpp-4tile-to-16bpp-4tile-downscaling
-kms_flip_scaled_crc@flip-64bpp-linear-to-16bpp-linear-downscaling
-kms_flip_scaled_crc@flip-32bpp-ytileccs-to-64bpp-ytile-downscaling
-kms_flip_scaled_crc@flip-32bpp-yftileccs-to-64bpp-yftile-downscaling
-kms_flip_scaled_crc@flip-32bpp-ytile-to-32bpp-ytilegen12rcccs-downscaling
-kms_flip_scaled_crc@flip-32bpp-4tile-to-32bpp-4tiledg2rcccs-downscaling
-kms_flip_scaled_crc@flip-32bpp-ytile-to-32bpp-ytileccs-downscaling
-kms_flip_scaled_crc@flip-32bpp-yftile-to-32bpp-yftileccs-downscaling
-kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilercccs-downscaling
-kms_flip_scaled_crc@flip-64bpp-4tile-to-32bpp-4tiledg2rcccs-downscaling
-kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-upscaling
-kms_flip_scaled_crc@flip-32bpp-yftile-to-64bpp-yftile-upscaling
-kms_flip_scaled_crc@flip-32bpp-xtile-to-64bpp-xtile-upscaling
-kms_flip_scaled_crc@flip-32bpp-4tile-to-64bpp-4tile-upscaling
-kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-upscaling
-kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-upscaling
-kms_flip_scaled_crc@flip-64bpp-yftile-to-32bpp-yftile-upscaling
-kms_flip_scaled_crc@flip-64bpp-xtile-to-32bpp-xtile-upscaling
-kms_flip_scaled_crc@flip-64bpp-4tile-to-32bpp-4tile-upscaling
-kms_flip_scaled_crc@flip-64bpp-linear-to-32bpp-linear-upscaling
-kms_flip_scaled_crc@flip-64bpp-ytile-to-16bpp-ytile-upscaling
-kms_flip_scaled_crc@flip-64bpp-yftile-to-16bpp-yftile-upscaling
-kms_flip_scaled_crc@flip-64bpp-xtile-to-16bpp-xtile-upscaling
-kms_flip_scaled_crc@flip-64bpp-4tile-to-16bpp-4tile-upscaling
-kms_flip_scaled_crc@flip-64bpp-linear-to-16bpp-linear-upscaling
-kms_flip_scaled_crc@flip-32bpp-ytileccs-to-64bpp-ytile-upscaling
-kms_flip_scaled_crc@flip-32bpp-yftileccs-to-64bpp-yftile-upscaling
-kms_flip_scaled_crc@flip-32bpp-ytile-to-32bpp-ytilegen12rcccs-upscaling
-kms_flip_scaled_crc@flip-32bpp-4tile-to-32bpp-4tiledg2rcccs-upscaling
-kms_flip_scaled_crc@flip-32bpp-ytile-to-32bpp-ytileccs-upscaling
-kms_flip_scaled_crc@flip-32bpp-yftile-to-32bpp-yftileccs-upscaling
-kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilegen12rcccs-upscaling
-kms_flip_scaled_crc@flip-64bpp-4tile-to-32bpp-4tiledg2rcccs-upscaling
-kms_force_connector_basic@force-load-detect
-kms_force_connector_basic@force-connector-state
-kms_force_connector_basic@force-edid
-kms_force_connector_basic@prune-stale-modes
-kms_frontbuffer_tracking@fbc-1p-rte
-kms_frontbuffer_tracking@fbc-2p-rte
-kms_frontbuffer_tracking@psr-1p-rte
-kms_frontbuffer_tracking@psr-2p-rte
-kms_frontbuffer_tracking@fbcpsr-1p-rte
-kms_frontbuffer_tracking@fbcpsr-2p-rte
-kms_frontbuffer_tracking@drrs-1p-rte
-kms_frontbuffer_tracking@drrs-2p-rte
-kms_frontbuffer_tracking@fbcdrrs-1p-rte
-kms_frontbuffer_tracking@fbcdrrs-2p-rte
-kms_frontbuffer_tracking@psrdrrs-1p-rte
-kms_frontbuffer_tracking@psrdrrs-2p-rte
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-rte
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-rte
-kms_frontbuffer_tracking@fbc-1p-primscrn-pri-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbc-1p-primscrn-pri-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbc-1p-primscrn-pri-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbc-1p-primscrn-pri-indfb-draw-pwrite
-kms_frontbuffer_tracking@fbc-1p-primscrn-pri-indfb-draw-blt
-kms_frontbuffer_tracking@fbc-1p-primscrn-pri-indfb-draw-render
-kms_frontbuffer_tracking@fbc-1p-primscrn-pri-shrfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbc-1p-primscrn-pri-shrfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbc-1p-primscrn-pri-shrfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbc-1p-primscrn-pri-shrfb-draw-pwrite
-kms_frontbuffer_tracking@fbc-1p-primscrn-pri-shrfb-draw-blt
-kms_frontbuffer_tracking@fbc-1p-primscrn-pri-shrfb-draw-render
-kms_frontbuffer_tracking@fbc-1p-primscrn-cur-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbc-1p-primscrn-cur-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbc-1p-primscrn-cur-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbc-1p-primscrn-cur-indfb-draw-pwrite
-kms_frontbuffer_tracking@fbc-1p-primscrn-cur-indfb-draw-blt
-kms_frontbuffer_tracking@fbc-1p-primscrn-cur-indfb-draw-render
-kms_frontbuffer_tracking@fbc-1p-primscrn-spr-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbc-1p-primscrn-spr-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbc-1p-primscrn-spr-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbc-1p-primscrn-spr-indfb-draw-pwrite
-kms_frontbuffer_tracking@fbc-1p-primscrn-spr-indfb-draw-blt
-kms_frontbuffer_tracking@fbc-1p-primscrn-spr-indfb-draw-render
-kms_frontbuffer_tracking@fbc-1p-offscren-pri-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbc-1p-offscren-pri-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbc-1p-offscren-pri-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbc-1p-offscren-pri-indfb-draw-pwrite
-kms_frontbuffer_tracking@fbc-1p-offscren-pri-indfb-draw-blt
-kms_frontbuffer_tracking@fbc-1p-offscren-pri-indfb-draw-render
-kms_frontbuffer_tracking@fbc-1p-offscren-pri-shrfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbc-1p-offscren-pri-shrfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbc-1p-offscren-pri-shrfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbc-1p-offscren-pri-shrfb-draw-pwrite
-kms_frontbuffer_tracking@fbc-1p-offscren-pri-shrfb-draw-blt
-kms_frontbuffer_tracking@fbc-1p-offscren-pri-shrfb-draw-render
-kms_frontbuffer_tracking@fbc-2p-primscrn-pri-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbc-2p-primscrn-pri-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbc-2p-primscrn-pri-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbc-2p-primscrn-pri-indfb-draw-pwrite
-kms_frontbuffer_tracking@fbc-2p-primscrn-pri-indfb-draw-blt
-kms_frontbuffer_tracking@fbc-2p-primscrn-pri-indfb-draw-render
-kms_frontbuffer_tracking@fbc-2p-primscrn-pri-shrfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbc-2p-primscrn-pri-shrfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbc-2p-primscrn-pri-shrfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbc-2p-primscrn-pri-shrfb-draw-pwrite
-kms_frontbuffer_tracking@fbc-2p-primscrn-pri-shrfb-draw-blt
-kms_frontbuffer_tracking@fbc-2p-primscrn-pri-shrfb-draw-render
-kms_frontbuffer_tracking@fbc-2p-primscrn-cur-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbc-2p-primscrn-cur-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbc-2p-primscrn-cur-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbc-2p-primscrn-cur-indfb-draw-pwrite
-kms_frontbuffer_tracking@fbc-2p-primscrn-cur-indfb-draw-blt
-kms_frontbuffer_tracking@fbc-2p-primscrn-cur-indfb-draw-render
-kms_frontbuffer_tracking@fbc-2p-primscrn-spr-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbc-2p-primscrn-spr-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbc-2p-primscrn-spr-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbc-2p-primscrn-spr-indfb-draw-pwrite
-kms_frontbuffer_tracking@fbc-2p-primscrn-spr-indfb-draw-blt
-kms_frontbuffer_tracking@fbc-2p-primscrn-spr-indfb-draw-render
-kms_frontbuffer_tracking@fbc-2p-scndscrn-pri-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbc-2p-scndscrn-pri-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbc-2p-scndscrn-pri-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbc-2p-scndscrn-pri-indfb-draw-pwrite
-kms_frontbuffer_tracking@fbc-2p-scndscrn-pri-indfb-draw-blt
-kms_frontbuffer_tracking@fbc-2p-scndscrn-pri-indfb-draw-render
-kms_frontbuffer_tracking@fbc-2p-scndscrn-pri-shrfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbc-2p-scndscrn-pri-shrfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbc-2p-scndscrn-pri-shrfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbc-2p-scndscrn-pri-shrfb-draw-pwrite
-kms_frontbuffer_tracking@fbc-2p-scndscrn-pri-shrfb-draw-blt
-kms_frontbuffer_tracking@fbc-2p-scndscrn-pri-shrfb-draw-render
-kms_frontbuffer_tracking@fbc-2p-scndscrn-cur-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbc-2p-scndscrn-cur-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbc-2p-scndscrn-cur-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbc-2p-scndscrn-cur-indfb-draw-pwrite
-kms_frontbuffer_tracking@fbc-2p-scndscrn-cur-indfb-draw-blt
-kms_frontbuffer_tracking@fbc-2p-scndscrn-cur-indfb-draw-render
-kms_frontbuffer_tracking@fbc-2p-scndscrn-spr-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbc-2p-scndscrn-spr-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbc-2p-scndscrn-spr-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbc-2p-scndscrn-spr-indfb-draw-pwrite
-kms_frontbuffer_tracking@fbc-2p-scndscrn-spr-indfb-draw-blt
-kms_frontbuffer_tracking@fbc-2p-scndscrn-spr-indfb-draw-render
-kms_frontbuffer_tracking@psr-1p-primscrn-pri-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@psr-1p-primscrn-pri-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@psr-1p-primscrn-pri-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@psr-1p-primscrn-pri-indfb-draw-pwrite
-kms_frontbuffer_tracking@psr-1p-primscrn-pri-indfb-draw-blt
-kms_frontbuffer_tracking@psr-1p-primscrn-pri-indfb-draw-render
-kms_frontbuffer_tracking@psr-1p-primscrn-pri-shrfb-draw-mmap-cpu
-kms_frontbuffer_tracking@psr-1p-primscrn-pri-shrfb-draw-mmap-gtt
-kms_frontbuffer_tracking@psr-1p-primscrn-pri-shrfb-draw-mmap-wc
-kms_frontbuffer_tracking@psr-1p-primscrn-pri-shrfb-draw-pwrite
-kms_frontbuffer_tracking@psr-1p-primscrn-pri-shrfb-draw-blt
-kms_frontbuffer_tracking@psr-1p-primscrn-pri-shrfb-draw-render
-kms_frontbuffer_tracking@psr-1p-primscrn-cur-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@psr-1p-primscrn-cur-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@psr-1p-primscrn-cur-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@psr-1p-primscrn-cur-indfb-draw-pwrite
-kms_frontbuffer_tracking@psr-1p-primscrn-cur-indfb-draw-blt
-kms_frontbuffer_tracking@psr-1p-primscrn-cur-indfb-draw-render
-kms_frontbuffer_tracking@psr-1p-primscrn-spr-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@psr-1p-primscrn-spr-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@psr-1p-primscrn-spr-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@psr-1p-primscrn-spr-indfb-draw-pwrite
-kms_frontbuffer_tracking@psr-1p-primscrn-spr-indfb-draw-blt
-kms_frontbuffer_tracking@psr-1p-primscrn-spr-indfb-draw-render
-kms_frontbuffer_tracking@psr-1p-offscren-pri-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@psr-1p-offscren-pri-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@psr-1p-offscren-pri-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@psr-1p-offscren-pri-indfb-draw-pwrite
-kms_frontbuffer_tracking@psr-1p-offscren-pri-indfb-draw-blt
-kms_frontbuffer_tracking@psr-1p-offscren-pri-indfb-draw-render
-kms_frontbuffer_tracking@psr-1p-offscren-pri-shrfb-draw-mmap-cpu
-kms_frontbuffer_tracking@psr-1p-offscren-pri-shrfb-draw-mmap-gtt
-kms_frontbuffer_tracking@psr-1p-offscren-pri-shrfb-draw-mmap-wc
-kms_frontbuffer_tracking@psr-1p-offscren-pri-shrfb-draw-pwrite
-kms_frontbuffer_tracking@psr-1p-offscren-pri-shrfb-draw-blt
-kms_frontbuffer_tracking@psr-1p-offscren-pri-shrfb-draw-render
-kms_frontbuffer_tracking@psr-2p-primscrn-pri-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@psr-2p-primscrn-pri-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@psr-2p-primscrn-pri-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@psr-2p-primscrn-pri-indfb-draw-pwrite
-kms_frontbuffer_tracking@psr-2p-primscrn-pri-indfb-draw-blt
-kms_frontbuffer_tracking@psr-2p-primscrn-pri-indfb-draw-render
-kms_frontbuffer_tracking@psr-2p-primscrn-pri-shrfb-draw-mmap-cpu
-kms_frontbuffer_tracking@psr-2p-primscrn-pri-shrfb-draw-mmap-gtt
-kms_frontbuffer_tracking@psr-2p-primscrn-pri-shrfb-draw-mmap-wc
-kms_frontbuffer_tracking@psr-2p-primscrn-pri-shrfb-draw-pwrite
-kms_frontbuffer_tracking@psr-2p-primscrn-pri-shrfb-draw-blt
-kms_frontbuffer_tracking@psr-2p-primscrn-pri-shrfb-draw-render
-kms_frontbuffer_tracking@psr-2p-primscrn-cur-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@psr-2p-primscrn-cur-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@psr-2p-primscrn-cur-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@psr-2p-primscrn-cur-indfb-draw-pwrite
-kms_frontbuffer_tracking@psr-2p-primscrn-cur-indfb-draw-blt
-kms_frontbuffer_tracking@psr-2p-primscrn-cur-indfb-draw-render
-kms_frontbuffer_tracking@psr-2p-primscrn-spr-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@psr-2p-primscrn-spr-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@psr-2p-primscrn-spr-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@psr-2p-primscrn-spr-indfb-draw-pwrite
-kms_frontbuffer_tracking@psr-2p-primscrn-spr-indfb-draw-blt
-kms_frontbuffer_tracking@psr-2p-primscrn-spr-indfb-draw-render
-kms_frontbuffer_tracking@psr-2p-scndscrn-pri-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@psr-2p-scndscrn-pri-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@psr-2p-scndscrn-pri-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@psr-2p-scndscrn-pri-indfb-draw-pwrite
-kms_frontbuffer_tracking@psr-2p-scndscrn-pri-indfb-draw-blt
-kms_frontbuffer_tracking@psr-2p-scndscrn-pri-indfb-draw-render
-kms_frontbuffer_tracking@psr-2p-scndscrn-pri-shrfb-draw-mmap-cpu
-kms_frontbuffer_tracking@psr-2p-scndscrn-pri-shrfb-draw-mmap-gtt
-kms_frontbuffer_tracking@psr-2p-scndscrn-pri-shrfb-draw-mmap-wc
-kms_frontbuffer_tracking@psr-2p-scndscrn-pri-shrfb-draw-pwrite
-kms_frontbuffer_tracking@psr-2p-scndscrn-pri-shrfb-draw-blt
-kms_frontbuffer_tracking@psr-2p-scndscrn-pri-shrfb-draw-render
-kms_frontbuffer_tracking@psr-2p-scndscrn-cur-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@psr-2p-scndscrn-cur-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@psr-2p-scndscrn-cur-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@psr-2p-scndscrn-cur-indfb-draw-pwrite
-kms_frontbuffer_tracking@psr-2p-scndscrn-cur-indfb-draw-blt
-kms_frontbuffer_tracking@psr-2p-scndscrn-cur-indfb-draw-render
-kms_frontbuffer_tracking@psr-2p-scndscrn-spr-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@psr-2p-scndscrn-spr-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@psr-2p-scndscrn-spr-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@psr-2p-scndscrn-spr-indfb-draw-pwrite
-kms_frontbuffer_tracking@psr-2p-scndscrn-spr-indfb-draw-blt
-kms_frontbuffer_tracking@psr-2p-scndscrn-spr-indfb-draw-render
-kms_frontbuffer_tracking@fbcpsr-1p-primscrn-pri-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcpsr-1p-primscrn-pri-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcpsr-1p-primscrn-pri-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbcpsr-1p-primscrn-pri-indfb-draw-pwrite
-kms_frontbuffer_tracking@fbcpsr-1p-primscrn-pri-indfb-draw-blt
-kms_frontbuffer_tracking@fbcpsr-1p-primscrn-pri-indfb-draw-render
-kms_frontbuffer_tracking@fbcpsr-1p-primscrn-pri-shrfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcpsr-1p-primscrn-pri-shrfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcpsr-1p-primscrn-pri-shrfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbcpsr-1p-primscrn-pri-shrfb-draw-pwrite
-kms_frontbuffer_tracking@fbcpsr-1p-primscrn-pri-shrfb-draw-blt
-kms_frontbuffer_tracking@fbcpsr-1p-primscrn-pri-shrfb-draw-render
-kms_frontbuffer_tracking@fbcpsr-1p-primscrn-cur-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcpsr-1p-primscrn-cur-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcpsr-1p-primscrn-cur-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbcpsr-1p-primscrn-cur-indfb-draw-pwrite
-kms_frontbuffer_tracking@fbcpsr-1p-primscrn-cur-indfb-draw-blt
-kms_frontbuffer_tracking@fbcpsr-1p-primscrn-cur-indfb-draw-render
-kms_frontbuffer_tracking@fbcpsr-1p-primscrn-spr-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcpsr-1p-primscrn-spr-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcpsr-1p-primscrn-spr-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbcpsr-1p-primscrn-spr-indfb-draw-pwrite
-kms_frontbuffer_tracking@fbcpsr-1p-primscrn-spr-indfb-draw-blt
-kms_frontbuffer_tracking@fbcpsr-1p-primscrn-spr-indfb-draw-render
-kms_frontbuffer_tracking@fbcpsr-1p-offscren-pri-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcpsr-1p-offscren-pri-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcpsr-1p-offscren-pri-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbcpsr-1p-offscren-pri-indfb-draw-pwrite
-kms_frontbuffer_tracking@fbcpsr-1p-offscren-pri-indfb-draw-blt
-kms_frontbuffer_tracking@fbcpsr-1p-offscren-pri-indfb-draw-render
-kms_frontbuffer_tracking@fbcpsr-1p-offscren-pri-shrfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcpsr-1p-offscren-pri-shrfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcpsr-1p-offscren-pri-shrfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbcpsr-1p-offscren-pri-shrfb-draw-pwrite
-kms_frontbuffer_tracking@fbcpsr-1p-offscren-pri-shrfb-draw-blt
-kms_frontbuffer_tracking@fbcpsr-1p-offscren-pri-shrfb-draw-render
-kms_frontbuffer_tracking@fbcpsr-2p-primscrn-pri-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcpsr-2p-primscrn-pri-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcpsr-2p-primscrn-pri-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbcpsr-2p-primscrn-pri-indfb-draw-pwrite
-kms_frontbuffer_tracking@fbcpsr-2p-primscrn-pri-indfb-draw-blt
-kms_frontbuffer_tracking@fbcpsr-2p-primscrn-pri-indfb-draw-render
-kms_frontbuffer_tracking@fbcpsr-2p-primscrn-pri-shrfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcpsr-2p-primscrn-pri-shrfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcpsr-2p-primscrn-pri-shrfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbcpsr-2p-primscrn-pri-shrfb-draw-pwrite
-kms_frontbuffer_tracking@fbcpsr-2p-primscrn-pri-shrfb-draw-blt
-kms_frontbuffer_tracking@fbcpsr-2p-primscrn-pri-shrfb-draw-render
-kms_frontbuffer_tracking@fbcpsr-2p-primscrn-cur-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcpsr-2p-primscrn-cur-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcpsr-2p-primscrn-cur-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbcpsr-2p-primscrn-cur-indfb-draw-pwrite
-kms_frontbuffer_tracking@fbcpsr-2p-primscrn-cur-indfb-draw-blt
-kms_frontbuffer_tracking@fbcpsr-2p-primscrn-cur-indfb-draw-render
-kms_frontbuffer_tracking@fbcpsr-2p-primscrn-spr-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcpsr-2p-primscrn-spr-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcpsr-2p-primscrn-spr-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbcpsr-2p-primscrn-spr-indfb-draw-pwrite
-kms_frontbuffer_tracking@fbcpsr-2p-primscrn-spr-indfb-draw-blt
-kms_frontbuffer_tracking@fbcpsr-2p-primscrn-spr-indfb-draw-render
-kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-pri-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-pri-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-pri-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-pri-indfb-draw-pwrite
-kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-pri-indfb-draw-blt
-kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-pri-indfb-draw-render
-kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-pri-shrfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-pri-shrfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-pri-shrfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-pri-shrfb-draw-pwrite
-kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-pri-shrfb-draw-blt
-kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-pri-shrfb-draw-render
-kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-cur-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-cur-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-cur-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-cur-indfb-draw-pwrite
-kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-cur-indfb-draw-blt
-kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-cur-indfb-draw-render
-kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-spr-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-spr-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-spr-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-spr-indfb-draw-pwrite
-kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-spr-indfb-draw-blt
-kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-spr-indfb-draw-render
-kms_frontbuffer_tracking@drrs-1p-primscrn-pri-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@drrs-1p-primscrn-pri-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@drrs-1p-primscrn-pri-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@drrs-1p-primscrn-pri-indfb-draw-pwrite
-kms_frontbuffer_tracking@drrs-1p-primscrn-pri-indfb-draw-blt
-kms_frontbuffer_tracking@drrs-1p-primscrn-pri-indfb-draw-render
-kms_frontbuffer_tracking@drrs-1p-primscrn-pri-shrfb-draw-mmap-cpu
-kms_frontbuffer_tracking@drrs-1p-primscrn-pri-shrfb-draw-mmap-gtt
-kms_frontbuffer_tracking@drrs-1p-primscrn-pri-shrfb-draw-mmap-wc
-kms_frontbuffer_tracking@drrs-1p-primscrn-pri-shrfb-draw-pwrite
-kms_frontbuffer_tracking@drrs-1p-primscrn-pri-shrfb-draw-blt
-kms_frontbuffer_tracking@drrs-1p-primscrn-pri-shrfb-draw-render
-kms_frontbuffer_tracking@drrs-1p-primscrn-cur-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@drrs-1p-primscrn-cur-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@drrs-1p-primscrn-cur-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@drrs-1p-primscrn-cur-indfb-draw-pwrite
-kms_frontbuffer_tracking@drrs-1p-primscrn-cur-indfb-draw-blt
-kms_frontbuffer_tracking@drrs-1p-primscrn-cur-indfb-draw-render
-kms_frontbuffer_tracking@drrs-1p-primscrn-spr-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@drrs-1p-primscrn-spr-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@drrs-1p-primscrn-spr-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@drrs-1p-primscrn-spr-indfb-draw-pwrite
-kms_frontbuffer_tracking@drrs-1p-primscrn-spr-indfb-draw-blt
-kms_frontbuffer_tracking@drrs-1p-primscrn-spr-indfb-draw-render
-kms_frontbuffer_tracking@drrs-1p-offscren-pri-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@drrs-1p-offscren-pri-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@drrs-1p-offscren-pri-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@drrs-1p-offscren-pri-indfb-draw-pwrite
-kms_frontbuffer_tracking@drrs-1p-offscren-pri-indfb-draw-blt
-kms_frontbuffer_tracking@drrs-1p-offscren-pri-indfb-draw-render
-kms_frontbuffer_tracking@drrs-1p-offscren-pri-shrfb-draw-mmap-cpu
-kms_frontbuffer_tracking@drrs-1p-offscren-pri-shrfb-draw-mmap-gtt
-kms_frontbuffer_tracking@drrs-1p-offscren-pri-shrfb-draw-mmap-wc
-kms_frontbuffer_tracking@drrs-1p-offscren-pri-shrfb-draw-pwrite
-kms_frontbuffer_tracking@drrs-1p-offscren-pri-shrfb-draw-blt
-kms_frontbuffer_tracking@drrs-1p-offscren-pri-shrfb-draw-render
-kms_frontbuffer_tracking@drrs-2p-primscrn-pri-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@drrs-2p-primscrn-pri-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@drrs-2p-primscrn-pri-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@drrs-2p-primscrn-pri-indfb-draw-pwrite
-kms_frontbuffer_tracking@drrs-2p-primscrn-pri-indfb-draw-blt
-kms_frontbuffer_tracking@drrs-2p-primscrn-pri-indfb-draw-render
-kms_frontbuffer_tracking@drrs-2p-primscrn-pri-shrfb-draw-mmap-cpu
-kms_frontbuffer_tracking@drrs-2p-primscrn-pri-shrfb-draw-mmap-gtt
-kms_frontbuffer_tracking@drrs-2p-primscrn-pri-shrfb-draw-mmap-wc
-kms_frontbuffer_tracking@drrs-2p-primscrn-pri-shrfb-draw-pwrite
-kms_frontbuffer_tracking@drrs-2p-primscrn-pri-shrfb-draw-blt
-kms_frontbuffer_tracking@drrs-2p-primscrn-pri-shrfb-draw-render
-kms_frontbuffer_tracking@drrs-2p-primscrn-cur-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@drrs-2p-primscrn-cur-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@drrs-2p-primscrn-cur-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@drrs-2p-primscrn-cur-indfb-draw-pwrite
-kms_frontbuffer_tracking@drrs-2p-primscrn-cur-indfb-draw-blt
-kms_frontbuffer_tracking@drrs-2p-primscrn-cur-indfb-draw-render
-kms_frontbuffer_tracking@drrs-2p-primscrn-spr-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@drrs-2p-primscrn-spr-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@drrs-2p-primscrn-spr-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@drrs-2p-primscrn-spr-indfb-draw-pwrite
-kms_frontbuffer_tracking@drrs-2p-primscrn-spr-indfb-draw-blt
-kms_frontbuffer_tracking@drrs-2p-primscrn-spr-indfb-draw-render
-kms_frontbuffer_tracking@drrs-2p-scndscrn-pri-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@drrs-2p-scndscrn-pri-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@drrs-2p-scndscrn-pri-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@drrs-2p-scndscrn-pri-indfb-draw-pwrite
-kms_frontbuffer_tracking@drrs-2p-scndscrn-pri-indfb-draw-blt
-kms_frontbuffer_tracking@drrs-2p-scndscrn-pri-indfb-draw-render
-kms_frontbuffer_tracking@drrs-2p-scndscrn-pri-shrfb-draw-mmap-cpu
-kms_frontbuffer_tracking@drrs-2p-scndscrn-pri-shrfb-draw-mmap-gtt
-kms_frontbuffer_tracking@drrs-2p-scndscrn-pri-shrfb-draw-mmap-wc
-kms_frontbuffer_tracking@drrs-2p-scndscrn-pri-shrfb-draw-pwrite
-kms_frontbuffer_tracking@drrs-2p-scndscrn-pri-shrfb-draw-blt
-kms_frontbuffer_tracking@drrs-2p-scndscrn-pri-shrfb-draw-render
-kms_frontbuffer_tracking@drrs-2p-scndscrn-cur-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@drrs-2p-scndscrn-cur-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@drrs-2p-scndscrn-cur-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@drrs-2p-scndscrn-cur-indfb-draw-pwrite
-kms_frontbuffer_tracking@drrs-2p-scndscrn-cur-indfb-draw-blt
-kms_frontbuffer_tracking@drrs-2p-scndscrn-cur-indfb-draw-render
-kms_frontbuffer_tracking@drrs-2p-scndscrn-spr-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@drrs-2p-scndscrn-spr-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@drrs-2p-scndscrn-spr-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@drrs-2p-scndscrn-spr-indfb-draw-pwrite
-kms_frontbuffer_tracking@drrs-2p-scndscrn-spr-indfb-draw-blt
-kms_frontbuffer_tracking@drrs-2p-scndscrn-spr-indfb-draw-render
-kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-pri-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-pri-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-pri-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-pri-indfb-draw-pwrite
-kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-pri-indfb-draw-blt
-kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-pri-indfb-draw-render
-kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-pri-shrfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-pri-shrfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-pri-shrfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-pri-shrfb-draw-pwrite
-kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-pri-shrfb-draw-blt
-kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-pri-shrfb-draw-render
-kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-cur-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-cur-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-cur-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-cur-indfb-draw-pwrite
-kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-cur-indfb-draw-blt
-kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-cur-indfb-draw-render
-kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-spr-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-spr-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-spr-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-spr-indfb-draw-pwrite
-kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-spr-indfb-draw-blt
-kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-spr-indfb-draw-render
-kms_frontbuffer_tracking@fbcdrrs-1p-offscren-pri-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcdrrs-1p-offscren-pri-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcdrrs-1p-offscren-pri-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbcdrrs-1p-offscren-pri-indfb-draw-pwrite
-kms_frontbuffer_tracking@fbcdrrs-1p-offscren-pri-indfb-draw-blt
-kms_frontbuffer_tracking@fbcdrrs-1p-offscren-pri-indfb-draw-render
-kms_frontbuffer_tracking@fbcdrrs-1p-offscren-pri-shrfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcdrrs-1p-offscren-pri-shrfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcdrrs-1p-offscren-pri-shrfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbcdrrs-1p-offscren-pri-shrfb-draw-pwrite
-kms_frontbuffer_tracking@fbcdrrs-1p-offscren-pri-shrfb-draw-blt
-kms_frontbuffer_tracking@fbcdrrs-1p-offscren-pri-shrfb-draw-render
-kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-pri-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-pri-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-pri-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-pri-indfb-draw-pwrite
-kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-pri-indfb-draw-blt
-kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-pri-indfb-draw-render
-kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-pri-shrfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-pri-shrfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-pri-shrfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-pri-shrfb-draw-pwrite
-kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-pri-shrfb-draw-blt
-kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-pri-shrfb-draw-render
-kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-cur-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-cur-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-cur-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-cur-indfb-draw-pwrite
-kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-cur-indfb-draw-blt
-kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-cur-indfb-draw-render
-kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-spr-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-spr-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-spr-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-spr-indfb-draw-pwrite
-kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-spr-indfb-draw-blt
-kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-spr-indfb-draw-render
-kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-pri-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-pri-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-pri-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-pri-indfb-draw-pwrite
-kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-pri-indfb-draw-blt
-kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-pri-indfb-draw-render
-kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-pri-shrfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-pri-shrfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-pri-shrfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-pri-shrfb-draw-pwrite
-kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-pri-shrfb-draw-blt
-kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-pri-shrfb-draw-render
-kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-cur-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-cur-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-cur-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-cur-indfb-draw-pwrite
-kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-cur-indfb-draw-blt
-kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-cur-indfb-draw-render
-kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-spr-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-spr-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-spr-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-spr-indfb-draw-pwrite
-kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-spr-indfb-draw-blt
-kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-spr-indfb-draw-render
-kms_frontbuffer_tracking@psrdrrs-1p-primscrn-pri-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@psrdrrs-1p-primscrn-pri-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@psrdrrs-1p-primscrn-pri-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@psrdrrs-1p-primscrn-pri-indfb-draw-pwrite
-kms_frontbuffer_tracking@psrdrrs-1p-primscrn-pri-indfb-draw-blt
-kms_frontbuffer_tracking@psrdrrs-1p-primscrn-pri-indfb-draw-render
-kms_frontbuffer_tracking@psrdrrs-1p-primscrn-pri-shrfb-draw-mmap-cpu
-kms_frontbuffer_tracking@psrdrrs-1p-primscrn-pri-shrfb-draw-mmap-gtt
-kms_frontbuffer_tracking@psrdrrs-1p-primscrn-pri-shrfb-draw-mmap-wc
-kms_frontbuffer_tracking@psrdrrs-1p-primscrn-pri-shrfb-draw-pwrite
-kms_frontbuffer_tracking@psrdrrs-1p-primscrn-pri-shrfb-draw-blt
-kms_frontbuffer_tracking@psrdrrs-1p-primscrn-pri-shrfb-draw-render
-kms_frontbuffer_tracking@psrdrrs-1p-primscrn-cur-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@psrdrrs-1p-primscrn-cur-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@psrdrrs-1p-primscrn-cur-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@psrdrrs-1p-primscrn-cur-indfb-draw-pwrite
-kms_frontbuffer_tracking@psrdrrs-1p-primscrn-cur-indfb-draw-blt
-kms_frontbuffer_tracking@psrdrrs-1p-primscrn-cur-indfb-draw-render
-kms_frontbuffer_tracking@psrdrrs-1p-primscrn-spr-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@psrdrrs-1p-primscrn-spr-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@psrdrrs-1p-primscrn-spr-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@psrdrrs-1p-primscrn-spr-indfb-draw-pwrite
-kms_frontbuffer_tracking@psrdrrs-1p-primscrn-spr-indfb-draw-blt
-kms_frontbuffer_tracking@psrdrrs-1p-primscrn-spr-indfb-draw-render
-kms_frontbuffer_tracking@psrdrrs-1p-offscren-pri-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@psrdrrs-1p-offscren-pri-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@psrdrrs-1p-offscren-pri-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@psrdrrs-1p-offscren-pri-indfb-draw-pwrite
-kms_frontbuffer_tracking@psrdrrs-1p-offscren-pri-indfb-draw-blt
-kms_frontbuffer_tracking@psrdrrs-1p-offscren-pri-indfb-draw-render
-kms_frontbuffer_tracking@psrdrrs-1p-offscren-pri-shrfb-draw-mmap-cpu
-kms_frontbuffer_tracking@psrdrrs-1p-offscren-pri-shrfb-draw-mmap-gtt
-kms_frontbuffer_tracking@psrdrrs-1p-offscren-pri-shrfb-draw-mmap-wc
-kms_frontbuffer_tracking@psrdrrs-1p-offscren-pri-shrfb-draw-pwrite
-kms_frontbuffer_tracking@psrdrrs-1p-offscren-pri-shrfb-draw-blt
-kms_frontbuffer_tracking@psrdrrs-1p-offscren-pri-shrfb-draw-render
-kms_frontbuffer_tracking@psrdrrs-2p-primscrn-pri-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@psrdrrs-2p-primscrn-pri-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@psrdrrs-2p-primscrn-pri-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@psrdrrs-2p-primscrn-pri-indfb-draw-pwrite
-kms_frontbuffer_tracking@psrdrrs-2p-primscrn-pri-indfb-draw-blt
-kms_frontbuffer_tracking@psrdrrs-2p-primscrn-pri-indfb-draw-render
-kms_frontbuffer_tracking@psrdrrs-2p-primscrn-pri-shrfb-draw-mmap-cpu
-kms_frontbuffer_tracking@psrdrrs-2p-primscrn-pri-shrfb-draw-mmap-gtt
-kms_frontbuffer_tracking@psrdrrs-2p-primscrn-pri-shrfb-draw-mmap-wc
-kms_frontbuffer_tracking@psrdrrs-2p-primscrn-pri-shrfb-draw-pwrite
-kms_frontbuffer_tracking@psrdrrs-2p-primscrn-pri-shrfb-draw-blt
-kms_frontbuffer_tracking@psrdrrs-2p-primscrn-pri-shrfb-draw-render
-kms_frontbuffer_tracking@psrdrrs-2p-primscrn-cur-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@psrdrrs-2p-primscrn-cur-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@psrdrrs-2p-primscrn-cur-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@psrdrrs-2p-primscrn-cur-indfb-draw-pwrite
-kms_frontbuffer_tracking@psrdrrs-2p-primscrn-cur-indfb-draw-blt
-kms_frontbuffer_tracking@psrdrrs-2p-primscrn-cur-indfb-draw-render
-kms_frontbuffer_tracking@psrdrrs-2p-primscrn-spr-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@psrdrrs-2p-primscrn-spr-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@psrdrrs-2p-primscrn-spr-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@psrdrrs-2p-primscrn-spr-indfb-draw-pwrite
-kms_frontbuffer_tracking@psrdrrs-2p-primscrn-spr-indfb-draw-blt
-kms_frontbuffer_tracking@psrdrrs-2p-primscrn-spr-indfb-draw-render
-kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-pri-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-pri-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-pri-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-pri-indfb-draw-pwrite
-kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-pri-indfb-draw-blt
-kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-pri-indfb-draw-render
-kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-pri-shrfb-draw-mmap-cpu
-kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-pri-shrfb-draw-mmap-gtt
-kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-pri-shrfb-draw-mmap-wc
-kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-pri-shrfb-draw-pwrite
-kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-pri-shrfb-draw-blt
-kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-pri-shrfb-draw-render
-kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-cur-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-cur-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-cur-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-cur-indfb-draw-pwrite
-kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-cur-indfb-draw-blt
-kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-cur-indfb-draw-render
-kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-spr-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-spr-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-spr-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-spr-indfb-draw-pwrite
-kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-spr-indfb-draw-blt
-kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-spr-indfb-draw-render
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-pri-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-pri-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-pri-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-pri-indfb-draw-pwrite
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-pri-indfb-draw-blt
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-pri-indfb-draw-render
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-pri-shrfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-pri-shrfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-pri-shrfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-pri-shrfb-draw-pwrite
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-pri-shrfb-draw-blt
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-pri-shrfb-draw-render
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-cur-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-cur-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-cur-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-cur-indfb-draw-pwrite
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-cur-indfb-draw-blt
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-cur-indfb-draw-render
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-spr-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-spr-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-spr-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-spr-indfb-draw-pwrite
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-spr-indfb-draw-blt
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-spr-indfb-draw-render
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-offscren-pri-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-offscren-pri-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-offscren-pri-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-offscren-pri-indfb-draw-pwrite
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-offscren-pri-indfb-draw-blt
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-offscren-pri-indfb-draw-render
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-offscren-pri-shrfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-offscren-pri-shrfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-offscren-pri-shrfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-offscren-pri-shrfb-draw-pwrite
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-offscren-pri-shrfb-draw-blt
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-offscren-pri-shrfb-draw-render
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-pri-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-pri-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-pri-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-pri-indfb-draw-pwrite
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-pri-indfb-draw-blt
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-pri-indfb-draw-render
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-pri-shrfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-pri-shrfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-pri-shrfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-pri-shrfb-draw-pwrite
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-pri-shrfb-draw-blt
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-pri-shrfb-draw-render
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-cur-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-cur-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-cur-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-cur-indfb-draw-pwrite
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-cur-indfb-draw-blt
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-cur-indfb-draw-render
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-spr-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-spr-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-spr-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-spr-indfb-draw-pwrite
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-spr-indfb-draw-blt
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-spr-indfb-draw-render
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-pri-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-pri-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-pri-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-pri-indfb-draw-pwrite
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-pri-indfb-draw-blt
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-pri-indfb-draw-render
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-pri-shrfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-pri-shrfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-pri-shrfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-pri-shrfb-draw-pwrite
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-pri-shrfb-draw-blt
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-pri-shrfb-draw-render
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-cur-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-cur-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-cur-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-cur-indfb-draw-pwrite
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-cur-indfb-draw-blt
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-cur-indfb-draw-render
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-spr-indfb-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-spr-indfb-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-spr-indfb-draw-mmap-wc
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-spr-indfb-draw-pwrite
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-spr-indfb-draw-blt
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-spr-indfb-draw-render
-kms_frontbuffer_tracking@fbc-1p-primscrn-indfb-pgflip-blt
-kms_frontbuffer_tracking@fbc-1p-primscrn-indfb-msflip-blt
-kms_frontbuffer_tracking@fbc-1p-primscrn-indfb-plflip-blt
-kms_frontbuffer_tracking@fbc-1p-primscrn-shrfb-pgflip-blt
-kms_frontbuffer_tracking@fbc-1p-primscrn-shrfb-msflip-blt
-kms_frontbuffer_tracking@fbc-1p-primscrn-shrfb-plflip-blt
-kms_frontbuffer_tracking@fbc-2p-primscrn-indfb-pgflip-blt
-kms_frontbuffer_tracking@fbc-2p-primscrn-indfb-msflip-blt
-kms_frontbuffer_tracking@fbc-2p-primscrn-indfb-plflip-blt
-kms_frontbuffer_tracking@fbc-2p-primscrn-shrfb-pgflip-blt
-kms_frontbuffer_tracking@fbc-2p-primscrn-shrfb-msflip-blt
-kms_frontbuffer_tracking@fbc-2p-primscrn-shrfb-plflip-blt
-kms_frontbuffer_tracking@fbc-2p-scndscrn-indfb-pgflip-blt
-kms_frontbuffer_tracking@fbc-2p-scndscrn-indfb-msflip-blt
-kms_frontbuffer_tracking@fbc-2p-scndscrn-indfb-plflip-blt
-kms_frontbuffer_tracking@fbc-2p-scndscrn-shrfb-pgflip-blt
-kms_frontbuffer_tracking@fbc-2p-scndscrn-shrfb-msflip-blt
-kms_frontbuffer_tracking@fbc-2p-scndscrn-shrfb-plflip-blt
-kms_frontbuffer_tracking@psr-1p-primscrn-indfb-pgflip-blt
-kms_frontbuffer_tracking@psr-1p-primscrn-indfb-msflip-blt
-kms_frontbuffer_tracking@psr-1p-primscrn-indfb-plflip-blt
-kms_frontbuffer_tracking@psr-1p-primscrn-shrfb-pgflip-blt
-kms_frontbuffer_tracking@psr-1p-primscrn-shrfb-msflip-blt
-kms_frontbuffer_tracking@psr-1p-primscrn-shrfb-plflip-blt
-kms_frontbuffer_tracking@psr-2p-primscrn-indfb-pgflip-blt
-kms_frontbuffer_tracking@psr-2p-primscrn-indfb-msflip-blt
-kms_frontbuffer_tracking@psr-2p-primscrn-indfb-plflip-blt
-kms_frontbuffer_tracking@psr-2p-primscrn-shrfb-pgflip-blt
-kms_frontbuffer_tracking@psr-2p-primscrn-shrfb-msflip-blt
-kms_frontbuffer_tracking@psr-2p-primscrn-shrfb-plflip-blt
-kms_frontbuffer_tracking@psr-2p-scndscrn-indfb-pgflip-blt
-kms_frontbuffer_tracking@psr-2p-scndscrn-indfb-msflip-blt
-kms_frontbuffer_tracking@psr-2p-scndscrn-indfb-plflip-blt
-kms_frontbuffer_tracking@psr-2p-scndscrn-shrfb-pgflip-blt
-kms_frontbuffer_tracking@psr-2p-scndscrn-shrfb-msflip-blt
-kms_frontbuffer_tracking@psr-2p-scndscrn-shrfb-plflip-blt
-kms_frontbuffer_tracking@fbcpsr-1p-primscrn-indfb-pgflip-blt
-kms_frontbuffer_tracking@fbcpsr-1p-primscrn-indfb-msflip-blt
-kms_frontbuffer_tracking@fbcpsr-1p-primscrn-indfb-plflip-blt
-kms_frontbuffer_tracking@fbcpsr-1p-primscrn-shrfb-pgflip-blt
-kms_frontbuffer_tracking@fbcpsr-1p-primscrn-shrfb-msflip-blt
-kms_frontbuffer_tracking@fbcpsr-1p-primscrn-shrfb-plflip-blt
-kms_frontbuffer_tracking@fbcpsr-2p-primscrn-indfb-pgflip-blt
-kms_frontbuffer_tracking@fbcpsr-2p-primscrn-indfb-msflip-blt
-kms_frontbuffer_tracking@fbcpsr-2p-primscrn-indfb-plflip-blt
-kms_frontbuffer_tracking@fbcpsr-2p-primscrn-shrfb-pgflip-blt
-kms_frontbuffer_tracking@fbcpsr-2p-primscrn-shrfb-msflip-blt
-kms_frontbuffer_tracking@fbcpsr-2p-primscrn-shrfb-plflip-blt
-kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-indfb-pgflip-blt
-kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-indfb-msflip-blt
-kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-indfb-plflip-blt
-kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-shrfb-pgflip-blt
-kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-shrfb-msflip-blt
-kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-shrfb-plflip-blt
-kms_frontbuffer_tracking@drrs-1p-primscrn-indfb-pgflip-blt
-kms_frontbuffer_tracking@drrs-1p-primscrn-indfb-msflip-blt
-kms_frontbuffer_tracking@drrs-1p-primscrn-indfb-plflip-blt
-kms_frontbuffer_tracking@drrs-1p-primscrn-shrfb-pgflip-blt
-kms_frontbuffer_tracking@drrs-1p-primscrn-shrfb-msflip-blt
-kms_frontbuffer_tracking@drrs-1p-primscrn-shrfb-plflip-blt
-kms_frontbuffer_tracking@drrs-2p-primscrn-indfb-pgflip-blt
-kms_frontbuffer_tracking@drrs-2p-primscrn-indfb-msflip-blt
-kms_frontbuffer_tracking@drrs-2p-primscrn-indfb-plflip-blt
-kms_frontbuffer_tracking@drrs-2p-primscrn-shrfb-pgflip-blt
-kms_frontbuffer_tracking@drrs-2p-primscrn-shrfb-msflip-blt
-kms_frontbuffer_tracking@drrs-2p-primscrn-shrfb-plflip-blt
-kms_frontbuffer_tracking@drrs-2p-scndscrn-indfb-pgflip-blt
-kms_frontbuffer_tracking@drrs-2p-scndscrn-indfb-msflip-blt
-kms_frontbuffer_tracking@drrs-2p-scndscrn-indfb-plflip-blt
-kms_frontbuffer_tracking@drrs-2p-scndscrn-shrfb-pgflip-blt
-kms_frontbuffer_tracking@drrs-2p-scndscrn-shrfb-msflip-blt
-kms_frontbuffer_tracking@drrs-2p-scndscrn-shrfb-plflip-blt
-kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-indfb-pgflip-blt
-kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-indfb-msflip-blt
-kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-indfb-plflip-blt
-kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-shrfb-pgflip-blt
-kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-shrfb-msflip-blt
-kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-shrfb-plflip-blt
-kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-indfb-pgflip-blt
-kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-indfb-msflip-blt
-kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-indfb-plflip-blt
-kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-shrfb-pgflip-blt
-kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-shrfb-msflip-blt
-kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-shrfb-plflip-blt
-kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-indfb-pgflip-blt
-kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-indfb-msflip-blt
-kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-indfb-plflip-blt
-kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-shrfb-pgflip-blt
-kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-shrfb-msflip-blt
-kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-shrfb-plflip-blt
-kms_frontbuffer_tracking@psrdrrs-1p-primscrn-indfb-pgflip-blt
-kms_frontbuffer_tracking@psrdrrs-1p-primscrn-indfb-msflip-blt
-kms_frontbuffer_tracking@psrdrrs-1p-primscrn-indfb-plflip-blt
-kms_frontbuffer_tracking@psrdrrs-1p-primscrn-shrfb-pgflip-blt
-kms_frontbuffer_tracking@psrdrrs-1p-primscrn-shrfb-msflip-blt
-kms_frontbuffer_tracking@psrdrrs-1p-primscrn-shrfb-plflip-blt
-kms_frontbuffer_tracking@psrdrrs-2p-primscrn-indfb-pgflip-blt
-kms_frontbuffer_tracking@psrdrrs-2p-primscrn-indfb-msflip-blt
-kms_frontbuffer_tracking@psrdrrs-2p-primscrn-indfb-plflip-blt
-kms_frontbuffer_tracking@psrdrrs-2p-primscrn-shrfb-pgflip-blt
-kms_frontbuffer_tracking@psrdrrs-2p-primscrn-shrfb-msflip-blt
-kms_frontbuffer_tracking@psrdrrs-2p-primscrn-shrfb-plflip-blt
-kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-indfb-pgflip-blt
-kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-indfb-msflip-blt
-kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-indfb-plflip-blt
-kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-shrfb-pgflip-blt
-kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-shrfb-msflip-blt
-kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-shrfb-plflip-blt
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-indfb-pgflip-blt
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-indfb-msflip-blt
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-indfb-plflip-blt
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-shrfb-pgflip-blt
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-shrfb-msflip-blt
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-shrfb-plflip-blt
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-indfb-pgflip-blt
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-indfb-msflip-blt
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-indfb-plflip-blt
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-shrfb-pgflip-blt
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-shrfb-msflip-blt
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-shrfb-plflip-blt
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-indfb-pgflip-blt
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-indfb-msflip-blt
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-indfb-plflip-blt
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-shrfb-pgflip-blt
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-shrfb-msflip-blt
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-shrfb-plflip-blt
-kms_frontbuffer_tracking@fbc-1p-indfb-fliptrack-mmap-gtt
-kms_frontbuffer_tracking@fbc-1p-shrfb-fliptrack-mmap-gtt
-kms_frontbuffer_tracking@fbc-2p-indfb-fliptrack-mmap-gtt
-kms_frontbuffer_tracking@fbc-2p-shrfb-fliptrack-mmap-gtt
-kms_frontbuffer_tracking@fbcpsr-1p-indfb-fliptrack-mmap-gtt
-kms_frontbuffer_tracking@fbcpsr-1p-shrfb-fliptrack-mmap-gtt
-kms_frontbuffer_tracking@fbcpsr-2p-indfb-fliptrack-mmap-gtt
-kms_frontbuffer_tracking@fbcpsr-2p-shrfb-fliptrack-mmap-gtt
-kms_frontbuffer_tracking@fbcdrrs-1p-indfb-fliptrack-mmap-gtt
-kms_frontbuffer_tracking@fbcdrrs-1p-shrfb-fliptrack-mmap-gtt
-kms_frontbuffer_tracking@fbcdrrs-2p-indfb-fliptrack-mmap-gtt
-kms_frontbuffer_tracking@fbcdrrs-2p-shrfb-fliptrack-mmap-gtt
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-indfb-fliptrack-mmap-gtt
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-shrfb-fliptrack-mmap-gtt
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-indfb-fliptrack-mmap-gtt
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-shrfb-fliptrack-mmap-gtt
-kms_frontbuffer_tracking@fbc-1p-primscrn-cur-indfb-move
-kms_frontbuffer_tracking@fbc-1p-primscrn-cur-indfb-onoff
-kms_frontbuffer_tracking@fbc-1p-primscrn-spr-indfb-move
-kms_frontbuffer_tracking@fbc-1p-primscrn-spr-indfb-onoff
-kms_frontbuffer_tracking@fbc-2p-primscrn-cur-indfb-move
-kms_frontbuffer_tracking@fbc-2p-primscrn-cur-indfb-onoff
-kms_frontbuffer_tracking@fbc-2p-primscrn-spr-indfb-move
-kms_frontbuffer_tracking@fbc-2p-primscrn-spr-indfb-onoff
-kms_frontbuffer_tracking@fbc-2p-scndscrn-cur-indfb-move
-kms_frontbuffer_tracking@fbc-2p-scndscrn-cur-indfb-onoff
-kms_frontbuffer_tracking@fbc-2p-scndscrn-spr-indfb-move
-kms_frontbuffer_tracking@fbc-2p-scndscrn-spr-indfb-onoff
-kms_frontbuffer_tracking@psr-1p-primscrn-cur-indfb-move
-kms_frontbuffer_tracking@psr-1p-primscrn-cur-indfb-onoff
-kms_frontbuffer_tracking@psr-1p-primscrn-spr-indfb-move
-kms_frontbuffer_tracking@psr-1p-primscrn-spr-indfb-onoff
-kms_frontbuffer_tracking@psr-2p-primscrn-cur-indfb-move
-kms_frontbuffer_tracking@psr-2p-primscrn-cur-indfb-onoff
-kms_frontbuffer_tracking@psr-2p-primscrn-spr-indfb-move
-kms_frontbuffer_tracking@psr-2p-primscrn-spr-indfb-onoff
-kms_frontbuffer_tracking@psr-2p-scndscrn-cur-indfb-move
-kms_frontbuffer_tracking@psr-2p-scndscrn-cur-indfb-onoff
-kms_frontbuffer_tracking@psr-2p-scndscrn-spr-indfb-move
-kms_frontbuffer_tracking@psr-2p-scndscrn-spr-indfb-onoff
-kms_frontbuffer_tracking@fbcpsr-1p-primscrn-cur-indfb-move
-kms_frontbuffer_tracking@fbcpsr-1p-primscrn-cur-indfb-onoff
-kms_frontbuffer_tracking@fbcpsr-1p-primscrn-spr-indfb-move
-kms_frontbuffer_tracking@fbcpsr-1p-primscrn-spr-indfb-onoff
-kms_frontbuffer_tracking@fbcpsr-2p-primscrn-cur-indfb-move
-kms_frontbuffer_tracking@fbcpsr-2p-primscrn-cur-indfb-onoff
-kms_frontbuffer_tracking@fbcpsr-2p-primscrn-spr-indfb-move
-kms_frontbuffer_tracking@fbcpsr-2p-primscrn-spr-indfb-onoff
-kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-cur-indfb-move
-kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-cur-indfb-onoff
-kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-spr-indfb-move
-kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-spr-indfb-onoff
-kms_frontbuffer_tracking@drrs-1p-primscrn-cur-indfb-move
-kms_frontbuffer_tracking@drrs-1p-primscrn-cur-indfb-onoff
-kms_frontbuffer_tracking@drrs-1p-primscrn-spr-indfb-move
-kms_frontbuffer_tracking@drrs-1p-primscrn-spr-indfb-onoff
-kms_frontbuffer_tracking@drrs-2p-primscrn-cur-indfb-move
-kms_frontbuffer_tracking@drrs-2p-primscrn-cur-indfb-onoff
-kms_frontbuffer_tracking@drrs-2p-primscrn-spr-indfb-move
-kms_frontbuffer_tracking@drrs-2p-primscrn-spr-indfb-onoff
-kms_frontbuffer_tracking@drrs-2p-scndscrn-cur-indfb-move
-kms_frontbuffer_tracking@drrs-2p-scndscrn-cur-indfb-onoff
-kms_frontbuffer_tracking@drrs-2p-scndscrn-spr-indfb-move
-kms_frontbuffer_tracking@drrs-2p-scndscrn-spr-indfb-onoff
-kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-cur-indfb-move
-kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-cur-indfb-onoff
-kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-spr-indfb-move
-kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-spr-indfb-onoff
-kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-cur-indfb-move
-kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-cur-indfb-onoff
-kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-spr-indfb-move
-kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-spr-indfb-onoff
-kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-cur-indfb-move
-kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-cur-indfb-onoff
-kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-spr-indfb-move
-kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-spr-indfb-onoff
-kms_frontbuffer_tracking@psrdrrs-1p-primscrn-cur-indfb-move
-kms_frontbuffer_tracking@psrdrrs-1p-primscrn-cur-indfb-onoff
-kms_frontbuffer_tracking@psrdrrs-1p-primscrn-spr-indfb-move
-kms_frontbuffer_tracking@psrdrrs-1p-primscrn-spr-indfb-onoff
-kms_frontbuffer_tracking@psrdrrs-2p-primscrn-cur-indfb-move
-kms_frontbuffer_tracking@psrdrrs-2p-primscrn-cur-indfb-onoff
-kms_frontbuffer_tracking@psrdrrs-2p-primscrn-spr-indfb-move
-kms_frontbuffer_tracking@psrdrrs-2p-primscrn-spr-indfb-onoff
-kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-cur-indfb-move
-kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-cur-indfb-onoff
-kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-spr-indfb-move
-kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-spr-indfb-onoff
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-cur-indfb-move
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-cur-indfb-onoff
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-spr-indfb-move
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-spr-indfb-onoff
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-cur-indfb-move
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-cur-indfb-onoff
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-spr-indfb-move
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-spr-indfb-onoff
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-cur-indfb-move
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-cur-indfb-onoff
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-spr-indfb-move
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-spr-indfb-onoff
-kms_frontbuffer_tracking@fbc-1p-primscrn-spr-indfb-fullscreen
-kms_frontbuffer_tracking@fbc-2p-primscrn-spr-indfb-fullscreen
-kms_frontbuffer_tracking@fbc-2p-scndscrn-spr-indfb-fullscreen
-kms_frontbuffer_tracking@psr-1p-primscrn-spr-indfb-fullscreen
-kms_frontbuffer_tracking@psr-2p-primscrn-spr-indfb-fullscreen
-kms_frontbuffer_tracking@psr-2p-scndscrn-spr-indfb-fullscreen
-kms_frontbuffer_tracking@fbcpsr-1p-primscrn-spr-indfb-fullscreen
-kms_frontbuffer_tracking@fbcpsr-2p-primscrn-spr-indfb-fullscreen
-kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-spr-indfb-fullscreen
-kms_frontbuffer_tracking@drrs-1p-primscrn-spr-indfb-fullscreen
-kms_frontbuffer_tracking@drrs-2p-primscrn-spr-indfb-fullscreen
-kms_frontbuffer_tracking@drrs-2p-scndscrn-spr-indfb-fullscreen
-kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-spr-indfb-fullscreen
-kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-spr-indfb-fullscreen
-kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-spr-indfb-fullscreen
-kms_frontbuffer_tracking@psrdrrs-1p-primscrn-spr-indfb-fullscreen
-kms_frontbuffer_tracking@psrdrrs-2p-primscrn-spr-indfb-fullscreen
-kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-spr-indfb-fullscreen
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-spr-indfb-fullscreen
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-spr-indfb-fullscreen
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-spr-indfb-fullscreen
-kms_frontbuffer_tracking@fbc-1p-pri-indfb-multidraw
-kms_frontbuffer_tracking@fbc-2p-pri-indfb-multidraw
-kms_frontbuffer_tracking@psr-1p-pri-indfb-multidraw
-kms_frontbuffer_tracking@psr-2p-pri-indfb-multidraw
-kms_frontbuffer_tracking@fbcpsr-1p-pri-indfb-multidraw
-kms_frontbuffer_tracking@fbcpsr-2p-pri-indfb-multidraw
-kms_frontbuffer_tracking@drrs-1p-pri-indfb-multidraw
-kms_frontbuffer_tracking@drrs-2p-pri-indfb-multidraw
-kms_frontbuffer_tracking@fbcdrrs-1p-pri-indfb-multidraw
-kms_frontbuffer_tracking@fbcdrrs-2p-pri-indfb-multidraw
-kms_frontbuffer_tracking@psrdrrs-1p-pri-indfb-multidraw
-kms_frontbuffer_tracking@psrdrrs-2p-pri-indfb-multidraw
-kms_frontbuffer_tracking@fbcpsrdrrs-1p-pri-indfb-multidraw
-kms_frontbuffer_tracking@fbcpsrdrrs-2p-pri-indfb-multidraw
-kms_frontbuffer_tracking@fbc-farfromfence-mmap-gtt
-kms_frontbuffer_tracking@psr-farfromfence-mmap-gtt
-kms_frontbuffer_tracking@fbcpsr-farfromfence-mmap-gtt
-kms_frontbuffer_tracking@drrs-farfromfence-mmap-gtt
-kms_frontbuffer_tracking@fbcdrrs-farfromfence-mmap-gtt
-kms_frontbuffer_tracking@psrdrrs-farfromfence-mmap-gtt
-kms_frontbuffer_tracking@fbcpsrdrrs-farfromfence-mmap-gtt
-kms_frontbuffer_tracking@fbc-rgb565-draw-mmap-cpu
-kms_frontbuffer_tracking@fbc-rgb101010-draw-mmap-cpu
-kms_frontbuffer_tracking@fbc-rgb565-draw-mmap-gtt
-kms_frontbuffer_tracking@fbc-rgb101010-draw-mmap-gtt
-kms_frontbuffer_tracking@fbc-rgb565-draw-mmap-wc
-kms_frontbuffer_tracking@fbc-rgb101010-draw-mmap-wc
-kms_frontbuffer_tracking@fbc-rgb565-draw-pwrite
-kms_frontbuffer_tracking@fbc-rgb101010-draw-pwrite
-kms_frontbuffer_tracking@fbc-rgb565-draw-blt
-kms_frontbuffer_tracking@fbc-rgb101010-draw-blt
-kms_frontbuffer_tracking@fbc-rgb565-draw-render
-kms_frontbuffer_tracking@fbc-rgb101010-draw-render
-kms_frontbuffer_tracking@psr-rgb565-draw-mmap-cpu
-kms_frontbuffer_tracking@psr-rgb101010-draw-mmap-cpu
-kms_frontbuffer_tracking@psr-rgb565-draw-mmap-gtt
-kms_frontbuffer_tracking@psr-rgb101010-draw-mmap-gtt
-kms_frontbuffer_tracking@psr-rgb565-draw-mmap-wc
-kms_frontbuffer_tracking@psr-rgb101010-draw-mmap-wc
-kms_frontbuffer_tracking@psr-rgb565-draw-pwrite
-kms_frontbuffer_tracking@psr-rgb101010-draw-pwrite
-kms_frontbuffer_tracking@psr-rgb565-draw-blt
-kms_frontbuffer_tracking@psr-rgb101010-draw-blt
-kms_frontbuffer_tracking@psr-rgb565-draw-render
-kms_frontbuffer_tracking@psr-rgb101010-draw-render
-kms_frontbuffer_tracking@fbcpsr-rgb565-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcpsr-rgb101010-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcpsr-rgb565-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcpsr-rgb101010-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcpsr-rgb565-draw-mmap-wc
-kms_frontbuffer_tracking@fbcpsr-rgb101010-draw-mmap-wc
-kms_frontbuffer_tracking@fbcpsr-rgb565-draw-pwrite
-kms_frontbuffer_tracking@fbcpsr-rgb101010-draw-pwrite
-kms_frontbuffer_tracking@fbcpsr-rgb565-draw-blt
-kms_frontbuffer_tracking@fbcpsr-rgb101010-draw-blt
-kms_frontbuffer_tracking@fbcpsr-rgb565-draw-render
-kms_frontbuffer_tracking@fbcpsr-rgb101010-draw-render
-kms_frontbuffer_tracking@drrs-rgb565-draw-mmap-cpu
-kms_frontbuffer_tracking@drrs-rgb101010-draw-mmap-cpu
-kms_frontbuffer_tracking@drrs-rgb565-draw-mmap-gtt
-kms_frontbuffer_tracking@drrs-rgb101010-draw-mmap-gtt
-kms_frontbuffer_tracking@drrs-rgb565-draw-mmap-wc
-kms_frontbuffer_tracking@drrs-rgb101010-draw-mmap-wc
-kms_frontbuffer_tracking@drrs-rgb565-draw-pwrite
-kms_frontbuffer_tracking@drrs-rgb101010-draw-pwrite
-kms_frontbuffer_tracking@drrs-rgb565-draw-blt
-kms_frontbuffer_tracking@drrs-rgb101010-draw-blt
-kms_frontbuffer_tracking@drrs-rgb565-draw-render
-kms_frontbuffer_tracking@drrs-rgb101010-draw-render
-kms_frontbuffer_tracking@fbcdrrs-rgb565-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcdrrs-rgb101010-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcdrrs-rgb565-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcdrrs-rgb101010-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcdrrs-rgb565-draw-mmap-wc
-kms_frontbuffer_tracking@fbcdrrs-rgb101010-draw-mmap-wc
-kms_frontbuffer_tracking@fbcdrrs-rgb565-draw-pwrite
-kms_frontbuffer_tracking@fbcdrrs-rgb101010-draw-pwrite
-kms_frontbuffer_tracking@fbcdrrs-rgb565-draw-blt
-kms_frontbuffer_tracking@fbcdrrs-rgb101010-draw-blt
-kms_frontbuffer_tracking@fbcdrrs-rgb565-draw-render
-kms_frontbuffer_tracking@fbcdrrs-rgb101010-draw-render
-kms_frontbuffer_tracking@psrdrrs-rgb565-draw-mmap-cpu
-kms_frontbuffer_tracking@psrdrrs-rgb101010-draw-mmap-cpu
-kms_frontbuffer_tracking@psrdrrs-rgb565-draw-mmap-gtt
-kms_frontbuffer_tracking@psrdrrs-rgb101010-draw-mmap-gtt
-kms_frontbuffer_tracking@psrdrrs-rgb565-draw-mmap-wc
-kms_frontbuffer_tracking@psrdrrs-rgb101010-draw-mmap-wc
-kms_frontbuffer_tracking@psrdrrs-rgb565-draw-pwrite
-kms_frontbuffer_tracking@psrdrrs-rgb101010-draw-pwrite
-kms_frontbuffer_tracking@psrdrrs-rgb565-draw-blt
-kms_frontbuffer_tracking@psrdrrs-rgb101010-draw-blt
-kms_frontbuffer_tracking@psrdrrs-rgb565-draw-render
-kms_frontbuffer_tracking@psrdrrs-rgb101010-draw-render
-kms_frontbuffer_tracking@fbcpsrdrrs-rgb565-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcpsrdrrs-rgb101010-draw-mmap-cpu
-kms_frontbuffer_tracking@fbcpsrdrrs-rgb565-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcpsrdrrs-rgb101010-draw-mmap-gtt
-kms_frontbuffer_tracking@fbcpsrdrrs-rgb565-draw-mmap-wc
-kms_frontbuffer_tracking@fbcpsrdrrs-rgb101010-draw-mmap-wc
-kms_frontbuffer_tracking@fbcpsrdrrs-rgb565-draw-pwrite
-kms_frontbuffer_tracking@fbcpsrdrrs-rgb101010-draw-pwrite
-kms_frontbuffer_tracking@fbcpsrdrrs-rgb565-draw-blt
-kms_frontbuffer_tracking@fbcpsrdrrs-rgb101010-draw-blt
-kms_frontbuffer_tracking@fbcpsrdrrs-rgb565-draw-render
-kms_frontbuffer_tracking@fbcpsrdrrs-rgb101010-draw-render
-kms_frontbuffer_tracking@fbc-indfb-scaledprimary
-kms_frontbuffer_tracking@fbc-shrfb-scaledprimary
-kms_frontbuffer_tracking@psr-indfb-scaledprimary
-kms_frontbuffer_tracking@psr-shrfb-scaledprimary
-kms_frontbuffer_tracking@fbcpsr-indfb-scaledprimary
-kms_frontbuffer_tracking@fbcpsr-shrfb-scaledprimary
-kms_frontbuffer_tracking@drrs-indfb-scaledprimary
-kms_frontbuffer_tracking@drrs-shrfb-scaledprimary
-kms_frontbuffer_tracking@fbcdrrs-indfb-scaledprimary
-kms_frontbuffer_tracking@fbcdrrs-shrfb-scaledprimary
-kms_frontbuffer_tracking@psrdrrs-indfb-scaledprimary
-kms_frontbuffer_tracking@psrdrrs-shrfb-scaledprimary
-kms_frontbuffer_tracking@fbcpsrdrrs-indfb-scaledprimary
-kms_frontbuffer_tracking@fbcpsrdrrs-shrfb-scaledprimary
-kms_frontbuffer_tracking@fbc-modesetfrombusy
-kms_frontbuffer_tracking@fbc-stridechange
-kms_frontbuffer_tracking@fbc-tiling-linear
-kms_frontbuffer_tracking@fbc-tiling-y
-kms_frontbuffer_tracking@fbc-tiling-4
-kms_frontbuffer_tracking@fbc-suspend
-kms_frontbuffer_tracking@psr-modesetfrombusy
-kms_frontbuffer_tracking@psr-slowdraw
-kms_frontbuffer_tracking@psr-suspend
-kms_frontbuffer_tracking@fbcpsr-modesetfrombusy
-kms_frontbuffer_tracking@fbcpsr-stridechange
-kms_frontbuffer_tracking@fbcpsr-tiling-linear
-kms_frontbuffer_tracking@fbcpsr-tiling-y
-kms_frontbuffer_tracking@fbcpsr-tiling-4
-kms_frontbuffer_tracking@fbcpsr-slowdraw
-kms_frontbuffer_tracking@fbcpsr-suspend
-kms_frontbuffer_tracking@drrs-modesetfrombusy
-kms_frontbuffer_tracking@drrs-slowdraw
-kms_frontbuffer_tracking@drrs-suspend
-kms_frontbuffer_tracking@fbcdrrs-modesetfrombusy
-kms_frontbuffer_tracking@fbcdrrs-stridechange
-kms_frontbuffer_tracking@fbcdrrs-tiling-linear
-kms_frontbuffer_tracking@fbcdrrs-tiling-y
-kms_frontbuffer_tracking@fbcdrrs-tiling-4
-kms_frontbuffer_tracking@fbcdrrs-slowdraw
-kms_frontbuffer_tracking@fbcdrrs-suspend
-kms_frontbuffer_tracking@psrdrrs-modesetfrombusy
-kms_frontbuffer_tracking@psrdrrs-slowdraw
-kms_frontbuffer_tracking@psrdrrs-suspend
-kms_frontbuffer_tracking@fbcpsrdrrs-modesetfrombusy
-kms_frontbuffer_tracking@fbcpsrdrrs-stridechange
-kms_frontbuffer_tracking@fbcpsrdrrs-tiling-linear
-kms_frontbuffer_tracking@fbcpsrdrrs-tiling-y
-kms_frontbuffer_tracking@fbcpsrdrrs-tiling-4
-kms_frontbuffer_tracking@fbcpsrdrrs-slowdraw
-kms_frontbuffer_tracking@fbcpsrdrrs-suspend
-kms_frontbuffer_tracking@basic
-kms_getfb@getfb-handle-zero
-kms_getfb@getfb-handle-valid
-kms_getfb@getfb-handle-closed
-kms_getfb@getfb-handle-not-fb
-kms_getfb@getfb-addfb-different-handles
-kms_getfb@getfb-repeated-different-handles
-kms_getfb@getfb-reject-ccs
-kms_getfb@getfb2-handle-zero
-kms_getfb@getfb2-handle-closed
-kms_getfb@getfb2-handle-not-fb
-kms_getfb@getfb2-accept-ccs
-kms_getfb@getfb2-into-addfb2
-kms_getfb@getfb-handle-protection
-kms_getfb@getfb2-handle-protection
-kms_hdmi_inject@inject-4k
-kms_hdmi_inject@inject-audio
-kms_hdr@bpc-switch
-kms_hdr@bpc-switch-dpms
-kms_hdr@bpc-switch-suspend
-kms_hdr@static-toggle
-kms_hdr@static-toggle-dpms
-kms_hdr@static-toggle-suspend
-kms_hdr@static-swap
-kms_hdr@invalid-metadata-sizes
-kms_hdr@invalid-hdr
-kms_invalid_mode@clock-too-high
-kms_invalid_mode@zero-clock
-kms_invalid_mode@int-max-clock
-kms_invalid_mode@uint-max-clock
-kms_invalid_mode@zero-hdisplay
-kms_invalid_mode@zero-vdisplay
-kms_invalid_mode@bad-hsync-start
-kms_invalid_mode@bad-vsync-start
-kms_invalid_mode@bad-hsync-end
-kms_invalid_mode@bad-vsync-end
-kms_invalid_mode@bad-htotal
-kms_invalid_mode@bad-vtotal
-kms_legacy_colorkey@basic
-kms_legacy_colorkey@invalid-plane
-kms_multipipe_modeset@basic-max-pipe-crc-check
-kms_panel_fitting@legacy
-kms_panel_fitting@atomic-fastset
-kms_pipe_b_c_ivb@pipe-B-dpms-off-modeset-pipe-C
-kms_pipe_b_c_ivb@pipe-B-double-modeset-then-modeset-pipe-C
-kms_pipe_b_c_ivb@disable-pipe-B-enable-pipe-C
-kms_pipe_b_c_ivb@from-pipe-C-to-B-with-3-lanes
-kms_pipe_b_c_ivb@enable-pipe-C-while-B-has-3-lanes
-kms_pipe_crc_basic@bad-source
-kms_pipe_crc_basic@read-crc
-kms_pipe_crc_basic@read-crc-frame-sequence
-kms_pipe_crc_basic@nonblocking-crc
-kms_pipe_crc_basic@nonblocking-crc-frame-sequence
-kms_pipe_crc_basic@suspend-read-crc
-kms_pipe_crc_basic@hang-read-crc
-kms_pipe_crc_basic@disable-crc-after-crtc
-kms_pipe_crc_basic@compare-crc-sanitycheck-xr24
-kms_pipe_crc_basic@compare-crc-sanitycheck-nv12
-kms_plane@pixel-format
-kms_plane@pixel-format-source-clamping
-kms_plane@plane-position-covered
-kms_plane@plane-position-hole
-kms_plane@plane-position-hole-dpms
-kms_plane@plane-panning-top-left
-kms_plane@plane-panning-bottom-right
-kms_plane@plane-panning-bottom-right-suspend
-kms_plane@planar-pixel-format-settings
-kms_plane_alpha_blend@alpha-basic
-kms_plane_alpha_blend@alpha-7efc
-kms_plane_alpha_blend@coverage-7efc
-kms_plane_alpha_blend@coverage-vs-premult-vs-constant
-kms_plane_alpha_blend@alpha-transparent-fb
-kms_plane_alpha_blend@alpha-opaque-fb
-kms_plane_alpha_blend@constant-alpha-min
-kms_plane_alpha_blend@constant-alpha-mid
-kms_plane_alpha_blend@constant-alpha-max
-kms_plane_cursor@primary
-kms_plane_cursor@overlay
-kms_plane_cursor@viewport
-kms_plane_lowres@tiling-none
-kms_plane_lowres@tiling-x
-kms_plane_lowres@tiling-y
-kms_plane_lowres@tiling-yf
-kms_plane_lowres@tiling-4
-kms_plane_multiple@tiling-none
-kms_plane_multiple@tiling-x
-kms_plane_multiple@tiling-y
-kms_plane_multiple@tiling-yf
-kms_plane_multiple@tiling-4
-kms_plane_scaling@plane-upscale-20x20-with-pixel-format
-kms_plane_scaling@plane-upscale-factor-0-25-with-pixel-format
-kms_plane_scaling@plane-downscale-factor-0-25-with-pixel-format
-kms_plane_scaling@plane-downscale-factor-0-5-with-pixel-format
-kms_plane_scaling@plane-downscale-factor-0-75-with-pixel-format
-kms_plane_scaling@plane-scaler-unity-scaling-with-pixel-format
-kms_plane_scaling@plane-upscale-20x20-with-rotation
-kms_plane_scaling@plane-upscale-factor-0-25-with-rotation
-kms_plane_scaling@plane-downscale-factor-0-25-with-rotation
-kms_plane_scaling@plane-downscale-factor-0-5-with-rotation
-kms_plane_scaling@plane-downscale-factor-0-75-with-rotation
-kms_plane_scaling@plane-scaler-unity-scaling-with-rotation
-kms_plane_scaling@plane-upscale-20x20-with-modifiers
-kms_plane_scaling@plane-upscale-factor-0-25-with-modifiers
-kms_plane_scaling@plane-downscale-factor-0-25-with-modifiers
-kms_plane_scaling@plane-downscale-factor-0-5-with-modifiers
-kms_plane_scaling@plane-downscale-factor-0-75-with-modifiers
-kms_plane_scaling@plane-scaler-unity-scaling-with-modifiers
-kms_plane_scaling@plane-scaler-with-clipping-clamping-pixel-formats
-kms_plane_scaling@plane-scaler-with-clipping-clamping-rotation
-kms_plane_scaling@plane-scaler-with-clipping-clamping-modifiers
-kms_plane_scaling@planes-upscale-20x20
-kms_plane_scaling@planes-upscale-factor-0-25
-kms_plane_scaling@planes-scaler-unity-scaling
-kms_plane_scaling@planes-downscale-factor-0-25
-kms_plane_scaling@planes-downscale-factor-0-5
-kms_plane_scaling@planes-downscale-factor-0-75
-kms_plane_scaling@planes-upscale-20x20-downscale-factor-0-25
-kms_plane_scaling@planes-upscale-20x20-downscale-factor-0-5
-kms_plane_scaling@planes-upscale-20x20-downscale-factor-0-75
-kms_plane_scaling@planes-upscale-factor-0-25-downscale-factor-0-25
-kms_plane_scaling@planes-upscale-factor-0-25-downscale-factor-0-5
-kms_plane_scaling@planes-upscale-factor-0-25-downscale-factor-0-75
-kms_plane_scaling@planes-unity-scaling-downscale-factor-0-25
-kms_plane_scaling@planes-unity-scaling-downscale-factor-0-5
-kms_plane_scaling@planes-unity-scaling-downscale-factor-0-75
-kms_plane_scaling@planes-downscale-factor-0-25-upscale-20x20
-kms_plane_scaling@planes-downscale-factor-0-25-upscale-factor-0-25
-kms_plane_scaling@planes-downscale-factor-0-25-unity-scaling
-kms_plane_scaling@planes-downscale-factor-0-5-upscale-20x20
-kms_plane_scaling@planes-downscale-factor-0-5-upscale-factor-0-25
-kms_plane_scaling@planes-downscale-factor-0-5-unity-scaling
-kms_plane_scaling@planes-downscale-factor-0-75-upscale-20x20
-kms_plane_scaling@planes-downscale-factor-0-75-upscale-factor-0-25
-kms_plane_scaling@planes-downscale-factor-0-75-unity-scaling
-kms_plane_scaling@intel-max-src-size
-kms_plane_scaling@invalid-num-scalers
-kms_plane_scaling@invalid-parameters
-kms_plane_scaling@2x-scaler-multi-pipe
-kms_prime@basic-crc-hybrid
-kms_prime@basic-modeset-hybrid
-kms_prime@D3hot
-kms_prime@basic-crc-vgem
-kms_prop_blob@basic
-kms_prop_blob@blob-prop-core
-kms_prop_blob@blob-prop-validate
-kms_prop_blob@blob-prop-lifetime
-kms_prop_blob@blob-multiple
-kms_prop_blob@invalid-get-prop-any
-kms_prop_blob@invalid-get-prop
-kms_prop_blob@invalid-set-prop-any
-kms_prop_blob@invalid-set-prop
-kms_properties@plane-properties-legacy
-kms_properties@plane-properties-atomic
-kms_properties@crtc-properties-legacy
-kms_properties@crtc-properties-atomic
-kms_properties@connector-properties-legacy
-kms_properties@connector-properties-atomic
-kms_properties@invalid-properties-legacy
-kms_properties@invalid-properties-atomic
-kms_properties@get_properties-sanity-atomic
-kms_properties@get_properties-sanity-non-atomic
-kms_psr@pr-basic
-kms_psr@pr-no-drrs
-kms_psr@pr-primary-page-flip
-kms_psr@pr-primary-mmap-gtt
-kms_psr@pr-primary-mmap-cpu
-kms_psr@pr-primary-blt
-kms_psr@pr-primary-render
-kms_psr@pr-sprite-mmap-gtt
-kms_psr@pr-cursor-mmap-gtt
-kms_psr@pr-sprite-mmap-cpu
-kms_psr@pr-cursor-mmap-cpu
-kms_psr@pr-sprite-blt
-kms_psr@pr-cursor-blt
-kms_psr@pr-sprite-render
-kms_psr@pr-cursor-render
-kms_psr@pr-sprite-plane-move
-kms_psr@pr-cursor-plane-move
-kms_psr@pr-sprite-plane-onoff
-kms_psr@pr-cursor-plane-onoff
-kms_psr@pr-dpms
-kms_psr@pr-suspend
-kms_psr@psr-basic
-kms_psr@psr-no-drrs
-kms_psr@psr-primary-page-flip
-kms_psr@psr-primary-mmap-gtt
-kms_psr@psr-primary-mmap-cpu
-kms_psr@psr-primary-blt
-kms_psr@psr-primary-render
-kms_psr@psr-sprite-mmap-gtt
-kms_psr@psr-cursor-mmap-gtt
-kms_psr@psr-sprite-mmap-cpu
-kms_psr@psr-cursor-mmap-cpu
-kms_psr@psr-sprite-blt
-kms_psr@psr-cursor-blt
-kms_psr@psr-sprite-render
-kms_psr@psr-cursor-render
-kms_psr@psr-sprite-plane-move
-kms_psr@psr-cursor-plane-move
-kms_psr@psr-sprite-plane-onoff
-kms_psr@psr-cursor-plane-onoff
-kms_psr@psr-dpms
-kms_psr@psr-suspend
-kms_psr@psr2-basic
-kms_psr@psr2-no-drrs
-kms_psr@psr2-primary-page-flip
-kms_psr@psr2-primary-mmap-gtt
-kms_psr@psr2-primary-mmap-cpu
-kms_psr@psr2-primary-blt
-kms_psr@psr2-primary-render
-kms_psr@psr2-sprite-mmap-gtt
-kms_psr@psr2-cursor-mmap-gtt
-kms_psr@psr2-sprite-mmap-cpu
-kms_psr@psr2-cursor-mmap-cpu
-kms_psr@psr2-sprite-blt
-kms_psr@psr2-cursor-blt
-kms_psr@psr2-sprite-render
-kms_psr@psr2-cursor-render
-kms_psr@psr2-sprite-plane-move
-kms_psr@psr2-cursor-plane-move
-kms_psr@psr2-sprite-plane-onoff
-kms_psr@psr2-cursor-plane-onoff
-kms_psr@psr2-dpms
-kms_psr@psr2-suspend
-kms_psr2_sf@primary-plane-update-sf-dmg-area
-kms_psr2_sf@primary-plane-update-sf-dmg-area-big-fb
-kms_psr2_sf@overlay-plane-update-sf-dmg-area
-kms_psr2_sf@cursor-plane-update-sf
-kms_psr2_sf@cursor-plane-move-continuous-sf
-kms_psr2_sf@cursor-plane-move-continuous-exceed-sf
-kms_psr2_sf@cursor-plane-move-continuous-exceed-fully-sf
-kms_psr2_sf@plane-move-sf-dmg-area
-kms_psr2_sf@overlay-plane-move-continuous-sf
-kms_psr2_sf@overlay-plane-move-continuous-exceed-sf
-kms_psr2_sf@overlay-plane-move-continuous-exceed-fully-sf
-kms_psr2_sf@overlay-primary-update-sf-dmg-area
-kms_psr2_sf@overlay-plane-update-continuous-sf
-kms_psr2_su@page_flip-XRGB8888
-kms_psr2_su@page_flip-NV12
-kms_psr2_su@page_flip-P010
-kms_psr2_su@frontbuffer-XRGB8888
-kms_pwrite_crc
-kms_rmfb@rmfb-ioctl
-kms_rmfb@close-fd
-kms_rotation_crc@primary-rotation-90
-kms_rotation_crc@primary-rotation-180
-kms_rotation_crc@primary-rotation-270
-kms_rotation_crc@sprite-rotation-90
-kms_rotation_crc@sprite-rotation-180
-kms_rotation_crc@sprite-rotation-270
-kms_rotation_crc@cursor-rotation-180
-kms_rotation_crc@sprite-rotation-90-pos-100-0
-kms_rotation_crc@bad-pixel-format
-kms_rotation_crc@bad-tiling
-kms_rotation_crc@primary-x-tiled-reflect-x-0
-kms_rotation_crc@primary-x-tiled-reflect-x-180
-kms_rotation_crc@primary-y-tiled-reflect-x-0
-kms_rotation_crc@primary-y-tiled-reflect-x-90
-kms_rotation_crc@primary-y-tiled-reflect-x-180
-kms_rotation_crc@primary-y-tiled-reflect-x-270
-kms_rotation_crc@primary-yf-tiled-reflect-x-0
-kms_rotation_crc@primary-yf-tiled-reflect-x-90
-kms_rotation_crc@primary-yf-tiled-reflect-x-180
-kms_rotation_crc@primary-yf-tiled-reflect-x-270
-kms_rotation_crc@primary-4-tiled-reflect-x-0
-kms_rotation_crc@primary-4-tiled-reflect-x-180
-kms_rotation_crc@multiplane-rotation
-kms_rotation_crc@multiplane-rotation-cropping-top
-kms_rotation_crc@multiplane-rotation-cropping-bottom
-kms_rotation_crc@exhaust-fences
-kms_scaling_modes@scaling-mode-full
-kms_scaling_modes@scaling-mode-center
-kms_scaling_modes@scaling-mode-full-aspect
-kms_scaling_modes@scaling-mode-none
-kms_selftest@drm_cmdline_parser
-kms_selftest@drm_damage_helper
-kms_selftest@drm_dp_mst_helper
-kms_selftest@drm_format_helper
-kms_selftest@drm_format
-kms_selftest@drm_framebuffer
-kms_selftest@drm_plane_helper
-kms_setmode@basic
-kms_setmode@basic-clone-single-crtc
-kms_setmode@invalid-clone-single-crtc
-kms_setmode@invalid-clone-exclusive-crtc
-kms_setmode@clone-exclusive-crtc
-kms_setmode@invalid-clone-single-crtc-stealing
-kms_sysfs_edid_timing
-kms_tv_load_detect@load-detect
-kms_universal_plane@universal-plane-functional
-kms_universal_plane@universal-plane-sanity
-kms_universal_plane@disable-primary-vs-flip
-kms_universal_plane@cursor-fb-leak
-kms_universal_plane@universal-plane-pageflip-windowed
-kms_vblank@invalid
-kms_vblank@crtc-id
-kms_vblank@accuracy-idle
-kms_vblank@query-idle
-kms_vblank@query-idle-hang
-kms_vblank@query-forked
-kms_vblank@query-forked-hang
-kms_vblank@query-busy
-kms_vblank@query-busy-hang
-kms_vblank@query-forked-busy
-kms_vblank@query-forked-busy-hang
-kms_vblank@wait-idle
-kms_vblank@wait-idle-hang
-kms_vblank@wait-forked
-kms_vblank@wait-forked-hang
-kms_vblank@wait-busy
-kms_vblank@wait-busy-hang
-kms_vblank@wait-forked-busy
-kms_vblank@wait-forked-busy-hang
-kms_vblank@ts-continuation-idle
-kms_vblank@ts-continuation-idle-hang
-kms_vblank@ts-continuation-dpms-rpm
-kms_vblank@ts-continuation-dpms-suspend
-kms_vblank@ts-continuation-suspend
-kms_vblank@ts-continuation-modeset
-kms_vblank@ts-continuation-modeset-hang
-kms_vblank@ts-continuation-modeset-rpm
-kms_vrr@flip-basic
-kms_vrr@flip-dpms
-kms_vrr@flip-suspend
-kms_vrr@flipline
-kms_vrr@negative-basic
-kms_writeback@writeback-pixel-formats
-kms_writeback@writeback-invalid-parameters
-kms_writeback@writeback-fb-id
-kms_writeback@writeback-check-output
-prime_mmap_kms@buffer-sharing
-msm_shrink@copy-gpu-sanitycheck-8
-msm_shrink@copy-gpu-sanitycheck-32
-msm_shrink@copy-gpu-8
-msm_shrink@copy-gpu-32
-msm_shrink@copy-gpu-madvise-8
-msm_shrink@copy-gpu-madvise-32
-msm_shrink@copy-gpu-oom-8
-msm_shrink@copy-gpu-oom-32
-msm_shrink@copy-mmap-sanitycheck-8
-msm_shrink@copy-mmap-sanitycheck-32
-msm_shrink@copy-mmap-8
-msm_shrink@copy-mmap-32
-msm_shrink@copy-mmap-madvise-8
-msm_shrink@copy-mmap-madvise-32
-msm_shrink@copy-mmap-oom-8
-msm_shrink@copy-mmap-oom-32
-msm_shrink@copy-mmap-dmabuf-sanitycheck-8
-msm_shrink@copy-mmap-dmabuf-sanitycheck-32
-msm_shrink@copy-mmap-dmabuf-8
-msm_shrink@copy-mmap-dmabuf-32
-msm_shrink@copy-mmap-dmabuf-madvise-8
-msm_shrink@copy-mmap-dmabuf-madvise-32
-msm_shrink@copy-mmap-dmabuf-oom-8
-msm_shrink@copy-mmap-dmabuf-oom-32
-msm_mapping@ring
-msm_mapping@sqefw
-msm_mapping@shadow
-msm_submitoverhead@submitbench-10-bos
-msm_submitoverhead@submitbench-10-bos-no-implicit-sync
-msm_submitoverhead@submitbench-100-bos
-msm_submitoverhead@submitbench-100-bos-no-implicit-sync
-msm_submitoverhead@submitbench-250-bos
-msm_submitoverhead@submitbench-250-bos-no-implicit-sync
-msm_submitoverhead@submitbench-500-bos
-msm_submitoverhead@submitbench-500-bos-no-implicit-sync
-msm_submitoverhead@submitbench-1000-bos
-msm_submitoverhead@submitbench-1000-bos-no-implicit-sync
-msm_recovery@hangcheck
-msm_recovery@gpu-fault
-msm_recovery@gpu-fault-parallel
-msm_recovery@iova-fault
-msm_submit@empty-submit
-msm_submit@invalid-queue-submit
-msm_submit@invalid-flags-submit
-msm_submit@invalid-in-fence-submit
-msm_submit@invalid-duplicate-bo-submit
-msm_submit@invalid-cmd-idx-submit
-msm_submit@invalid-cmd-type-submit
-msm_submit@valid-submit
diff --git a/drivers/gpu/drm/ci/x86_64.config b/drivers/gpu/drm/ci/x86_64.config
index 1cbd49a5b23a..8eaba388b141 100644
--- a/drivers/gpu/drm/ci/x86_64.config
+++ b/drivers/gpu/drm/ci/x86_64.config
@@ -24,6 +24,7 @@ CONFIG_DRM=y
CONFIG_DRM_PANEL_SIMPLE=y
CONFIG_PWM_CROS_EC=y
CONFIG_BACKLIGHT_PWM=y
+CONFIG_DRM_VKMS=m
# Strip out some stuff we don't need for graphics testing, to reduce
# the build.
diff --git a/drivers/gpu/drm/ci/xfails/amdgpu-stoney-fails.txt b/drivers/gpu/drm/ci/xfails/amdgpu-stoney-fails.txt
index ea87dc46bc2b..e8c2f4044a92 100644
--- a/drivers/gpu/drm/ci/xfails/amdgpu-stoney-fails.txt
+++ b/drivers/gpu/drm/ci/xfails/amdgpu-stoney-fails.txt
@@ -1,27 +1,40 @@
+amdgpu/amd_abm@abm_enabled,Fail
+amdgpu/amd_abm@abm_gradual,Fail
+amdgpu/amd_abm@backlight_monotonic_abm,Fail
+amdgpu/amd_abm@backlight_monotonic_basic,Fail
+amdgpu/amd_assr@assr-links,Fail
+amdgpu/amd_assr@assr-links-dpms,Fail
+amdgpu/amd_mall@static-screen,Crash
+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
+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_uvd_dec@amdgpu_uvd_decode,Fail
+dumb_buffer@invalid-bpp,Fail
kms_addfb_basic@bad-pitch-65536,Fail
kms_addfb_basic@bo-too-small,Fail
kms_addfb_basic@too-high,Fail
-kms_async_flips@async-flip-with-page-flip-events,Fail
-kms_async_flips@crc,Fail
-kms_async_flips@invalid-async-flip,Fail
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
kms_atomic_transition@plane-toggle-modeset-transition,Fail
kms_atomic_transition@plane-use-after-nonblocking-unbind,Fail
-kms_bw@linear-tiling-1-displays-2560x1440p,Fail
-kms_bw@linear-tiling-1-displays-3840x2160p,Fail
-kms_bw@linear-tiling-2-displays-3840x2160p,Fail
-kms_bw@linear-tiling-3-displays-1920x1080p,Fail
-kms_color@degamma,Fail
+kms_cursor_crc@cursor-onscreen-64x21,Fail
+kms_cursor_crc@cursor-onscreen-64x64,Fail
+kms_cursor_crc@cursor-random-64x21,Fail
+kms_cursor_crc@cursor-random-64x64,Fail
kms_cursor_crc@cursor-size-change,Fail
-kms_cursor_crc@pipe-A-cursor-size-change,Fail
-kms_cursor_crc@pipe-B-cursor-size-change,Fail
+kms_cursor_crc@cursor-sliding-64x21,Fail
+kms_cursor_crc@cursor-sliding-64x64,Fail
kms_flip@flip-vs-modeset-vs-hang,Fail
kms_flip@flip-vs-panning-vs-hang,Fail
-kms_hdr@bpc-switch,Fail
-kms_hdr@bpc-switch-dpms,Fail
+kms_lease@lease-uevent,Fail
kms_plane@pixel-format,Fail
-kms_plane_multiple@atomic-pipe-A-tiling-none,Fail
-kms_rmfb@close-fd,Fail
+kms_plane_cursor@primary,Fail
kms_rotation_crc@primary-rotation-180,Fail
+perf@i915-ref-count,Fail
+tools_test@tools_test,Fail
diff --git a/drivers/gpu/drm/ci/xfails/amdgpu-stoney-flakes.txt b/drivers/gpu/drm/ci/xfails/amdgpu-stoney-flakes.txt
index 6faf75e667d3..ea512ff8c352 100644
--- a/drivers/gpu/drm/ci/xfails/amdgpu-stoney-flakes.txt
+++ b/drivers/gpu/drm/ci/xfails/amdgpu-stoney-flakes.txt
@@ -1 +1,8 @@
+# Board Name: hp-11A-G6-EE-grunt
+# Bug Report: https://lore.kernel.org/amd-gfx/3542730f-b8d7-404d-a947-b7a5e95d661c@collabora.com/T/#u
+# IGT Version: 1.28-g0df7b9b97
+# Linux Version: 6.9.0-rc7
+# Failure Rate: 50
kms_async_flips@async-flip-with-page-flip-events
+kms_async_flips@crc
+kms_plane@pixel-format-source-clamping
diff --git a/drivers/gpu/drm/ci/xfails/amdgpu-stoney-skips.txt b/drivers/gpu/drm/ci/xfails/amdgpu-stoney-skips.txt
index e2c538a0f954..3a2ce45d3cb9 100644
--- a/drivers/gpu/drm/ci/xfails/amdgpu-stoney-skips.txt
+++ b/drivers/gpu/drm/ci/xfails/amdgpu-stoney-skips.txt
@@ -1,2 +1,33 @@
# Suspend to RAM seems to be broken on this machine
-.*suspend.* \ No newline at end of file
+.*suspend.*
+
+# Skip driver specific tests
+msm_.*
+nouveau_.*
+panfrost_.*
+^v3d.*
+^vc4.*
+^vmwgfx*
+
+# Skip intel specific tests
+gem_.*
+i915_.*
+xe_.*
+
+# Currently fails and causes coverage loss for other tests
+# since core_getversion also fails.
+amdgpu/amd_module_load@reload
+core_hotunplug.*
+
+# GPU reset seen and it hangs the machine
+amdgpu/amd_deadlock@amdgpu-deadlock-sdma
+amdgpu/amd_deadlock@amdgpu-gfx-illegal-reg-access
+amdgpu/amd_dispatch@amdgpu-reset-test-gfx-with-IP-GFX-and-COMPUTE
+
+# Hangs the machine and timeout occurs
+amdgpu/amd_pci_unplug@amdgpu_hotunplug_simple
+amdgpu/amd_pci_unplug@amdgpu_hotunplug_with_cs
+amdgpu/amd_pci_unplug@amdgpu_hotunplug_with_exported_bo
+amdgpu/amd_pci_unplug@amdgpu_hotunplug_with_exported_fence
+amdgpu/amd_vrr_range@freesync-parsing
+device_reset.*
diff --git a/drivers/gpu/drm/ci/xfails/i915-amly-fails.txt b/drivers/gpu/drm/ci/xfails/i915-amly-fails.txt
index 59438e4df86e..6641520ac587 100644
--- a/drivers/gpu/drm/ci/xfails/i915-amly-fails.txt
+++ b/drivers/gpu/drm/ci/xfails/i915-amly-fails.txt
@@ -1,3 +1,16 @@
+core_setmaster@master-drop-set-user,Fail
+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_async_flips@invalid-async-flip,Timeout
+kms_atomic_transition@modeset-transition-fencing,Timeout
+kms_ccs@crc-primary-rotation-180-yf-tiled-ccs,Timeout
+kms_fb_coherency@memset-crc,Crash
+kms_flip@flip-vs-dpms-off-vs-modeset,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
@@ -20,7 +33,25 @@ 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_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@plane-scaler-with-clipping-clamping-rotation,Timeout
+kms_pm_rpm@modeset-lpsp-stress,Timeout
+kms_pm_rpm@modeset-stress-extra-wait,Timeout
+kms_pm_rpm@universal-planes,Timeout
+kms_pm_rpm@universal-planes-dpms,Timeout
+perf@i915-ref-count,Fail
+perf_pmu@module-unload,Fail
+perf_pmu@rc6,Crash
+sysfs_heartbeat_interval@long,Timeout
+sysfs_heartbeat_interval@off,Timeout
+sysfs_preempt_timeout@off,Timeout
+sysfs_timeslice_duration@off,Timeout
+xe_module_load@force-load,Fail
+xe_module_load@load,Fail
+xe_module_load@many-reload,Fail
+xe_module_load@reload,Fail
+xe_module_load@reload-no-display,Fail
diff --git a/drivers/gpu/drm/ci/xfails/i915-amly-flakes.txt b/drivers/gpu/drm/ci/xfails/i915-amly-flakes.txt
new file mode 100644
index 000000000000..0a76547a103d
--- /dev/null
+++ b/drivers/gpu/drm/ci/xfails/i915-amly-flakes.txt
@@ -0,0 +1,9 @@
+# Board Name: asus-C433TA-AJ0005-rammus
+# Bug Report: https://lore.kernel.org/intel-gfx/af4ca4df-a3ef-4943-bdbf-4c3af2c333af@collabora.com/T/#u
+# IGT Version: 1.28-g0df7b9b97
+# Linux Version: 6.9.0-rc7
+# Failure Rate: 50
+i915_hangman@engine-engine-error
+i915_hangman@gt-engine-hang
+kms_async_flips@crc
+kms_universal_plane@cursor-fb-leak
diff --git a/drivers/gpu/drm/ci/xfails/i915-amly-skips.txt b/drivers/gpu/drm/ci/xfails/i915-amly-skips.txt
index fe55540a3f9a..5663ed0420a7 100644
--- a/drivers/gpu/drm/ci/xfails/i915-amly-skips.txt
+++ b/drivers/gpu/drm/ci/xfails/i915-amly-skips.txt
@@ -1,4 +1,24 @@
# Suspend to RAM seems to be broken on this machine
.*suspend.*
# This is generating kernel oops with divide error
-kms_plane_scaling@invalid-parameters \ No newline at end of file
+kms_plane_scaling@invalid-parameters
+
+# Skip driver specific tests
+^amdgpu.*
+msm_.*
+nouveau_.*
+panfrost_.*
+^v3d.*
+^vc4.*
+^vmwgfx*
+
+# GEM tests takes ~1000 hours, so skip it
+gem_.*
+
+# Hangs the machine and timeout occurs
+i915_pm_rc6_residency.*
+i915_suspend.*
+kms_scaling_modes.*
+
+# Kernel panic
+drm_fdinfo.*
diff --git a/drivers/gpu/drm/ci/xfails/i915-apl-fails.txt b/drivers/gpu/drm/ci/xfails/i915-apl-fails.txt
index 2e3b7c5dac3c..e612281149aa 100644
--- a/drivers/gpu/drm/ci/xfails/i915-apl-fails.txt
+++ b/drivers/gpu/drm/ci/xfails/i915-apl-fails.txt
@@ -1,13 +1,7 @@
-kms_3d,Timeout
-kms_bw@linear-tiling-2-displays-1920x1080p,Fail
-kms_bw@linear-tiling-2-displays-2560x1440p,Fail
-kms_bw@linear-tiling-2-displays-3840x2160p,Fail
-kms_bw@linear-tiling-3-displays-1920x1080p,Fail
-kms_bw@linear-tiling-3-displays-2560x1440p,Fail
-kms_bw@linear-tiling-3-displays-3840x2160p,Fail
-kms_bw@linear-tiling-4-displays-1920x1080p,Fail
-kms_bw@linear-tiling-4-displays-2560x1440p,Fail
-kms_bw@linear-tiling-4-displays-3840x2160p,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
@@ -30,18 +24,30 @@ 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-ytilercccs-upscaling,Fail
+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_alpha_blend@pipe-A-alpha-opaque-fb,Fail
-kms_plane_alpha_blend@pipe-A-alpha-transparent-fb,Fail
-kms_plane_alpha_blend@pipe-A-constant-alpha-max,Fail
-kms_plane_alpha_blend@pipe-B-alpha-opaque-fb,Fail
-kms_plane_alpha_blend@pipe-B-alpha-transparent-fb,Fail
-kms_plane_alpha_blend@pipe-B-constant-alpha-max,Fail
-kms_plane_alpha_blend@pipe-C-alpha-opaque-fb,Fail
-kms_plane_alpha_blend@pipe-C-alpha-transparent-fb,Fail
-kms_plane_alpha_blend@pipe-C-constant-alpha-max,Fail
+kms_pm_backlight@basic-brightness,Fail
+kms_pm_backlight@fade,Fail
+kms_pm_backlight@fade-with-dpms,Fail
+kms_pm_rpm@legacy-planes,Timeout
+kms_pm_rpm@legacy-planes-dpms,Timeout
+kms_pm_rpm@modeset-stress-extra-wait,Timeout
+kms_pm_rpm@universal-planes,Timeout
+kms_pm_rpm@universal-planes-dpms,Timeout
kms_sysfs_edid_timing,Fail
+perf@i915-ref-count,Fail
+perf@non-zero-reason,Timeout
+perf_pmu@module-unload,Fail
+perf_pmu@rc6,Crash
+sysfs_heartbeat_interval@long,Timeout
+sysfs_heartbeat_interval@off,Timeout
+sysfs_preempt_timeout@off,Timeout
+sysfs_timeslice_duration@off,Timeout
+xe_module_load@force-load,Fail
+xe_module_load@load,Fail
+xe_module_load@many-reload,Fail
+xe_module_load@reload,Fail
+xe_module_load@reload-no-display,Fail
diff --git a/drivers/gpu/drm/ci/xfails/i915-apl-flakes.txt b/drivers/gpu/drm/ci/xfails/i915-apl-flakes.txt
new file mode 100644
index 000000000000..cb010c153a6a
--- /dev/null
+++ b/drivers/gpu/drm/ci/xfails/i915-apl-flakes.txt
@@ -0,0 +1,6 @@
+# Board Name: asus-C523NA-A20057-coral
+# Bug Report: https://lore.kernel.org/intel-gfx/af4ca4df-a3ef-4943-bdbf-4c3af2c333af@collabora.com/T/#u
+# IGT Version: 1.28-g0df7b9b97
+# Linux Version: 6.9.0-rc7
+# Failure Rate: 50
+kms_fb_coherency@memset-crc
diff --git a/drivers/gpu/drm/ci/xfails/i915-apl-skips.txt b/drivers/gpu/drm/ci/xfails/i915-apl-skips.txt
index 3430b215c06e..ab588e7a447c 100644
--- a/drivers/gpu/drm/ci/xfails/i915-apl-skips.txt
+++ b/drivers/gpu/drm/ci/xfails/i915-apl-skips.txt
@@ -3,4 +3,28 @@
# This is generating kernel oops with divide error
kms_plane_scaling@invalid-parameters
# This is cascading issues
-kms_3d \ No newline at end of file
+kms_3d
+
+# Skip driver specific tests
+^amdgpu.*
+msm_.*
+nouveau_.*
+panfrost_.*
+^v3d.*
+^vc4.*
+^vmwgfx*
+
+# GEM tests takes ~1000 hours, so skip it
+gem_.*
+
+# Hangs the machine and timeout occurs
+i915_pm_rc6_residency.*
+i915_suspend.*
+i915_pm_rpm.*
+device_reset.*
+api_intel_allocator.*
+kms_frontbuffer_tracking.*
+kms_ccs.*
+
+# Kernel panic
+drm_fdinfo.*
diff --git a/drivers/gpu/drm/ci/xfails/i915-cml-fails.txt b/drivers/gpu/drm/ci/xfails/i915-cml-fails.txt
index 240ef8467c26..26cd62bbf30a 100644
--- a/drivers/gpu/drm/ci/xfails/i915-cml-fails.txt
+++ b/drivers/gpu/drm/ci/xfails/i915-cml-fails.txt
@@ -1,3 +1,19 @@
+core_setmaster@master-drop-set-user,Fail
+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_pipe_stress@stress-xrgb8888-untiled,Fail
+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_async_flips@invalid-async-flip,Timeout
+kms_atomic_transition@modeset-transition-fencing,Timeout
+kms_ccs@crc-primary-rotation-180-yf-tiled-ccs,Timeout
+kms_fb_coherency@memset-crc,Crash
+kms_flip@flip-vs-dpms-off-vs-modeset,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
@@ -20,11 +36,33 @@ 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_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_alpha_blend@constant-alpha-min,Fail
+kms_plane_scaling@plane-scaler-with-clipping-clamping-rotation,Timeout
+kms_pm_rpm@modeset-stress-extra-wait,Timeout
+kms_pm_rpm@universal-planes,Timeout
+kms_pm_rpm@universal-planes-dpms,Timeout
+kms_psr2_sf@fbc-plane-move-sf-dmg-area,Timeout
+kms_psr2_sf@overlay-plane-update-continuous-sf,Fail
+kms_psr2_sf@overlay-plane-update-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_su@page_flip-NV12,Fail
kms_psr2_su@page_flip-P010,Fail
+kms_psr@psr-sprite-render,Timeout
kms_setmode@basic,Fail
+perf@i915-ref-count,Fail
+perf_pmu@module-unload,Fail
+perf_pmu@rc6,Crash
+perf_pmu@rc6-suspend,Crash
+sysfs_heartbeat_interval@long,Timeout
+sysfs_heartbeat_interval@off,Timeout
+sysfs_preempt_timeout@off,Timeout
+sysfs_timeslice_duration@off,Timeout
+xe_module_load@force-load,Fail
+xe_module_load@load,Fail
+xe_module_load@many-reload,Fail
diff --git a/drivers/gpu/drm/ci/xfails/i915-cml-flakes.txt b/drivers/gpu/drm/ci/xfails/i915-cml-flakes.txt
new file mode 100644
index 000000000000..bb560ff1e2cd
--- /dev/null
+++ b/drivers/gpu/drm/ci/xfails/i915-cml-flakes.txt
@@ -0,0 +1,6 @@
+# Board Name: asus-C436FA-Flip-hatch
+# Bug Report: https://lore.kernel.org/intel-gfx/af4ca4df-a3ef-4943-bdbf-4c3af2c333af@collabora.com/T/#u
+# IGT Version: 1.28-g0df7b9b97
+# Linux Version: 6.9.0-rc7
+# Failure Rate: 50
+kms_plane_alpha_blend@constant-alpha-min
diff --git a/drivers/gpu/drm/ci/xfails/i915-cml-skips.txt b/drivers/gpu/drm/ci/xfails/i915-cml-skips.txt
index 6d3d7ddc377f..93b7736fffbb 100644
--- a/drivers/gpu/drm/ci/xfails/i915-cml-skips.txt
+++ b/drivers/gpu/drm/ci/xfails/i915-cml-skips.txt
@@ -1,2 +1,25 @@
# This is generating kernel oops with divide error
kms_plane_scaling@invalid-parameters
+
+# Skip driver specific tests
+^amdgpu.*
+msm_.*
+nouveau_.*
+panfrost_.*
+^v3d.*
+^vc4.*
+^vmwgfx*
+
+# GEM tests takes ~1000 hours, so skip it
+gem_.*
+
+# Hangs the machine and timeout occurs
+i915_pm_rc6_residency.*
+i915_suspend.*
+xe_module_load.*
+api_intel_allocator.*
+kms_cursor_legacy.*
+
+# Kernel panic
+drm_fdinfo.*
+kms_frontbuffer_tracking.*
diff --git a/drivers/gpu/drm/ci/xfails/i915-glk-fails.txt b/drivers/gpu/drm/ci/xfails/i915-glk-fails.txt
index 4596055d7e5e..fca15b487929 100644
--- a/drivers/gpu/drm/ci/xfails/i915-glk-fails.txt
+++ b/drivers/gpu/drm/ci/xfails/i915-glk-fails.txt
@@ -1,5 +1,20 @@
-kms_fbcon_fbt@fbc,Fail
-kms_flip@blocking-wf_vblank,Fail
+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_async_flips@invalid-async-flip,Timeout
+kms_atomic_transition@modeset-transition-fencing,Timeout
+kms_big_fb@linear-16bpp-rotate-0,Fail
+kms_big_fb@linear-16bpp-rotate-180,Fail
+kms_big_fb@linear-32bpp-rotate-0,Fail
+kms_big_fb@linear-32bpp-rotate-180,Fail
+kms_big_fb@linear-8bpp-rotate-0,Fail
+kms_big_fb@linear-8bpp-rotate-180,Fail
+kms_big_fb@linear-max-hw-stride-32bpp-rotate-0,Fail
+kms_dirtyfb@default-dirtyfb-ioctl,Fail
+kms_draw_crc@draw-method-render,Fail
+kms_flip@flip-vs-dpms-off-vs-modeset,Timeout
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
@@ -11,7 +26,6 @@ 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
@@ -26,11 +40,24 @@ 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-tiling-linear,Fail
kms_frontbuffer_tracking@fbcdrrs-tiling-linear,Fail
-kms_plane_alpha_blend@alpha-basic,Fail
+kms_lease@lease-uevent,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@plane-scaler-with-clipping-clamping-rotation,Timeout
+kms_pm_rpm@legacy-planes,Timeout
+kms_pm_rpm@legacy-planes-dpms,Timeout
+kms_pm_rpm@modeset-stress-extra-wait,Timeout
+kms_pm_rpm@universal-planes,Timeout
+kms_pm_rpm@universal-planes-dpms,Timeout
kms_rotation_crc@multiplane-rotation,Fail
kms_rotation_crc@multiplane-rotation-cropping-bottom,Fail
kms_rotation_crc@multiplane-rotation-cropping-top,Fail
-kms_setmode@basic,Fail
+perf@non-zero-reason,Timeout
+sysfs_heartbeat_interval@long,Timeout
+sysfs_heartbeat_interval@off,Timeout
+sysfs_preempt_timeout@off,Timeout
+sysfs_timeslice_duration@off,Timeout
+xe_module_load@force-load,Fail
+xe_module_load@load,Fail
+xe_module_load@many-reload,Fail
+xe_module_load@reload,Fail
+xe_module_load@reload-no-display,Fail
diff --git a/drivers/gpu/drm/ci/xfails/i915-glk-flakes.txt b/drivers/gpu/drm/ci/xfails/i915-glk-flakes.txt
new file mode 100644
index 000000000000..58fc424f8a42
--- /dev/null
+++ b/drivers/gpu/drm/ci/xfails/i915-glk-flakes.txt
@@ -0,0 +1,7 @@
+# Board Name: hp-x360-12b-ca0010nr-n4020-octopus
+# Bug Report: https://lore.kernel.org/intel-gfx/af4ca4df-a3ef-4943-bdbf-4c3af2c333af@collabora.com/T/#u
+# IGT Version: 1.28-g0df7b9b97
+# Linux Version: 6.9.0-rc7
+# Failure Rate: 50
+core_hotunplug@unplug-rescan
+kms_fb_coherency@memset-crc
diff --git a/drivers/gpu/drm/ci/xfails/i915-glk-skips.txt b/drivers/gpu/drm/ci/xfails/i915-glk-skips.txt
index 4c7d00ce14bc..b3226b2d9ba1 100644
--- a/drivers/gpu/drm/ci/xfails/i915-glk-skips.txt
+++ b/drivers/gpu/drm/ci/xfails/i915-glk-skips.txt
@@ -2,4 +2,28 @@
.*suspend.*
# This is generating kernel oops with divide error
-kms_plane_scaling@invalid-parameters \ No newline at end of file
+kms_plane_scaling@invalid-parameters
+
+# Skip driver specific tests
+^amdgpu.*
+msm_.*
+nouveau_.*
+panfrost_.*
+^v3d.*
+^vc4.*
+^vmwgfx*
+
+# GEM tests takes ~1000 hours, so skip it
+gem_.*
+
+# Hangs the machine and timeout occurs
+i915_pm_rc6_residency.*
+i915_suspend.*
+i915_pm_rpm.*
+kms_ccs.*
+kms_plane_multiple.*
+perf.*
+
+# Kernel panic
+drm_fdinfo.*
+kms_plane_alpha_blend.*
diff --git a/drivers/gpu/drm/ci/xfails/i915-kbl-fails.txt b/drivers/gpu/drm/ci/xfails/i915-kbl-fails.txt
index dab202716909..d4fba4f55ec1 100644
--- a/drivers/gpu/drm/ci/xfails/i915-kbl-fails.txt
+++ b/drivers/gpu/drm/ci/xfails/i915-kbl-fails.txt
@@ -1,32 +1,28 @@
-kms_bw@linear-tiling-2-displays-2560x1440p,Fail
-kms_bw@linear-tiling-4-displays-2560x1440p,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
+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-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_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilercccs-upscaling,Fail
-kms_plane_alpha_blend@alpha-basic,Fail
-kms_plane_alpha_blend@alpha-opaque-fb,Fail
+kms_lease@lease-uevent,Fail
kms_plane_alpha_blend@alpha-transparent-fb,Fail
-kms_plane_alpha_blend@constant-alpha-max,Fail
-kms_plane_alpha_blend@pipe-A-constant-alpha-max,Fail
-kms_plane_alpha_blend@pipe-B-alpha-opaque-fb,Fail
-kms_plane_alpha_blend@pipe-C-constant-alpha-max,Fail
+perf@i915-ref-count,Fail
+perf_pmu@busy-accuracy-50,Fail
+perf_pmu@module-unload,Fail
+perf_pmu@rc6,Crash
+sysfs_heartbeat_interval@long,Timeout
+sysfs_heartbeat_interval@off,Timeout
+sysfs_preempt_timeout@off,Timeout
+sysfs_timeslice_duration@off,Timeout
+xe_module_load@force-load,Fail
+xe_module_load@load,Fail
+xe_module_load@many-reload,Fail
+xe_module_load@reload,Fail
+xe_module_load@reload-no-display,Fail
diff --git a/drivers/gpu/drm/ci/xfails/i915-kbl-flakes.txt b/drivers/gpu/drm/ci/xfails/i915-kbl-flakes.txt
index a12f888530dd..6cf1fed2e575 100644
--- a/drivers/gpu/drm/ci/xfails/i915-kbl-flakes.txt
+++ b/drivers/gpu/drm/ci/xfails/i915-kbl-flakes.txt
@@ -1 +1,6 @@
-kms_async_flips@crc
+# Board Name: hp-x360-14-G1-sona
+# Bug Report: https://lore.kernel.org/intel-gfx/af4ca4df-a3ef-4943-bdbf-4c3af2c333af@collabora.com/T/#u
+# IGT Version: 1.28-g0df7b9b97
+# Linux Version: 6.9.0-rc7
+# Failure Rate: 50
+prime_busy@hang
diff --git a/drivers/gpu/drm/ci/xfails/i915-kbl-skips.txt b/drivers/gpu/drm/ci/xfails/i915-kbl-skips.txt
index 4c7d00ce14bc..f0cf8a6dda25 100644
--- a/drivers/gpu/drm/ci/xfails/i915-kbl-skips.txt
+++ b/drivers/gpu/drm/ci/xfails/i915-kbl-skips.txt
@@ -2,4 +2,38 @@
.*suspend.*
# This is generating kernel oops with divide error
-kms_plane_scaling@invalid-parameters \ No newline at end of file
+kms_plane_scaling@invalid-parameters
+
+# Skip driver specific tests
+^amdgpu.*
+msm_.*
+nouveau_.*
+panfrost_.*
+^v3d.*
+^vc4.*
+^vmwgfx*
+
+# GEM tests takes ~1000 hours, so skip it
+gem_.*
+
+# Hangs the machine and timeout occurs
+i915_.*
+api_intel_bb.*
+
+# Kernel panic
+drm_fdinfo.*
+kms_.*
+prime_mmap_coherency.*
+perf.*
+drm_read.*
+api_intel_allocator.*
+sysfs_preempt_timeout.*
+dumb_buffer.*
+gen9_exec_parse.*
+debugfs_test.*
+core_hotunplug.*
+tools_test.*
+
+# GPU hang
+sysfs_timeslice_.*
+sysfs_heartbeat_.*
diff --git a/drivers/gpu/drm/ci/xfails/i915-tgl-fails.txt b/drivers/gpu/drm/ci/xfails/i915-tgl-fails.txt
index 27bfca1c6f2c..9a50e894c3e7 100644
--- a/drivers/gpu/drm/ci/xfails/i915-tgl-fails.txt
+++ b/drivers/gpu/drm/ci/xfails/i915-tgl-fails.txt
@@ -1,36 +1,43 @@
-kms_bw@linear-tiling-2-displays-3840x2160p,Fail
-kms_bw@linear-tiling-3-displays-1920x1080p,Fail
-kms_bw@linear-tiling-3-displays-2560x1440p,Fail
-kms_bw@linear-tiling-3-displays-3840x2160p,Fail
-kms_bw@linear-tiling-4-displays-1920x1080p,Fail
-kms_bw@linear-tiling-4-displays-2560x1440p,Fail
-kms_bw@linear-tiling-4-displays-3840x2160p,Fail
-kms_bw@linear-tiling-5-displays-1920x1080p,Fail
-kms_bw@linear-tiling-5-displays-2560x1440p,Fail
-kms_bw@linear-tiling-5-displays-3840x2160p,Fail
-kms_flip@flip-vs-panning-vs-hang,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-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_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilercccs-upscaling,Fail
-kms_rotation_crc@bad-pixel-format,Fail
+api_intel_bb@blit-noreloc-keep-cache,Timeout
+api_intel_bb@offset-control,Timeout
+api_intel_bb@render-ccs,Timeout
+core_getclient,Timeout
+core_hotunplug@hotreplug-lateclose,Timeout
+drm_read@short-buffer-block,Timeout
+drm_read@short-buffer-nonblock,Timeout
+dumb_buffer@map-uaf,Timeout
+gen3_render_tiledx_blits,Timeout
+gen7_exec_parse@basic-allocation,Timeout
+gen7_exec_parse@batch-without-end,Timeout
+gen9_exec_parse@batch-invalid-length,Timeout
+gen9_exec_parse@bb-secure,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_pciid,Timeout
+i915_query@engine-info,Timeout
+kms_lease@lease-uevent,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@busy,Timeout
+perf_pmu@enable-race,Timeout
+perf_pmu@event-wait,Timeout
+perf_pmu@gt-awake,Timeout
+perf_pmu@module-unload,Fail
+perf_pmu@rc6,Crash
+prime_mmap@test_map_unmap,Timeout
+prime_self_import@basic-with_one_bo,Timeout
+syncobj_basic@bad-destroy,Timeout
+syncobj_eventfd@invalid-bad-pad,Timeout
+syncobj_wait@invalid-multi-wait-unsubmitted-signaled,Timeout
+syncobj_wait@invalid-signal-illegal-handle,Timeout
+syncobj_wait@invalid-single-wait-all-unsubmitted,Timeout
+syncobj_wait@multi-wait-all-submitted,Timeout
+syncobj_wait@multi-wait-for-submit-submitted-signaled,Timeout
+syncobj_wait@wait-any-complex,Timeout
+syncobj_wait@wait-delayed-signal,Timeout
+xe_module_load@force-load,Fail
+xe_module_load@load,Fail
+xe_module_load@reload,Fail
+xe_module_load@reload-no-display,Fail
diff --git a/drivers/gpu/drm/ci/xfails/i915-tgl-skips.txt b/drivers/gpu/drm/ci/xfails/i915-tgl-skips.txt
index 1d0621750b14..e600782ef96a 100644
--- a/drivers/gpu/drm/ci/xfails/i915-tgl-skips.txt
+++ b/drivers/gpu/drm/ci/xfails/i915-tgl-skips.txt
@@ -8,4 +8,30 @@ gem_eio.*
kms_flip@absolute-wf_vblank@a-edp1
# This is generating kernel oops with divide error
-kms_plane_scaling@invalid-parameters \ No newline at end of file
+kms_plane_scaling@invalid-parameters
+
+# Skip driver specific tests
+^amdgpu.*
+msm_.*
+nouveau_.*
+panfrost_.*
+^v3d.*
+^vc4.*
+^vmwgfx*
+
+# GEM tests takes ~1000 hours, so skip it
+gem_.*
+
+# Kernel panic
+drm_fdinfo.*
+
+# Hangs the machine and timeout occurs
+i915_pm_rc6_residency.*
+i915_suspend.*
+sysfs_heartbeat_interval.*
+syncobj_timeline.*
+sysfs_timeslice_duration.*
+syncobj_wait.*
+
+# Kernel panic and test hangs with multiple kms tests
+kms_.*
diff --git a/drivers/gpu/drm/ci/xfails/i915-whl-fails.txt b/drivers/gpu/drm/ci/xfails/i915-whl-fails.txt
index 967327ddc1ac..7582d313dd9b 100644
--- a/drivers/gpu/drm/ci/xfails/i915-whl-fails.txt
+++ b/drivers/gpu/drm/ci/xfails/i915-whl-fails.txt
@@ -1,14 +1,25 @@
-kms_bw@linear-tiling-2-displays-1920x1080p,Fail
-kms_bw@linear-tiling-2-displays-2560x1440p,Fail
-kms_bw@linear-tiling-2-displays-3840x2160p,Fail
-kms_bw@linear-tiling-3-displays-1920x1080p,Fail
-kms_bw@linear-tiling-3-displays-2560x1440p,Fail
-kms_bw@linear-tiling-3-displays-3840x2160p,Fail
-kms_bw@linear-tiling-4-displays-1920x1080p,Fail
-kms_bw@linear-tiling-4-displays-2560x1440p,Fail
-kms_bw@linear-tiling-4-displays-3840x2160p,Fail
-kms_fbcon_fbt@fbc,Fail
-kms_fbcon_fbt@fbc-suspend,Fail
+core_setmaster@master-drop-set-user,Fail
+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
+i915_pm_rpm@system-suspend-execbuf,Timeout
+kms_async_flips@invalid-async-flip,Timeout
+kms_atomic_transition@modeset-transition-fencing,Timeout
+kms_big_fb@linear-16bpp-rotate-0,Fail
+kms_big_fb@linear-16bpp-rotate-180,Fail
+kms_big_fb@linear-32bpp-rotate-0,Fail
+kms_big_fb@linear-32bpp-rotate-180,Fail
+kms_big_fb@linear-8bpp-rotate-0,Fail
+kms_big_fb@linear-8bpp-rotate-180,Fail
+kms_big_fb@linear-max-hw-stride-32bpp-rotate-0,Fail
+kms_ccs@crc-primary-rotation-180-yf-tiled-ccs,Timeout
+kms_dirtyfb@default-dirtyfb-ioctl,Fail
+kms_draw_crc@draw-method-render,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
@@ -18,8 +29,6 @@ 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
@@ -31,18 +40,26 @@ 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-ytilercccs-upscaling,Fail
kms_frontbuffer_tracking@fbc-tiling-linear,Fail
+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_alpha_blend@pipe-A-alpha-opaque-fb,Fail
-kms_plane_alpha_blend@pipe-A-alpha-transparent-fb,Fail
-kms_plane_alpha_blend@pipe-A-constant-alpha-max,Fail
-kms_plane_alpha_blend@pipe-B-alpha-opaque-fb,Fail
-kms_plane_alpha_blend@pipe-B-alpha-transparent-fb,Fail
-kms_plane_alpha_blend@pipe-B-constant-alpha-max,Fail
-kms_plane_alpha_blend@pipe-C-alpha-opaque-fb,Fail
-kms_plane_alpha_blend@pipe-C-alpha-transparent-fb,Fail
-kms_plane_alpha_blend@pipe-C-constant-alpha-max,Fail
+kms_plane_scaling@plane-scaler-with-clipping-clamping-rotation,Timeout
+kms_pm_rpm@modeset-stress-extra-wait,Timeout
+kms_pm_rpm@universal-planes,Timeout
+kms_pm_rpm@universal-planes-dpms,Timeout
+perf@i915-ref-count,Fail
+perf_pmu@module-unload,Fail
+perf_pmu@rc6,Crash
+perf_pmu@rc6-suspend,Crash
+sysfs_heartbeat_interval@long,Timeout
+sysfs_heartbeat_interval@off,Timeout
+sysfs_preempt_timeout@off,Timeout
+sysfs_timeslice_duration@off,Timeout
+xe_module_load@force-load,Fail
+xe_module_load@load,Fail
+xe_module_load@many-reload,Fail
+xe_module_load@reload,Fail
+xe_module_load@reload-no-display,Fail
diff --git a/drivers/gpu/drm/ci/xfails/i915-whl-flakes.txt b/drivers/gpu/drm/ci/xfails/i915-whl-flakes.txt
new file mode 100644
index 000000000000..1167a58c7dd1
--- /dev/null
+++ b/drivers/gpu/drm/ci/xfails/i915-whl-flakes.txt
@@ -0,0 +1,6 @@
+# Board Name: dell-latitude-5400-8665U-sarien
+# Bug Report: https://lore.kernel.org/intel-gfx/af4ca4df-a3ef-4943-bdbf-4c3af2c333af@collabora.com/T/#u
+# IGT Version: 1.28-g0df7b9b97
+# Linux Version: 6.9.0-rc7
+# Failure Rate: 50
+kms_pm_rpm@modeset-lpsp-stress
diff --git a/drivers/gpu/drm/ci/xfails/i915-whl-skips.txt b/drivers/gpu/drm/ci/xfails/i915-whl-skips.txt
index f3be0888a214..20bd91525f45 100644
--- a/drivers/gpu/drm/ci/xfails/i915-whl-skips.txt
+++ b/drivers/gpu/drm/ci/xfails/i915-whl-skips.txt
@@ -1,2 +1,22 @@
# This is generating kernel oops with divide error
-kms_plane_scaling@invalid-parameters \ No newline at end of file
+kms_plane_scaling@invalid-parameters
+
+# Skip driver specific tests
+^amdgpu.*
+msm_.*
+nouveau_.*
+panfrost_.*
+^v3d.*
+^vc4.*
+^vmwgfx*
+
+# GEM tests takes ~1000 hours, so skip it
+gem_.*
+
+# Hangs the machine and timeout occurs
+i915_pm_rc6_residency.*
+i915_suspend.*
+kms_flip.*
+
+# Kernel panic
+drm_fdinfo.*
diff --git a/drivers/gpu/drm/ci/xfails/mediatek-mt8173-fails.txt b/drivers/gpu/drm/ci/xfails/mediatek-mt8173-fails.txt
index ef0cb7c3698c..cc5e9c1c2d57 100644
--- a/drivers/gpu/drm/ci/xfails/mediatek-mt8173-fails.txt
+++ b/drivers/gpu/drm/ci/xfails/mediatek-mt8173-fails.txt
@@ -1,36 +1,30 @@
+device_reset@cold-reset-bound,Fail
+device_reset@reset-bound,Fail
+device_reset@unbind-cold-reset-rebind,Fail
+device_reset@unbind-reset-rebind,Fail
+dumb_buffer@invalid-bpp,Fail
+fbdev@eof,Fail
+fbdev@read,Fail
+fbdev@unaligned-write,Fail
kms_3d,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
kms_bw@linear-tiling-2-displays-3840x2160p,Fail
-kms_bw@linear-tiling-3-displays-1920x1080p,Fail
-kms_bw@linear-tiling-3-displays-2560x1440p,Fail
-kms_bw@linear-tiling-3-displays-3840x2160p,Fail
kms_color@invalid-gamma-lut-sizes,Fail
-kms_color@pipe-A-invalid-gamma-lut-sizes,Fail
-kms_color@pipe-B-invalid-gamma-lut-sizes,Fail
kms_cursor_legacy@cursor-vs-flip-atomic,Fail
kms_cursor_legacy@cursor-vs-flip-legacy,Fail
kms_flip@flip-vs-modeset-vs-hang,Fail
kms_flip@flip-vs-panning-vs-hang,Fail
kms_flip@flip-vs-suspend,Fail
kms_flip@flip-vs-suspend-interruptible,Fail
-kms_force_connector_basic@force-edid,Fail
-kms_force_connector_basic@force-load-detect,Fail
-kms_force_connector_basic@prune-stale-modes,Fail
-kms_hdmi_inject@inject-4k,Fail
-kms_plane_scaling@planes-upscale-20x20,Fail
-kms_plane_scaling@planes-upscale-20x20-downscale-factor-0-25,Fail
-kms_plane_scaling@planes-upscale-20x20-downscale-factor-0-5,Fail
-kms_plane_scaling@planes-upscale-20x20-downscale-factor-0-75,Fail
-kms_plane_scaling@upscale-with-modifier-20x20,Fail
-kms_plane_scaling@upscale-with-pixel-format-20x20,Fail
-kms_plane_scaling@upscale-with-rotation-20x20,Fail
+kms_lease@lease-uevent,Fail
kms_properties@get_properties-sanity-atomic,Fail
kms_properties@plane-properties-atomic,Fail
kms_properties@plane-properties-legacy,Fail
kms_rmfb@close-fd,Fail
-kms_selftest@drm_format,Timeout
-kms_selftest@drm_format_helper,Timeout
+tools_test@tools_test,Fail
diff --git a/drivers/gpu/drm/ci/xfails/mediatek-mt8173-flakes.txt b/drivers/gpu/drm/ci/xfails/mediatek-mt8173-flakes.txt
new file mode 100644
index 000000000000..395ac0463404
--- /dev/null
+++ b/drivers/gpu/drm/ci/xfails/mediatek-mt8173-flakes.txt
@@ -0,0 +1,11 @@
+# Board Name: mt8173-elm-hana
+# Bug Report: https://lore.kernel.org/linux-mediatek/0b2a1899-15dd-42fa-8f63-ea0ca28dbb17@collabora.com/T/#u
+# IGT Version: 1.28-g0df7b9b97
+# Linux Version: 6.9.0-rc7
+# Failure Rate: 50
+core_setmaster_vs_auth
+dumb_buffer@create-clear
+fbdev@unaligned-write
+fbdev@write
+kms_cursor_legacy@cursor-vs-flip-atomic-transitions
+kms_prop_blob@invalid-set-prop
diff --git a/drivers/gpu/drm/ci/xfails/mediatek-mt8173-skips.txt b/drivers/gpu/drm/ci/xfails/mediatek-mt8173-skips.txt
new file mode 100644
index 000000000000..0c6108392140
--- /dev/null
+++ b/drivers/gpu/drm/ci/xfails/mediatek-mt8173-skips.txt
@@ -0,0 +1,16 @@
+# Skip driver specific tests
+^amdgpu.*
+msm_.*
+nouveau_.*
+panfrost_.*
+^v3d.*
+^vc4.*
+^vmwgfx*
+
+# Skip intel specific tests
+gem_.*
+i915_.*
+
+# Currently fails and causes coverage loss for other tests
+# since core_getversion also fails.
+core_hotunplug.*
diff --git a/drivers/gpu/drm/ci/xfails/mediatek-mt8183-fails.txt b/drivers/gpu/drm/ci/xfails/mediatek-mt8183-fails.txt
index 67d690fc4037..9ef460646d76 100644
--- a/drivers/gpu/drm/ci/xfails/mediatek-mt8183-fails.txt
+++ b/drivers/gpu/drm/ci/xfails/mediatek-mt8183-fails.txt
@@ -1,13 +1,8 @@
-kms_addfb_basic@addfb25-bad-modifier,Fail
-kms_bw@linear-tiling-1-displays-2560x1440p,Fail
-kms_bw@linear-tiling-2-displays-1920x1080p,Fail
-kms_bw@linear-tiling-2-displays-2560x1440p,Fail
-kms_bw@linear-tiling-2-displays-3840x2160p,Fail
-kms_bw@linear-tiling-3-displays-2560x1440p,Fail
-kms_bw@linear-tiling-3-displays-3840x2160p,Fail
-kms_color@pipe-A-invalid-gamma-lut-sizes,Fail
-kms_plane_cursor@overlay,Fail
-kms_plane_cursor@primary,Fail
-kms_plane_cursor@viewport,Fail
-kms_plane_scaling@upscale-with-rotation-20x20,Fail
-kms_rmfb@close-fd,Fail
+dumb_buffer@create-clear,Fail
+dumb_buffer@create-valid-dumb,Fail
+dumb_buffer@invalid-bpp,Fail
+dumb_buffer@map-invalid-size,Fail
+dumb_buffer@map-uaf,Fail
+dumb_buffer@map-valid,Fail
+panfrost_prime@gem-prime-import,Fail
+tools_test@tools_test,Fail
diff --git a/drivers/gpu/drm/ci/xfails/mediatek-mt8183-skips.txt b/drivers/gpu/drm/ci/xfails/mediatek-mt8183-skips.txt
new file mode 100644
index 000000000000..715b9a8f4997
--- /dev/null
+++ b/drivers/gpu/drm/ci/xfails/mediatek-mt8183-skips.txt
@@ -0,0 +1,18 @@
+# Skip driver specific tests
+^amdgpu.*
+msm_.*
+nouveau_.*
+^v3d.*
+^vc4.*
+^vmwgfx*
+
+# Skip intel specific tests
+gem_.*
+i915_.*
+
+# Panfrost is not a KMS driver, so skip the KMS tests
+kms_.*
+
+# Currently fails and causes coverage loss for other tests
+# since core_getversion also fails.
+core_hotunplug.*
diff --git a/drivers/gpu/drm/ci/xfails/meson-g12b-fails.txt b/drivers/gpu/drm/ci/xfails/meson-g12b-fails.txt
index 56a2ae7047b4..9ef460646d76 100644
--- a/drivers/gpu/drm/ci/xfails/meson-g12b-fails.txt
+++ b/drivers/gpu/drm/ci/xfails/meson-g12b-fails.txt
@@ -1,16 +1,8 @@
-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_force_connector_basic@force-edid,Fail
-kms_hdmi_inject@inject-4k,Fail
-kms_plane_cursor@overlay,Fail
-kms_plane_cursor@primary,Fail
-kms_plane_cursor@viewport,Fail
-kms_properties@connector-properties-atomic,Fail
-kms_properties@connector-properties-legacy,Fail
-kms_properties@get_properties-sanity-atomic,Fail
-kms_properties@get_properties-sanity-non-atomic,Fail
+dumb_buffer@create-clear,Fail
+dumb_buffer@create-valid-dumb,Fail
+dumb_buffer@invalid-bpp,Fail
+dumb_buffer@map-invalid-size,Fail
+dumb_buffer@map-uaf,Fail
+dumb_buffer@map-valid,Fail
+panfrost_prime@gem-prime-import,Fail
+tools_test@tools_test,Fail
diff --git a/drivers/gpu/drm/ci/xfails/meson-g12b-skips.txt b/drivers/gpu/drm/ci/xfails/meson-g12b-skips.txt
new file mode 100644
index 000000000000..715b9a8f4997
--- /dev/null
+++ b/drivers/gpu/drm/ci/xfails/meson-g12b-skips.txt
@@ -0,0 +1,18 @@
+# Skip driver specific tests
+^amdgpu.*
+msm_.*
+nouveau_.*
+^v3d.*
+^vc4.*
+^vmwgfx*
+
+# Skip intel specific tests
+gem_.*
+i915_.*
+
+# Panfrost is not a KMS driver, so skip the KMS tests
+kms_.*
+
+# Currently fails and causes coverage loss for other tests
+# since core_getversion also fails.
+core_hotunplug.*
diff --git a/drivers/gpu/drm/ci/xfails/msm-apq8016-fails.txt b/drivers/gpu/drm/ci/xfails/msm-apq8016-fails.txt
index 44a5c62dedad..6e7fd1ccd1e3 100644
--- a/drivers/gpu/drm/ci/xfails/msm-apq8016-fails.txt
+++ b/drivers/gpu/drm/ci/xfails/msm-apq8016-fails.txt
@@ -1,19 +1,15 @@
+device_reset@cold-reset-bound,Fail
+device_reset@reset-bound,Fail
+device_reset@unbind-cold-reset-rebind,Fail
+device_reset@unbind-reset-rebind,Fail
+dumb_buffer@invalid-bpp,Fail
kms_3d,Fail
-kms_addfb_basic@addfb25-bad-modifier,Fail
-kms_cursor_legacy@all-pipes-forked-bo,Fail
-kms_cursor_legacy@all-pipes-forked-move,Fail
-kms_cursor_legacy@all-pipes-single-bo,Fail
-kms_cursor_legacy@all-pipes-single-move,Fail
-kms_cursor_legacy@all-pipes-torture-bo,Fail
-kms_cursor_legacy@all-pipes-torture-move,Fail
-kms_cursor_legacy@pipe-A-forked-bo,Fail
-kms_cursor_legacy@pipe-A-forked-move,Fail
-kms_cursor_legacy@pipe-A-single-bo,Fail
-kms_cursor_legacy@pipe-A-single-move,Fail
-kms_cursor_legacy@pipe-A-torture-bo,Fail
-kms_cursor_legacy@pipe-A-torture-move,Fail
+kms_cursor_legacy@forked-move,Fail
+kms_cursor_legacy@single-bo,Fail
+kms_cursor_legacy@torture-bo,Fail
+kms_cursor_legacy@torture-move,Fail
kms_force_connector_basic@force-edid,Fail
kms_hdmi_inject@inject-4k,Fail
-kms_selftest@drm_format,Timeout
-kms_selftest@drm_format_helper,Timeout
+kms_lease@lease-uevent,Fail
msm_mapping@ring,Fail
+tools_test@tools_test,Fail
diff --git a/drivers/gpu/drm/ci/xfails/msm-apq8016-skips.txt b/drivers/gpu/drm/ci/xfails/msm-apq8016-skips.txt
new file mode 100644
index 000000000000..ff12202abb6e
--- /dev/null
+++ b/drivers/gpu/drm/ci/xfails/msm-apq8016-skips.txt
@@ -0,0 +1,15 @@
+# Skip driver specific tests
+^amdgpu.*
+nouveau_.*
+panfrost_.*
+^v3d.*
+^vc4.*
+^vmwgfx*
+
+# Skip intel specific tests
+gem_.*
+i915_.*
+
+# Currently fails and causes coverage loss for other tests
+# since core_getversion also fails.
+core_hotunplug.*
diff --git a/drivers/gpu/drm/ci/xfails/msm-apq8096-fails.txt b/drivers/gpu/drm/ci/xfails/msm-apq8096-fails.txt
index 88a1fc0a3b0d..46ca69ce2ffe 100644
--- a/drivers/gpu/drm/ci/xfails/msm-apq8096-fails.txt
+++ b/drivers/gpu/drm/ci/xfails/msm-apq8096-fails.txt
@@ -1,2 +1,8 @@
+device_reset@cold-reset-bound,Fail
+device_reset@reset-bound,Fail
+device_reset@unbind-cold-reset-rebind,Fail
+device_reset@unbind-reset-rebind,Fail
+dumb_buffer@invalid-bpp,Fail
kms_3d,Fail
-kms_addfb_basic@addfb25-bad-modifier,Fail
+kms_lease@lease-uevent,Fail
+tools_test@tools_test,Fail
diff --git a/drivers/gpu/drm/ci/xfails/msm-apq8096-flakes.txt b/drivers/gpu/drm/ci/xfails/msm-apq8096-flakes.txt
new file mode 100644
index 000000000000..a275584c8bbb
--- /dev/null
+++ b/drivers/gpu/drm/ci/xfails/msm-apq8096-flakes.txt
@@ -0,0 +1,6 @@
+# Board Name: apq8096-db820c
+# Bug Report: https://lore.kernel.org/linux-arm-msm/661483c8-ad82-400d-bcd8-e94986d20d7d@collabora.com/T/#u
+# IGT Version: 1.28-g0df7b9b97
+# Linux Version: 6.9.0-rc7
+# Failure Rate: 50
+dumb_buffer@create-clear
diff --git a/drivers/gpu/drm/ci/xfails/msm-apq8096-skips.txt b/drivers/gpu/drm/ci/xfails/msm-apq8096-skips.txt
index cd49c8ce2059..1c45fc6c512d 100644
--- a/drivers/gpu/drm/ci/xfails/msm-apq8096-skips.txt
+++ b/drivers/gpu/drm/ci/xfails/msm-apq8096-skips.txt
@@ -1,2 +1,26 @@
# Whole machine hangs
-kms_cursor_legacy@all-pipes-torture-move \ No newline at end of file
+kms_cursor_legacy@all-pipes-torture-move
+
+# Skip driver specific tests
+^amdgpu.*
+nouveau_.*
+panfrost_.*
+^v3d.*
+^vc4.*
+^vmwgfx*
+
+# Skip intel specific tests
+gem_.*
+i915_.*
+
+# Currently fails and causes coverage loss for other tests
+# since core_getversion also fails.
+core_hotunplug.*
+
+# gpu fault
+# [IGT] msm_mapping: executing
+# [IGT] msm_mapping: starting subtest shadow
+# *** gpu fault: ttbr0=00000001030ea000 iova=0000000001074000 dir=WRITE type=PERMISSION source=1f030000 (0,0,0,0)
+# msm_mdp 901000.display-controller: RBBM | ME master split | status=0x701000B0
+# watchdog: BUG: soft lockup - CPU#0 stuck for 26s! [kworker/u16:3:46]
+msm_mapping@shadow
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 f0576aa629e8..eb7a3886d397 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,18 +1,191 @@
+device_reset@cold-reset-bound,Fail
+device_reset@reset-bound,Fail
+device_reset@unbind-cold-reset-rebind,Fail
+device_reset@unbind-reset-rebind,Fail
+dumb_buffer@invalid-bpp,Fail
+kms_atomic_transition@plane-primary-toggle-with-vblank-wait,Fail
kms_color@ctm-0-25,Fail
kms_color@ctm-0-50,Fail
kms_color@ctm-0-75,Fail
kms_color@ctm-blue-to-red,Fail
kms_color@ctm-green-to-red,Fail
+kms_color@ctm-max,Fail
kms_color@ctm-negative,Fail
kms_color@ctm-red-to-blue,Fail
kms_color@ctm-signed,Fail
+kms_content_protection@atomic,Crash
+kms_content_protection@atomic-dpms,Crash
+kms_content_protection@content-type-change,Crash
+kms_content_protection@lic-type-0,Crash
+kms_content_protection@lic-type-1,Crash
+kms_content_protection@srm,Crash
+kms_content_protection@type1,Crash
+kms_content_protection@uevent,Crash
+kms_cursor_crc@cursor-alpha-opaque,Fail
+kms_cursor_crc@cursor-alpha-transparent,Fail
+kms_cursor_crc@cursor-dpms,Fail
+kms_cursor_crc@cursor-offscreen-128x128,Fail
+kms_cursor_crc@cursor-offscreen-128x42,Fail
+kms_cursor_crc@cursor-offscreen-256x256,Fail
+kms_cursor_crc@cursor-offscreen-256x85,Fail
+kms_cursor_crc@cursor-offscreen-32x10,Fail
+kms_cursor_crc@cursor-offscreen-32x32,Fail
+kms_cursor_crc@cursor-offscreen-512x170,Fail
+kms_cursor_crc@cursor-offscreen-512x512,Fail
+kms_cursor_crc@cursor-offscreen-64x21,Fail
+kms_cursor_crc@cursor-offscreen-64x64,Fail
+kms_cursor_crc@cursor-onscreen-128x128,Fail
+kms_cursor_crc@cursor-onscreen-128x42,Fail
+kms_cursor_crc@cursor-onscreen-256x256,Fail
+kms_cursor_crc@cursor-onscreen-256x85,Fail
+kms_cursor_crc@cursor-onscreen-32x10,Fail
+kms_cursor_crc@cursor-onscreen-32x32,Fail
+kms_cursor_crc@cursor-onscreen-512x170,Fail
+kms_cursor_crc@cursor-onscreen-512x512,Fail
+kms_cursor_crc@cursor-onscreen-64x21,Fail
+kms_cursor_crc@cursor-onscreen-64x64,Fail
+kms_cursor_crc@cursor-random-128x128,Fail
+kms_cursor_crc@cursor-random-128x42,Fail
+kms_cursor_crc@cursor-random-256x256,Fail
+kms_cursor_crc@cursor-random-256x85,Fail
+kms_cursor_crc@cursor-random-32x10,Fail
+kms_cursor_crc@cursor-random-32x32,Fail
+kms_cursor_crc@cursor-random-512x170,Fail
+kms_cursor_crc@cursor-random-512x512,Fail
+kms_cursor_crc@cursor-random-64x21,Fail
+kms_cursor_crc@cursor-random-64x64,Fail
+kms_cursor_crc@cursor-rapid-movement-128x128,Fail
+kms_cursor_crc@cursor-rapid-movement-128x42,Fail
+kms_cursor_crc@cursor-rapid-movement-256x256,Fail
+kms_cursor_crc@cursor-rapid-movement-256x85,Fail
+kms_cursor_crc@cursor-rapid-movement-32x10,Fail
+kms_cursor_crc@cursor-rapid-movement-32x32,Fail
+kms_cursor_crc@cursor-rapid-movement-512x170,Fail
+kms_cursor_crc@cursor-rapid-movement-512x512,Fail
+kms_cursor_crc@cursor-rapid-movement-64x21,Fail
+kms_cursor_crc@cursor-rapid-movement-64x64,Fail
+kms_cursor_crc@cursor-size-change,Fail
+kms_cursor_crc@cursor-sliding-128x128,Fail
+kms_cursor_crc@cursor-sliding-128x42,Fail
+kms_cursor_crc@cursor-sliding-256x256,Fail
+kms_cursor_crc@cursor-sliding-256x85,Fail
+kms_cursor_crc@cursor-sliding-32x10,Fail
+kms_cursor_crc@cursor-sliding-32x32,Fail
+kms_cursor_crc@cursor-sliding-512x170,Fail
+kms_cursor_crc@cursor-sliding-512x512,Fail
+kms_cursor_crc@cursor-sliding-64x21,Fail
+kms_cursor_crc@cursor-sliding-64x64,Fail
+kms_cursor_edge_walk@128x128-left-edge,Fail
+kms_cursor_edge_walk@128x128-right-edge,Fail
+kms_cursor_edge_walk@128x128-top-bottom,Fail
+kms_cursor_edge_walk@128x128-top-edge,Fail
+kms_cursor_edge_walk@256x256-left-edge,Fail
+kms_cursor_edge_walk@256x256-right-edge,Fail
+kms_cursor_edge_walk@256x256-top-bottom,Fail
+kms_cursor_edge_walk@256x256-top-edge,Fail
+kms_cursor_edge_walk@64x64-left-edge,Fail
+kms_cursor_edge_walk@64x64-right-edge,Fail
+kms_cursor_edge_walk@64x64-top-bottom,Fail
+kms_cursor_edge_walk@64x64-top-edge,Fail
+kms_cursor_legacy@2x-cursor-vs-flip-atomic,Fail
+kms_cursor_legacy@2x-cursor-vs-flip-legacy,Fail
+kms_cursor_legacy@2x-flip-vs-cursor-atomic,Fail
+kms_cursor_legacy@2x-flip-vs-cursor-legacy,Fail
+kms_cursor_legacy@2x-long-cursor-vs-flip-atomic,Fail
+kms_cursor_legacy@2x-long-cursor-vs-flip-legacy,Fail
+kms_cursor_legacy@2x-long-flip-vs-cursor-atomic,Fail
+kms_cursor_legacy@2x-long-flip-vs-cursor-legacy,Fail
kms_cursor_legacy@cursor-vs-flip-toggle,Fail
kms_cursor_legacy@cursor-vs-flip-varying-size,Fail
+kms_display_modes@extended-mode-basic,Fail
+kms_flip@2x-flip-vs-modeset-vs-hang,Fail
+kms_flip@2x-flip-vs-panning-vs-hang,Fail
+kms_flip@absolute-wf_vblank,Fail
+kms_flip@absolute-wf_vblank-interruptible,Fail
+kms_flip@basic-flip-vs-wf_vblank,Fail
+kms_flip@basic-plain-flip,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-off-confusion,Fail
+kms_flip@dpms-off-confusion-interruptible,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,Fail
+kms_flip@flip-vs-panning-interruptible,Fail
kms_flip@flip-vs-panning-vs-hang,Fail
+kms_flip@flip-vs-rmfb,Fail
+kms_flip@flip-vs-rmfb-interruptible,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-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_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_multipipe_modeset@basic-max-pipe-crc-check,Fail
kms_pipe_crc_basic@compare-crc-sanitycheck-nv12,Fail
+kms_pipe_crc_basic@compare-crc-sanitycheck-xr24,Fail
+kms_pipe_crc_basic@disable-crc-after-crtc,Fail
+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@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@plane-position-hole-dpms,Fail
kms_plane_alpha_blend@alpha-7efc,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_alpha_blend@constant-alpha-mid,Fail
+kms_plane_alpha_blend@constant-alpha-min,Fail
kms_plane_alpha_blend@coverage-7efc,Fail
kms_plane_alpha_blend@coverage-vs-premult-vs-constant,Fail
+kms_plane_cursor@primary,Fail
+kms_plane_lowres@tiling-none,Fail
+kms_plane_multiple@tiling-none,Fail
kms_rmfb@close-fd,Fail
-kms_universal_plane@universal-plane-sanity,Fail
+kms_rotation_crc@cursor-rotation-180,Fail
+kms_rotation_crc@primary-rotation-180,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_vblank@accuracy-idle,Fail
+kms_vblank@crtc-id,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-idle,Fail
+kms_vblank@ts-continuation-modeset,Fail
+kms_vblank@ts-continuation-modeset-rpm,Fail
+kms_vblank@wait-busy,Fail
+kms_vblank@wait-forked,Fail
+kms_vblank@wait-forked-busy,Fail
+kms_vblank@wait-idle,Fail
+tools_test@tools_test,Fail
diff --git a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-flakes.txt b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-flakes.txt
new file mode 100644
index 000000000000..6dec63d48cfb
--- /dev/null
+++ b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-flakes.txt
@@ -0,0 +1,8 @@
+# Board Name: sc7180-trogdor-kingoftown
+# Bug Report: https://lore.kernel.org/linux-arm-msm/661483c8-ad82-400d-bcd8-e94986d20d7d@collabora.com/T/#u
+# IGT Version: 1.28-g0df7b9b97
+# Linux Version: 6.9.0-rc7
+# Failure Rate: 50
+msm_mapping@shadow
+msm_shrink@copy-gpu-oom-32
+msm_shrink@copy-gpu-oom-8
diff --git a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-skips.txt b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-skips.txt
index 327039f70252..68c96005ba54 100644
--- a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-skips.txt
+++ b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-skips.txt
@@ -1,2 +1,21 @@
# Suspend to RAM seems to be broken on this machine
.*suspend.*
+
+# Skip driver specific tests
+^amdgpu.*
+nouveau_.*
+panfrost_.*
+^v3d.*
+^vc4.*
+^vmwgfx*
+
+# Skip intel specific tests
+gem_.*
+i915_.*
+
+# Currently fails and causes coverage loss for other tests
+# since core_getversion also fails.
+core_hotunplug.*
+
+# Timeout occurs
+kms_flip@2x-wf_vblank-ts-check
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 f0576aa629e8..eb7a3886d397 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,18 +1,191 @@
+device_reset@cold-reset-bound,Fail
+device_reset@reset-bound,Fail
+device_reset@unbind-cold-reset-rebind,Fail
+device_reset@unbind-reset-rebind,Fail
+dumb_buffer@invalid-bpp,Fail
+kms_atomic_transition@plane-primary-toggle-with-vblank-wait,Fail
kms_color@ctm-0-25,Fail
kms_color@ctm-0-50,Fail
kms_color@ctm-0-75,Fail
kms_color@ctm-blue-to-red,Fail
kms_color@ctm-green-to-red,Fail
+kms_color@ctm-max,Fail
kms_color@ctm-negative,Fail
kms_color@ctm-red-to-blue,Fail
kms_color@ctm-signed,Fail
+kms_content_protection@atomic,Crash
+kms_content_protection@atomic-dpms,Crash
+kms_content_protection@content-type-change,Crash
+kms_content_protection@lic-type-0,Crash
+kms_content_protection@lic-type-1,Crash
+kms_content_protection@srm,Crash
+kms_content_protection@type1,Crash
+kms_content_protection@uevent,Crash
+kms_cursor_crc@cursor-alpha-opaque,Fail
+kms_cursor_crc@cursor-alpha-transparent,Fail
+kms_cursor_crc@cursor-dpms,Fail
+kms_cursor_crc@cursor-offscreen-128x128,Fail
+kms_cursor_crc@cursor-offscreen-128x42,Fail
+kms_cursor_crc@cursor-offscreen-256x256,Fail
+kms_cursor_crc@cursor-offscreen-256x85,Fail
+kms_cursor_crc@cursor-offscreen-32x10,Fail
+kms_cursor_crc@cursor-offscreen-32x32,Fail
+kms_cursor_crc@cursor-offscreen-512x170,Fail
+kms_cursor_crc@cursor-offscreen-512x512,Fail
+kms_cursor_crc@cursor-offscreen-64x21,Fail
+kms_cursor_crc@cursor-offscreen-64x64,Fail
+kms_cursor_crc@cursor-onscreen-128x128,Fail
+kms_cursor_crc@cursor-onscreen-128x42,Fail
+kms_cursor_crc@cursor-onscreen-256x256,Fail
+kms_cursor_crc@cursor-onscreen-256x85,Fail
+kms_cursor_crc@cursor-onscreen-32x10,Fail
+kms_cursor_crc@cursor-onscreen-32x32,Fail
+kms_cursor_crc@cursor-onscreen-512x170,Fail
+kms_cursor_crc@cursor-onscreen-512x512,Fail
+kms_cursor_crc@cursor-onscreen-64x21,Fail
+kms_cursor_crc@cursor-onscreen-64x64,Fail
+kms_cursor_crc@cursor-random-128x128,Fail
+kms_cursor_crc@cursor-random-128x42,Fail
+kms_cursor_crc@cursor-random-256x256,Fail
+kms_cursor_crc@cursor-random-256x85,Fail
+kms_cursor_crc@cursor-random-32x10,Fail
+kms_cursor_crc@cursor-random-32x32,Fail
+kms_cursor_crc@cursor-random-512x170,Fail
+kms_cursor_crc@cursor-random-512x512,Fail
+kms_cursor_crc@cursor-random-64x21,Fail
+kms_cursor_crc@cursor-random-64x64,Fail
+kms_cursor_crc@cursor-rapid-movement-128x128,Fail
+kms_cursor_crc@cursor-rapid-movement-128x42,Fail
+kms_cursor_crc@cursor-rapid-movement-256x256,Fail
+kms_cursor_crc@cursor-rapid-movement-256x85,Fail
+kms_cursor_crc@cursor-rapid-movement-32x10,Fail
+kms_cursor_crc@cursor-rapid-movement-32x32,Fail
+kms_cursor_crc@cursor-rapid-movement-512x170,Fail
+kms_cursor_crc@cursor-rapid-movement-512x512,Fail
+kms_cursor_crc@cursor-rapid-movement-64x21,Fail
+kms_cursor_crc@cursor-rapid-movement-64x64,Fail
+kms_cursor_crc@cursor-size-change,Fail
+kms_cursor_crc@cursor-sliding-128x128,Fail
+kms_cursor_crc@cursor-sliding-128x42,Fail
+kms_cursor_crc@cursor-sliding-256x256,Fail
+kms_cursor_crc@cursor-sliding-256x85,Fail
+kms_cursor_crc@cursor-sliding-32x10,Fail
+kms_cursor_crc@cursor-sliding-32x32,Fail
+kms_cursor_crc@cursor-sliding-512x170,Fail
+kms_cursor_crc@cursor-sliding-512x512,Fail
+kms_cursor_crc@cursor-sliding-64x21,Fail
+kms_cursor_crc@cursor-sliding-64x64,Fail
+kms_cursor_edge_walk@128x128-left-edge,Fail
+kms_cursor_edge_walk@128x128-right-edge,Fail
+kms_cursor_edge_walk@128x128-top-bottom,Fail
+kms_cursor_edge_walk@128x128-top-edge,Fail
+kms_cursor_edge_walk@256x256-left-edge,Fail
+kms_cursor_edge_walk@256x256-right-edge,Fail
+kms_cursor_edge_walk@256x256-top-bottom,Fail
+kms_cursor_edge_walk@256x256-top-edge,Fail
+kms_cursor_edge_walk@64x64-left-edge,Fail
+kms_cursor_edge_walk@64x64-right-edge,Fail
+kms_cursor_edge_walk@64x64-top-bottom,Fail
+kms_cursor_edge_walk@64x64-top-edge,Fail
+kms_cursor_legacy@2x-cursor-vs-flip-atomic,Fail
+kms_cursor_legacy@2x-cursor-vs-flip-legacy,Fail
+kms_cursor_legacy@2x-flip-vs-cursor-atomic,Fail
+kms_cursor_legacy@2x-flip-vs-cursor-legacy,Fail
+kms_cursor_legacy@2x-long-cursor-vs-flip-atomic,Fail
+kms_cursor_legacy@2x-long-cursor-vs-flip-legacy,Fail
+kms_cursor_legacy@2x-long-flip-vs-cursor-atomic,Fail
+kms_cursor_legacy@2x-long-flip-vs-cursor-legacy,Fail
kms_cursor_legacy@cursor-vs-flip-toggle,Fail
kms_cursor_legacy@cursor-vs-flip-varying-size,Fail
+kms_display_modes@extended-mode-basic,Fail
+kms_flip@2x-flip-vs-modeset-vs-hang,Fail
+kms_flip@2x-flip-vs-panning-vs-hang,Fail
+kms_flip@absolute-wf_vblank,Fail
+kms_flip@absolute-wf_vblank-interruptible,Fail
+kms_flip@basic-flip-vs-wf_vblank,Fail
+kms_flip@basic-plain-flip,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-off-confusion,Fail
+kms_flip@dpms-off-confusion-interruptible,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,Fail
+kms_flip@flip-vs-panning-interruptible,Fail
kms_flip@flip-vs-panning-vs-hang,Fail
+kms_flip@flip-vs-rmfb,Fail
+kms_flip@flip-vs-rmfb-interruptible,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-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_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_multipipe_modeset@basic-max-pipe-crc-check,Fail
kms_pipe_crc_basic@compare-crc-sanitycheck-nv12,Fail
+kms_pipe_crc_basic@compare-crc-sanitycheck-xr24,Fail
+kms_pipe_crc_basic@disable-crc-after-crtc,Fail
+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@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@plane-position-hole-dpms,Fail
kms_plane_alpha_blend@alpha-7efc,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_alpha_blend@constant-alpha-mid,Fail
+kms_plane_alpha_blend@constant-alpha-min,Fail
kms_plane_alpha_blend@coverage-7efc,Fail
kms_plane_alpha_blend@coverage-vs-premult-vs-constant,Fail
+kms_plane_cursor@primary,Fail
+kms_plane_lowres@tiling-none,Fail
+kms_plane_multiple@tiling-none,Fail
kms_rmfb@close-fd,Fail
-kms_universal_plane@universal-plane-sanity,Fail
+kms_rotation_crc@cursor-rotation-180,Fail
+kms_rotation_crc@primary-rotation-180,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_vblank@accuracy-idle,Fail
+kms_vblank@crtc-id,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-idle,Fail
+kms_vblank@ts-continuation-modeset,Fail
+kms_vblank@ts-continuation-modeset-rpm,Fail
+kms_vblank@wait-busy,Fail
+kms_vblank@wait-forked,Fail
+kms_vblank@wait-forked-busy,Fail
+kms_vblank@wait-idle,Fail
+tools_test@tools_test,Fail
diff --git a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-flakes.txt b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-flakes.txt
new file mode 100644
index 000000000000..dcb24b835dc3
--- /dev/null
+++ b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-flakes.txt
@@ -0,0 +1,6 @@
+# Board Name: sc7180-trogdor-lazor-limozeen-nots-r5
+# Bug Report: https://lore.kernel.org/linux-arm-msm/661483c8-ad82-400d-bcd8-e94986d20d7d@collabora.com/T/#u
+# IGT Version: 1.28-g0df7b9b97
+# Linux Version: 6.9.0-rc7
+# Failure Rate: 50
+msm_mapping@shadow
diff --git a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-skips.txt b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-skips.txt
index 327039f70252..1168c53acd2d 100644
--- a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-skips.txt
+++ b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-skips.txt
@@ -1,2 +1,18 @@
# Suspend to RAM seems to be broken on this machine
.*suspend.*
+
+# Skip driver specific tests
+^amdgpu.*
+nouveau_.*
+panfrost_.*
+^v3d.*
+^vc4.*
+^vmwgfx*
+
+# Skip intel specific tests
+gem_.*
+i915_.*
+
+# Currently fails and causes coverage loss for other tests
+# since core_getversion also fails.
+core_hotunplug.*
diff --git a/drivers/gpu/drm/ci/xfails/msm-sdm845-fails.txt b/drivers/gpu/drm/ci/xfails/msm-sdm845-fails.txt
index e9043a00383e..8f010c8a9c4f 100644
--- a/drivers/gpu/drm/ci/xfails/msm-sdm845-fails.txt
+++ b/drivers/gpu/drm/ci/xfails/msm-sdm845-fails.txt
@@ -1,3 +1,8 @@
+device_reset@cold-reset-bound,Fail
+device_reset@reset-bound,Fail
+device_reset@unbind-cold-reset-rebind,Fail
+device_reset@unbind-reset-rebind,Fail
+dumb_buffer@invalid-bpp,Fail
kms_color@ctm-0-25,Fail
kms_color@ctm-0-50,Fail
kms_color@ctm-0-75,Fail
@@ -6,17 +11,6 @@ kms_color@ctm-green-to-red,Fail
kms_color@ctm-negative,Fail
kms_color@ctm-red-to-blue,Fail
kms_color@ctm-signed,Fail
-kms_color@pipe-A-ctm-0-25,Fail
-kms_color@pipe-A-ctm-0-5,Fail
-kms_color@pipe-A-ctm-0-75,Fail
-kms_color@pipe-A-ctm-blue-to-red,Fail
-kms_color@pipe-A-ctm-green-to-red,Fail
-kms_color@pipe-A-ctm-max,Fail
-kms_color@pipe-A-ctm-negative,Fail
-kms_color@pipe-A-ctm-red-to-blue,Fail
-kms_color@pipe-A-legacy-gamma,Fail
-kms_cursor_legacy@basic-flip-after-cursor-atomic,Fail
-kms_cursor_legacy@basic-flip-after-cursor-varying-size,Fail
kms_cursor_legacy@basic-flip-before-cursor-atomic,Fail
kms_cursor_legacy@basic-flip-before-cursor-legacy,Fail
kms_cursor_legacy@cursor-vs-flip-atomic,Fail
@@ -31,30 +25,12 @@ kms_cursor_legacy@flip-vs-cursor-crc-legacy,Fail
kms_cursor_legacy@flip-vs-cursor-legacy,Fail
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_alpha_blend@alpha-7efc,Fail
kms_plane_alpha_blend@coverage-7efc,Fail
kms_plane_alpha_blend@coverage-vs-premult-vs-constant,Fail
-kms_plane_alpha_blend@pipe-A-alpha-7efc,Fail
-kms_plane_alpha_blend@pipe-A-coverage-7efc,Fail
-kms_plane_alpha_blend@pipe-A-coverage-vs-premult-vs-constant,Fail
kms_plane_cursor@overlay,Fail
-kms_plane_cursor@pipe-A-overlay-size-128,Fail
-kms_plane_cursor@pipe-A-overlay-size-256,Fail
-kms_plane_cursor@pipe-A-overlay-size-64,Fail
-kms_plane_cursor@pipe-A-viewport-size-128,Fail
-kms_plane_cursor@pipe-A-viewport-size-256,Fail
-kms_plane_cursor@pipe-A-viewport-size-64,Fail
kms_plane_cursor@viewport,Fail
-kms_plane_scaling@downscale-with-pixel-format-factor-0-25,Timeout
-kms_plane_scaling@downscale-with-pixel-format-factor-0-5,Timeout
-kms_plane_scaling@downscale-with-pixel-format-factor-0-75,Timeout
-kms_plane_scaling@plane-downscale-with-pixel-format-factor-0-25,Timeout
-kms_plane_scaling@plane-downscale-with-pixel-format-factor-0-5,Timeout
-kms_plane_scaling@plane-downscale-with-pixel-format-factor-0-75,Timeout
-kms_plane_scaling@plane-scaler-with-clipping-clamping-pixel-formats,Timeout
-kms_plane_scaling@plane-scaler-with-pixel-format-unity-scaling,Timeout
-kms_plane_scaling@planes-downscale-factor-0-25,Fail
-kms_plane_scaling@scaler-with-clipping-clamping,Timeout
-kms_plane_scaling@scaler-with-pixel-format-unity-scaling,Timeout
kms_rmfb@close-fd,Fail
+tools_test@tools_test,Fail
diff --git a/drivers/gpu/drm/ci/xfails/msm-sdm845-flakes.txt b/drivers/gpu/drm/ci/xfails/msm-sdm845-flakes.txt
index 8a492f01eaa4..2c5f62b07632 100644
--- a/drivers/gpu/drm/ci/xfails/msm-sdm845-flakes.txt
+++ b/drivers/gpu/drm/ci/xfails/msm-sdm845-flakes.txt
@@ -1,22 +1,19 @@
-# Board Name: msm:sdm845
-# Bug Report: https://lore.kernel.org/dri-devel/46287831-edfa-78e8-6055-d7a08831c445@collabora.com/T/#u
+# Board Name: sdm845-cheza-r3
+# Bug Report: https://lore.kernel.org/linux-arm-msm/661483c8-ad82-400d-bcd8-e94986d20d7d@collabora.com/T/#u
+# IGT Version: 1.28-g0df7b9b97
+# Linux Version: 6.9.0-rc7
# Failure Rate: 50
-# IGT Version: 1.28-gd2af13d9f
-# Linux Version: 6.7.0-rc3
-
-# Reported by deqp-runner
+kms_cursor_legacy@basic-flip-after-cursor-atomic
kms_cursor_legacy@basic-flip-after-cursor-legacy
-kms_cursor_legacy@flip-vs-cursor-toggle
+kms_cursor_legacy@basic-flip-after-cursor-varying-size
+kms_cursor_legacy@basic-flip-before-cursor-varying-size
+kms_cursor_legacy@flip-vs-cursor-atomic-transitions
+kms_cursor_legacy@flip-vs-cursor-atomic-transitions-varying-size
kms_cursor_legacy@flip-vs-cursor-varying-size
+kms_cursor_legacy@short-flip-after-cursor-atomic-transitions
+kms_cursor_legacy@short-flip-after-cursor-atomic-transitions-varying-size
kms_cursor_legacy@short-flip-after-cursor-toggle
kms_cursor_legacy@short-flip-before-cursor-atomic-transitions
kms_cursor_legacy@short-flip-before-cursor-atomic-transitions-varying-size
msm_shrink@copy-gpu-32
msm_shrink@copy-gpu-oom-32
-
-# The below test shows inconsistency across multiple runs, giving
-# results of Pass and Fail alternately.
-kms_cursor_legacy@basic-flip-before-cursor-varying-size
-kms_cursor_legacy@flip-vs-cursor-atomic-transitions
-kms_cursor_legacy@short-flip-after-cursor-atomic-transitions
-kms_cursor_legacy@short-flip-after-cursor-atomic-transitions-varying-size
diff --git a/drivers/gpu/drm/ci/xfails/msm-sdm845-skips.txt b/drivers/gpu/drm/ci/xfails/msm-sdm845-skips.txt
index 618e3a3a7277..5185212c8fb2 100644
--- a/drivers/gpu/drm/ci/xfails/msm-sdm845-skips.txt
+++ b/drivers/gpu/drm/ci/xfails/msm-sdm845-skips.txt
@@ -5,3 +5,22 @@ kms_bw.*
# https://gitlab.freedesktop.org/gfx-ci/linux/-/commit/4b49f902ec6f2bb382cbbf489870573f4b43371e
# https://gitlab.freedesktop.org/gfx-ci/linux/-/commit/38cdf4c5559771e2474ae0fecef8469f65147bc1
msm_mapping@*
+
+# Skip driver specific tests
+^amdgpu.*
+nouveau_.*
+panfrost_.*
+^v3d.*
+^vc4.*
+^vmwgfx*
+
+# Skip intel specific tests
+gem_.*
+i915_.*
+
+# Currently fails and causes coverage loss for other tests
+# since core_getversion also fails.
+core_hotunplug.*
+
+# Whole machine hangs
+kms_cursor_crc.*
diff --git a/drivers/gpu/drm/ci/xfails/rockchip-rk3288-fails.txt b/drivers/gpu/drm/ci/xfails/rockchip-rk3288-fails.txt
index 90c63f519e9e..f9b99bf27105 100644
--- a/drivers/gpu/drm/ci/xfails/rockchip-rk3288-fails.txt
+++ b/drivers/gpu/drm/ci/xfails/rockchip-rk3288-fails.txt
@@ -1,54 +1,8 @@
-kms_3d,Crash
-kms_bw@linear-tiling-2-displays-1920x1080p,Fail
-kms_bw@linear-tiling-2-displays-2560x1440p,Fail
-kms_bw@linear-tiling-2-displays-3840x2160p,Fail
-kms_bw@linear-tiling-3-displays-1920x1080p,Fail
-kms_bw@linear-tiling-3-displays-2560x1440p,Fail
-kms_bw@linear-tiling-3-displays-3840x2160p,Fail
-kms_flip@flip-vs-modeset-vs-hang,Crash
-kms_flip@flip-vs-panning-vs-hang,Crash
-kms_force_connector_basic@force-load-detect,Fail
-kms_invalid_mode@int-max-clock,Crash
-kms_pipe_crc_basic@compare-crc-sanitycheck-nv12,Crash
-kms_pipe_crc_basic@nonblocking-crc-frame-sequence,Crash
-kms_pipe_crc_basic@read-crc-frame-sequence,Crash
-kms_plane@pixel-format,Crash
-kms_plane@pixel-format-source-clamping,Crash
-kms_plane@plane-position-hole,Crash
-kms_plane@plane-position-hole-dpms,Crash
-kms_plane_cursor@overlay,Crash
-kms_plane_cursor@pipe-A-overlay-size-128,Fail
-kms_plane_cursor@pipe-A-overlay-size-256,Fail
-kms_plane_cursor@pipe-A-overlay-size-64,Fail
-kms_plane_cursor@pipe-A-primary-size-128,Fail
-kms_plane_cursor@pipe-A-primary-size-256,Fail
-kms_plane_cursor@pipe-A-primary-size-64,Fail
-kms_plane_cursor@pipe-A-viewport-size-128,Fail
-kms_plane_cursor@pipe-A-viewport-size-256,Fail
-kms_plane_cursor@pipe-A-viewport-size-64,Fail
-kms_plane_cursor@pipe-B-overlay-size-128,Fail
-kms_plane_cursor@pipe-B-overlay-size-256,Fail
-kms_plane_cursor@pipe-B-overlay-size-64,Fail
-kms_plane_cursor@pipe-B-primary-size-128,Fail
-kms_plane_cursor@pipe-B-primary-size-256,Fail
-kms_plane_cursor@pipe-B-primary-size-64,Fail
-kms_plane_cursor@pipe-B-viewport-size-128,Fail
-kms_plane_cursor@pipe-B-viewport-size-256,Fail
-kms_plane_cursor@pipe-B-viewport-size-64,Fail
-kms_plane_cursor@primary,Crash
-kms_plane_cursor@viewport,Crash
-kms_plane_lowres@tiling-none,Fail
-kms_plane_scaling@downscale-with-modifier-factor-0-25,Fail
-kms_plane_scaling@downscale-with-rotation-factor-0-25,Fail
-kms_plane_scaling@upscale-with-modifier-20x20,Fail
-kms_plane_scaling@upscale-with-modifier-factor-0-25,Fail
-kms_plane_scaling@upscale-with-pixel-format-20x20,Fail
-kms_plane_scaling@upscale-with-pixel-format-factor-0-25,Fail
-kms_plane_scaling@upscale-with-rotation-20x20,Fail
-kms_prime@basic-crc,Fail
-kms_properties@connector-properties-atomic,Crash
-kms_properties@connector-properties-legacy,Crash
-kms_properties@get_properties-sanity-atomic,Crash
-kms_properties@get_properties-sanity-non-atomic,Crash
-kms_rmfb@close-fd,Crash
-kms_setmode@invalid-clone-single-crtc,Crash
+dumb_buffer@create-clear,Crash
+dumb_buffer@create-valid-dumb,Crash
+dumb_buffer@invalid-bpp,Crash
+dumb_buffer@map-invalid-size,Crash
+dumb_buffer@map-uaf,Crash
+dumb_buffer@map-valid,Crash
+panfrost_prime@gem-prime-import,Crash
+tools_test@tools_test,Crash
diff --git a/drivers/gpu/drm/ci/xfails/rockchip-rk3288-skips.txt b/drivers/gpu/drm/ci/xfails/rockchip-rk3288-skips.txt
index f20c3574b75a..6d3757dca83b 100644
--- a/drivers/gpu/drm/ci/xfails/rockchip-rk3288-skips.txt
+++ b/drivers/gpu/drm/ci/xfails/rockchip-rk3288-skips.txt
@@ -49,4 +49,23 @@ kms_plane_lowres@pipe-F-tiling-y
kms_cursor_crc.*
# Machine is hanging in this test, so skip it
-kms_pipe_crc_basic@disable-crc-after-crtc \ No newline at end of file
+kms_pipe_crc_basic@disable-crc-after-crtc
+
+# Skip driver specific tests
+^amdgpu.*
+msm_.*
+nouveau_.*
+^v3d.*
+^vc4.*
+^vmwgfx*
+
+# Skip intel specific tests
+gem_.*
+i915_.*
+
+# Panfrost is not a KMS driver, so skip the KMS tests
+kms_.*
+
+# Currently fails and causes coverage loss for other tests
+# since core_getversion also fails.
+core_hotunplug.*
diff --git a/drivers/gpu/drm/ci/xfails/rockchip-rk3399-fails.txt b/drivers/gpu/drm/ci/xfails/rockchip-rk3399-fails.txt
index d516d9c1d546..9ef460646d76 100644
--- a/drivers/gpu/drm/ci/xfails/rockchip-rk3399-fails.txt
+++ b/drivers/gpu/drm/ci/xfails/rockchip-rk3399-fails.txt
@@ -1,75 +1,8 @@
-kms_color@gamma,Fail
-kms_color@legacy-gamma,Fail
-kms_color@pipe-A-legacy-gamma,Fail
-kms_color@pipe-B-legacy-gamma,Fail
-kms_cursor_crc@cursor-alpha-opaque,Fail
-kms_cursor_crc@cursor-alpha-transparent,Fail
-kms_cursor_crc@cursor-dpms,Fail
-kms_cursor_crc@cursor-offscreen-32x10,Fail
-kms_cursor_crc@cursor-offscreen-32x32,Fail
-kms_cursor_crc@cursor-offscreen-64x64,Fail
-kms_cursor_crc@cursor-onscreen-32x10,Fail
-kms_cursor_crc@cursor-onscreen-32x32,Fail
-kms_cursor_crc@cursor-onscreen-64x21,Fail
-kms_cursor_crc@cursor-onscreen-64x64,Fail
-kms_cursor_crc@cursor-random-32x10,Fail
-kms_cursor_crc@cursor-random-32x32,Fail
-kms_cursor_crc@cursor-random-64x21,Fail
-kms_cursor_crc@cursor-random-64x64,Fail
-kms_cursor_crc@cursor-rapid-movement-32x32,Fail
-kms_cursor_crc@cursor-rapid-movement-64x21,Fail
-kms_cursor_crc@cursor-rapid-movement-64x64,Fail
-kms_cursor_crc@cursor-size-change,Fail
-kms_cursor_crc@cursor-sliding-32x10,Fail
-kms_cursor_crc@cursor-sliding-32x32,Fail
-kms_cursor_crc@cursor-sliding-64x21,Fail
-kms_cursor_crc@cursor-sliding-64x64,Fail
-kms_flip@basic-flip-vs-wf_vblank,Fail
-kms_flip@blocking-wf_vblank,Fail
-kms_flip@dpms-vs-vblank-race,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-modeset-vs-hang,Fail
-kms_flip@flip-vs-panning,Fail
-kms_flip@flip-vs-panning-interruptible,Fail
-kms_flip@flip-vs-panning-vs-hang,Fail
-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,Fail
-kms_flip@wf_vblank-ts-check-interruptible,Fail
-kms_invalid_mode@int-max-clock,Fail
-kms_pipe_crc_basic@compare-crc-sanitycheck-nv12,Fail
-kms_pipe_crc_basic@compare-crc-sanitycheck-xr24,Fail
-kms_pipe_crc_basic@disable-crc-after-crtc,Fail
-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@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@plane-position-hole-dpms,Fail
-kms_plane_cursor@overlay,Fail
-kms_plane_cursor@pipe-B-overlay-size-128,Fail
-kms_plane_cursor@pipe-B-overlay-size-256,Fail
-kms_plane_cursor@pipe-B-overlay-size-64,Fail
-kms_plane_cursor@pipe-B-primary-size-128,Fail
-kms_plane_cursor@pipe-B-primary-size-256,Fail
-kms_plane_cursor@pipe-B-primary-size-64,Fail
-kms_plane_cursor@pipe-B-viewport-size-128,Fail
-kms_plane_cursor@pipe-B-viewport-size-256,Fail
-kms_plane_cursor@pipe-B-viewport-size-64,Fail
-kms_plane_cursor@primary,Fail
-kms_plane_cursor@viewport,Fail
-kms_plane_multiple@atomic-pipe-B-tiling-none,Fail
-kms_plane_multiple@tiling-none,Fail
-kms_prime@basic-crc,Fail
-kms_rmfb@close-fd,Fail
-kms_universal_plane@universal-plane-pipe-B-functional,Fail
+dumb_buffer@create-clear,Fail
+dumb_buffer@create-valid-dumb,Fail
+dumb_buffer@invalid-bpp,Fail
+dumb_buffer@map-invalid-size,Fail
+dumb_buffer@map-uaf,Fail
+dumb_buffer@map-valid,Fail
+panfrost_prime@gem-prime-import,Fail
+tools_test@tools_test,Fail
diff --git a/drivers/gpu/drm/ci/xfails/rockchip-rk3399-flakes.txt b/drivers/gpu/drm/ci/xfails/rockchip-rk3399-flakes.txt
index c9fdc623ab91..742c27d9a598 100644
--- a/drivers/gpu/drm/ci/xfails/rockchip-rk3399-flakes.txt
+++ b/drivers/gpu/drm/ci/xfails/rockchip-rk3399-flakes.txt
@@ -1,7 +1,6 @@
-kms_bw@linear-tiling-2-displays-1920x1080p
-kms_cursor_crc@cursor-offscreen-64x21
-kms_flip@dpms-vs-vblank-race-interruptible
-kms_flip@flip-vs-wf_vblank-interruptible
-kms_plane_cursor@overlay
-kms_plane_cursor@primary
-kms_plane_cursor@viewport
+# Board Name: rk3399-gru-kevin
+# Bug Report: https://lore.kernel.org/dri-devel/5cc34a8b-c1fa-4744-9031-2d33ecf41011@collabora.com/T/#u
+# IGT Version: 1.28-g0df7b9b97
+# Linux Version: 6.9.0-rc7
+# Failure Rate: 50
+panfrost_submit@pan-unhandled-pagefault
diff --git a/drivers/gpu/drm/ci/xfails/rockchip-rk3399-skips.txt b/drivers/gpu/drm/ci/xfails/rockchip-rk3399-skips.txt
index 10c3d81a919a..5c52b25b4213 100644
--- a/drivers/gpu/drm/ci/xfails/rockchip-rk3399-skips.txt
+++ b/drivers/gpu/drm/ci/xfails/rockchip-rk3399-skips.txt
@@ -3,3 +3,22 @@
# Too unstable, machine ends up hanging after lots of Oopses
kms_cursor_legacy.*
+
+# Skip driver specific tests
+^amdgpu.*
+msm_.*
+nouveau_.*
+^v3d.*
+^vc4.*
+^vmwgfx*
+
+# Skip intel specific tests
+gem_.*
+i915_.*
+
+# Panfrost is not a KMS driver, so skip the KMS tests
+kms_.*
+
+# Currently fails and causes coverage loss for other tests
+# since core_getversion also fails.
+core_hotunplug.*
diff --git a/drivers/gpu/drm/ci/xfails/update-xfails.py b/drivers/gpu/drm/ci/xfails/update-xfails.py
index e9f0ec7fed8d..a446e98d72a1 100755
--- a/drivers/gpu/drm/ci/xfails/update-xfails.py
+++ b/drivers/gpu/drm/ci/xfails/update-xfails.py
@@ -93,10 +93,10 @@ def add_unit_test_or_update_result_to_fails_if_present(fails_txt, unit_test, fai
def split_unit_test_from_collate(xfails):
for job_name in xfails.keys():
for job_id in xfails[job_name].copy().keys():
- if "not found" in xfails[job_name][job_id]:
+ if "not found" in xfails[job_name][job_id].content_as_str:
del xfails[job_name][job_id]
continue
- xfails[job_name][job_id] = xfails[job_name][job_id].strip().split("\n")
+ xfails[job_name][job_id] = xfails[job_name][job_id].content_as_str.splitlines()
def get_xfails_from_pipeline_url(pipeline_url):
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 007f21e56d89..fdf09fe11566 100644
--- a/drivers/gpu/drm/ci/xfails/virtio_gpu-none-fails.txt
+++ b/drivers/gpu/drm/ci/xfails/virtio_gpu-none-fails.txt
@@ -1,33 +1,72 @@
-kms_addfb_basic@addfb25-bad-modifier,Fail
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@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
+kms_bw@linear-tiling-10-displays-3840x2160p,Fail
+kms_bw@linear-tiling-11-displays-1920x1080p,Fail
+kms_bw@linear-tiling-11-displays-2160x1440p,Fail
+kms_bw@linear-tiling-11-displays-2560x1440p,Fail
+kms_bw@linear-tiling-11-displays-3840x2160p,Fail
+kms_bw@linear-tiling-12-displays-1920x1080p,Fail
+kms_bw@linear-tiling-12-displays-2160x1440p,Fail
+kms_bw@linear-tiling-12-displays-2560x1440p,Fail
+kms_bw@linear-tiling-12-displays-3840x2160p,Fail
+kms_bw@linear-tiling-13-displays-1920x1080p,Fail
+kms_bw@linear-tiling-13-displays-2160x1440p,Fail
+kms_bw@linear-tiling-13-displays-2560x1440p,Fail
+kms_bw@linear-tiling-13-displays-3840x2160p,Fail
+kms_bw@linear-tiling-14-displays-1920x1080p,Fail
+kms_bw@linear-tiling-14-displays-2160x1440p,Fail
+kms_bw@linear-tiling-14-displays-2560x1440p,Fail
+kms_bw@linear-tiling-14-displays-3840x2160p,Fail
+kms_bw@linear-tiling-15-displays-1920x1080p,Fail
+kms_bw@linear-tiling-15-displays-2160x1440p,Fail
+kms_bw@linear-tiling-15-displays-2560x1440p,Fail
+kms_bw@linear-tiling-15-displays-3840x2160p,Fail
+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-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_bw@linear-tiling-3-displays-1920x1080p,Fail
+kms_bw@linear-tiling-3-displays-2160x1440p,Fail
kms_bw@linear-tiling-3-displays-2560x1440p,Fail
kms_bw@linear-tiling-3-displays-3840x2160p,Fail
kms_bw@linear-tiling-4-displays-1920x1080p,Fail
+kms_bw@linear-tiling-4-displays-2160x1440p,Fail
kms_bw@linear-tiling-4-displays-2560x1440p,Fail
kms_bw@linear-tiling-4-displays-3840x2160p,Fail
kms_bw@linear-tiling-5-displays-1920x1080p,Fail
+kms_bw@linear-tiling-5-displays-2160x1440p,Fail
kms_bw@linear-tiling-5-displays-2560x1440p,Fail
kms_bw@linear-tiling-5-displays-3840x2160p,Fail
kms_bw@linear-tiling-6-displays-1920x1080p,Fail
+kms_bw@linear-tiling-6-displays-2160x1440p,Fail
kms_bw@linear-tiling-6-displays-2560x1440p,Fail
kms_bw@linear-tiling-6-displays-3840x2160p,Fail
kms_bw@linear-tiling-7-displays-1920x1080p,Fail
+kms_bw@linear-tiling-7-displays-2160x1440p,Fail
kms_bw@linear-tiling-7-displays-2560x1440p,Fail
kms_bw@linear-tiling-7-displays-3840x2160p,Fail
kms_bw@linear-tiling-8-displays-1920x1080p,Fail
+kms_bw@linear-tiling-8-displays-2160x1440p,Fail
kms_bw@linear-tiling-8-displays-2560x1440p,Fail
kms_bw@linear-tiling-8-displays-3840x2160p,Fail
+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
@@ -54,31 +93,34 @@ 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_plane_scaling@downscale-with-modifier-factor-0-25,Fail
-kms_plane_scaling@downscale-with-rotation-factor-0-25,Fail
-kms_plane_scaling@planes-upscale-20x20,Fail
-kms_plane_scaling@planes-upscale-20x20-downscale-factor-0-25,Fail
-kms_plane_scaling@planes-upscale-20x20-downscale-factor-0-5,Fail
-kms_plane_scaling@planes-upscale-20x20-downscale-factor-0-75,Fail
-kms_plane_scaling@upscale-with-modifier-20x20,Fail
-kms_plane_scaling@upscale-with-modifier-factor-0-25,Fail
-kms_plane_scaling@upscale-with-pixel-format-20x20,Fail
-kms_plane_scaling@upscale-with-pixel-format-factor-0-25,Fail
-kms_plane_scaling@upscale-with-rotation-20x20,Fail
-kms_selftest@drm_format,Timeout
-kms_selftest@drm_format_helper,Timeout
+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@pipe-A-accuracy-idle,Fail
-kms_vblank@pipe-A-query-busy,Fail
-kms_vblank@pipe-A-query-forked,Fail
-kms_vblank@pipe-A-query-forked-busy,Fail
-kms_vblank@pipe-A-query-idle,Fail
-kms_vblank@pipe-A-ts-continuation-idle,Fail
-kms_vblank@pipe-A-ts-continuation-modeset,Fail
-kms_vblank@pipe-A-ts-continuation-suspend,Fail
-kms_vblank@pipe-A-wait-busy,Fail
-kms_vblank@pipe-A-wait-forked,Fail
-kms_vblank@pipe-A-wait-forked-busy,Fail
-kms_vblank@pipe-A-wait-idle,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
+tools_test@tools_test,Fail
diff --git a/drivers/gpu/drm/ci/xfails/virtio_gpu-none-skips.txt b/drivers/gpu/drm/ci/xfails/virtio_gpu-none-skips.txt
index 78be18174012..e0ca4fadb84f 100644
--- a/drivers/gpu/drm/ci/xfails/virtio_gpu-none-skips.txt
+++ b/drivers/gpu/drm/ci/xfails/virtio_gpu-none-skips.txt
@@ -3,4 +3,22 @@
kms_cursor_legacy.*
# Job just hangs without any output
-kms_flip@flip-vs-suspend.* \ No newline at end of file
+kms_flip@flip-vs-suspend.*
+
+# Skip driver specific tests
+^amdgpu.*
+msm_.*
+nouveau_.*
+panfrost_.*
+^v3d.*
+^vc4.*
+^vmwgfx*
+
+# Skip intel specific tests
+gem_.*
+i915_.*
+xe_.*
+
+# Currently fails and causes coverage loss for other tests
+# since core_getversion also fails.
+core_hotunplug.*
diff --git a/drivers/gpu/drm/ci/xfails/vkms-none-fails.txt b/drivers/gpu/drm/ci/xfails/vkms-none-fails.txt
new file mode 100644
index 000000000000..691c383b21a0
--- /dev/null
+++ b/drivers/gpu/drm/ci/xfails/vkms-none-fails.txt
@@ -0,0 +1,57 @@
+core_hotunplug@hotrebind,Fail
+core_hotunplug@hotrebind-lateclose,Fail
+core_hotunplug@hotreplug,Fail
+core_hotunplug@hotreplug-lateclose,Fail
+core_hotunplug@hotunbind-rebind,Fail
+core_hotunplug@hotunplug-rescan,Fail
+core_hotunplug@unbind-rebind,Fail
+core_hotunplug@unplug-rescan,Fail
+device_reset@cold-reset-bound,Fail
+device_reset@reset-bound,Fail
+device_reset@unbind-cold-reset-rebind,Fail
+device_reset@unbind-reset-rebind,Fail
+dumb_buffer@invalid-bpp,Fail
+kms_content_protection@atomic,Crash
+kms_content_protection@atomic-dpms,Crash
+kms_content_protection@content-type-change,Crash
+kms_content_protection@lic-type-0,Crash
+kms_content_protection@lic-type-1,Crash
+kms_content_protection@srm,Crash
+kms_content_protection@type1,Crash
+kms_content_protection@uevent,Crash
+kms_cursor_crc@cursor-rapid-movement-128x128,Fail
+kms_cursor_crc@cursor-rapid-movement-128x42,Fail
+kms_cursor_crc@cursor-rapid-movement-256x256,Fail
+kms_cursor_crc@cursor-rapid-movement-256x85,Fail
+kms_cursor_crc@cursor-rapid-movement-32x10,Fail
+kms_cursor_crc@cursor-rapid-movement-32x32,Fail
+kms_cursor_crc@cursor-rapid-movement-512x170,Fail
+kms_cursor_crc@cursor-rapid-movement-512x512,Fail
+kms_cursor_crc@cursor-rapid-movement-64x21,Fail
+kms_cursor_crc@cursor-rapid-movement-64x64,Fail
+kms_cursor_legacy@basic-flip-before-cursor-atomic,Fail
+kms_cursor_legacy@basic-flip-before-cursor-legacy,Fail
+kms_cursor_legacy@cursor-vs-flip-atomic,Fail
+kms_cursor_legacy@cursor-vs-flip-legacy,Fail
+kms_cursor_legacy@cursor-vs-flip-toggle,Fail
+kms_cursor_legacy@cursor-vs-flip-varying-size,Fail
+kms_cursor_legacy@flip-vs-cursor-atomic,Fail
+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_flip@flip-vs-modeset-vs-hang,Fail
+kms_flip@flip-vs-panning-vs-hang,Fail
+kms_flip@flip-vs-suspend,Timeout
+kms_flip@flip-vs-suspend-interruptible,Timeout
+kms_flip@plain-flip-fb-recreate,Fail
+kms_lease@lease-uevent,Fail
+kms_pipe_crc_basic@nonblocking-crc,Fail
+kms_pipe_crc_basic@nonblocking-crc-frame-sequence,Fail
+kms_writeback@writeback-check-output,Fail
+kms_writeback@writeback-check-output-XRGB2101010,Fail
+kms_writeback@writeback-fb-id,Fail
+kms_writeback@writeback-fb-id-XRGB2101010,Fail
+kms_writeback@writeback-invalid-parameters,Fail
+kms_writeback@writeback-pixel-formats,Fail
+perf@i915-ref-count,Fail
+tools_test@tools_test,Fail
diff --git a/drivers/gpu/drm/ci/xfails/vkms-none-flakes.txt b/drivers/gpu/drm/ci/xfails/vkms-none-flakes.txt
new file mode 100644
index 000000000000..eeaa1d5825af
--- /dev/null
+++ b/drivers/gpu/drm/ci/xfails/vkms-none-flakes.txt
@@ -0,0 +1,69 @@
+# Board Name: vkms
+# Bug Report: https://lore.kernel.org/dri-devel/61ed26af-062c-443c-9df2-d1ee319f3fb0@collabora.com/T/#u
+# Failure Rate: 50
+# IGT Version: 1.28-g0df7b9b97
+# Linux Version: 6.9.0-rc7
+kms_cursor_legacy@long-nonblocking-modeset-vs-cursor-atomic
+
+# Board Name: vkms
+# Bug Report: https://lore.kernel.org/dri-devel/61ed26af-062c-443c-9df2-d1ee319f3fb0@collabora.com/T/#u
+# Failure Rate: 50
+# IGT Version: 1.28-g0df7b9b97
+# Linux Version: 6.9.0-rc7
+kms_flip@basic-flip-vs-wf_vblank
+
+# Board Name: vkms
+# Bug Report: https://lore.kernel.org/dri-devel/61ed26af-062c-443c-9df2-d1ee319f3fb0@collabora.com/T/#u
+# Failure Rate: 50
+# IGT Version: 1.28-g0df7b9b97
+# Linux Version: 6.9.0-rc7
+kms_flip@flip-vs-expired-vblank-interruptible
+
+# Board Name: vkms
+# Bug Report: https://lore.kernel.org/dri-devel/61ed26af-062c-443c-9df2-d1ee319f3fb0@collabora.com/T/#u
+# Failure Rate: 50
+# IGT Version: 1.28-g0df7b9b97
+# Linux Version: 6.9.0-rc7
+kms_flip@flip-vs-wf_vblank-interruptible
+
+# Board Name: vkms
+# Bug Report: https://lore.kernel.org/dri-devel/61ed26af-062c-443c-9df2-d1ee319f3fb0@collabora.com/T/#u
+# Failure Rate: 50
+# IGT Version: 1.28-g0df7b9b97
+# Linux Version: 6.9.0-rc7
+kms_flip@plain-flip-fb-recreate-interruptible
+
+# Board Name: vkms
+# Bug Report: https://lore.kernel.org/dri-devel/61ed26af-062c-443c-9df2-d1ee319f3fb0@collabora.com/T/#u
+# Failure Rate: 50
+# IGT Version: 1.28-g0df7b9b97
+# Linux Version: 6.9.0-rc7
+kms_flip@plain-flip-ts-check
+
+# Board Name: vkms
+# Bug Report: https://lore.kernel.org/dri-devel/61ed26af-062c-443c-9df2-d1ee319f3fb0@collabora.com/T/#u
+# Failure Rate: 50
+# IGT Version: 1.28-g0df7b9b97
+# Linux Version: 6.9.0-rc7
+kms_flip@plain-flip-ts-check-interruptible
+
+# Board Name: vkms
+# Bug Report: https://lore.kernel.org/dri-devel/61ed26af-062c-443c-9df2-d1ee319f3fb0@collabora.com/T/#u
+# Failure Rate: 50
+# IGT Version: 1.28-g0df7b9b97
+# Linux Version: 6.9.0-rc7
+kms_flip@flip-vs-absolute-wf_vblank
+
+# Board Name: vkms
+# Bug Report: https://lore.kernel.org/dri-devel/61ed26af-062c-443c-9df2-d1ee319f3fb0@collabora.com/T/#u
+# Failure Rate: 50
+# IGT Version: 1.28-g0df7b9b97
+# Linux Version: 6.9.0-rc7
+kms_flip@flip-vs-absolute-wf_vblank-interruptible
+
+# Board Name: vkms
+# Bug Report: https://lore.kernel.org/dri-devel/61ed26af-062c-443c-9df2-d1ee319f3fb0@collabora.com/T/#u
+# Failure Rate: 50
+# IGT Version: 1.28-g0df7b9b97
+# Linux Version: 6.9.0-rc7
+kms_flip@flip-vs-blocking-wf-vblank
diff --git a/drivers/gpu/drm/ci/xfails/vkms-none-skips.txt b/drivers/gpu/drm/ci/xfails/vkms-none-skips.txt
new file mode 100644
index 000000000000..fd5d1271115f
--- /dev/null
+++ b/drivers/gpu/drm/ci/xfails/vkms-none-skips.txt
@@ -0,0 +1,119 @@
+# keeps printing vkms_vblank_simulate: vblank timer overrun and never ends
+kms_invalid_mode@int-max-clock
+
+# Kernel panic
+kms_cursor_crc@cursor-rapid-movement-32x10
+# Oops: 0000 [#1] PREEMPT SMP NOPTI
+# CPU: 0 PID: 2635 Comm: kworker/u8:13 Not tainted 6.9.0-rc7-g40935263a1fd #1
+# Hardware name: ChromiumOS crosvm, BIOS 0
+# Workqueue: vkms_composer vkms_composer_worker [vkms]
+# RIP: 0010:compose_active_planes+0x1c7/0x4e0 [vkms]
+# Code: c9 0f 84 6a 01 00 00 8b 42 30 2b 42 28 41 39 c5 0f 8c 6f 01 00 00 49 83 c7 01 49 39 df 74 3b 4b 8b 34 fc 48 8b 96 48 01 00 00 <8b> 42 78 89 c1 83 e1 0a a8 20 74 b1 45 89 f5 41 f7 d5 44 03 6a 34
+# RSP: 0018:ffffbb4700c17d58 EFLAGS: 00010246
+# RAX: 0000000000000400 RBX: 0000000000000002 RCX: 0000000000000002
+# RDX: 0000000000000000 RSI: ffffa2ad0788c000 RDI: 00000000fff479a8
+# RBP: 0000000000000004 R08: 0000000000000000 R09: 0000000000000000
+# R10: ffffa2ad0bb14000 R11: 0000000000000000 R12: ffffa2ad03e21700
+# R13: 0000000000000003 R14: 0000000000000004 R15: 0000000000000000
+# FS: 0000000000000000(0000) GS:ffffa2ad2bc00000(0000) knlGS:0000000000000000
+# CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+# CR2: 0000000000000078 CR3: 000000010bd30000 CR4: 0000000000350ef0
+# Call Trace:
+# <TASK>
+# ? __die+0x1e/0x60
+# ? page_fault_oops+0x17b/0x490
+# ? exc_page_fault+0x6d/0x230
+# ? asm_exc_page_fault+0x26/0x30
+# ? compose_active_planes+0x1c7/0x4e0 [vkms]
+# ? compose_active_planes+0x2a3/0x4e0 [vkms]
+# ? srso_return_thunk+0x5/0x5f
+# vkms_composer_worker+0x205/0x240 [vkms]
+# process_one_work+0x1f4/0x6b0
+# ? lock_is_held_type+0x9e/0x110
+# worker_thread+0x17e/0x350
+# ? __pfx_worker_thread+0x10/0x10
+# kthread+0xce/0x100
+# ? __pfx_kthread+0x10/0x10
+# ret_from_fork+0x2f/0x50
+# ? __pfx_kthread+0x10/0x10
+# ret_from_fork_asm+0x1a/0x30
+# </TASK>
+# Modules linked in: vkms
+# CR2: 0000000000000078
+# ---[ end trace 0000000000000000 ]---
+# RIP: 0010:compose_active_planes+0x1c7/0x4e0 [vkms]
+# Code: c9 0f 84 6a 01 00 00 8b 42 30 2b 42 28 41 39 c5 0f 8c 6f 01 00 00 49 83 c7 01 49 39 df 74 3b 4b 8b 34 fc 48 8b 96 48 01 00 00 <8b> 42 78 89 c1 83 e1 0a a8 20 74 b1 45 89 f5 41 f7 d5 44 03 6a 34
+# RSP: 0018:ffffbb4700c17d58 EFLAGS: 00010246
+# RAX: 0000000000000400 RBX: 0000000000000002 RCX: 0000000000000002
+# RDX: 0000000000000000 RSI: ffffa2ad0788c000 RDI: 00000000fff479a8
+# RBP: 0000000000000004 R08: 0000000000000000 R09: 0000000000000000
+# R10: ffffa2ad0bb14000 R11: 0000000000000000 R12: ffffa2ad03e21700
+# R13: 0000000000000003 R14: 0000000000000004 R15: 0000000000000000
+# FS: 0000000000000000(0000) GS:ffffa2ad2bc00000(0000) knlGS:0000000000000000
+# CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+
+kms_cursor_crc@cursor-rapid-movement-256x85
+# [drm:drm_crtc_add_crc_entry] *ERROR* Overflow of CRC buffer, userspace reads too slow.
+# Oops: 0000 [#1] PREEMPT SMP NOPTI
+# CPU: 1 PID: 10 Comm: kworker/u8:0 Not tainted 6.9.0-rc7-g646381cde463 #1
+# Hardware name: ChromiumOS crosvm, BIOS 0
+# Workqueue: vkms_composer vkms_composer_worker [vkms]
+# RIP: 0010:compose_active_planes+0x1c7/0x4e0 [vkms]
+# Code: c9 0f 84 6a 01 00 00 8b 42 30 2b 42 28 41 39 c5 0f 8c 6f 01 00 00 49 83 c7 01 49 39 df 74 3b 4b 8b 34 fc 48 8b 96 48 01 00 00 <8b> 42 78 89 c1 83 e1 0a a8 20 74 b1 45 89 f5 41 f7 d5 44 03 6a 34
+# RSP: 0018:ffffa7e980057d58 EFLAGS: 00010246
+# RAX: 0000000000000400 RBX: 0000000000000002 RCX: 0000000000000002
+# RDX: 0000000000000000 RSI: ffff977987aa5c00 RDI: 000000001b43a85f
+# RBP: 0000000000000001 R08: 0000000000000000 R09: 0000000000000000
+# R10: ffff977981bf0000 R11: 0000000000000000 R12: ffff977989622590
+# R13: 0000000000000000 R14: 0000000000000001 R15: 0000000000000000
+# FS: 0000000000000000(0000) GS:ffff9779abd00000(0000) knlGS:0000000000000000
+# CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+# CR2: 0000000000000078 CR3: 0000000109b38000 CR4: 0000000000350ef0
+# Call Trace:
+# <TASK>
+# ? __die+0x1e/0x60
+# ? page_fault_oops+0x17b/0x490
+# ? exc_page_fault+0x6d/0x230
+# ? asm_exc_page_fault+0x26/0x30
+# ? compose_active_planes+0x1c7/0x4e0 [vkms]
+# ? compose_active_planes+0x2a3/0x4e0 [vkms]
+# ? srso_return_thunk+0x5/0x5f
+# vkms_composer_worker+0x205/0x240 [vkms]
+# process_one_work+0x1f4/0x6b0
+# ? lock_is_held_type+0x9e/0x110
+# worker_thread+0x17e/0x350
+# ? __pfx_worker_thread+0x10/0x10
+# kthread+0xce/0x100
+# ? __pfx_kthread+0x10/0x10
+# ret_from_fork+0x2f/0x50
+# ? __pfx_kthread+0x10/0x10
+# ret_from_fork_asm+0x1a/0x30
+# </TASK>
+# Modules linked in: vkms
+# CR2: 0000000000000078
+# ---[ end trace 0000000000000000 ]---
+# RIP: 0010:compose_active_planes+0x1c7/0x4e0 [vkms]
+# Code: c9 0f 84 6a 01 00 00 8b 42 30 2b 42 28 41 39 c5 0f 8c 6f 01 00 00 49 83 c7 01 49 39 df 74 3b 4b 8b 34 fc 48 8b 96 48 01 00 00 <8b> 42 78 89 c1 83 e1 0a a8 20 74 b1 45 89 f5 41 f7 d5 44 03 6a 34
+# RSP: 0018:ffffa7e980057d58 EFLAGS: 00010246
+# RAX: 0000000000000400 RBX: 0000000000000002 RCX: 0000000000000002
+# RDX: 0000000000000000 RSI: ffff977987aa5c00 RDI: 000000001b43a85f
+# RBP: 0000000000000001 R08: 0000000000000000 R09: 0000000000000000
+# R10: ffff977981bf0000 R11: 0000000000000000 R12: ffff977989622590
+# R13: 0000000000000000 R14: 0000000000000001 R15: 0000000000000000
+# FS: 0000000000000000(0000) GS:ffff9779abd00000(0000) knlGS:0000000000000000
+# CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+# CR2: 0000000000000078 CR3: 0000000109b38000 CR4: 0000000000350ef0
+
+# Skip driver specific tests
+^amdgpu.*
+msm_.*
+nouveau_.*
+panfrost_.*
+^v3d.*
+^vc4.*
+^vmwgfx*
+
+# Skip intel specific tests
+gem_.*
+i915_.*
+xe_.*
diff --git a/drivers/gpu/drm/display/Kconfig b/drivers/gpu/drm/display/Kconfig
index 864a6488bfdf..479e62690d75 100644
--- a/drivers/gpu/drm/display/Kconfig
+++ b/drivers/gpu/drm/display/Kconfig
@@ -70,3 +70,10 @@ config DRM_DISPLAY_HDMI_HELPER
depends on DRM_DISPLAY_HELPER
help
DRM display helpers for HDMI.
+
+config DRM_DISPLAY_HDMI_STATE_HELPER
+ bool
+ depends on DRM_DISPLAY_HELPER
+ select DRM_DISPLAY_HDMI_HELPER
+ help
+ DRM KMS state helpers for HDMI.
diff --git a/drivers/gpu/drm/display/Makefile b/drivers/gpu/drm/display/Makefile
index 17d2cc73ff56..629df2f4d322 100644
--- a/drivers/gpu/drm/display/Makefile
+++ b/drivers/gpu/drm/display/Makefile
@@ -14,6 +14,8 @@ drm_display_helper-$(CONFIG_DRM_DISPLAY_HDCP_HELPER) += drm_hdcp_helper.o
drm_display_helper-$(CONFIG_DRM_DISPLAY_HDMI_HELPER) += \
drm_hdmi_helper.o \
drm_scdc_helper.o
+drm_display_helper-$(CONFIG_DRM_DISPLAY_HDMI_STATE_HELPER) += \
+ drm_hdmi_state_helper.o
drm_display_helper-$(CONFIG_DRM_DISPLAY_DP_AUX_CHARDEV) += drm_dp_aux_dev.o
drm_display_helper-$(CONFIG_DRM_DISPLAY_DP_AUX_CEC) += drm_dp_cec.o
diff --git a/drivers/gpu/drm/display/drm_dp_aux_bus.c b/drivers/gpu/drm/display/drm_dp_aux_bus.c
index 5afc26be9d2a..d810529ebfb6 100644
--- a/drivers/gpu/drm/display/drm_dp_aux_bus.c
+++ b/drivers/gpu/drm/display/drm_dp_aux_bus.c
@@ -36,7 +36,7 @@ struct dp_aux_ep_device_with_data {
*
* Return: True if this driver matches this device; false otherwise.
*/
-static int dp_aux_ep_match(struct device *dev, struct device_driver *drv)
+static int dp_aux_ep_match(struct device *dev, const struct device_driver *drv)
{
return !!of_match_device(drv->of_match_table, dev);
}
diff --git a/drivers/gpu/drm/display/drm_dp_helper.c b/drivers/gpu/drm/display/drm_dp_helper.c
index 79a615667aab..d4c34f364140 100644
--- a/drivers/gpu/drm/display/drm_dp_helper.c
+++ b/drivers/gpu/drm/display/drm_dp_helper.c
@@ -35,6 +35,7 @@
#include <drm/display/drm_dp_helper.h>
#include <drm/display/drm_dp_mst_helper.h>
#include <drm/drm_edid.h>
+#include <drm/drm_fixed.h>
#include <drm/drm_print.h>
#include <drm/drm_vblank.h>
#include <drm/drm_panel.h>
@@ -4151,9 +4152,9 @@ int drm_dp_bw_overhead(int lane_count, int hactive,
int symbol_cycles;
if (lane_count == 0 || hactive == 0 || bpp_x16 == 0) {
- DRM_DEBUG_KMS("Invalid BW overhead params: lane_count %d, hactive %d, bpp_x16 %d.%04d\n",
+ DRM_DEBUG_KMS("Invalid BW overhead params: lane_count %d, hactive %d, bpp_x16 " FXP_Q4_FMT "\n",
lane_count, hactive,
- bpp_x16 >> 4, (bpp_x16 & 0xf) * 625);
+ FXP_Q4_ARGS(bpp_x16));
return 0;
}
diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index a892ef8e8a2d..bcc5bbed9bd0 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -2931,7 +2931,7 @@ static int drm_dp_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
/* FIXME: Actually do some real error handling here */
ret = drm_dp_mst_wait_tx_reply(mstb, txmsg);
- if (ret <= 0) {
+ if (ret < 0) {
drm_err(mgr->dev, "Sending link address failed with %d\n", ret);
goto out;
}
@@ -2983,7 +2983,7 @@ static int drm_dp_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
mutex_unlock(&mgr->lock);
out:
- if (ret <= 0)
+ if (ret < 0)
mstb->link_address_sent = false;
kfree(txmsg);
return ret < 0 ? ret : changed;
@@ -4098,6 +4098,7 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
if (up_req->msg.req_type == DP_CONNECTION_STATUS_NOTIFY) {
const struct drm_dp_connection_status_notify *conn_stat =
&up_req->msg.u.conn_stat;
+ bool handle_csn;
drm_dbg_kms(mgr->dev, "Got CSN: pn: %d ldps:%d ddps: %d mcs: %d ip: %d pdt: %d\n",
conn_stat->port_number,
@@ -4106,6 +4107,16 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
conn_stat->message_capability_status,
conn_stat->input_port,
conn_stat->peer_device_type);
+
+ mutex_lock(&mgr->probe_lock);
+ handle_csn = mgr->mst_primary->link_address_sent;
+ mutex_unlock(&mgr->probe_lock);
+
+ if (!handle_csn) {
+ drm_dbg_kms(mgr->dev, "Got CSN before finish topology probing. Skip it.");
+ kfree(up_req);
+ goto out;
+ }
} else if (up_req->msg.req_type == DP_RESOURCE_STATUS_NOTIFY) {
const struct drm_dp_resource_status_notify *res_stat =
&up_req->msg.u.resource_stat;
diff --git a/drivers/gpu/drm/display/drm_dsc_helper.c b/drivers/gpu/drm/display/drm_dsc_helper.c
index 4424380c6cb6..6900f4dac520 100644
--- a/drivers/gpu/drm/display/drm_dsc_helper.c
+++ b/drivers/gpu/drm/display/drm_dsc_helper.c
@@ -14,6 +14,7 @@
#include <drm/display/drm_dp_helper.h>
#include <drm/display/drm_dsc_helper.h>
+#include <drm/drm_fixed.h>
#include <drm/drm_print.h>
/**
@@ -1472,3 +1473,93 @@ u32 drm_dsc_flatness_det_thresh(const struct drm_dsc_config *dsc)
return 2 << (dsc->bits_per_component - 8);
}
EXPORT_SYMBOL(drm_dsc_flatness_det_thresh);
+
+static void drm_dsc_dump_config_main_params(struct drm_printer *p, int indent,
+ const struct drm_dsc_config *cfg)
+{
+ drm_printf_indent(p, indent,
+ "dsc-cfg: version: %d.%d, picture: w=%d, h=%d, slice: count=%d, w=%d, h=%d, size=%d\n",
+ cfg->dsc_version_major, cfg->dsc_version_minor,
+ cfg->pic_width, cfg->pic_height,
+ cfg->slice_count, cfg->slice_width, cfg->slice_height, cfg->slice_chunk_size);
+ drm_printf_indent(p, indent,
+ "dsc-cfg: mode: block-pred=%s, vbr=%s, rgb=%s, simple-422=%s, native-422=%s, native-420=%s\n",
+ str_yes_no(cfg->block_pred_enable), str_yes_no(cfg->vbr_enable),
+ str_yes_no(cfg->convert_rgb),
+ str_yes_no(cfg->simple_422), str_yes_no(cfg->native_422), str_yes_no(cfg->native_420));
+ drm_printf_indent(p, indent,
+ "dsc-cfg: color-depth: uncompressed-bpc=%d, compressed-bpp=" FXP_Q4_FMT " line-buf-bpp=%d\n",
+ cfg->bits_per_component, FXP_Q4_ARGS(cfg->bits_per_pixel), cfg->line_buf_depth);
+ drm_printf_indent(p, indent,
+ "dsc-cfg: rc-model: size=%d, bits=%d, mux-word-size: %d, initial-delays: xmit=%d, dec=%d\n",
+ cfg->rc_model_size, cfg->rc_bits, cfg->mux_word_size,
+ cfg->initial_xmit_delay, cfg->initial_dec_delay);
+ drm_printf_indent(p, indent,
+ "dsc-cfg: offsets: initial=%d, final=%d, slice-bpg=%d\n",
+ cfg->initial_offset, cfg->final_offset, cfg->slice_bpg_offset);
+ drm_printf_indent(p, indent,
+ "dsc-cfg: line-bpg-offsets: first=%d, non-first=%d, second=%d, non-second=%d, second-adj=%d\n",
+ cfg->first_line_bpg_offset, cfg->nfl_bpg_offset,
+ cfg->second_line_bpg_offset, cfg->nsl_bpg_offset, cfg->second_line_offset_adj);
+ drm_printf_indent(p, indent,
+ "dsc-cfg: rc-tgt-offsets: low=%d, high=%d, rc-edge-factor: %d, rc-quant-incr-limits: [0]=%d, [1]=%d\n",
+ cfg->rc_tgt_offset_low, cfg->rc_tgt_offset_high,
+ cfg->rc_edge_factor, cfg->rc_quant_incr_limit0, cfg->rc_quant_incr_limit1);
+ drm_printf_indent(p, indent,
+ "dsc-cfg: initial-scale: %d, scale-intervals: increment=%d, decrement=%d\n",
+ cfg->initial_scale_value, cfg->scale_increment_interval, cfg->scale_decrement_interval);
+ drm_printf_indent(p, indent,
+ "dsc-cfg: flatness: min-qp=%d, max-qp=%d\n",
+ cfg->flatness_min_qp, cfg->flatness_max_qp);
+}
+
+static void drm_dsc_dump_config_rc_params(struct drm_printer *p, int indent,
+ const struct drm_dsc_config *cfg)
+{
+ const u16 *bt = cfg->rc_buf_thresh;
+ const struct drm_dsc_rc_range_parameters *rp = cfg->rc_range_params;
+
+ BUILD_BUG_ON(ARRAY_SIZE(cfg->rc_buf_thresh) != 14);
+ BUILD_BUG_ON(ARRAY_SIZE(cfg->rc_range_params) != 15);
+
+ drm_printf_indent(p, indent,
+ "dsc-cfg: rc-level: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14\n");
+ drm_printf_indent(p, indent,
+ "dsc-cfg: rc-buf-thresh: %3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d\n",
+ bt[0], bt[1], bt[2], bt[3], bt[4], bt[5], bt[6], bt[7],
+ bt[8], bt[9], bt[10], bt[11], bt[12], bt[13]);
+ drm_printf_indent(p, indent,
+ "dsc-cfg: rc-min-qp: %3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d\n",
+ rp[0].range_min_qp, rp[1].range_min_qp, rp[2].range_min_qp, rp[3].range_min_qp,
+ rp[4].range_min_qp, rp[5].range_min_qp, rp[6].range_min_qp, rp[7].range_min_qp,
+ rp[8].range_min_qp, rp[9].range_min_qp, rp[10].range_min_qp, rp[11].range_min_qp,
+ rp[12].range_min_qp, rp[13].range_min_qp, rp[14].range_min_qp);
+ drm_printf_indent(p, indent,
+ "dsc-cfg: rc-max-qp: %3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d\n",
+ rp[0].range_max_qp, rp[1].range_max_qp, rp[2].range_max_qp, rp[3].range_max_qp,
+ rp[4].range_max_qp, rp[5].range_max_qp, rp[6].range_max_qp, rp[7].range_max_qp,
+ rp[8].range_max_qp, rp[9].range_max_qp, rp[10].range_max_qp, rp[11].range_max_qp,
+ rp[12].range_max_qp, rp[13].range_max_qp, rp[14].range_max_qp);
+ drm_printf_indent(p, indent,
+ "dsc-cfg: rc-bpg-offset: %3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d\n",
+ rp[0].range_bpg_offset, rp[1].range_bpg_offset, rp[2].range_bpg_offset, rp[3].range_bpg_offset,
+ rp[4].range_bpg_offset, rp[5].range_bpg_offset, rp[6].range_bpg_offset, rp[7].range_bpg_offset,
+ rp[8].range_bpg_offset, rp[9].range_bpg_offset, rp[10].range_bpg_offset, rp[11].range_bpg_offset,
+ rp[12].range_bpg_offset, rp[13].range_bpg_offset, rp[14].range_bpg_offset);
+}
+
+/**
+ * drm_dsc_dump_config - Dump the provided DSC configuration
+ * @p: The printer used for output
+ * @indent: Tab indentation level (max 5)
+ * @cfg: DSC configuration to print
+ *
+ * Print the provided DSC configuration in @cfg.
+ */
+void drm_dsc_dump_config(struct drm_printer *p, int indent,
+ const struct drm_dsc_config *cfg)
+{
+ drm_dsc_dump_config_main_params(p, indent, cfg);
+ drm_dsc_dump_config_rc_params(p, indent, cfg);
+}
+EXPORT_SYMBOL(drm_dsc_dump_config);
diff --git a/drivers/gpu/drm/display/drm_hdmi_helper.c b/drivers/gpu/drm/display/drm_hdmi_helper.c
index faf5e9efa7d3..74dd4d01dd9b 100644
--- a/drivers/gpu/drm/display/drm_hdmi_helper.c
+++ b/drivers/gpu/drm/display/drm_hdmi_helper.c
@@ -195,3 +195,64 @@ void drm_hdmi_avi_infoframe_content_type(struct hdmi_avi_infoframe *frame,
frame->itc = conn_state->content_type != DRM_MODE_CONTENT_TYPE_NO_DATA;
}
EXPORT_SYMBOL(drm_hdmi_avi_infoframe_content_type);
+
+/**
+ * drm_hdmi_compute_mode_clock() - Computes the TMDS Character Rate
+ * @mode: Display mode to compute the clock for
+ * @bpc: Bits per character
+ * @fmt: Output Pixel Format used
+ *
+ * Returns the TMDS Character Rate for a given mode, bpc count and output format.
+ *
+ * RETURNS:
+ * The TMDS Character Rate, in Hertz, or 0 on error.
+ */
+unsigned long long
+drm_hdmi_compute_mode_clock(const struct drm_display_mode *mode,
+ unsigned int bpc, enum hdmi_colorspace fmt)
+{
+ unsigned long long clock = mode->clock * 1000ULL;
+ unsigned int vic = drm_match_cea_mode(mode);
+
+ /*
+ * CTA-861-G Spec, section 5.4 - Color Coding and Quantization
+ * mandates that VIC 1 always uses 8 bpc.
+ */
+ if (vic == 1 && bpc != 8)
+ return 0;
+
+ if (fmt == HDMI_COLORSPACE_YUV422) {
+ /*
+ * HDMI 1.0 Spec, section 6.5 - Pixel Encoding states that
+ * YUV422 sends 24 bits over three channels, with Cb and Cr
+ * components being sent on odd and even pixels, respectively.
+ *
+ * If fewer than 12 bpc are sent, data are left justified.
+ */
+ if (bpc > 12)
+ return 0;
+
+ /*
+ * HDMI 1.0 Spec, section 6.5 - Pixel Encoding
+ * specifies that YUV422 sends two 12-bits components over
+ * three TMDS channels per pixel clock, which is equivalent to
+ * three 8-bits components over three channels used by RGB as
+ * far as the clock rate goes.
+ */
+ bpc = 8;
+ }
+
+ /*
+ * HDMI 2.0 Spec, Section 7.1 - YCbCr 4:2:0 Pixel Encoding
+ * specifies that YUV420 encoding is carried at a TMDS Character Rate
+ * equal to half the pixel clock rate.
+ */
+ if (fmt == HDMI_COLORSPACE_YUV420)
+ clock = clock / 2;
+
+ if (mode->flags & DRM_MODE_FLAG_DBLCLK)
+ clock = clock * 2;
+
+ return DIV_ROUND_CLOSEST_ULL(clock * bpc, 8);
+}
+EXPORT_SYMBOL(drm_hdmi_compute_mode_clock);
diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
new file mode 100644
index 000000000000..7854820089ec
--- /dev/null
+++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
@@ -0,0 +1,752 @@
+// SPDX-License-Identifier: MIT
+
+#include <drm/drm_atomic.h>
+#include <drm/drm_connector.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_print.h>
+
+#include <drm/display/drm_hdmi_helper.h>
+#include <drm/display/drm_hdmi_state_helper.h>
+
+/**
+ * __drm_atomic_helper_connector_hdmi_reset() - Initializes all HDMI @drm_connector_state resources
+ * @connector: DRM connector
+ * @new_conn_state: connector state to reset
+ *
+ * Initializes all HDMI resources from a @drm_connector_state without
+ * actually allocating it. This is useful for HDMI drivers, in
+ * combination with __drm_atomic_helper_connector_reset() or
+ * drm_atomic_helper_connector_reset().
+ */
+void __drm_atomic_helper_connector_hdmi_reset(struct drm_connector *connector,
+ struct drm_connector_state *new_conn_state)
+{
+ unsigned int max_bpc = connector->max_bpc;
+
+ new_conn_state->max_bpc = max_bpc;
+ new_conn_state->max_requested_bpc = max_bpc;
+ new_conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_AUTO;
+}
+EXPORT_SYMBOL(__drm_atomic_helper_connector_hdmi_reset);
+
+static const struct drm_display_mode *
+connector_state_get_mode(const struct drm_connector_state *conn_state)
+{
+ struct drm_atomic_state *state;
+ struct drm_crtc_state *crtc_state;
+ struct drm_crtc *crtc;
+
+ state = conn_state->state;
+ if (!state)
+ return NULL;
+
+ crtc = conn_state->crtc;
+ if (!crtc)
+ return NULL;
+
+ crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+ if (!crtc_state)
+ return NULL;
+
+ return &crtc_state->mode;
+}
+
+static bool hdmi_is_limited_range(const struct drm_connector *connector,
+ const struct drm_connector_state *conn_state)
+{
+ const struct drm_display_info *info = &connector->display_info;
+ const struct drm_display_mode *mode =
+ connector_state_get_mode(conn_state);
+
+ /*
+ * The Broadcast RGB property only applies to RGB format, and
+ * i915 just assumes limited range for YCbCr output, so let's
+ * just do the same.
+ */
+ if (conn_state->hdmi.output_format != HDMI_COLORSPACE_RGB)
+ return true;
+
+ if (conn_state->hdmi.broadcast_rgb == DRM_HDMI_BROADCAST_RGB_FULL)
+ return false;
+
+ if (conn_state->hdmi.broadcast_rgb == DRM_HDMI_BROADCAST_RGB_LIMITED)
+ return true;
+
+ if (!info->is_hdmi)
+ return false;
+
+ return drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_LIMITED;
+}
+
+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)
+{
+ struct drm_device *dev = connector->dev;
+ u8 vic = drm_match_cea_mode(mode);
+
+ /*
+ * CTA-861-F, section 5.4 - Color Coding & Quantization states
+ * that the bpc must be 8, 10, 12 or 16 except for the default
+ * 640x480 VIC1 where the value must be 8.
+ *
+ * The definition of default here is ambiguous but the spec
+ * refers to VIC1 being the default timing in several occasions
+ * so our understanding is that for the default timing (ie,
+ * VIC1), the bpc must be 8.
+ */
+ if (vic == 1 && bpc != 8) {
+ drm_dbg_kms(dev, "VIC1 requires a bpc of 8, got %u\n", bpc);
+ return false;
+ }
+
+ if (!info->is_hdmi &&
+ (format != HDMI_COLORSPACE_RGB || bpc != 8)) {
+ drm_dbg_kms(dev, "DVI Monitors require an RGB output at 8 bpc\n");
+ return false;
+ }
+
+ if (!(connector->hdmi.supported_formats & BIT(format))) {
+ drm_dbg_kms(dev, "%s format unsupported by the connector.\n",
+ drm_hdmi_connector_get_output_format_name(format));
+ return false;
+ }
+
+ switch (format) {
+ case HDMI_COLORSPACE_RGB:
+ drm_dbg_kms(dev, "RGB Format, checking the constraints.\n");
+
+ /*
+ * In some cases, like when the EDID readout fails, or
+ * is not an HDMI compliant EDID for some reason, the
+ * color_formats field will be blank and not report any
+ * format supported. In such a case, assume that RGB is
+ * supported so we can keep things going and light up
+ * the display.
+ */
+ if (!(info->color_formats & DRM_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)) {
+ drm_dbg_kms(dev, "10 BPC but sink doesn't support Deep Color 30.\n");
+ return false;
+ }
+
+ if (bpc == 12 && !(info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_36)) {
+ drm_dbg_kms(dev, "12 BPC but sink doesn't support Deep Color 36.\n");
+ return false;
+ }
+
+ drm_dbg_kms(dev, "RGB format supported in that configuration.\n");
+
+ return true;
+
+ case HDMI_COLORSPACE_YUV420:
+ /* TODO: YUV420 is unsupported at the moment. */
+ drm_dbg_kms(dev, "YUV420 format isn't supported yet.\n");
+ return false;
+
+ case HDMI_COLORSPACE_YUV422:
+ drm_dbg_kms(dev, "YUV422 format, checking the constraints.\n");
+
+ if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR422)) {
+ drm_dbg_kms(dev, "Sink doesn't support YUV422.\n");
+ return false;
+ }
+
+ if (bpc > 12) {
+ drm_dbg_kms(dev, "YUV422 only supports 12 bpc or lower.\n");
+ return false;
+ }
+
+ /*
+ * HDMI Spec 1.3 - Section 6.5 Pixel Encodings and Color Depth
+ * states that Deep Color is not relevant for YUV422 so we
+ * don't need to check the Deep Color bits in the EDIDs here.
+ */
+
+ drm_dbg_kms(dev, "YUV422 format supported in that configuration.\n");
+
+ return true;
+
+ case HDMI_COLORSPACE_YUV444:
+ drm_dbg_kms(dev, "YUV444 format, checking the constraints.\n");
+
+ if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR444)) {
+ drm_dbg_kms(dev, "Sink doesn't support YUV444.\n");
+ return false;
+ }
+
+ if (bpc == 10 && !(info->edid_hdmi_ycbcr444_dc_modes & DRM_EDID_HDMI_DC_30)) {
+ drm_dbg_kms(dev, "10 BPC but sink doesn't support Deep Color 30.\n");
+ return false;
+ }
+
+ if (bpc == 12 && !(info->edid_hdmi_ycbcr444_dc_modes & DRM_EDID_HDMI_DC_36)) {
+ drm_dbg_kms(dev, "12 BPC but sink doesn't support Deep Color 36.\n");
+ return false;
+ }
+
+ drm_dbg_kms(dev, "YUV444 format supported in that configuration.\n");
+
+ return true;
+ }
+
+ drm_dbg_kms(dev, "Unsupported pixel format.\n");
+ return false;
+}
+
+static enum drm_mode_status
+hdmi_clock_valid(const struct drm_connector *connector,
+ const struct drm_display_mode *mode,
+ unsigned long long clock)
+{
+ const struct drm_connector_hdmi_funcs *funcs = connector->hdmi.funcs;
+ const struct drm_display_info *info = &connector->display_info;
+
+ if (info->max_tmds_clock && clock > info->max_tmds_clock * 1000)
+ return MODE_CLOCK_HIGH;
+
+ if (funcs && funcs->tmds_char_rate_valid) {
+ enum drm_mode_status status;
+
+ status = funcs->tmds_char_rate_valid(connector, mode, clock);
+ if (status != MODE_OK)
+ return status;
+ }
+
+ return MODE_OK;
+}
+
+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)
+{
+ enum drm_mode_status status;
+ unsigned long long clock;
+
+ clock = drm_hdmi_compute_mode_clock(mode, bpc, fmt);
+ if (!clock)
+ return -EINVAL;
+
+ status = hdmi_clock_valid(connector, mode, clock);
+ if (status != MODE_OK)
+ return -EINVAL;
+
+ conn_state->hdmi.tmds_char_rate = clock;
+
+ return 0;
+}
+
+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)
+{
+ const struct drm_display_info *info = &connector->display_info;
+ struct drm_device *dev = connector->dev;
+ int ret;
+
+ drm_dbg_kms(dev, "Trying %s output format\n",
+ drm_hdmi_connector_get_output_format_name(fmt));
+
+ if (!sink_supports_format_bpc(connector, info, mode, fmt, bpc)) {
+ drm_dbg_kms(dev, "%s output format not supported with %u bpc\n",
+ drm_hdmi_connector_get_output_format_name(fmt),
+ bpc);
+ return false;
+ }
+
+ ret = hdmi_compute_clock(connector, conn_state, mode, bpc, fmt);
+ if (ret) {
+ drm_dbg_kms(dev, "Couldn't compute clock for %s output format and %u bpc\n",
+ drm_hdmi_connector_get_output_format_name(fmt),
+ bpc);
+ return false;
+ }
+
+ drm_dbg_kms(dev, "%s output format supported with %u (TMDS char rate: %llu Hz)\n",
+ drm_hdmi_connector_get_output_format_name(fmt),
+ bpc, conn_state->hdmi.tmds_char_rate);
+
+ return true;
+}
+
+static int
+hdmi_compute_format(const struct drm_connector *connector,
+ struct drm_connector_state *conn_state,
+ const struct drm_display_mode *mode,
+ unsigned int bpc)
+{
+ struct drm_device *dev = connector->dev;
+
+ /*
+ * TODO: Add support for YCbCr420 output for HDMI 2.0 capable
+ * devices, for modes that only support YCbCr420.
+ */
+ if (hdmi_try_format_bpc(connector, conn_state, mode, bpc, HDMI_COLORSPACE_RGB)) {
+ conn_state->hdmi.output_format = HDMI_COLORSPACE_RGB;
+ return 0;
+ }
+
+ drm_dbg_kms(dev, "Failed. No Format Supported for that bpc count.\n");
+
+ return -EINVAL;
+}
+
+static int
+hdmi_compute_config(const struct drm_connector *connector,
+ struct drm_connector_state *conn_state,
+ const struct drm_display_mode *mode)
+{
+ struct drm_device *dev = connector->dev;
+ unsigned int max_bpc = clamp_t(unsigned int,
+ conn_state->max_bpc,
+ 8, connector->max_bpc);
+ unsigned int bpc;
+ int ret;
+
+ for (bpc = max_bpc; bpc >= 8; bpc -= 2) {
+ drm_dbg_kms(dev, "Trying with a %d bpc output\n", bpc);
+
+ ret = hdmi_compute_format(connector, conn_state, mode, bpc);
+ if (ret)
+ continue;
+
+ conn_state->hdmi.output_bpc = bpc;
+
+ drm_dbg_kms(dev,
+ "Mode %ux%u @ %uHz: Found configuration: bpc: %u, fmt: %s, clock: %llu\n",
+ mode->hdisplay, mode->vdisplay, drm_mode_vrefresh(mode),
+ conn_state->hdmi.output_bpc,
+ drm_hdmi_connector_get_output_format_name(conn_state->hdmi.output_format),
+ conn_state->hdmi.tmds_char_rate);
+
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int hdmi_generate_avi_infoframe(const struct drm_connector *connector,
+ struct drm_connector_state *conn_state)
+{
+ const struct drm_display_mode *mode =
+ connector_state_get_mode(conn_state);
+ struct drm_connector_hdmi_infoframe *infoframe =
+ &conn_state->hdmi.infoframes.avi;
+ struct hdmi_avi_infoframe *frame =
+ &infoframe->data.avi;
+ bool is_limited_range = conn_state->hdmi.is_limited_range;
+ enum hdmi_quantization_range rgb_quant_range =
+ is_limited_range ? HDMI_QUANTIZATION_RANGE_LIMITED : HDMI_QUANTIZATION_RANGE_FULL;
+ int ret;
+
+ ret = drm_hdmi_avi_infoframe_from_display_mode(frame, connector, mode);
+ if (ret)
+ return ret;
+
+ frame->colorspace = conn_state->hdmi.output_format;
+
+ /*
+ * FIXME: drm_hdmi_avi_infoframe_quant_range() doesn't handle
+ * YUV formats at all at the moment, so if we ever support YUV
+ * formats this needs to be revised.
+ */
+ drm_hdmi_avi_infoframe_quant_range(frame, connector, mode, rgb_quant_range);
+ drm_hdmi_avi_infoframe_colorimetry(frame, conn_state);
+ drm_hdmi_avi_infoframe_bars(frame, conn_state);
+
+ infoframe->set = true;
+
+ return 0;
+}
+
+static int hdmi_generate_spd_infoframe(const struct drm_connector *connector,
+ struct drm_connector_state *conn_state)
+{
+ struct drm_connector_hdmi_infoframe *infoframe =
+ &conn_state->hdmi.infoframes.spd;
+ struct hdmi_spd_infoframe *frame =
+ &infoframe->data.spd;
+ int ret;
+
+ ret = hdmi_spd_infoframe_init(frame,
+ connector->hdmi.vendor,
+ connector->hdmi.product);
+ if (ret)
+ return ret;
+
+ frame->sdi = HDMI_SPD_SDI_PC;
+
+ infoframe->set = true;
+
+ return 0;
+}
+
+static int hdmi_generate_hdr_infoframe(const struct drm_connector *connector,
+ struct drm_connector_state *conn_state)
+{
+ struct drm_connector_hdmi_infoframe *infoframe =
+ &conn_state->hdmi.infoframes.hdr_drm;
+ struct hdmi_drm_infoframe *frame =
+ &infoframe->data.drm;
+ int ret;
+
+ if (connector->max_bpc < 10)
+ return 0;
+
+ if (!conn_state->hdr_output_metadata)
+ return 0;
+
+ ret = drm_hdmi_infoframe_set_hdr_metadata(frame, conn_state);
+ if (ret)
+ return ret;
+
+ infoframe->set = true;
+
+ return 0;
+}
+
+static int hdmi_generate_hdmi_vendor_infoframe(const struct drm_connector *connector,
+ struct drm_connector_state *conn_state)
+{
+ const struct drm_display_info *info = &connector->display_info;
+ const struct drm_display_mode *mode =
+ connector_state_get_mode(conn_state);
+ struct drm_connector_hdmi_infoframe *infoframe =
+ &conn_state->hdmi.infoframes.hdmi;
+ struct hdmi_vendor_infoframe *frame =
+ &infoframe->data.vendor.hdmi;
+ int ret;
+
+ if (!info->has_hdmi_infoframe)
+ return 0;
+
+ ret = drm_hdmi_vendor_infoframe_from_display_mode(frame, connector, mode);
+ if (ret)
+ return ret;
+
+ infoframe->set = true;
+
+ return 0;
+}
+
+static int
+hdmi_generate_infoframes(const struct drm_connector *connector,
+ struct drm_connector_state *conn_state)
+{
+ const struct drm_display_info *info = &connector->display_info;
+ int ret;
+
+ if (!info->is_hdmi)
+ return 0;
+
+ ret = hdmi_generate_avi_infoframe(connector, conn_state);
+ if (ret)
+ return ret;
+
+ ret = hdmi_generate_spd_infoframe(connector, conn_state);
+ if (ret)
+ return ret;
+
+ /*
+ * Audio Infoframes will be generated by ALSA, and updated by
+ * drm_atomic_helper_connector_hdmi_update_audio_infoframe().
+ */
+
+ ret = hdmi_generate_hdr_infoframe(connector, conn_state);
+ if (ret)
+ return ret;
+
+ ret = hdmi_generate_hdmi_vendor_infoframe(connector, conn_state);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+/**
+ * drm_atomic_helper_connector_hdmi_check() - Helper to check HDMI connector atomic state
+ * @connector: DRM Connector
+ * @state: the DRM State object
+ *
+ * Provides a default connector state check handler for HDMI connectors.
+ * Checks that a desired connector update is valid, and updates various
+ * fields of derived state.
+ *
+ * RETURNS:
+ * Zero on success, or an errno code otherwise.
+ */
+int drm_atomic_helper_connector_hdmi_check(struct drm_connector *connector,
+ struct drm_atomic_state *state)
+{
+ struct drm_connector_state *old_conn_state =
+ drm_atomic_get_old_connector_state(state, connector);
+ struct drm_connector_state *new_conn_state =
+ drm_atomic_get_new_connector_state(state, connector);
+ const struct drm_display_mode *mode =
+ connector_state_get_mode(new_conn_state);
+ int ret;
+
+ new_conn_state->hdmi.is_limited_range = hdmi_is_limited_range(connector, new_conn_state);
+
+ ret = hdmi_compute_config(connector, new_conn_state, mode);
+ if (ret)
+ return ret;
+
+ ret = hdmi_generate_infoframes(connector, new_conn_state);
+ if (ret)
+ return ret;
+
+ if (old_conn_state->hdmi.broadcast_rgb != new_conn_state->hdmi.broadcast_rgb ||
+ old_conn_state->hdmi.output_bpc != new_conn_state->hdmi.output_bpc ||
+ old_conn_state->hdmi.output_format != new_conn_state->hdmi.output_format) {
+ struct drm_crtc *crtc = new_conn_state->crtc;
+ struct drm_crtc_state *crtc_state;
+
+ crtc_state = drm_atomic_get_crtc_state(state, crtc);
+ if (IS_ERR(crtc_state))
+ return PTR_ERR(crtc_state);
+
+ crtc_state->mode_changed = true;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_check);
+
+#define HDMI_MAX_INFOFRAME_SIZE 29
+
+static int clear_device_infoframe(struct drm_connector *connector,
+ enum hdmi_infoframe_type type)
+{
+ const struct drm_connector_hdmi_funcs *funcs = connector->hdmi.funcs;
+ struct drm_device *dev = connector->dev;
+ int ret;
+
+ drm_dbg_kms(dev, "Clearing infoframe type 0x%x\n", type);
+
+ if (!funcs || !funcs->clear_infoframe) {
+ drm_dbg_kms(dev, "Function not implemented, bailing.\n");
+ return 0;
+ }
+
+ ret = funcs->clear_infoframe(connector, type);
+ if (ret) {
+ drm_dbg_kms(dev, "Call failed: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int clear_infoframe(struct drm_connector *connector,
+ struct drm_connector_hdmi_infoframe *old_frame)
+{
+ int ret;
+
+ ret = clear_device_infoframe(connector, old_frame->data.any.type);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int write_device_infoframe(struct drm_connector *connector,
+ union hdmi_infoframe *frame)
+{
+ const struct drm_connector_hdmi_funcs *funcs = connector->hdmi.funcs;
+ struct drm_device *dev = connector->dev;
+ u8 buffer[HDMI_MAX_INFOFRAME_SIZE];
+ int ret;
+ int len;
+
+ drm_dbg_kms(dev, "Writing infoframe type %x\n", frame->any.type);
+
+ if (!funcs || !funcs->write_infoframe) {
+ drm_dbg_kms(dev, "Function not implemented, bailing.\n");
+ return -EINVAL;
+ }
+
+ len = hdmi_infoframe_pack(frame, buffer, sizeof(buffer));
+ if (len < 0)
+ return len;
+
+ ret = funcs->write_infoframe(connector, frame->any.type, buffer, len);
+ if (ret) {
+ drm_dbg_kms(dev, "Call failed: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int write_infoframe(struct drm_connector *connector,
+ struct drm_connector_hdmi_infoframe *new_frame)
+{
+ int ret;
+
+ ret = write_device_infoframe(connector, &new_frame->data);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int write_or_clear_infoframe(struct drm_connector *connector,
+ struct drm_connector_hdmi_infoframe *old_frame,
+ struct drm_connector_hdmi_infoframe *new_frame)
+{
+ if (new_frame->set)
+ return write_infoframe(connector, new_frame);
+
+ if (old_frame->set && !new_frame->set)
+ return clear_infoframe(connector, old_frame);
+
+ return 0;
+}
+
+/**
+ * drm_atomic_helper_connector_hdmi_update_infoframes - Update the Infoframes
+ * @connector: A pointer to the HDMI connector
+ * @state: The HDMI connector state to generate the infoframe from
+ *
+ * This function is meant for HDMI connector drivers to write their
+ * infoframes. It will typically be used in a
+ * @drm_connector_helper_funcs.atomic_enable implementation.
+ *
+ * Returns:
+ * Zero on success, error code on failure.
+ */
+int drm_atomic_helper_connector_hdmi_update_infoframes(struct drm_connector *connector,
+ struct drm_atomic_state *state)
+{
+ struct drm_connector_state *old_conn_state =
+ drm_atomic_get_old_connector_state(state, connector);
+ struct drm_connector_state *new_conn_state =
+ drm_atomic_get_new_connector_state(state, connector);
+ struct drm_display_info *info = &connector->display_info;
+ int ret;
+
+ if (!info->is_hdmi)
+ return 0;
+
+ mutex_lock(&connector->hdmi.infoframes.lock);
+
+ ret = write_or_clear_infoframe(connector,
+ &old_conn_state->hdmi.infoframes.avi,
+ &new_conn_state->hdmi.infoframes.avi);
+ if (ret)
+ goto out;
+
+ if (connector->hdmi.infoframes.audio.set) {
+ ret = write_infoframe(connector,
+ &connector->hdmi.infoframes.audio);
+ if (ret)
+ goto out;
+ }
+
+ ret = write_or_clear_infoframe(connector,
+ &old_conn_state->hdmi.infoframes.hdr_drm,
+ &new_conn_state->hdmi.infoframes.hdr_drm);
+ if (ret)
+ goto out;
+
+ ret = write_or_clear_infoframe(connector,
+ &old_conn_state->hdmi.infoframes.spd,
+ &new_conn_state->hdmi.infoframes.spd);
+ if (ret)
+ goto out;
+
+ if (info->has_hdmi_infoframe) {
+ ret = write_or_clear_infoframe(connector,
+ &old_conn_state->hdmi.infoframes.hdmi,
+ &new_conn_state->hdmi.infoframes.hdmi);
+ if (ret)
+ goto out;
+ }
+
+out:
+ mutex_unlock(&connector->hdmi.infoframes.lock);
+ return ret;
+}
+EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_update_infoframes);
+
+/**
+ * drm_atomic_helper_connector_hdmi_update_audio_infoframe - Update the Audio Infoframe
+ * @connector: A pointer to the HDMI connector
+ * @frame: A pointer to the audio infoframe to write
+ *
+ * This function is meant for HDMI connector drivers to update their
+ * audio infoframe. It will typically be used in one of the ALSA hooks
+ * (most likely prepare).
+ *
+ * Returns:
+ * Zero on success, error code on failure.
+ */
+int
+drm_atomic_helper_connector_hdmi_update_audio_infoframe(struct drm_connector *connector,
+ struct hdmi_audio_infoframe *frame)
+{
+ struct drm_connector_hdmi_infoframe *infoframe =
+ &connector->hdmi.infoframes.audio;
+ struct drm_display_info *info = &connector->display_info;
+ int ret;
+
+ if (!info->is_hdmi)
+ return 0;
+
+ mutex_lock(&connector->hdmi.infoframes.lock);
+
+ memcpy(&infoframe->data, frame, sizeof(infoframe->data));
+ infoframe->set = true;
+
+ ret = write_infoframe(connector, infoframe);
+
+ mutex_unlock(&connector->hdmi.infoframes.lock);
+
+ return ret;
+}
+EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_update_audio_infoframe);
+
+/**
+ * drm_atomic_helper_connector_hdmi_clear_audio_infoframe - Stop sending the Audio Infoframe
+ * @connector: A pointer to the HDMI connector
+ *
+ * This function is meant for HDMI connector drivers to stop sending their
+ * audio infoframe. It will typically be used in one of the ALSA hooks
+ * (most likely shutdown).
+ *
+ * Returns:
+ * Zero on success, error code on failure.
+ */
+int
+drm_atomic_helper_connector_hdmi_clear_audio_infoframe(struct drm_connector *connector)
+{
+ struct drm_connector_hdmi_infoframe *infoframe =
+ &connector->hdmi.infoframes.audio;
+ struct drm_display_info *info = &connector->display_info;
+ int ret;
+
+ if (!info->is_hdmi)
+ return 0;
+
+ mutex_lock(&connector->hdmi.infoframes.lock);
+
+ infoframe->set = false;
+
+ ret = clear_infoframe(connector, infoframe);
+
+ memset(&infoframe->data, 0, sizeof(infoframe->data));
+
+ mutex_unlock(&connector->hdmi.infoframes.lock);
+
+ return ret;
+}
+EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_clear_audio_infoframe);
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index e22560213b8e..6e516c39a372 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -1140,6 +1140,17 @@ static void drm_atomic_connector_print_state(struct drm_printer *p,
drm_printf(p, "\tmax_requested_bpc=%d\n", state->max_requested_bpc);
drm_printf(p, "\tcolorspace=%s\n", drm_get_colorspace_name(state->colorspace));
+ if (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA ||
+ connector->connector_type == DRM_MODE_CONNECTOR_HDMIB) {
+ drm_printf(p, "\tbroadcast_rgb=%s\n",
+ drm_hdmi_connector_get_broadcast_rgb_name(state->hdmi.broadcast_rgb));
+ drm_printf(p, "\tis_limited_range=%c\n", state->hdmi.is_limited_range ? 'y' : 'n');
+ drm_printf(p, "\toutput_bpc=%u\n", state->hdmi.output_bpc);
+ drm_printf(p, "\toutput_format=%s\n",
+ drm_hdmi_connector_get_output_format_name(state->hdmi.output_format));
+ drm_printf(p, "\ttmds_char_rate=%llu\n", state->hdmi.tmds_char_rate);
+ }
+
if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
if (state->writeback_job && state->writeback_job->fb)
drm_printf(p, "\tfb=%d\n", state->writeback_job->fb->base.id);
diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
index fc16fddee5c5..22bbb2d83e30 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -776,6 +776,8 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector,
state->max_requested_bpc = val;
} else if (property == connector->privacy_screen_sw_state_property) {
state->privacy_screen_sw_state = val;
+ } else if (property == connector->broadcast_rgb_property) {
+ state->hdmi.broadcast_rgb = val;
} else if (connector->funcs->atomic_set_property) {
return connector->funcs->atomic_set_property(connector,
state, property, val);
@@ -859,6 +861,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector,
*val = state->max_requested_bpc;
} else if (property == connector->privacy_screen_sw_state_property) {
*val = state->privacy_screen_sw_state;
+ } else if (property == connector->broadcast_rgb_property) {
+ *val = state->hdmi.broadcast_rgb;
} else if (connector->funcs->atomic_get_property) {
return connector->funcs->atomic_get_property(connector,
state, property, val);
diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index 28abe9aa99ca..d44f055dbe3e 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -353,13 +353,8 @@ err_reset_bridge:
bridge->encoder = NULL;
list_del(&bridge->chain_node);
-#ifdef CONFIG_OF
DRM_ERROR("failed to attach bridge %pOF to encoder %s: %d\n",
bridge->of_node, encoder->name, ret);
-#else
- DRM_ERROR("failed to attach bridge to encoder %s: %d\n",
- encoder->name, ret);
-#endif
return ret;
}
@@ -473,43 +468,6 @@ void drm_bridge_detach(struct drm_bridge *bridge)
*/
/**
- * drm_bridge_chain_mode_fixup - fixup proposed mode for all bridges in the
- * encoder chain
- * @bridge: bridge control structure
- * @mode: desired mode to be set for the bridge
- * @adjusted_mode: updated mode that works for this bridge
- *
- * Calls &drm_bridge_funcs.mode_fixup for all the bridges in the
- * encoder chain, starting from the first bridge to the last.
- *
- * Note: the bridge passed should be the one closest to the encoder
- *
- * RETURNS:
- * true on success, false on failure
- */
-bool drm_bridge_chain_mode_fixup(struct drm_bridge *bridge,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- struct drm_encoder *encoder;
-
- if (!bridge)
- return true;
-
- encoder = bridge->encoder;
- list_for_each_entry_from(bridge, &encoder->bridge_chain, chain_node) {
- if (!bridge->funcs->mode_fixup)
- continue;
-
- if (!bridge->funcs->mode_fixup(bridge, mode, adjusted_mode))
- return false;
- }
-
- return true;
-}
-EXPORT_SYMBOL(drm_bridge_chain_mode_fixup);
-
-/**
* drm_bridge_chain_mode_valid - validate the mode against all bridges in the
* encoder chain.
* @bridge: bridge control structure
diff --git a/drivers/gpu/drm/drm_bridge_connector.c b/drivers/gpu/drm/drm_bridge_connector.c
index 982552c9f92c..0869b663f17e 100644
--- a/drivers/gpu/drm/drm_bridge_connector.c
+++ b/drivers/gpu/drm/drm_bridge_connector.c
@@ -15,8 +15,10 @@
#include <drm/drm_connector.h>
#include <drm/drm_device.h>
#include <drm/drm_edid.h>
+#include <drm/drm_managed.h>
#include <drm/drm_modeset_helper_vtables.h>
#include <drm/drm_probe_helper.h>
+#include <drm/display/drm_hdmi_state_helper.h>
/**
* DOC: overview
@@ -86,6 +88,13 @@ struct drm_bridge_connector {
* connector modes detection, if any (see &DRM_BRIDGE_OP_MODES).
*/
struct drm_bridge *bridge_modes;
+ /**
+ * @bridge_hdmi:
+ *
+ * The bridge in the chain that implements necessary support for the
+ * HDMI connector infrastructure, if any (see &DRM_BRIDGE_OP_HDMI).
+ */
+ struct drm_bridge *bridge_hdmi;
};
#define to_drm_bridge_connector(x) \
@@ -193,19 +202,6 @@ drm_bridge_connector_detect(struct drm_connector *connector, bool force)
return status;
}
-static void drm_bridge_connector_destroy(struct drm_connector *connector)
-{
- struct drm_bridge_connector *bridge_connector =
- to_drm_bridge_connector(connector);
-
- drm_connector_unregister(connector);
- drm_connector_cleanup(connector);
-
- fwnode_handle_put(connector->fwnode);
-
- kfree(bridge_connector);
-}
-
static void drm_bridge_connector_debugfs_init(struct drm_connector *connector,
struct dentry *root)
{
@@ -224,7 +220,6 @@ static const struct drm_connector_funcs drm_bridge_connector_funcs = {
.reset = drm_atomic_helper_connector_reset,
.detect = drm_bridge_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
- .destroy = drm_bridge_connector_destroy,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
.debugfs_init = drm_bridge_connector_debugfs_init,
@@ -300,6 +295,60 @@ static const struct drm_connector_helper_funcs drm_bridge_connector_helper_funcs
.disable_hpd = drm_bridge_connector_disable_hpd,
};
+static enum drm_mode_status
+drm_bridge_connector_tmds_char_rate_valid(const struct drm_connector *connector,
+ const struct drm_display_mode *mode,
+ unsigned long long tmds_rate)
+{
+ struct drm_bridge_connector *bridge_connector =
+ to_drm_bridge_connector(connector);
+ struct drm_bridge *bridge;
+
+ bridge = bridge_connector->bridge_hdmi;
+ if (!bridge)
+ return MODE_ERROR;
+
+ if (bridge->funcs->hdmi_tmds_char_rate_valid)
+ return bridge->funcs->hdmi_tmds_char_rate_valid(bridge, mode, tmds_rate);
+ else
+ return MODE_OK;
+}
+
+static int drm_bridge_connector_clear_infoframe(struct drm_connector *connector,
+ enum hdmi_infoframe_type type)
+{
+ struct drm_bridge_connector *bridge_connector =
+ to_drm_bridge_connector(connector);
+ struct drm_bridge *bridge;
+
+ bridge = bridge_connector->bridge_hdmi;
+ if (!bridge)
+ return -EINVAL;
+
+ return bridge->funcs->hdmi_clear_infoframe(bridge, type);
+}
+
+static int drm_bridge_connector_write_infoframe(struct drm_connector *connector,
+ enum hdmi_infoframe_type type,
+ const u8 *buffer, size_t len)
+{
+ struct drm_bridge_connector *bridge_connector =
+ to_drm_bridge_connector(connector);
+ struct drm_bridge *bridge;
+
+ bridge = bridge_connector->bridge_hdmi;
+ if (!bridge)
+ return -EINVAL;
+
+ return bridge->funcs->hdmi_write_infoframe(bridge, type, buffer, len);
+}
+
+static const struct drm_connector_hdmi_funcs drm_bridge_connector_hdmi_funcs = {
+ .tmds_char_rate_valid = drm_bridge_connector_tmds_char_rate_valid,
+ .clear_infoframe = drm_bridge_connector_clear_infoframe,
+ .write_infoframe = drm_bridge_connector_write_infoframe,
+};
+
/* -----------------------------------------------------------------------------
* Bridge Connector Initialisation
*/
@@ -325,10 +374,12 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm,
struct drm_connector *connector;
struct i2c_adapter *ddc = NULL;
struct drm_bridge *bridge, *panel_bridge = NULL;
+ unsigned int supported_formats = BIT(HDMI_COLORSPACE_RGB);
+ unsigned int max_bpc = 8;
int connector_type;
int ret;
- bridge_connector = kzalloc(sizeof(*bridge_connector), GFP_KERNEL);
+ bridge_connector = drmm_kzalloc(drm, sizeof(*bridge_connector), GFP_KERNEL);
if (!bridge_connector)
return ERR_PTR(-ENOMEM);
@@ -361,6 +412,20 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm,
bridge_connector->bridge_detect = bridge;
if (bridge->ops & DRM_BRIDGE_OP_MODES)
bridge_connector->bridge_modes = bridge;
+ if (bridge->ops & DRM_BRIDGE_OP_HDMI) {
+ if (bridge_connector->bridge_hdmi)
+ return ERR_PTR(-EBUSY);
+ if (!bridge->funcs->hdmi_write_infoframe ||
+ !bridge->funcs->hdmi_clear_infoframe)
+ return ERR_PTR(-EINVAL);
+
+ bridge_connector->bridge_hdmi = bridge;
+
+ if (bridge->supported_formats)
+ supported_formats = bridge->supported_formats;
+ if (bridge->max_bpc)
+ max_bpc = bridge->max_bpc;
+ }
if (!drm_bridge_get_next_bridge(bridge))
connector_type = bridge->type;
@@ -383,7 +448,17 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm,
return ERR_PTR(-EINVAL);
}
- ret = drm_connector_init_with_ddc(drm, connector,
+ if (bridge_connector->bridge_hdmi)
+ ret = drmm_connector_hdmi_init(drm, connector,
+ bridge_connector->bridge_hdmi->vendor,
+ bridge_connector->bridge_hdmi->product,
+ &drm_bridge_connector_funcs,
+ &drm_bridge_connector_hdmi_funcs,
+ connector_type, ddc,
+ supported_formats,
+ max_bpc);
+ else
+ ret = drmm_connector_init(drm, connector,
&drm_bridge_connector_funcs,
connector_type, ddc);
if (ret) {
diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c
index d021497841b8..3969dc548cff 100644
--- a/drivers/gpu/drm/drm_color_mgmt.c
+++ b/drivers/gpu/drm/drm_color_mgmt.c
@@ -532,7 +532,7 @@ int drm_plane_create_color_properties(struct drm_plane *plane,
{
struct drm_device *dev = plane->dev;
struct drm_property *prop;
- struct drm_prop_enum_list enum_list[max_t(int, DRM_COLOR_ENCODING_MAX,
+ struct drm_prop_enum_list enum_list[MAX_T(int, DRM_COLOR_ENCODING_MAX,
DRM_COLOR_RANGE_MAX)];
int i, len;
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 4d2df7f64dc5..ab6ab7ff7ea8 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -278,6 +278,7 @@ static int __drm_connector_init(struct drm_device *dev,
INIT_LIST_HEAD(&connector->modes);
mutex_init(&connector->mutex);
mutex_init(&connector->edid_override_mutex);
+ mutex_init(&connector->hdmi.infoframes.lock);
connector->edid_blob_ptr = NULL;
connector->epoch_counter = 0;
connector->tile_blob_ptr = NULL;
@@ -453,6 +454,86 @@ int drmm_connector_init(struct drm_device *dev,
EXPORT_SYMBOL(drmm_connector_init);
/**
+ * drmm_connector_hdmi_init - Init a preallocated HDMI connector
+ * @dev: DRM device
+ * @connector: A pointer to the HDMI connector to init
+ * @vendor: HDMI Controller Vendor name
+ * @product: HDMI Controller Product name
+ * @funcs: callbacks for this connector
+ * @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
+ * @max_bpc: Maximum bits per char the HDMI connector supports
+ *
+ * Initialises a preallocated HDMI connector. Connectors can be
+ * subclassed as part of driver connector objects.
+ *
+ * Cleanup is automatically handled with a call to
+ * drm_connector_cleanup() in a DRM-managed action.
+ *
+ * The connector structure should be allocated with drmm_kzalloc().
+ *
+ * Returns:
+ * Zero on success, error code on failure.
+ */
+int drmm_connector_hdmi_init(struct drm_device *dev,
+ struct drm_connector *connector,
+ const char *vendor, const char *product,
+ const struct drm_connector_funcs *funcs,
+ const struct drm_connector_hdmi_funcs *hdmi_funcs,
+ int connector_type,
+ struct i2c_adapter *ddc,
+ unsigned long supported_formats,
+ unsigned int max_bpc)
+{
+ int ret;
+
+ if (!vendor || !product)
+ return -EINVAL;
+
+ if ((strlen(vendor) > DRM_CONNECTOR_HDMI_VENDOR_LEN) ||
+ (strlen(product) > DRM_CONNECTOR_HDMI_PRODUCT_LEN))
+ return -EINVAL;
+
+ if (!(connector_type == DRM_MODE_CONNECTOR_HDMIA ||
+ connector_type == DRM_MODE_CONNECTOR_HDMIB))
+ return -EINVAL;
+
+ if (!supported_formats || !(supported_formats & BIT(HDMI_COLORSPACE_RGB)))
+ return -EINVAL;
+
+ if (!(max_bpc == 8 || max_bpc == 10 || max_bpc == 12))
+ return -EINVAL;
+
+ ret = drmm_connector_init(dev, connector, funcs, connector_type, ddc);
+ if (ret)
+ return ret;
+
+ connector->hdmi.supported_formats = supported_formats;
+ strtomem_pad(connector->hdmi.vendor, vendor, 0);
+ strtomem_pad(connector->hdmi.product, product, 0);
+
+ /*
+ * drm_connector_attach_max_bpc_property() requires the
+ * connector to have a state.
+ */
+ if (connector->funcs->reset)
+ connector->funcs->reset(connector);
+
+ drm_connector_attach_max_bpc_property(connector, 8, max_bpc);
+ connector->max_bpc = max_bpc;
+
+ if (max_bpc > 8)
+ drm_connector_attach_hdr_output_metadata_property(connector);
+
+ connector->hdmi.funcs = hdmi_funcs;
+
+ return 0;
+}
+EXPORT_SYMBOL(drmm_connector_hdmi_init);
+
+/**
* drm_connector_attach_edid_property - attach edid property.
* @connector: the connector
*
@@ -584,6 +665,7 @@ void drm_connector_cleanup(struct drm_connector *connector)
connector->funcs->atomic_destroy_state(connector,
connector->state);
+ mutex_destroy(&connector->hdmi.infoframes.lock);
mutex_destroy(&connector->mutex);
memset(connector, 0, sizeof(*connector));
@@ -1005,6 +1087,7 @@ static const struct drm_prop_enum_list drm_tv_mode_enum_list[] = {
{ DRM_MODE_TV_MODE_PAL_M, "PAL-M" },
{ DRM_MODE_TV_MODE_PAL_N, "PAL-N" },
{ DRM_MODE_TV_MODE_SECAM, "SECAM" },
+ { DRM_MODE_TV_MODE_MONOCHROME, "Mono" },
};
DRM_ENUM_NAME_FN(drm_get_tv_mode_name, drm_tv_mode_enum_list)
@@ -1144,6 +1227,53 @@ static const u32 dp_colorspaces =
BIT(DRM_MODE_COLORIMETRY_BT2020_CYCC) |
BIT(DRM_MODE_COLORIMETRY_BT2020_YCC);
+static const struct drm_prop_enum_list broadcast_rgb_names[] = {
+ { DRM_HDMI_BROADCAST_RGB_AUTO, "Automatic" },
+ { DRM_HDMI_BROADCAST_RGB_FULL, "Full" },
+ { DRM_HDMI_BROADCAST_RGB_LIMITED, "Limited 16:235" },
+};
+
+/*
+ * drm_hdmi_connector_get_broadcast_rgb_name - Return a string for HDMI connector RGB broadcast selection
+ * @broadcast_rgb: Broadcast RGB selection to compute name of
+ *
+ * Returns: the name of the Broadcast RGB selection, or NULL if the type
+ * is not valid.
+ */
+const char *
+drm_hdmi_connector_get_broadcast_rgb_name(enum drm_hdmi_broadcast_rgb broadcast_rgb)
+{
+ if (broadcast_rgb >= ARRAY_SIZE(broadcast_rgb_names))
+ return NULL;
+
+ return broadcast_rgb_names[broadcast_rgb].name;
+}
+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_hdmi_connector_get_output_format_name() - Return a string for HDMI connector output format
+ * @fmt: Output format to compute name of
+ *
+ * Returns: the name of the output format, or NULL if the type is not
+ * valid.
+ */
+const char *
+drm_hdmi_connector_get_output_format_name(enum hdmi_colorspace fmt)
+{
+ if (fmt >= ARRAY_SIZE(output_format_str))
+ return NULL;
+
+ return output_format_str[fmt];
+}
+EXPORT_SYMBOL(drm_hdmi_connector_get_output_format_name);
+
/**
* DOC: standard connector properties
*
@@ -1616,6 +1746,38 @@ EXPORT_SYMBOL(drm_connector_attach_dp_subconnector_property);
/**
* DOC: HDMI connector properties
*
+ * Broadcast RGB (HDMI specific)
+ * Indicates the Quantization Range (Full vs Limited) used. The color
+ * processing pipeline will be adjusted to match the value of the
+ * property, and the Infoframes will be generated and sent accordingly.
+ *
+ * This property is only relevant if the HDMI output format is RGB. If
+ * it's one of the YCbCr variant, it will be ignored.
+ *
+ * The CRTC attached to the connector must be configured by user-space to
+ * always produce full-range pixels.
+ *
+ * The value of this property can be one of the following:
+ *
+ * Automatic:
+ * The quantization range is selected automatically based on the
+ * mode according to the HDMI specifications (HDMI 1.4b - Section
+ * 6.6 - Video Quantization Ranges).
+ *
+ * Full:
+ * Full quantization range is forced.
+ *
+ * Limited 16:235:
+ * Limited quantization range is forced. Unlike the name suggests,
+ * this works for any number of bits-per-component.
+ *
+ * Property values other than Automatic can result in colors being off (if
+ * limited is selected but the display expects full), or a black screen
+ * (if full is selected but the display expects limited).
+ *
+ * Drivers can set up this property by calling
+ * drm_connector_attach_broadcast_rgb_property().
+ *
* content type (HDMI specific):
* Indicates content type setting to be used in HDMI infoframes to indicate
* content type for the external device, so that it adjusts its display
@@ -1697,6 +1859,12 @@ EXPORT_SYMBOL(drm_connector_attach_dp_subconnector_property);
* TV Mode is CCIR System B (aka 625-lines) together with
* the SECAM Color Encoding.
*
+ * Mono:
+ *
+ * Use timings appropriate to the DRM mode, including
+ * equalizing pulses for a 525-line or 625-line mode,
+ * with no pedestal or color encoding.
+ *
* Drivers can set up this property by calling
* drm_mode_create_tv_properties().
*/
@@ -2479,6 +2647,39 @@ int drm_connector_attach_hdr_output_metadata_property(struct drm_connector *conn
EXPORT_SYMBOL(drm_connector_attach_hdr_output_metadata_property);
/**
+ * drm_connector_attach_broadcast_rgb_property - attach "Broadcast RGB" property
+ * @connector: connector to attach the property on.
+ *
+ * This is used to add support for forcing the RGB range on a connector
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_connector_attach_broadcast_rgb_property(struct drm_connector *connector)
+{
+ struct drm_device *dev = connector->dev;
+ struct drm_property *prop;
+
+ prop = connector->broadcast_rgb_property;
+ if (!prop) {
+ prop = drm_property_create_enum(dev, DRM_MODE_PROP_ENUM,
+ "Broadcast RGB",
+ broadcast_rgb_names,
+ ARRAY_SIZE(broadcast_rgb_names));
+ if (!prop)
+ return -EINVAL;
+
+ connector->broadcast_rgb_property = prop;
+ }
+
+ drm_object_attach_property(&connector->base, prop,
+ DRM_HDMI_BROADCAST_RGB_AUTO);
+
+ return 0;
+}
+EXPORT_SYMBOL(drm_connector_attach_broadcast_rgb_property);
+
+/**
* drm_connector_attach_colorspace_property - attach "Colorspace" property
* @connector: connector to attach the property on.
*
diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h
index e207759ca045..1f73b8d6d750 100644
--- a/drivers/gpu/drm/drm_crtc_internal.h
+++ b/drivers/gpu/drm/drm_crtc_internal.h
@@ -301,6 +301,8 @@ const u8 *drm_edid_find_extension(const struct drm_edid *drm_edid,
int ext_id, int *ext_index);
void drm_edid_cta_sad_get(const struct cea_sad *cta_sad, u8 *sad);
void drm_edid_cta_sad_set(struct cea_sad *cta_sad, const u8 *sad);
+ssize_t drm_edid_connector_property_show(struct drm_connector *connector,
+ char *buf, loff_t off, size_t count);
/* drm_edid_load.c */
#ifdef CONFIG_DRM_LOAD_EDID_FIRMWARE
diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c
index 08fcefd804bc..6b239a24f1df 100644
--- a/drivers/gpu/drm/drm_debugfs.c
+++ b/drivers/gpu/drm/drm_debugfs.c
@@ -520,6 +520,156 @@ static const struct file_operations drm_connector_fops = {
.write = connector_write
};
+#define HDMI_MAX_INFOFRAME_SIZE 29
+
+static ssize_t
+audio_infoframe_read(struct file *filp, char __user *ubuf, size_t count, loff_t *ppos)
+{
+ struct drm_connector_hdmi_infoframe *infoframe;
+ struct drm_connector *connector;
+ union hdmi_infoframe *frame;
+ u8 buf[HDMI_INFOFRAME_SIZE(AUDIO)];
+ ssize_t len = 0;
+
+ connector = filp->private_data;
+ mutex_lock(&connector->hdmi.infoframes.lock);
+
+ infoframe = &connector->hdmi.infoframes.audio;
+ if (!infoframe->set)
+ goto out;
+
+ frame = &infoframe->data;
+ len = hdmi_infoframe_pack(frame, buf, sizeof(buf));
+ if (len < 0)
+ goto out;
+
+ len = simple_read_from_buffer(ubuf, count, ppos, buf, len);
+
+out:
+ mutex_unlock(&connector->hdmi.infoframes.lock);
+ return len;
+}
+
+static const struct file_operations audio_infoframe_fops = {
+ .owner = THIS_MODULE,
+ .open = simple_open,
+ .read = audio_infoframe_read,
+};
+
+static int create_hdmi_audio_infoframe_file(struct drm_connector *connector,
+ struct dentry *parent)
+{
+ struct dentry *file;
+
+ file = debugfs_create_file("audio", 0400, parent, connector, &audio_infoframe_fops);
+ if (IS_ERR(file))
+ return PTR_ERR(file);
+
+ return 0;
+}
+
+#define DEFINE_INFOFRAME_FILE(_f) \
+static ssize_t _f##_read_infoframe(struct file *filp, \
+ char __user *ubuf, \
+ size_t count, \
+ loff_t *ppos) \
+{ \
+ struct drm_connector_hdmi_infoframe *infoframe; \
+ struct drm_connector_state *conn_state; \
+ struct drm_connector *connector; \
+ union hdmi_infoframe *frame; \
+ struct drm_device *dev; \
+ u8 buf[HDMI_MAX_INFOFRAME_SIZE]; \
+ ssize_t len = 0; \
+ \
+ connector = filp->private_data; \
+ dev = connector->dev; \
+ \
+ drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); \
+ \
+ conn_state = connector->state; \
+ infoframe = &conn_state->hdmi.infoframes._f; \
+ if (!infoframe->set) \
+ goto out; \
+ \
+ frame = &infoframe->data; \
+ len = hdmi_infoframe_pack(frame, buf, sizeof(buf)); \
+ if (len < 0) \
+ goto out; \
+ \
+ len = simple_read_from_buffer(ubuf, count, ppos, buf, len); \
+ \
+out: \
+ drm_modeset_unlock(&dev->mode_config.connection_mutex); \
+ return len; \
+} \
+\
+static const struct file_operations _f##_infoframe_fops = { \
+ .owner = THIS_MODULE, \
+ .open = simple_open, \
+ .read = _f##_read_infoframe, \
+}; \
+\
+static int create_hdmi_## _f ## _infoframe_file(struct drm_connector *connector, \
+ struct dentry *parent) \
+{ \
+ struct dentry *file; \
+ \
+ file = debugfs_create_file(#_f, 0400, parent, connector, &_f ## _infoframe_fops); \
+ if (IS_ERR(file)) \
+ return PTR_ERR(file); \
+ \
+ return 0; \
+}
+
+DEFINE_INFOFRAME_FILE(avi);
+DEFINE_INFOFRAME_FILE(hdmi);
+DEFINE_INFOFRAME_FILE(hdr_drm);
+DEFINE_INFOFRAME_FILE(spd);
+
+static int create_hdmi_infoframe_files(struct drm_connector *connector,
+ struct dentry *parent)
+{
+ int ret;
+
+ ret = create_hdmi_audio_infoframe_file(connector, parent);
+ if (ret)
+ return ret;
+
+ ret = create_hdmi_avi_infoframe_file(connector, parent);
+ if (ret)
+ return ret;
+
+ ret = create_hdmi_hdmi_infoframe_file(connector, parent);
+ if (ret)
+ return ret;
+
+ ret = create_hdmi_hdr_drm_infoframe_file(connector, parent);
+ if (ret)
+ return ret;
+
+ ret = create_hdmi_spd_infoframe_file(connector, parent);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static void hdmi_debugfs_add(struct drm_connector *connector)
+{
+ struct dentry *dir;
+
+ if (!(connector->connector_type == DRM_MODE_CONNECTOR_HDMIA ||
+ connector->connector_type == DRM_MODE_CONNECTOR_HDMIB))
+ return;
+
+ dir = debugfs_create_dir("infoframes", connector->debugfs_entry);
+ if (IS_ERR(dir))
+ return;
+
+ create_hdmi_infoframe_files(connector, dir);
+}
+
void drm_debugfs_connector_add(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
@@ -547,6 +697,8 @@ void drm_debugfs_connector_add(struct drm_connector *connector)
debugfs_create_file("output_bpc", 0444, root, connector,
&output_bpc_fops);
+ hdmi_debugfs_add(connector);
+
if (connector->funcs->debugfs_init)
connector->funcs->debugfs_init(connector, root);
}
@@ -597,10 +749,10 @@ static int bridges_show(struct seq_file *m, void *data)
drm_printf(&p, "\ttype: [%d] %s\n",
bridge->type,
drm_get_connector_type_name(bridge->type));
-#ifdef CONFIG_OF
+
if (bridge->of_node)
drm_printf(&p, "\tOF: %pOFfc\n", bridge->of_node);
-#endif
+
drm_printf(&p, "\tops: [0x%x]", bridge->ops);
if (bridge->ops & DRM_BRIDGE_OP_DETECT)
drm_puts(&p, " detect");
@@ -610,6 +762,8 @@ static int bridges_show(struct seq_file *m, void *data)
drm_puts(&p, " hpd");
if (bridge->ops & DRM_BRIDGE_OP_MODES)
drm_puts(&p, " modes");
+ if (bridge->ops & DRM_BRIDGE_OP_HDMI)
+ drm_puts(&p, " hdmi");
drm_puts(&p, "\n");
}
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 535b624d4c9d..93543071a500 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -346,7 +346,7 @@ void drm_minor_release(struct drm_minor *minor)
* if (ret)
* return ret;
*
- * drm_fbdev_generic_setup(drm, 32);
+ * drm_fbdev_{...}_setup(drm, 32);
*
* return 0;
* }
@@ -947,9 +947,9 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags)
}
drm_panic_register(dev);
- DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n",
+ DRM_INFO("Initialized %s %d.%d.%d for %s on minor %d\n",
driver->name, driver->major, driver->minor,
- driver->patchlevel, driver->date,
+ driver->patchlevel,
dev->dev ? dev_name(dev->dev) : "virtual device",
dev->primary ? dev->primary->index : dev->accel->index);
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 4f54c91b31b2..f68a41eeb1fa 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -2465,34 +2465,6 @@ fail:
}
/**
- * drm_do_get_edid - get EDID data using a custom EDID block read function
- * @connector: connector we're probing
- * @read_block: EDID block read function
- * @context: private data passed to the block read function
- *
- * When the I2C adapter connected to the DDC bus is hidden behind a device that
- * exposes a different interface to read EDID blocks this function can be used
- * to get EDID data using a custom block read function.
- *
- * As in the general case the DDC bus is accessible by the kernel at the I2C
- * level, drivers must make all reasonable efforts to expose it as an I2C
- * adapter and use drm_get_edid() instead of abusing this function.
- *
- * The EDID may be overridden using debugfs override_edid or firmware EDID
- * (drm_edid_load_firmware() and drm.edid_firmware parameter), in this priority
- * order. Having either of them bypasses actual EDID reads.
- *
- * Return: Pointer to valid EDID or NULL if we couldn't find any.
- */
-struct edid *drm_do_get_edid(struct drm_connector *connector,
- read_block_fn read_block,
- void *context)
-{
- return _drm_do_get_edid(connector, read_block, context, NULL);
-}
-EXPORT_SYMBOL_GPL(drm_do_get_edid);
-
-/**
* drm_edid_raw - Get a pointer to the raw EDID data.
* @drm_edid: drm_edid container
*
@@ -6969,6 +6941,39 @@ out:
return ret;
}
+/* For sysfs edid show implementation */
+ssize_t drm_edid_connector_property_show(struct drm_connector *connector,
+ char *buf, loff_t off, size_t count)
+{
+ const void *edid;
+ size_t size;
+ ssize_t ret = 0;
+
+ mutex_lock(&connector->dev->mode_config.mutex);
+
+ if (!connector->edid_blob_ptr)
+ goto unlock;
+
+ edid = connector->edid_blob_ptr->data;
+ size = connector->edid_blob_ptr->length;
+ if (!edid)
+ goto unlock;
+
+ if (off >= size)
+ goto unlock;
+
+ if (off + count > size)
+ count = size - off;
+
+ memcpy(buf, edid + off, count);
+
+ ret = count;
+unlock:
+ mutex_unlock(&connector->dev->mode_config.mutex);
+
+ return ret;
+}
+
/**
* drm_edid_connector_update - Update connector information from EDID
* @connector: Connector
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index d612133e2cf7..18565ec68451 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -85,12 +85,8 @@ static DEFINE_MUTEX(kernel_fb_helper_lock);
* The fb helper functions are useful to provide an fbdev on top of a drm kernel
* mode setting driver. They can be used mostly independently from the crtc
* helper functions used by many drivers to implement the kernel mode setting
- * interfaces.
- *
- * Drivers that support a dumb buffer with a virtual address and mmap support,
- * should try out the generic fbdev emulation using drm_fbdev_generic_setup().
- * It will automatically set up deferred I/O if the driver requires a shadow
- * buffer.
+ * interfaces. Drivers that use one of the shared memory managers, TTM, SHMEM,
+ * DMA, should instead use the corresponding fbdev emulation.
*
* Existing fbdev implementations should restore the fbdev console by using
* drm_fb_helper_lastclose() as their &drm_driver.lastclose callback.
@@ -126,9 +122,6 @@ static DEFINE_MUTEX(kernel_fb_helper_lock);
* atomic context. If drm_fb_helper_deferred_io() is used as the deferred_io
* callback it will also schedule dirty_work with the damage collected from the
* mmap page writes.
- *
- * Deferred I/O is not compatible with SHMEM. Such drivers should request an
- * fbdev shadow buffer and call drm_fbdev_generic_setup() instead.
*/
static void drm_fb_helper_restore_lut_atomic(struct drm_crtc *crtc)
@@ -524,6 +517,9 @@ struct fb_info *drm_fb_helper_alloc_info(struct drm_fb_helper *fb_helper)
if (!info)
return ERR_PTR(-ENOMEM);
+ if (!drm_leak_fbdev_smem)
+ info->flags |= FBINFO_HIDE_SMEM_START;
+
ret = fb_alloc_cmap(&info->cmap, 256, 0);
if (ret)
goto err_release;
@@ -1860,9 +1856,6 @@ __drm_fb_helper_initial_config_and_unlock(struct drm_fb_helper *fb_helper)
info = fb_helper->info;
info->var.pixclock = 0;
- if (!drm_leak_fbdev_smem)
- info->flags |= FBINFO_HIDE_SMEM_START;
-
/* Need to drop locks to avoid recursive deadlock in
* register_framebuffer. This is ok because the only thing left to do is
* register the fbdev emulation instance in kernel_fb_helper_list. */
diff --git a/drivers/gpu/drm/drm_fbdev_dma.c b/drivers/gpu/drm/drm_fbdev_dma.c
index 6c9427bb4053..7ef5a48c8029 100644
--- a/drivers/gpu/drm/drm_fbdev_dma.c
+++ b/drivers/gpu/drm/drm_fbdev_dma.c
@@ -4,6 +4,7 @@
#include <drm/drm_crtc_helper.h>
#include <drm/drm_drv.h>
+#include <drm/drm_fb_dma_helper.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_dma_helper.h>
@@ -35,6 +36,22 @@ static int drm_fbdev_dma_fb_release(struct fb_info *info, int user)
return 0;
}
+FB_GEN_DEFAULT_DEFERRED_DMAMEM_OPS(drm_fbdev_dma,
+ drm_fb_helper_damage_range,
+ drm_fb_helper_damage_area);
+
+static int drm_fbdev_dma_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+ struct drm_fb_helper *fb_helper = info->par;
+ struct drm_framebuffer *fb = fb_helper->fb;
+ struct drm_gem_dma_object *dma = drm_fb_dma_get_gem_obj(fb, 0);
+
+ if (!dma->map_noncoherent)
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+
+ return fb_deferred_io_mmap(info, vma);
+}
+
static void drm_fbdev_dma_fb_destroy(struct fb_info *info)
{
struct drm_fb_helper *fb_helper = info->par;
@@ -42,6 +59,7 @@ static void drm_fbdev_dma_fb_destroy(struct fb_info *info)
if (!fb_helper->dev)
return;
+ fb_deferred_io_cleanup(info);
drm_fb_helper_fini(fb_helper);
drm_client_buffer_vunmap(fb_helper->buffer);
@@ -51,20 +69,13 @@ static void drm_fbdev_dma_fb_destroy(struct fb_info *info)
kfree(fb_helper);
}
-static int drm_fbdev_dma_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
-{
- struct drm_fb_helper *fb_helper = info->par;
-
- return drm_gem_prime_mmap(fb_helper->buffer->gem, vma);
-}
-
static const struct fb_ops drm_fbdev_dma_fb_ops = {
.owner = THIS_MODULE,
.fb_open = drm_fbdev_dma_fb_open,
.fb_release = drm_fbdev_dma_fb_release,
- __FB_DEFAULT_DMAMEM_OPS_RDWR,
+ __FB_DEFAULT_DEFERRED_OPS_RDWR(drm_fbdev_dma),
DRM_FB_HELPER_DEFAULT_OPS,
- __FB_DEFAULT_DMAMEM_OPS_DRAW,
+ __FB_DEFAULT_DEFERRED_OPS_DRAW(drm_fbdev_dma),
.fb_mmap = drm_fbdev_dma_fb_mmap,
.fb_destroy = drm_fbdev_dma_fb_destroy,
};
@@ -90,7 +101,8 @@ static int drm_fbdev_dma_helper_fb_probe(struct drm_fb_helper *fb_helper,
sizes->surface_width, sizes->surface_height,
sizes->surface_bpp);
- format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth);
+ format = drm_driver_legacy_fb_format(dev, sizes->surface_bpp,
+ sizes->surface_depth);
buffer = drm_client_framebuffer_create(client, sizes->surface_width,
sizes->surface_height, format);
if (IS_ERR(buffer))
@@ -98,10 +110,6 @@ static int drm_fbdev_dma_helper_fb_probe(struct drm_fb_helper *fb_helper,
dma_obj = to_drm_gem_dma_obj(buffer->gem);
fb = buffer->fb;
- if (drm_WARN_ON(dev, fb->funcs->dirty)) {
- ret = -ENODEV; /* damage handling not supported; use generic emulation */
- goto err_drm_client_buffer_delete;
- }
ret = drm_client_buffer_vmap(buffer, &map);
if (ret) {
@@ -112,7 +120,7 @@ static int drm_fbdev_dma_helper_fb_probe(struct drm_fb_helper *fb_helper,
}
fb_helper->buffer = buffer;
- fb_helper->fb = buffer->fb;
+ fb_helper->fb = fb;
info = drm_fb_helper_alloc_info(fb_helper);
if (IS_ERR(info)) {
@@ -130,11 +138,25 @@ static int drm_fbdev_dma_helper_fb_probe(struct drm_fb_helper *fb_helper,
info->flags |= FBINFO_READS_FAST; /* signal caching */
info->screen_size = sizes->surface_height * fb->pitches[0];
info->screen_buffer = map.vaddr;
- info->fix.smem_start = page_to_phys(virt_to_page(info->screen_buffer));
+ if (!(info->flags & FBINFO_HIDE_SMEM_START)) {
+ if (!drm_WARN_ON(dev, is_vmalloc_addr(info->screen_buffer)))
+ info->fix.smem_start = page_to_phys(virt_to_page(info->screen_buffer));
+ }
info->fix.smem_len = info->screen_size;
+ /* deferred I/O */
+ fb_helper->fbdefio.delay = HZ / 20;
+ fb_helper->fbdefio.deferred_io = drm_fb_helper_deferred_io;
+
+ info->fbdefio = &fb_helper->fbdefio;
+ ret = fb_deferred_io_init(info);
+ if (ret)
+ goto err_drm_fb_helper_release_info;
+
return 0;
+err_drm_fb_helper_release_info:
+ drm_fb_helper_release_info(fb_helper);
err_drm_client_buffer_vunmap:
fb_helper->fb = NULL;
fb_helper->buffer = NULL;
@@ -144,8 +166,28 @@ err_drm_client_buffer_delete:
return ret;
}
+static int drm_fbdev_dma_helper_fb_dirty(struct drm_fb_helper *helper,
+ struct drm_clip_rect *clip)
+{
+ struct drm_device *dev = helper->dev;
+ int ret;
+
+ /* Call damage handlers only if necessary */
+ if (!(clip->x1 < clip->x2 && clip->y1 < clip->y2))
+ return 0;
+
+ if (helper->fb->funcs->dirty) {
+ ret = helper->fb->funcs->dirty(helper->fb, NULL, 0, 0, clip, 1);
+ if (drm_WARN_ONCE(dev, ret, "Dirty helper failed: ret=%d\n", ret))
+ return ret;
+ }
+
+ return 0;
+}
+
static const struct drm_fb_helper_funcs drm_fbdev_dma_helper_funcs = {
.fb_probe = drm_fbdev_dma_helper_fb_probe,
+ .fb_dirty = drm_fbdev_dma_helper_fb_dirty,
};
/*
diff --git a/drivers/gpu/drm/drm_fbdev_shmem.c b/drivers/gpu/drm/drm_fbdev_shmem.c
new file mode 100644
index 000000000000..0c785007f11b
--- /dev/null
+++ b/drivers/gpu/drm/drm_fbdev_shmem.c
@@ -0,0 +1,317 @@
+// SPDX-License-Identifier: MIT
+
+#include <linux/fb.h>
+
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_framebuffer.h>
+#include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_gem_shmem_helper.h>
+
+#include <drm/drm_fbdev_shmem.h>
+
+/*
+ * struct fb_ops
+ */
+
+static int drm_fbdev_shmem_fb_open(struct fb_info *info, int user)
+{
+ struct drm_fb_helper *fb_helper = info->par;
+
+ /* No need to take a ref for fbcon because it unbinds on unregister */
+ if (user && !try_module_get(fb_helper->dev->driver->fops->owner))
+ return -ENODEV;
+
+ return 0;
+}
+
+static int drm_fbdev_shmem_fb_release(struct fb_info *info, int user)
+{
+ struct drm_fb_helper *fb_helper = info->par;
+
+ if (user)
+ module_put(fb_helper->dev->driver->fops->owner);
+
+ return 0;
+}
+
+FB_GEN_DEFAULT_DEFERRED_SYSMEM_OPS(drm_fbdev_shmem,
+ drm_fb_helper_damage_range,
+ drm_fb_helper_damage_area);
+
+static int drm_fbdev_shmem_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+ struct drm_fb_helper *fb_helper = info->par;
+ struct drm_framebuffer *fb = fb_helper->fb;
+ struct drm_gem_object *obj = drm_gem_fb_get_obj(fb, 0);
+ struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
+
+ if (shmem->map_wc)
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+
+ return fb_deferred_io_mmap(info, vma);
+}
+
+static void drm_fbdev_shmem_fb_destroy(struct fb_info *info)
+{
+ struct drm_fb_helper *fb_helper = info->par;
+
+ if (!fb_helper->dev)
+ return;
+
+ fb_deferred_io_cleanup(info);
+ drm_fb_helper_fini(fb_helper);
+
+ drm_client_buffer_vunmap(fb_helper->buffer);
+ drm_client_framebuffer_delete(fb_helper->buffer);
+ drm_client_release(&fb_helper->client);
+ drm_fb_helper_unprepare(fb_helper);
+ kfree(fb_helper);
+}
+
+static const struct fb_ops drm_fbdev_shmem_fb_ops = {
+ .owner = THIS_MODULE,
+ .fb_open = drm_fbdev_shmem_fb_open,
+ .fb_release = drm_fbdev_shmem_fb_release,
+ __FB_DEFAULT_DEFERRED_OPS_RDWR(drm_fbdev_shmem),
+ DRM_FB_HELPER_DEFAULT_OPS,
+ __FB_DEFAULT_DEFERRED_OPS_DRAW(drm_fbdev_shmem),
+ .fb_mmap = drm_fbdev_shmem_fb_mmap,
+ .fb_destroy = drm_fbdev_shmem_fb_destroy,
+};
+
+static struct page *drm_fbdev_shmem_get_page(struct fb_info *info, unsigned long offset)
+{
+ struct drm_fb_helper *fb_helper = info->par;
+ struct drm_framebuffer *fb = fb_helper->fb;
+ struct drm_gem_object *obj = drm_gem_fb_get_obj(fb, 0);
+ struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
+ unsigned int i = offset >> PAGE_SHIFT;
+ struct page *page;
+
+ if (fb_WARN_ON_ONCE(info, offset > obj->size))
+ return NULL;
+
+ page = shmem->pages[i]; // protected by active vmap
+ if (page)
+ get_page(page);
+ fb_WARN_ON_ONCE(info, !page);
+
+ return page;
+}
+
+/*
+ * struct drm_fb_helper
+ */
+
+static int drm_fbdev_shmem_helper_fb_probe(struct drm_fb_helper *fb_helper,
+ struct drm_fb_helper_surface_size *sizes)
+{
+ struct drm_client_dev *client = &fb_helper->client;
+ struct drm_device *dev = fb_helper->dev;
+ struct drm_client_buffer *buffer;
+ struct drm_gem_shmem_object *shmem;
+ struct drm_framebuffer *fb;
+ struct fb_info *info;
+ u32 format;
+ struct iosys_map map;
+ int ret;
+
+ drm_dbg_kms(dev, "surface width(%d), height(%d) and bpp(%d)\n",
+ sizes->surface_width, sizes->surface_height,
+ sizes->surface_bpp);
+
+ format = drm_driver_legacy_fb_format(dev, sizes->surface_bpp, sizes->surface_depth);
+ buffer = drm_client_framebuffer_create(client, sizes->surface_width,
+ sizes->surface_height, format);
+ if (IS_ERR(buffer))
+ return PTR_ERR(buffer);
+ shmem = to_drm_gem_shmem_obj(buffer->gem);
+
+ fb = buffer->fb;
+
+ ret = drm_client_buffer_vmap(buffer, &map);
+ if (ret) {
+ goto err_drm_client_buffer_delete;
+ } else if (drm_WARN_ON(dev, map.is_iomem)) {
+ ret = -ENODEV; /* I/O memory not supported; use generic emulation */
+ goto err_drm_client_buffer_delete;
+ }
+
+ fb_helper->buffer = buffer;
+ fb_helper->fb = fb;
+
+ info = drm_fb_helper_alloc_info(fb_helper);
+ if (IS_ERR(info)) {
+ ret = PTR_ERR(info);
+ goto err_drm_client_buffer_vunmap;
+ }
+
+ drm_fb_helper_fill_info(info, fb_helper, sizes);
+
+ info->fbops = &drm_fbdev_shmem_fb_ops;
+
+ /* screen */
+ info->flags |= FBINFO_VIRTFB; /* system memory */
+ if (!shmem->map_wc)
+ info->flags |= FBINFO_READS_FAST; /* signal caching */
+ info->screen_size = sizes->surface_height * fb->pitches[0];
+ info->screen_buffer = map.vaddr;
+ info->fix.smem_len = info->screen_size;
+
+ /* deferred I/O */
+ fb_helper->fbdefio.delay = HZ / 20;
+ fb_helper->fbdefio.get_page = drm_fbdev_shmem_get_page;
+ fb_helper->fbdefio.deferred_io = drm_fb_helper_deferred_io;
+
+ info->fbdefio = &fb_helper->fbdefio;
+ ret = fb_deferred_io_init(info);
+ if (ret)
+ goto err_drm_fb_helper_release_info;
+
+ return 0;
+
+err_drm_fb_helper_release_info:
+ drm_fb_helper_release_info(fb_helper);
+err_drm_client_buffer_vunmap:
+ fb_helper->fb = NULL;
+ fb_helper->buffer = NULL;
+ drm_client_buffer_vunmap(buffer);
+err_drm_client_buffer_delete:
+ drm_client_framebuffer_delete(buffer);
+ return ret;
+}
+
+static int drm_fbdev_shmem_helper_fb_dirty(struct drm_fb_helper *helper,
+ struct drm_clip_rect *clip)
+{
+ struct drm_device *dev = helper->dev;
+ int ret;
+
+ /* Call damage handlers only if necessary */
+ if (!(clip->x1 < clip->x2 && clip->y1 < clip->y2))
+ return 0;
+
+ if (helper->fb->funcs->dirty) {
+ ret = helper->fb->funcs->dirty(helper->fb, NULL, 0, 0, clip, 1);
+ if (drm_WARN_ONCE(dev, ret, "Dirty helper failed: ret=%d\n", ret))
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct drm_fb_helper_funcs drm_fbdev_shmem_helper_funcs = {
+ .fb_probe = drm_fbdev_shmem_helper_fb_probe,
+ .fb_dirty = drm_fbdev_shmem_helper_fb_dirty,
+};
+
+/*
+ * struct drm_client_funcs
+ */
+
+static void drm_fbdev_shmem_client_unregister(struct drm_client_dev *client)
+{
+ struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client);
+
+ if (fb_helper->info) {
+ drm_fb_helper_unregister_info(fb_helper);
+ } else {
+ drm_client_release(&fb_helper->client);
+ drm_fb_helper_unprepare(fb_helper);
+ kfree(fb_helper);
+ }
+}
+
+static int drm_fbdev_shmem_client_restore(struct drm_client_dev *client)
+{
+ drm_fb_helper_lastclose(client->dev);
+
+ return 0;
+}
+
+static int drm_fbdev_shmem_client_hotplug(struct drm_client_dev *client)
+{
+ struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client);
+ struct drm_device *dev = client->dev;
+ int ret;
+
+ if (dev->fb_helper)
+ return drm_fb_helper_hotplug_event(dev->fb_helper);
+
+ ret = drm_fb_helper_init(dev, fb_helper);
+ if (ret)
+ goto err_drm_err;
+
+ if (!drm_drv_uses_atomic_modeset(dev))
+ drm_helper_disable_unused_functions(dev);
+
+ ret = drm_fb_helper_initial_config(fb_helper);
+ if (ret)
+ goto err_drm_fb_helper_fini;
+
+ return 0;
+
+err_drm_fb_helper_fini:
+ drm_fb_helper_fini(fb_helper);
+err_drm_err:
+ drm_err(dev, "fbdev-shmem: Failed to setup emulation (ret=%d)\n", ret);
+ return ret;
+}
+
+static const struct drm_client_funcs drm_fbdev_shmem_client_funcs = {
+ .owner = THIS_MODULE,
+ .unregister = drm_fbdev_shmem_client_unregister,
+ .restore = drm_fbdev_shmem_client_restore,
+ .hotplug = drm_fbdev_shmem_client_hotplug,
+};
+
+/**
+ * drm_fbdev_shmem_setup() - Setup fbdev emulation for GEM SHMEM helpers
+ * @dev: DRM device
+ * @preferred_bpp: Preferred bits per pixel for the device.
+ * 32 is used if this is zero.
+ *
+ * This function sets up fbdev emulation for GEM DMA drivers that support
+ * dumb buffers with a virtual address and that can be mmap'ed.
+ * drm_fbdev_shmem_setup() shall be called after the DRM driver registered
+ * the new DRM device with drm_dev_register().
+ *
+ * Restore, hotplug events and teardown are all taken care of. Drivers that do
+ * suspend/resume need to call drm_fb_helper_set_suspend_unlocked() themselves.
+ * Simple drivers might use drm_mode_config_helper_suspend().
+ *
+ * This function is safe to call even when there are no connectors present.
+ * Setup will be retried on the next hotplug event.
+ *
+ * The fbdev is destroyed by drm_dev_unregister().
+ */
+void drm_fbdev_shmem_setup(struct drm_device *dev, unsigned int preferred_bpp)
+{
+ struct drm_fb_helper *fb_helper;
+ int ret;
+
+ drm_WARN(dev, !dev->registered, "Device has not been registered.\n");
+ drm_WARN(dev, dev->fb_helper, "fb_helper is already set!\n");
+
+ fb_helper = kzalloc(sizeof(*fb_helper), GFP_KERNEL);
+ if (!fb_helper)
+ return;
+ drm_fb_helper_prepare(dev, fb_helper, preferred_bpp, &drm_fbdev_shmem_helper_funcs);
+
+ ret = drm_client_init(dev, &fb_helper->client, "fbdev", &drm_fbdev_shmem_client_funcs);
+ if (ret) {
+ drm_err(dev, "Failed to register client: %d\n", ret);
+ goto err_drm_client_init;
+ }
+
+ drm_client_register(&fb_helper->client);
+
+ return;
+
+err_drm_client_init:
+ drm_fb_helper_unprepare(fb_helper);
+ kfree(fb_helper);
+}
+EXPORT_SYMBOL(drm_fbdev_shmem_setup);
diff --git a/drivers/gpu/drm/drm_fbdev_generic.c b/drivers/gpu/drm/drm_fbdev_ttm.c
index 97e579c33d84..119ffb28aaf9 100644
--- a/drivers/gpu/drm/drm_fbdev_generic.c
+++ b/drivers/gpu/drm/drm_fbdev_ttm.c
@@ -10,10 +10,10 @@
#include <drm/drm_gem.h>
#include <drm/drm_print.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_ttm.h>
/* @user: 1=userspace, 0=fbcon */
-static int drm_fbdev_generic_fb_open(struct fb_info *info, int user)
+static int drm_fbdev_ttm_fb_open(struct fb_info *info, int user)
{
struct drm_fb_helper *fb_helper = info->par;
@@ -24,7 +24,7 @@ static int drm_fbdev_generic_fb_open(struct fb_info *info, int user)
return 0;
}
-static int drm_fbdev_generic_fb_release(struct fb_info *info, int user)
+static int drm_fbdev_ttm_fb_release(struct fb_info *info, int user)
{
struct drm_fb_helper *fb_helper = info->par;
@@ -34,11 +34,11 @@ static int drm_fbdev_generic_fb_release(struct fb_info *info, int user)
return 0;
}
-FB_GEN_DEFAULT_DEFERRED_SYSMEM_OPS(drm_fbdev_generic,
+FB_GEN_DEFAULT_DEFERRED_SYSMEM_OPS(drm_fbdev_ttm,
drm_fb_helper_damage_range,
drm_fb_helper_damage_area);
-static void drm_fbdev_generic_fb_destroy(struct fb_info *info)
+static void drm_fbdev_ttm_fb_destroy(struct fb_info *info)
{
struct drm_fb_helper *fb_helper = info->par;
void *shadow = info->screen_buffer;
@@ -56,19 +56,19 @@ static void drm_fbdev_generic_fb_destroy(struct fb_info *info)
kfree(fb_helper);
}
-static const struct fb_ops drm_fbdev_generic_fb_ops = {
+static const struct fb_ops drm_fbdev_ttm_fb_ops = {
.owner = THIS_MODULE,
- .fb_open = drm_fbdev_generic_fb_open,
- .fb_release = drm_fbdev_generic_fb_release,
- FB_DEFAULT_DEFERRED_OPS(drm_fbdev_generic),
+ .fb_open = drm_fbdev_ttm_fb_open,
+ .fb_release = drm_fbdev_ttm_fb_release,
+ FB_DEFAULT_DEFERRED_OPS(drm_fbdev_ttm),
DRM_FB_HELPER_DEFAULT_OPS,
- .fb_destroy = drm_fbdev_generic_fb_destroy,
+ .fb_destroy = drm_fbdev_ttm_fb_destroy,
};
/*
* This function uses the client API to create a framebuffer backed by a dumb buffer.
*/
-static int drm_fbdev_generic_helper_fb_probe(struct drm_fb_helper *fb_helper,
+static int drm_fbdev_ttm_helper_fb_probe(struct drm_fb_helper *fb_helper,
struct drm_fb_helper_surface_size *sizes)
{
struct drm_client_dev *client = &fb_helper->client;
@@ -84,7 +84,8 @@ static int drm_fbdev_generic_helper_fb_probe(struct drm_fb_helper *fb_helper,
sizes->surface_width, sizes->surface_height,
sizes->surface_bpp);
- format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth);
+ format = drm_driver_legacy_fb_format(dev, sizes->surface_bpp,
+ sizes->surface_depth);
buffer = drm_client_framebuffer_create(client, sizes->surface_width,
sizes->surface_height, format);
if (IS_ERR(buffer))
@@ -108,7 +109,7 @@ static int drm_fbdev_generic_helper_fb_probe(struct drm_fb_helper *fb_helper,
drm_fb_helper_fill_info(info, fb_helper, sizes);
- info->fbops = &drm_fbdev_generic_fb_ops;
+ info->fbops = &drm_fbdev_ttm_fb_ops;
/* screen */
info->flags |= FBINFO_VIRTFB | FBINFO_READS_FAST;
@@ -137,9 +138,9 @@ err_drm_client_framebuffer_delete:
return ret;
}
-static void drm_fbdev_generic_damage_blit_real(struct drm_fb_helper *fb_helper,
- struct drm_clip_rect *clip,
- struct iosys_map *dst)
+static void drm_fbdev_ttm_damage_blit_real(struct drm_fb_helper *fb_helper,
+ struct drm_clip_rect *clip,
+ struct iosys_map *dst)
{
struct drm_framebuffer *fb = fb_helper->fb;
size_t offset = clip->y1 * fb->pitches[0];
@@ -176,8 +177,8 @@ static void drm_fbdev_generic_damage_blit_real(struct drm_fb_helper *fb_helper,
}
}
-static int drm_fbdev_generic_damage_blit(struct drm_fb_helper *fb_helper,
- struct drm_clip_rect *clip)
+static int drm_fbdev_ttm_damage_blit(struct drm_fb_helper *fb_helper,
+ struct drm_clip_rect *clip)
{
struct drm_client_buffer *buffer = fb_helper->buffer;
struct iosys_map map, dst;
@@ -201,7 +202,7 @@ static int drm_fbdev_generic_damage_blit(struct drm_fb_helper *fb_helper,
goto out;
dst = map;
- drm_fbdev_generic_damage_blit_real(fb_helper, clip, &dst);
+ drm_fbdev_ttm_damage_blit_real(fb_helper, clip, &dst);
drm_client_buffer_vunmap_local(buffer);
@@ -211,8 +212,8 @@ out:
return ret;
}
-static int drm_fbdev_generic_helper_fb_dirty(struct drm_fb_helper *helper,
- struct drm_clip_rect *clip)
+static int drm_fbdev_ttm_helper_fb_dirty(struct drm_fb_helper *helper,
+ struct drm_clip_rect *clip)
{
struct drm_device *dev = helper->dev;
int ret;
@@ -221,7 +222,7 @@ static int drm_fbdev_generic_helper_fb_dirty(struct drm_fb_helper *helper,
if (!(clip->x1 < clip->x2 && clip->y1 < clip->y2))
return 0;
- ret = drm_fbdev_generic_damage_blit(helper, clip);
+ ret = drm_fbdev_ttm_damage_blit(helper, clip);
if (drm_WARN_ONCE(dev, ret, "Damage blitter failed: ret=%d\n", ret))
return ret;
@@ -234,12 +235,12 @@ static int drm_fbdev_generic_helper_fb_dirty(struct drm_fb_helper *helper,
return 0;
}
-static const struct drm_fb_helper_funcs drm_fbdev_generic_helper_funcs = {
- .fb_probe = drm_fbdev_generic_helper_fb_probe,
- .fb_dirty = drm_fbdev_generic_helper_fb_dirty,
+static const struct drm_fb_helper_funcs drm_fbdev_ttm_helper_funcs = {
+ .fb_probe = drm_fbdev_ttm_helper_fb_probe,
+ .fb_dirty = drm_fbdev_ttm_helper_fb_dirty,
};
-static void drm_fbdev_generic_client_unregister(struct drm_client_dev *client)
+static void drm_fbdev_ttm_client_unregister(struct drm_client_dev *client)
{
struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client);
@@ -252,14 +253,14 @@ static void drm_fbdev_generic_client_unregister(struct drm_client_dev *client)
}
}
-static int drm_fbdev_generic_client_restore(struct drm_client_dev *client)
+static int drm_fbdev_ttm_client_restore(struct drm_client_dev *client)
{
drm_fb_helper_lastclose(client->dev);
return 0;
}
-static int drm_fbdev_generic_client_hotplug(struct drm_client_dev *client)
+static int drm_fbdev_ttm_client_hotplug(struct drm_client_dev *client)
{
struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client);
struct drm_device *dev = client->dev;
@@ -284,32 +285,32 @@ static int drm_fbdev_generic_client_hotplug(struct drm_client_dev *client)
err_drm_fb_helper_fini:
drm_fb_helper_fini(fb_helper);
err_drm_err:
- drm_err(dev, "fbdev: Failed to setup generic emulation (ret=%d)\n", ret);
+ drm_err(dev, "fbdev: Failed to setup emulation (ret=%d)\n", ret);
return ret;
}
-static const struct drm_client_funcs drm_fbdev_generic_client_funcs = {
+static const struct drm_client_funcs drm_fbdev_ttm_client_funcs = {
.owner = THIS_MODULE,
- .unregister = drm_fbdev_generic_client_unregister,
- .restore = drm_fbdev_generic_client_restore,
- .hotplug = drm_fbdev_generic_client_hotplug,
+ .unregister = drm_fbdev_ttm_client_unregister,
+ .restore = drm_fbdev_ttm_client_restore,
+ .hotplug = drm_fbdev_ttm_client_hotplug,
};
/**
- * drm_fbdev_generic_setup() - Setup generic fbdev emulation
+ * drm_fbdev_ttm_setup() - Setup fbdev emulation for TTM-based drivers
* @dev: DRM device
* @preferred_bpp: Preferred bits per pixel for the device.
*
- * This function sets up generic fbdev emulation for drivers that supports
+ * This function sets up fbdev emulation for TTM-based drivers that support
* dumb buffers with a virtual address and that can be mmap'ed.
- * drm_fbdev_generic_setup() shall be called after the DRM driver registered
+ * drm_fbdev_ttm_setup() shall be called after the DRM driver registered
* the new DRM device with drm_dev_register().
*
* Restore, hotplug events and teardown are all taken care of. Drivers that do
* suspend/resume need to call drm_fb_helper_set_suspend_unlocked() themselves.
* Simple drivers might use drm_mode_config_helper_suspend().
*
- * In order to provide fixed mmap-able memory ranges, generic fbdev emulation
+ * In order to provide fixed mmap-able memory ranges, fbdev emulation
* uses a shadow buffer in system memory. The implementation blits the shadow
* fbdev buffer onto the real buffer in regular intervals.
*
@@ -318,7 +319,7 @@ static const struct drm_client_funcs drm_fbdev_generic_client_funcs = {
*
* The fbdev is destroyed by drm_dev_unregister().
*/
-void drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp)
+void drm_fbdev_ttm_setup(struct drm_device *dev, unsigned int preferred_bpp)
{
struct drm_fb_helper *fb_helper;
int ret;
@@ -329,9 +330,9 @@ void drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp)
fb_helper = kzalloc(sizeof(*fb_helper), GFP_KERNEL);
if (!fb_helper)
return;
- drm_fb_helper_prepare(dev, fb_helper, preferred_bpp, &drm_fbdev_generic_helper_funcs);
+ drm_fb_helper_prepare(dev, fb_helper, preferred_bpp, &drm_fbdev_ttm_helper_funcs);
- ret = drm_client_init(dev, &fb_helper->client, "fbdev", &drm_fbdev_generic_client_funcs);
+ ret = drm_client_init(dev, &fb_helper->client, "fbdev", &drm_fbdev_ttm_client_funcs);
if (ret) {
drm_err(dev, "Failed to register client: %d\n", ret);
goto err_drm_client_init;
@@ -346,4 +347,4 @@ err_drm_client_init:
kfree(fb_helper);
return;
}
-EXPORT_SYMBOL(drm_fbdev_generic_setup);
+EXPORT_SYMBOL(drm_fbdev_ttm_setup);
diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c
index 638ffa4444f5..714e42b05108 100644
--- a/drivers/gpu/drm/drm_file.c
+++ b/drivers/gpu/drm/drm_file.c
@@ -469,14 +469,12 @@ void drm_file_update_pid(struct drm_file *filp)
dev = filp->minor->dev;
mutex_lock(&dev->filelist_mutex);
+ get_pid(pid);
old = rcu_replace_pointer(filp->pid, pid, 1);
mutex_unlock(&dev->filelist_mutex);
- if (pid != old) {
- get_pid(pid);
- synchronize_rcu();
- put_pid(old);
- }
+ synchronize_rcu();
+ put_pid(old);
}
/**
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index e368fc084c77..51f39912866f 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -529,9 +529,10 @@ int drm_version(struct drm_device *dev, void *data,
version->version_patchlevel = dev->driver->patchlevel;
err = drm_copy_field(version->name, &version->name_len,
dev->driver->name);
+
+ /* Driver date is deprecated. Userspace expects a non-empty string. */
if (!err)
- err = drm_copy_field(version->date, &version->date_len,
- dev->driver->date);
+ err = drm_copy_field(version->date, &version->date_len, "0");
if (!err)
err = drm_copy_field(version->desc, &version->desc_len,
dev->driver->desc);
diff --git a/drivers/gpu/drm/drm_managed.c b/drivers/gpu/drm/drm_managed.c
index 7646f67bda4e..79ce86a5bd67 100644
--- a/drivers/gpu/drm/drm_managed.c
+++ b/drivers/gpu/drm/drm_managed.c
@@ -197,7 +197,7 @@ void drmm_release_action(struct drm_device *dev,
spin_lock_irqsave(&dev->managed.lock, flags);
list_for_each_entry_reverse(dr, &dev->managed.resources, node.entry) {
if (dr->node.release == action) {
- if (!data || (data && *(void **)dr->data == data)) {
+ if (!data || *(void **)dr->data == data) {
dr_match = dr;
del_dr(dev, dr_match);
break;
diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c
index daac649aabdb..34bca7567576 100644
--- a/drivers/gpu/drm/drm_mipi_dbi.c
+++ b/drivers/gpu/drm/drm_mipi_dbi.c
@@ -206,6 +206,7 @@ int mipi_dbi_buf_copy(void *dst, struct iosys_map *src, struct drm_framebuffer *
struct drm_rect *clip, bool swap,
struct drm_format_conv_state *fmtcnv_state)
{
+ struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(fb->dev);
struct drm_gem_object *gem = drm_gem_fb_get_obj(fb, 0);
struct iosys_map dst_map = IOSYS_MAP_INIT_VADDR(dst);
int ret;
@@ -222,8 +223,18 @@ int mipi_dbi_buf_copy(void *dst, struct iosys_map *src, struct drm_framebuffer *
else
drm_fb_memcpy(&dst_map, NULL, src, fb, clip);
break;
+ case DRM_FORMAT_RGB888:
+ drm_fb_memcpy(&dst_map, NULL, src, fb, clip);
+ break;
case DRM_FORMAT_XRGB8888:
- drm_fb_xrgb8888_to_rgb565(&dst_map, NULL, src, fb, clip, fmtcnv_state, swap);
+ switch (dbidev->pixel_format) {
+ case DRM_FORMAT_RGB565:
+ drm_fb_xrgb8888_to_rgb565(&dst_map, NULL, src, fb, clip, fmtcnv_state, swap);
+ break;
+ case DRM_FORMAT_RGB888:
+ drm_fb_xrgb8888_to_rgb888(&dst_map, NULL, src, fb, clip, fmtcnv_state);
+ break;
+ }
break;
default:
drm_err_once(fb->dev, "Format is not supported: %p4cc\n",
@@ -260,9 +271,11 @@ static void mipi_dbi_fb_dirty(struct iosys_map *src, struct drm_framebuffer *fb,
struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(fb->dev);
unsigned int height = rect->y2 - rect->y1;
unsigned int width = rect->x2 - rect->x1;
+ const struct drm_format_info *dst_format;
struct mipi_dbi *dbi = &dbidev->dbi;
bool swap = dbi->swap_bytes;
int ret = 0;
+ size_t len;
bool full;
void *tr;
@@ -283,8 +296,13 @@ static void mipi_dbi_fb_dirty(struct iosys_map *src, struct drm_framebuffer *fb,
mipi_dbi_set_window_address(dbidev, rect->x1, rect->x2 - 1, rect->y1,
rect->y2 - 1);
- ret = mipi_dbi_command_buf(dbi, MIPI_DCS_WRITE_MEMORY_START, tr,
- width * height * 2);
+ if (fb->format->format == DRM_FORMAT_XRGB8888)
+ dst_format = drm_format_info(dbidev->pixel_format);
+ else
+ dst_format = fb->format;
+ len = drm_format_info_min_pitch(dst_format, 0, width) * height;
+
+ ret = mipi_dbi_command_buf(dbi, MIPI_DCS_WRITE_MEMORY_START, tr, len);
err_msg:
if (ret)
drm_err_once(fb->dev, "Failed to update display %d\n", ret);
@@ -572,7 +590,7 @@ static const uint32_t mipi_dbi_formats[] = {
* 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 don't need custom formats.
+ * Use mipi_dbi_dev_init() if you want native RGB565 and emulated XRGB8888 format.
*
* Note:
* Some of the helper functions expects RGB565 to be the default format and the
@@ -631,6 +649,9 @@ int mipi_dbi_dev_init_with_formats(struct mipi_dbi_dev *dbidev,
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_DEBUG_KMS("rotation = %u\n", rotation);
@@ -824,15 +845,6 @@ u32 mipi_dbi_spi_cmd_max_speed(struct spi_device *spi, size_t len)
}
EXPORT_SYMBOL(mipi_dbi_spi_cmd_max_speed);
-static bool mipi_dbi_machine_little_endian(void)
-{
-#if defined(__LITTLE_ENDIAN)
- return true;
-#else
- return false;
-#endif
-}
-
/*
* MIPI DBI Type C Option 1
*
@@ -855,7 +867,7 @@ static int mipi_dbi_spi1e_transfer(struct mipi_dbi *dbi, int dc,
const void *buf, size_t len,
unsigned int bpw)
{
- bool swap_bytes = (bpw == 16 && mipi_dbi_machine_little_endian());
+ bool swap_bytes = (bpw == 16);
size_t chunk, max_chunk = dbi->tx_buf9_len;
struct spi_device *spi = dbi->spi;
struct spi_transfer tr = {
@@ -1004,7 +1016,7 @@ static int mipi_dbi_spi1_transfer(struct mipi_dbi *dbi, int dc,
size_t chunk = min(len, max_chunk);
unsigned int i;
- if (bpw == 16 && mipi_dbi_machine_little_endian()) {
+ if (bpw == 16) {
for (i = 0; i < (chunk * 2); i += 2) {
dst16[i] = *src16 >> 8;
dst16[i + 1] = *src16++ & 0xFF;
@@ -1088,7 +1100,7 @@ static int mipi_dbi_typec1_command_read(struct mipi_dbi *dbi, u8 *cmd,
static int mipi_dbi_typec1_command(struct mipi_dbi *dbi, u8 *cmd,
u8 *parameters, size_t num)
{
- unsigned int bpw = (*cmd == MIPI_DCS_WRITE_MEMORY_START) ? 16 : 8;
+ unsigned int bpw = 8;
int ret;
if (mipi_dbi_command_is_read(dbi, *cmd))
@@ -1100,6 +1112,9 @@ static int mipi_dbi_typec1_command(struct mipi_dbi *dbi, u8 *cmd,
if (ret || !num)
return ret;
+ if (*cmd == MIPI_DCS_WRITE_MEMORY_START)
+ bpw = dbi->write_memory_bpw;
+
return mipi_dbi_spi1_transfer(dbi, 1, parameters, num, bpw);
}
@@ -1193,8 +1208,8 @@ static int mipi_dbi_typec3_command(struct mipi_dbi *dbi, u8 *cmd,
if (ret || !num)
return ret;
- if (*cmd == MIPI_DCS_WRITE_MEMORY_START && !dbi->swap_bytes)
- bpw = 16;
+ if (*cmd == MIPI_DCS_WRITE_MEMORY_START)
+ bpw = dbi->write_memory_bpw;
spi_bus_lock(spi->controller);
gpiod_set_value_cansleep(dbi->dc, 1);
@@ -1218,11 +1233,23 @@ static int mipi_dbi_typec3_command(struct mipi_dbi *dbi, u8 *cmd,
* If @dc is set, a Type C Option 3 interface is assumed, if not
* Type C Option 1.
*
- * If the SPI master driver doesn't support the necessary bits per word,
- * the following transformation is used:
+ * If the command is %MIPI_DCS_WRITE_MEMORY_START and the pixel format is RGB565, endianness has
+ * to be taken into account. The MIPI DBI serial interface is big endian and framebuffers are
+ * assumed stored in memory as little endian (%DRM_FORMAT_BIG_ENDIAN is not supported).
*
- * - 9-bit: reorder buffer as 9x 8-bit words, padded with no-op command.
- * - 16-bit: if big endian send as 8-bit, if little endian swap bytes
+ * This is how endianness is handled:
+ *
+ * Option 1 (D/C as a bit): The buffer is sent on the wire byte by byte so the 16-bit buffer is
+ * byteswapped before transfer.
+ *
+ * Option 3 (D/C as a gpio): If the SPI controller supports 16 bits per word the buffer can be
+ * sent as-is. If not the caller is responsible for swapping the bytes
+ * before calling mipi_dbi_command_buf() and the buffer is sent 8 bpw.
+ *
+ * This handling is optimised for %DRM_FORMAT_RGB565 framebuffers.
+ *
+ * If the interface is Option 1 and the SPI controller doesn't support 9 bits per word,
+ * the buffer is sent as 9x 8-bit words, padded with MIPI DCS no-op commands if necessary.
*
* Returns:
* Zero on success, negative error code on failure.
@@ -1253,12 +1280,15 @@ int mipi_dbi_spi_init(struct spi_device *spi, struct mipi_dbi *dbi,
dbi->spi = spi;
dbi->read_commands = mipi_dbi_dcs_read_commands;
+ dbi->write_memory_bpw = 16;
if (dc) {
dbi->command = mipi_dbi_typec3_command;
dbi->dc = dc;
- if (mipi_dbi_machine_little_endian() && !spi_is_bpw_supported(spi, 16))
+ if (!spi_is_bpw_supported(spi, 16)) {
+ dbi->write_memory_bpw = 8;
dbi->swap_bytes = true;
+ }
} else {
dbi->command = mipi_dbi_typec1_command;
dbi->tx_buf9_len = SZ_16K;
@@ -1475,4 +1505,5 @@ EXPORT_SYMBOL(mipi_dbi_debugfs_init);
#endif
+MODULE_DESCRIPTION("MIPI Display Bus Interface (DBI) LCD controller support");
MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
index 795001bb7ff1..969cfd5a01ae 100644
--- a/drivers/gpu/drm/drm_mipi_dsi.c
+++ b/drivers/gpu/drm/drm_mipi_dsi.c
@@ -48,7 +48,7 @@
* subset of the MIPI DCS command set.
*/
-static int mipi_dsi_device_match(struct device *dev, struct device_driver *drv)
+static int mipi_dsi_device_match(struct device *dev, const struct device_driver *drv)
{
struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
@@ -765,6 +765,62 @@ ssize_t mipi_dsi_generic_write(struct mipi_dsi_device *dsi, const void *payload,
EXPORT_SYMBOL(mipi_dsi_generic_write);
/**
+ * mipi_dsi_generic_write_chatty() - mipi_dsi_generic_write() w/ an error log
+ * @dsi: DSI peripheral device
+ * @payload: buffer containing the payload
+ * @size: size of payload buffer
+ *
+ * Like mipi_dsi_generic_write() but includes a dev_err()
+ * call for you and returns 0 upon success, not the number of bytes sent.
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+int mipi_dsi_generic_write_chatty(struct mipi_dsi_device *dsi,
+ const void *payload, size_t size)
+{
+ struct device *dev = &dsi->dev;
+ ssize_t ret;
+
+ ret = mipi_dsi_generic_write(dsi, payload, size);
+ if (ret < 0) {
+ dev_err(dev, "sending generic data %*ph failed: %zd\n",
+ (int)size, payload, ret);
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(mipi_dsi_generic_write_chatty);
+
+/**
+ * mipi_dsi_generic_write_multi() - mipi_dsi_generic_write_chatty() w/ accum_err
+ * @ctx: Context for multiple DSI transactions
+ * @payload: buffer containing the payload
+ * @size: size of payload buffer
+ *
+ * Like mipi_dsi_generic_write_chatty() but deals with errors in a way that
+ * makes it convenient to make several calls in a row.
+ */
+void mipi_dsi_generic_write_multi(struct mipi_dsi_multi_context *ctx,
+ const void *payload, size_t size)
+{
+ struct mipi_dsi_device *dsi = ctx->dsi;
+ struct device *dev = &dsi->dev;
+ ssize_t ret;
+
+ if (ctx->accum_err)
+ return;
+
+ ret = mipi_dsi_generic_write(dsi, payload, size);
+ if (ret < 0) {
+ ctx->accum_err = ret;
+ dev_err(dev, "sending generic data %*ph failed: %d\n",
+ (int)size, payload, ctx->accum_err);
+ }
+}
+EXPORT_SYMBOL(mipi_dsi_generic_write_multi);
+
+/**
* mipi_dsi_generic_read() - receive data using a generic read packet
* @dsi: DSI peripheral device
* @params: buffer containing the request parameters
@@ -853,6 +909,62 @@ ssize_t mipi_dsi_dcs_write_buffer(struct mipi_dsi_device *dsi,
EXPORT_SYMBOL(mipi_dsi_dcs_write_buffer);
/**
+ * mipi_dsi_dcs_write_buffer_chatty - mipi_dsi_dcs_write_buffer() w/ an error log
+ * @dsi: DSI peripheral device
+ * @data: buffer containing data to be transmitted
+ * @len: size of transmission buffer
+ *
+ * Like mipi_dsi_dcs_write_buffer() but includes a dev_err()
+ * call for you and returns 0 upon success, not the number of bytes sent.
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+int mipi_dsi_dcs_write_buffer_chatty(struct mipi_dsi_device *dsi,
+ const void *data, size_t len)
+{
+ struct device *dev = &dsi->dev;
+ ssize_t ret;
+
+ ret = mipi_dsi_dcs_write_buffer(dsi, data, len);
+ if (ret < 0) {
+ dev_err(dev, "sending dcs data %*ph failed: %zd\n",
+ (int)len, data, ret);
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(mipi_dsi_dcs_write_buffer_chatty);
+
+/**
+ * mipi_dsi_dcs_write_buffer_multi - mipi_dsi_dcs_write_buffer_chatty() w/ accum_err
+ * @ctx: Context for multiple DSI transactions
+ * @data: buffer containing data to be transmitted
+ * @len: size of transmission buffer
+ *
+ * Like mipi_dsi_dcs_write_buffer_chatty() but deals with errors in a way that
+ * makes it convenient to make several calls in a row.
+ */
+void mipi_dsi_dcs_write_buffer_multi(struct mipi_dsi_multi_context *ctx,
+ const void *data, size_t len)
+{
+ struct mipi_dsi_device *dsi = ctx->dsi;
+ struct device *dev = &dsi->dev;
+ ssize_t ret;
+
+ if (ctx->accum_err)
+ return;
+
+ ret = mipi_dsi_dcs_write_buffer(dsi, data, len);
+ if (ret < 0) {
+ ctx->accum_err = ret;
+ dev_err(dev, "sending dcs data %*ph failed: %d\n",
+ (int)len, data, ctx->accum_err);
+ }
+}
+EXPORT_SYMBOL(mipi_dsi_dcs_write_buffer_multi);
+
+/**
* mipi_dsi_dcs_write() - send DCS write command
* @dsi: DSI peripheral device
* @cmd: DCS command
@@ -1317,6 +1429,216 @@ int mipi_dsi_dcs_get_display_brightness_large(struct mipi_dsi_device *dsi,
}
EXPORT_SYMBOL(mipi_dsi_dcs_get_display_brightness_large);
+/**
+ * mipi_dsi_picture_parameter_set_multi() - transmit the DSC PPS to the peripheral
+ * @ctx: Context for multiple DSI transactions
+ * @pps: VESA DSC 1.1 Picture Parameter Set
+ *
+ * Like mipi_dsi_picture_parameter_set() but deals with errors in a way that
+ * makes it convenient to make several calls in a row.
+ */
+void mipi_dsi_picture_parameter_set_multi(struct mipi_dsi_multi_context *ctx,
+ const struct drm_dsc_picture_parameter_set *pps)
+{
+ struct mipi_dsi_device *dsi = ctx->dsi;
+ struct device *dev = &dsi->dev;
+ ssize_t ret;
+
+ if (ctx->accum_err)
+ return;
+
+ ret = mipi_dsi_picture_parameter_set(dsi, pps);
+ if (ret < 0) {
+ ctx->accum_err = ret;
+ dev_err(dev, "sending PPS failed: %d\n",
+ ctx->accum_err);
+ }
+}
+EXPORT_SYMBOL(mipi_dsi_picture_parameter_set_multi);
+
+/**
+ * mipi_dsi_compression_mode_ext_multi() - enable/disable DSC on the peripheral
+ * @ctx: Context for multiple DSI transactions
+ * @enable: Whether to enable or disable the DSC
+ * @algo: Selected compression algorithm
+ * @pps_selector: Select PPS from the table of pre-stored or uploaded PPS entries
+ *
+ * Like mipi_dsi_compression_mode_ext() but deals with errors in a way that
+ * makes it convenient to make several calls in a row.
+ */
+void mipi_dsi_compression_mode_ext_multi(struct mipi_dsi_multi_context *ctx,
+ bool enable,
+ enum mipi_dsi_compression_algo algo,
+ unsigned int pps_selector)
+{
+ struct mipi_dsi_device *dsi = ctx->dsi;
+ struct device *dev = &dsi->dev;
+ ssize_t ret;
+
+ if (ctx->accum_err)
+ return;
+
+ ret = mipi_dsi_compression_mode_ext(dsi, enable, algo, pps_selector);
+ if (ret < 0) {
+ ctx->accum_err = ret;
+ dev_err(dev, "sending COMPRESSION_MODE failed: %d\n",
+ ctx->accum_err);
+ }
+}
+EXPORT_SYMBOL(mipi_dsi_compression_mode_ext_multi);
+
+/**
+ * mipi_dsi_dcs_nop_multi() - send DCS NOP packet
+ * @ctx: Context for multiple DSI transactions
+ *
+ * Like mipi_dsi_dcs_nop() but deals with errors in a way that
+ * makes it convenient to make several calls in a row.
+ */
+void mipi_dsi_dcs_nop_multi(struct mipi_dsi_multi_context *ctx)
+{
+ struct mipi_dsi_device *dsi = ctx->dsi;
+ struct device *dev = &dsi->dev;
+ ssize_t ret;
+
+ if (ctx->accum_err)
+ return;
+
+ ret = mipi_dsi_dcs_nop(dsi);
+ if (ret < 0) {
+ ctx->accum_err = ret;
+ dev_err(dev, "sending DCS NOP failed: %d\n",
+ ctx->accum_err);
+ }
+}
+EXPORT_SYMBOL(mipi_dsi_dcs_nop_multi);
+
+/**
+ * mipi_dsi_dcs_enter_sleep_mode_multi() - send DCS ENTER_SLEEP_MODE packet
+ * @ctx: Context for multiple DSI transactions
+ *
+ * Like mipi_dsi_dcs_enter_sleep_mode() but deals with errors in a way that
+ * makes it convenient to make several calls in a row.
+ */
+void mipi_dsi_dcs_enter_sleep_mode_multi(struct mipi_dsi_multi_context *ctx)
+{
+ struct mipi_dsi_device *dsi = ctx->dsi;
+ struct device *dev = &dsi->dev;
+ ssize_t ret;
+
+ if (ctx->accum_err)
+ return;
+
+ ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+ if (ret < 0) {
+ ctx->accum_err = ret;
+ dev_err(dev, "sending DCS ENTER_SLEEP_MODE failed: %d\n",
+ ctx->accum_err);
+ }
+}
+EXPORT_SYMBOL(mipi_dsi_dcs_enter_sleep_mode_multi);
+
+/**
+ * mipi_dsi_dcs_exit_sleep_mode_multi() - send DCS EXIT_SLEEP_MODE packet
+ * @ctx: Context for multiple DSI transactions
+ *
+ * Like mipi_dsi_dcs_exit_sleep_mode() but deals with errors in a way that
+ * makes it convenient to make several calls in a row.
+ */
+void mipi_dsi_dcs_exit_sleep_mode_multi(struct mipi_dsi_multi_context *ctx)
+{
+ struct mipi_dsi_device *dsi = ctx->dsi;
+ struct device *dev = &dsi->dev;
+ ssize_t ret;
+
+ if (ctx->accum_err)
+ return;
+
+ ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+ if (ret < 0) {
+ ctx->accum_err = ret;
+ dev_err(dev, "sending DCS EXIT_SLEEP_MODE failed: %d\n",
+ ctx->accum_err);
+ }
+}
+EXPORT_SYMBOL(mipi_dsi_dcs_exit_sleep_mode_multi);
+
+/**
+ * mipi_dsi_dcs_set_display_off_multi() - send DCS SET_DISPLAY_OFF packet
+ * @ctx: Context for multiple DSI transactions
+ *
+ * Like mipi_dsi_dcs_set_display_off() but deals with errors in a way that
+ * makes it convenient to make several calls in a row.
+ */
+void mipi_dsi_dcs_set_display_off_multi(struct mipi_dsi_multi_context *ctx)
+{
+ struct mipi_dsi_device *dsi = ctx->dsi;
+ struct device *dev = &dsi->dev;
+ ssize_t ret;
+
+ if (ctx->accum_err)
+ return;
+
+ ret = mipi_dsi_dcs_set_display_off(dsi);
+ if (ret < 0) {
+ ctx->accum_err = ret;
+ dev_err(dev, "sending DCS SET_DISPLAY_OFF failed: %d\n",
+ ctx->accum_err);
+ }
+}
+EXPORT_SYMBOL(mipi_dsi_dcs_set_display_off_multi);
+
+/**
+ * mipi_dsi_dcs_set_display_on_multi() - send DCS SET_DISPLAY_ON packet
+ * @ctx: Context for multiple DSI transactions
+ *
+ * Like mipi_dsi_dcs_set_display_on() but deals with errors in a way that
+ * makes it convenient to make several calls in a row.
+ */
+void mipi_dsi_dcs_set_display_on_multi(struct mipi_dsi_multi_context *ctx)
+{
+ struct mipi_dsi_device *dsi = ctx->dsi;
+ struct device *dev = &dsi->dev;
+ ssize_t ret;
+
+ if (ctx->accum_err)
+ return;
+
+ ret = mipi_dsi_dcs_set_display_on(dsi);
+ if (ret < 0) {
+ ctx->accum_err = ret;
+ dev_err(dev, "sending DCS SET_DISPLAY_ON failed: %d\n",
+ ctx->accum_err);
+ }
+}
+EXPORT_SYMBOL(mipi_dsi_dcs_set_display_on_multi);
+
+/**
+ * mipi_dsi_dcs_set_tear_on_multi() - send DCS SET_TEAR_ON packet
+ * @ctx: Context for multiple DSI transactions
+ * @mode: the Tearing Effect Output Line mode
+ *
+ * Like mipi_dsi_dcs_set_tear_on() but deals with errors in a way that
+ * makes it convenient to make several calls in a row.
+ */
+void mipi_dsi_dcs_set_tear_on_multi(struct mipi_dsi_multi_context *ctx,
+ enum mipi_dsi_dcs_tear_mode mode)
+{
+ struct mipi_dsi_device *dsi = ctx->dsi;
+ struct device *dev = &dsi->dev;
+ ssize_t ret;
+
+ if (ctx->accum_err)
+ return;
+
+ ret = mipi_dsi_dcs_set_tear_on(dsi, mode);
+ if (ret < 0) {
+ ctx->accum_err = ret;
+ dev_err(dev, "sending DCS SET_TEAR_ON failed: %d\n",
+ ctx->accum_err);
+ }
+}
+EXPORT_SYMBOL(mipi_dsi_dcs_set_tear_on_multi);
+
static int mipi_dsi_drv_probe(struct device *dev)
{
struct mipi_dsi_driver *drv = to_mipi_dsi_driver(dev->driver);
diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c
index 8257f9d4f619..5ace481c1901 100644
--- a/drivers/gpu/drm/drm_mm.c
+++ b/drivers/gpu/drm/drm_mm.c
@@ -649,41 +649,6 @@ void drm_mm_remove_node(struct drm_mm_node *node)
EXPORT_SYMBOL(drm_mm_remove_node);
/**
- * drm_mm_replace_node - move an allocation from @old to @new
- * @old: drm_mm_node to remove from the allocator
- * @new: drm_mm_node which should inherit @old's allocation
- *
- * This is useful for when drivers embed the drm_mm_node structure and hence
- * can't move allocations by reassigning pointers. It's a combination of remove
- * and insert with the guarantee that the allocation start will match.
- */
-void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new)
-{
- struct drm_mm *mm = old->mm;
-
- DRM_MM_BUG_ON(!drm_mm_node_allocated(old));
-
- *new = *old;
-
- __set_bit(DRM_MM_NODE_ALLOCATED_BIT, &new->flags);
- list_replace(&old->node_list, &new->node_list);
- rb_replace_node_cached(&old->rb, &new->rb, &mm->interval_tree);
-
- if (drm_mm_hole_follows(old)) {
- list_replace(&old->hole_stack, &new->hole_stack);
- rb_replace_node_cached(&old->rb_hole_size,
- &new->rb_hole_size,
- &mm->holes_size);
- rb_replace_node(&old->rb_hole_addr,
- &new->rb_hole_addr,
- &mm->holes_addr);
- }
-
- clear_bit_unlock(DRM_MM_NODE_ALLOCATED_BIT, &old->flags);
-}
-EXPORT_SYMBOL(drm_mm_replace_node);
-
-/**
* DOC: lru scan roster
*
* Very often GPUs need to have continuous allocations for a given object. When
diff --git a/drivers/gpu/drm/drm_mode_object.c b/drivers/gpu/drm/drm_mode_object.c
index 0e8355063eee..df4cc0e8e263 100644
--- a/drivers/gpu/drm/drm_mode_object.c
+++ b/drivers/gpu/drm/drm_mode_object.c
@@ -478,6 +478,7 @@ struct drm_property *drm_mode_obj_find_prop_id(struct drm_mode_object *obj,
return NULL;
}
+EXPORT_SYMBOL_FOR_TESTS_ONLY(drm_mode_obj_find_prop_id);
static int set_property_legacy(struct drm_mode_object *obj,
struct drm_property *prop,
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 2d8b0371619d..1a0890083aee 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -531,7 +531,8 @@ static int fill_analog_mode(struct drm_device *dev,
* @interlace: whether to compute an interlaced mode
*
* This function creates a struct drm_display_mode instance suited for
- * an analog TV output, for one of the usual analog TV mode.
+ * an analog TV output, for one of the usual analog TV modes. Where
+ * this is DRM_MODE_TV_MODE_MONOCHROME, a 625-line mode will be created.
*
* Note that @hdisplay is larger than the usual constraints for the PAL
* and NTSC timings, and we'll choose to ignore most timings constraints
@@ -569,6 +570,8 @@ struct drm_display_mode *drm_analog_tv_mode(struct drm_device *dev,
case DRM_MODE_TV_MODE_PAL_N:
fallthrough;
case DRM_MODE_TV_MODE_SECAM:
+ fallthrough;
+ case DRM_MODE_TV_MODE_MONOCHROME:
analog = DRM_MODE_ANALOG_PAL;
break;
diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c
index aa93129c3397..3f84d7527793 100644
--- a/drivers/gpu/drm/drm_panel_orientation_quirks.c
+++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c
@@ -202,6 +202,12 @@ static const struct dmi_system_id orientation_data[] = {
DMI_MATCH(DMI_BOARD_NAME, "NEXT"),
},
.driver_data = (void *)&lcd800x1280_rightside_up,
+ }, { /* AYA NEO KUN */
+ .matches = {
+ DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AYANEO"),
+ DMI_MATCH(DMI_BOARD_NAME, "KUN"),
+ },
+ .driver_data = (void *)&lcd1600x2560_rightside_up,
}, { /* Chuwi HiBook (CWI514) */
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"),
@@ -414,13 +420,20 @@ static const struct dmi_system_id orientation_data[] = {
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Galaxy Book 10.6"),
},
.driver_data = (void *)&lcd1280x1920_rightside_up,
- }, { /* Valve Steam Deck */
+ }, { /* Valve Steam Deck (Jupiter) */
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Valve"),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Jupiter"),
DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "1"),
},
.driver_data = (void *)&lcd800x1280_rightside_up,
+ }, { /* Valve Steam Deck (Galileo) */
+ .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Valve"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Galileo"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "1"),
+ },
+ .driver_data = (void *)&lcd800x1280_rightside_up,
}, { /* VIOS LTH17 */
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "VIOS"),
@@ -501,4 +514,5 @@ EXPORT_SYMBOL(drm_get_panel_orientation_quirk);
#endif
+MODULE_DESCRIPTION("Quirks for non-normal panel orientation");
MODULE_LICENSE("Dual MIT/GPL");
diff --git a/drivers/gpu/drm/drm_panic.c b/drivers/gpu/drm/drm_panic.c
index 7ece67086cec..948aed00595e 100644
--- a/drivers/gpu/drm/drm_panic.c
+++ b/drivers/gpu/drm/drm_panic.c
@@ -7,15 +7,19 @@
*/
#include <linux/font.h>
+#include <linux/init.h>
#include <linux/iosys-map.h>
#include <linux/kdebug.h>
#include <linux/kmsg_dump.h>
+#include <linux/linux_logo.h>
#include <linux/list.h>
+#include <linux/math.h>
#include <linux/module.h>
+#include <linux/overflow.h>
+#include <linux/printk.h>
#include <linux/types.h>
#include <drm/drm_drv.h>
-#include <drm/drm_format_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_modeset_helper_vtables.h>
@@ -27,6 +31,12 @@ MODULE_AUTHOR("Jocelyn Falempe");
MODULE_DESCRIPTION("DRM panic handler");
MODULE_LICENSE("GPL");
+static char drm_panic_screen[16] = CONFIG_DRM_PANIC_SCREEN;
+module_param_string(panic_screen, drm_panic_screen, sizeof(drm_panic_screen), 0644);
+MODULE_PARM_DESC(panic_screen,
+ "Choose what will be displayed by drm_panic, 'user' or 'kmsg' [default="
+ CONFIG_DRM_PANIC_SCREEN "]");
+
/**
* DOC: overview
*
@@ -71,7 +81,7 @@ static struct drm_panic_line panic_msg[] = {
PANIC_LINE("Please reboot your computer."),
};
-static const struct drm_panic_line logo[] = {
+static const struct drm_panic_line logo_ascii[] = {
PANIC_LINE(" .--. _"),
PANIC_LINE(" |o_o | | |"),
PANIC_LINE(" |:_/ | | |"),
@@ -81,6 +91,42 @@ static const struct drm_panic_line logo[] = {
PANIC_LINE(" \\___)=(___/"),
};
+#if defined(CONFIG_LOGO) && !defined(MODULE)
+static const struct linux_logo *logo_mono;
+
+static int drm_panic_setup_logo(void)
+{
+ const struct linux_logo *logo = fb_find_logo(1);
+ const unsigned char *logo_data;
+ struct linux_logo *logo_dup;
+
+ if (!logo || logo->type != LINUX_LOGO_MONO)
+ return 0;
+
+ /* The logo is __init, so we must make a copy for later use */
+ logo_data = kmemdup(logo->data,
+ size_mul(DIV_ROUND_UP(logo->width, BITS_PER_BYTE), logo->height),
+ GFP_KERNEL);
+ if (!logo_data)
+ return -ENOMEM;
+
+ logo_dup = kmemdup(logo, sizeof(*logo), GFP_KERNEL);
+ if (!logo_dup) {
+ kfree(logo_data);
+ return -ENOMEM;
+ }
+
+ logo_dup->data = logo_data;
+ logo_mono = logo_dup;
+
+ return 0;
+}
+
+device_initcall(drm_panic_setup_logo);
+#else
+#define logo_mono ((const struct linux_logo *)NULL)
+#endif
+
/*
* Color conversion
*/
@@ -194,40 +240,42 @@ static u32 convert_from_xrgb8888(u32 color, u32 format)
/*
* Blit & Fill
*/
+/* check if the pixel at coord x,y is 1 (foreground) or 0 (background) */
+static bool drm_panic_is_pixel_fg(const u8 *sbuf8, unsigned int spitch, int x, int y)
+{
+ return (sbuf8[(y * spitch) + x / 8] & (0x80 >> (x % 8))) != 0;
+}
+
static void drm_panic_blit16(struct iosys_map *dmap, unsigned int dpitch,
const u8 *sbuf8, unsigned int spitch,
unsigned int height, unsigned int width,
- u16 fg16, u16 bg16)
+ u16 fg16)
{
unsigned int y, x;
- u16 val16;
- for (y = 0; y < height; y++) {
- for (x = 0; x < width; x++) {
- val16 = (sbuf8[(y * spitch) + x / 8] & (0x80 >> (x % 8))) ? fg16 : bg16;
- iosys_map_wr(dmap, y * dpitch + x * sizeof(u16), u16, val16);
- }
- }
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width; x++)
+ if (drm_panic_is_pixel_fg(sbuf8, spitch, x, y))
+ iosys_map_wr(dmap, y * dpitch + x * sizeof(u16), u16, fg16);
}
static void drm_panic_blit24(struct iosys_map *dmap, unsigned int dpitch,
const u8 *sbuf8, unsigned int spitch,
unsigned int height, unsigned int width,
- u32 fg32, u32 bg32)
+ u32 fg32)
{
unsigned int y, x;
- u32 val32;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
u32 off = y * dpitch + x * 3;
- val32 = (sbuf8[(y * spitch) + x / 8] & (0x80 >> (x % 8))) ? fg32 : bg32;
-
- /* write blue-green-red to output in little endianness */
- iosys_map_wr(dmap, off, u8, (val32 & 0x000000FF) >> 0);
- iosys_map_wr(dmap, off + 1, u8, (val32 & 0x0000FF00) >> 8);
- iosys_map_wr(dmap, off + 2, u8, (val32 & 0x00FF0000) >> 16);
+ if (drm_panic_is_pixel_fg(sbuf8, spitch, x, y)) {
+ /* write blue-green-red to output in little endianness */
+ iosys_map_wr(dmap, off, u8, (fg32 & 0x000000FF) >> 0);
+ iosys_map_wr(dmap, off + 1, u8, (fg32 & 0x0000FF00) >> 8);
+ iosys_map_wr(dmap, off + 2, u8, (fg32 & 0x00FF0000) >> 16);
+ }
}
}
}
@@ -235,55 +283,64 @@ static void drm_panic_blit24(struct iosys_map *dmap, unsigned int dpitch,
static void drm_panic_blit32(struct iosys_map *dmap, unsigned int dpitch,
const u8 *sbuf8, unsigned int spitch,
unsigned int height, unsigned int width,
- u32 fg32, u32 bg32)
+ u32 fg32)
{
unsigned int y, x;
- u32 val32;
- for (y = 0; y < height; y++) {
- for (x = 0; x < width; x++) {
- val32 = (sbuf8[(y * spitch) + x / 8] & (0x80 >> (x % 8))) ? fg32 : bg32;
- iosys_map_wr(dmap, y * dpitch + x * sizeof(u32), u32, val32);
- }
- }
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width; x++)
+ if (drm_panic_is_pixel_fg(sbuf8, spitch, x, y))
+ iosys_map_wr(dmap, y * dpitch + x * sizeof(u32), u32, fg32);
+}
+
+static void drm_panic_blit_pixel(struct drm_scanout_buffer *sb, struct drm_rect *clip,
+ const u8 *sbuf8, unsigned int spitch, u32 fg_color)
+{
+ unsigned int y, x;
+
+ for (y = 0; y < drm_rect_height(clip); y++)
+ for (x = 0; x < drm_rect_width(clip); x++)
+ if (drm_panic_is_pixel_fg(sbuf8, spitch, x, y))
+ sb->set_pixel(sb, clip->x1 + x, clip->y1 + y, fg_color);
}
/*
* drm_panic_blit - convert a monochrome image to a linear framebuffer
- * @dmap: destination iosys_map
- * @dpitch: destination pitch in bytes
+ * @sb: destination scanout buffer
+ * @clip: destination rectangle
* @sbuf8: source buffer, in monochrome format, 8 pixels per byte.
* @spitch: source pitch in bytes
- * @height: height of the image to copy, in pixels
- * @width: width of the image to copy, in pixels
* @fg_color: foreground color, in destination format
- * @bg_color: background color, in destination format
- * @pixel_width: pixel width in bytes.
*
* This can be used to draw a font character, which is a monochrome image, to a
* framebuffer in other supported format.
*/
-static void drm_panic_blit(struct iosys_map *dmap, unsigned int dpitch,
- const u8 *sbuf8, unsigned int spitch,
- unsigned int height, unsigned int width,
- u32 fg_color, u32 bg_color,
- unsigned int pixel_width)
+static void drm_panic_blit(struct drm_scanout_buffer *sb, struct drm_rect *clip,
+ const u8 *sbuf8, unsigned int spitch, u32 fg_color)
{
- switch (pixel_width) {
+ struct iosys_map map;
+
+ if (sb->set_pixel)
+ return drm_panic_blit_pixel(sb, clip, sbuf8, spitch, fg_color);
+
+ map = sb->map[0];
+ iosys_map_incr(&map, clip->y1 * sb->pitch[0] + clip->x1 * sb->format->cpp[0]);
+
+ switch (sb->format->cpp[0]) {
case 2:
- drm_panic_blit16(dmap, dpitch, sbuf8, spitch,
- height, width, fg_color, bg_color);
+ drm_panic_blit16(&map, sb->pitch[0], sbuf8, spitch,
+ drm_rect_height(clip), drm_rect_width(clip), fg_color);
break;
case 3:
- drm_panic_blit24(dmap, dpitch, sbuf8, spitch,
- height, width, fg_color, bg_color);
+ drm_panic_blit24(&map, sb->pitch[0], sbuf8, spitch,
+ drm_rect_height(clip), drm_rect_width(clip), fg_color);
break;
case 4:
- drm_panic_blit32(dmap, dpitch, sbuf8, spitch,
- height, width, fg_color, bg_color);
+ drm_panic_blit32(&map, sb->pitch[0], sbuf8, spitch,
+ drm_rect_height(clip), drm_rect_width(clip), fg_color);
break;
default:
- WARN_ONCE(1, "Can't blit with pixel width %d\n", pixel_width);
+ WARN_ONCE(1, "Can't blit with pixel width %d\n", sb->format->cpp[0]);
}
}
@@ -327,33 +384,51 @@ static void drm_panic_fill32(struct iosys_map *dmap, unsigned int dpitch,
iosys_map_wr(dmap, y * dpitch + x * sizeof(u32), u32, color);
}
+static void drm_panic_fill_pixel(struct drm_scanout_buffer *sb,
+ struct drm_rect *clip,
+ u32 color)
+{
+ unsigned int y, x;
+
+ for (y = 0; y < drm_rect_height(clip); y++)
+ for (x = 0; x < drm_rect_width(clip); x++)
+ sb->set_pixel(sb, clip->x1 + x, clip->y1 + y, color);
+}
+
/*
* drm_panic_fill - Fill a rectangle with a color
- * @dmap: destination iosys_map, pointing to the top left corner of the rectangle
- * @dpitch: destination pitch in bytes
- * @height: height of the rectangle, in pixels
- * @width: width of the rectangle, in pixels
- * @color: color to fill the rectangle.
- * @pixel_width: pixel width in bytes
+ * @sb: destination scanout buffer
+ * @clip: destination rectangle
+ * @color: foreground color, in destination format
*
* Fill a rectangle with a color, in a linear framebuffer.
*/
-static void drm_panic_fill(struct iosys_map *dmap, unsigned int dpitch,
- unsigned int height, unsigned int width,
- u32 color, unsigned int pixel_width)
+static void drm_panic_fill(struct drm_scanout_buffer *sb, struct drm_rect *clip,
+ u32 color)
{
- switch (pixel_width) {
+ struct iosys_map map;
+
+ if (sb->set_pixel)
+ return drm_panic_fill_pixel(sb, clip, color);
+
+ map = sb->map[0];
+ iosys_map_incr(&map, clip->y1 * sb->pitch[0] + clip->x1 * sb->format->cpp[0]);
+
+ switch (sb->format->cpp[0]) {
case 2:
- drm_panic_fill16(dmap, dpitch, height, width, color);
+ drm_panic_fill16(&map, sb->pitch[0], drm_rect_height(clip),
+ drm_rect_width(clip), color);
break;
case 3:
- drm_panic_fill24(dmap, dpitch, height, width, color);
+ drm_panic_fill24(&map, sb->pitch[0], drm_rect_height(clip),
+ drm_rect_width(clip), color);
break;
case 4:
- drm_panic_fill32(dmap, dpitch, height, width, color);
+ drm_panic_fill32(&map, sb->pitch[0], drm_rect_height(clip),
+ drm_rect_width(clip), color);
break;
default:
- WARN_ONCE(1, "Can't fill with pixel width %d\n", pixel_width);
+ WARN_ONCE(1, "Can't fill with pixel width %d\n", sb->format->cpp[0]);
}
}
@@ -381,57 +456,57 @@ static void draw_txt_rectangle(struct drm_scanout_buffer *sb,
unsigned int msg_lines,
bool centered,
struct drm_rect *clip,
- u32 fg_color,
- u32 bg_color)
+ u32 color)
{
int i, j;
const u8 *src;
size_t font_pitch = DIV_ROUND_UP(font->width, 8);
- struct iosys_map dst;
- unsigned int px_width = sb->format->cpp[0];
- int left = 0;
+ struct drm_rect rec;
msg_lines = min(msg_lines, drm_rect_height(clip) / font->height);
for (i = 0; i < msg_lines; i++) {
size_t line_len = min(msg[i].len, drm_rect_width(clip) / font->width);
+ rec.y1 = clip->y1 + i * font->height;
+ rec.y2 = rec.y1 + font->height;
+ rec.x1 = clip->x1;
+
if (centered)
- left = (drm_rect_width(clip) - (line_len * font->width)) / 2;
+ rec.x1 += (drm_rect_width(clip) - (line_len * font->width)) / 2;
- dst = sb->map[0];
- iosys_map_incr(&dst, (clip->y1 + i * font->height) * sb->pitch[0] +
- (clip->x1 + left) * px_width);
for (j = 0; j < line_len; j++) {
src = get_char_bitmap(font, msg[i].txt[j], font_pitch);
- drm_panic_blit(&dst, sb->pitch[0], src, font_pitch,
- font->height, font->width,
- fg_color, bg_color, px_width);
- iosys_map_incr(&dst, font->width * px_width);
+ rec.x2 = rec.x1 + font->width;
+ drm_panic_blit(sb, &rec, src, font_pitch, color);
+ rec.x1 += font->width;
}
}
}
-/*
- * Draw the panic message at the center of the screen
- */
-static void draw_panic_static(struct drm_scanout_buffer *sb)
+static void draw_panic_static_user(struct drm_scanout_buffer *sb)
{
size_t msg_lines = ARRAY_SIZE(panic_msg);
- size_t logo_lines = ARRAY_SIZE(logo);
- u32 fg_color = CONFIG_DRM_PANIC_FOREGROUND_COLOR;
- u32 bg_color = CONFIG_DRM_PANIC_BACKGROUND_COLOR;
+ size_t logo_ascii_lines = ARRAY_SIZE(logo_ascii);
+ u32 fg_color = convert_from_xrgb8888(CONFIG_DRM_PANIC_FOREGROUND_COLOR, sb->format->format);
+ u32 bg_color = convert_from_xrgb8888(CONFIG_DRM_PANIC_BACKGROUND_COLOR, sb->format->format);
const struct font_desc *font = get_default_font(sb->width, sb->height, NULL, NULL);
- struct drm_rect r_logo, r_msg;
+ struct drm_rect r_screen, r_logo, r_msg;
+ unsigned int logo_width, logo_height;
if (!font)
return;
- fg_color = convert_from_xrgb8888(fg_color, sb->format->format);
- bg_color = convert_from_xrgb8888(bg_color, sb->format->format);
+ r_screen = DRM_RECT_INIT(0, 0, sb->width, sb->height);
+
+ if (logo_mono) {
+ logo_width = logo_mono->width;
+ logo_height = logo_mono->height;
+ } else {
+ logo_width = get_max_line_len(logo_ascii, logo_ascii_lines) * font->width;
+ logo_height = logo_ascii_lines * font->height;
+ }
- r_logo = DRM_RECT_INIT(0, 0,
- get_max_line_len(logo, logo_lines) * font->width,
- logo_lines * font->height);
+ r_logo = DRM_RECT_INIT(0, 0, logo_width, logo_height);
r_msg = DRM_RECT_INIT(0, 0,
min(get_max_line_len(panic_msg, msg_lines) * font->width, sb->width),
min(msg_lines * font->height, sb->height));
@@ -440,14 +515,97 @@ static void draw_panic_static(struct drm_scanout_buffer *sb)
drm_rect_translate(&r_msg, (sb->width - r_msg.x2) / 2, (sb->height - r_msg.y2) / 2);
/* Fill with the background color, and draw text on top */
- drm_panic_fill(&sb->map[0], sb->pitch[0], sb->height, sb->width,
- bg_color, sb->format->cpp[0]);
+ drm_panic_fill(sb, &r_screen, bg_color);
+
+ if ((r_msg.x1 >= logo_width || r_msg.y1 >= logo_height) &&
+ logo_width <= sb->width && logo_height <= sb->height) {
+ if (logo_mono)
+ drm_panic_blit(sb, &r_logo, logo_mono->data, DIV_ROUND_UP(logo_width, 8),
+ fg_color);
+ else
+ draw_txt_rectangle(sb, font, logo_ascii, logo_ascii_lines, false, &r_logo,
+ fg_color);
+ }
+ draw_txt_rectangle(sb, font, panic_msg, msg_lines, true, &r_msg, fg_color);
+}
- if ((r_msg.x1 >= drm_rect_width(&r_logo) || r_msg.y1 >= drm_rect_height(&r_logo)) &&
- drm_rect_width(&r_logo) < sb->width && drm_rect_height(&r_logo) < sb->height) {
- draw_txt_rectangle(sb, font, logo, logo_lines, false, &r_logo, fg_color, bg_color);
+/*
+ * Draw one line of kmsg, and handle wrapping if it won't fit in the screen width.
+ * Return the y-offset of the next line.
+ */
+static int draw_line_with_wrap(struct drm_scanout_buffer *sb, const struct font_desc *font,
+ struct drm_panic_line *line, int yoffset, u32 fg_color)
+{
+ int chars_per_row = sb->width / font->width;
+ struct drm_rect r_txt = DRM_RECT_INIT(0, yoffset, sb->width, sb->height);
+ struct drm_panic_line line_wrap;
+
+ if (line->len > chars_per_row) {
+ line_wrap.len = line->len % chars_per_row;
+ line_wrap.txt = line->txt + line->len - line_wrap.len;
+ draw_txt_rectangle(sb, font, &line_wrap, 1, false, &r_txt, fg_color);
+ r_txt.y1 -= font->height;
+ if (r_txt.y1 < 0)
+ return r_txt.y1;
+ while (line_wrap.txt > line->txt) {
+ line_wrap.txt -= chars_per_row;
+ line_wrap.len = chars_per_row;
+ draw_txt_rectangle(sb, font, &line_wrap, 1, false, &r_txt, fg_color);
+ r_txt.y1 -= font->height;
+ if (r_txt.y1 < 0)
+ return r_txt.y1;
+ }
+ } else {
+ draw_txt_rectangle(sb, font, line, 1, false, &r_txt, fg_color);
+ r_txt.y1 -= font->height;
+ }
+ return r_txt.y1;
+}
+
+/*
+ * Draw the kmsg buffer to the screen, starting from the youngest message at the bottom,
+ * and going up until reaching the top of the screen.
+ */
+static void draw_panic_static_kmsg(struct drm_scanout_buffer *sb)
+{
+ u32 fg_color = convert_from_xrgb8888(CONFIG_DRM_PANIC_FOREGROUND_COLOR, sb->format->format);
+ u32 bg_color = convert_from_xrgb8888(CONFIG_DRM_PANIC_BACKGROUND_COLOR, sb->format->format);
+ const struct font_desc *font = get_default_font(sb->width, sb->height, NULL, NULL);
+ struct drm_rect r_screen = DRM_RECT_INIT(0, 0, sb->width, sb->height);
+ struct kmsg_dump_iter iter;
+ char kmsg_buf[512];
+ size_t kmsg_len;
+ struct drm_panic_line line;
+ int yoffset;
+
+ if (!font)
+ return;
+
+ yoffset = sb->height - font->height - (sb->height % font->height) / 2;
+
+ /* Fill with the background color, and draw text on top */
+ drm_panic_fill(sb, &r_screen, bg_color);
+
+ kmsg_dump_rewind(&iter);
+ while (kmsg_dump_get_buffer(&iter, false, kmsg_buf, sizeof(kmsg_buf), &kmsg_len)) {
+ char *start;
+ char *end;
+
+ /* ignore terminating NUL and newline */
+ start = kmsg_buf + kmsg_len - 2;
+ end = kmsg_buf + kmsg_len - 1;
+ while (start > kmsg_buf && yoffset >= 0) {
+ while (start > kmsg_buf && *start != '\n')
+ start--;
+ /* don't count the newline character */
+ line.txt = start + (start == kmsg_buf ? 0 : 1);
+ line.len = end - line.txt;
+
+ yoffset = draw_line_with_wrap(sb, font, &line, yoffset, fg_color);
+ end = start;
+ start--;
+ }
}
- draw_txt_rectangle(sb, font, panic_msg, msg_lines, true, &r_msg, fg_color, bg_color);
}
/*
@@ -464,9 +622,18 @@ static bool drm_panic_is_format_supported(const struct drm_format_info *format)
return convert_from_xrgb8888(0xffffff, format->format) != 0;
}
+static void draw_panic_dispatch(struct drm_scanout_buffer *sb)
+{
+ if (!strcmp(drm_panic_screen, "kmsg")) {
+ draw_panic_static_kmsg(sb);
+ } else {
+ draw_panic_static_user(sb);
+ }
+}
+
static void draw_panic_plane(struct drm_plane *plane)
{
- struct drm_scanout_buffer sb;
+ struct drm_scanout_buffer sb = { };
int ret;
unsigned long flags;
@@ -476,7 +643,7 @@ static void draw_panic_plane(struct drm_plane *plane)
ret = plane->helper_private->get_scanout_buffer(plane, &sb);
if (!ret && drm_panic_is_format_supported(sb.format)) {
- draw_panic_static(&sb);
+ draw_panic_dispatch(&sb);
if (plane->helper_private->panic_flush)
plane->helper_private->panic_flush(plane);
}
diff --git a/drivers/gpu/drm/drm_print.c b/drivers/gpu/drm/drm_print.c
index cf2efb44722c..cf24dfdeb6b2 100644
--- a/drivers/gpu/drm/drm_print.c
+++ b/drivers/gpu/drm/drm_print.c
@@ -176,6 +176,32 @@ void __drm_printfn_seq_file(struct drm_printer *p, struct va_format *vaf)
}
EXPORT_SYMBOL(__drm_printfn_seq_file);
+static void __drm_dev_vprintk(const struct device *dev, const char *level,
+ const void *origin, const char *prefix,
+ struct va_format *vaf)
+{
+ const char *prefix_pad = prefix ? " " : "";
+
+ if (!prefix)
+ prefix = "";
+
+ if (dev) {
+ if (origin)
+ dev_printk(level, dev, "[" DRM_NAME ":%ps]%s%s %pV",
+ origin, prefix_pad, prefix, vaf);
+ else
+ dev_printk(level, dev, "[" DRM_NAME "]%s%s %pV",
+ prefix_pad, prefix, vaf);
+ } else {
+ if (origin)
+ printk("%s" "[" DRM_NAME ":%ps]%s%s %pV",
+ level, origin, prefix_pad, prefix, vaf);
+ else
+ printk("%s" "[" DRM_NAME "]%s%s %pV",
+ level, prefix_pad, prefix, vaf);
+ }
+}
+
void __drm_printfn_info(struct drm_printer *p, struct va_format *vaf)
{
dev_info(p->arg, "[" DRM_NAME "] %pV", vaf);
@@ -187,19 +213,11 @@ void __drm_printfn_dbg(struct drm_printer *p, struct va_format *vaf)
const struct drm_device *drm = p->arg;
const struct device *dev = drm ? drm->dev : NULL;
enum drm_debug_category category = p->category;
- const char *prefix = p->prefix ?: "";
- const char *prefix_pad = p->prefix ? " " : "";
if (!__drm_debug_enabled(category))
return;
- /* Note: __builtin_return_address(0) is useless here. */
- if (dev)
- dev_printk(KERN_DEBUG, dev, "[" DRM_NAME "]%s%s %pV",
- prefix_pad, prefix, vaf);
- else
- printk(KERN_DEBUG "[" DRM_NAME "]%s%s %pV",
- prefix_pad, prefix, vaf);
+ __drm_dev_vprintk(dev, KERN_DEBUG, p->origin, p->prefix, vaf);
}
EXPORT_SYMBOL(__drm_printfn_dbg);
@@ -287,12 +305,7 @@ void drm_dev_printk(const struct device *dev, const char *level,
vaf.fmt = format;
vaf.va = &args;
- if (dev)
- dev_printk(level, dev, "[" DRM_NAME ":%ps] %pV",
- __builtin_return_address(0), &vaf);
- else
- printk("%s" "[" DRM_NAME ":%ps] %pV",
- level, __builtin_return_address(0), &vaf);
+ __drm_dev_vprintk(dev, level, __builtin_return_address(0), NULL, &vaf);
va_end(args);
}
@@ -312,36 +325,12 @@ void __drm_dev_dbg(struct _ddebug *desc, const struct device *dev,
vaf.fmt = format;
vaf.va = &args;
- if (dev)
- dev_printk(KERN_DEBUG, dev, "[" DRM_NAME ":%ps] %pV",
- __builtin_return_address(0), &vaf);
- else
- printk(KERN_DEBUG "[" DRM_NAME ":%ps] %pV",
- __builtin_return_address(0), &vaf);
+ __drm_dev_vprintk(dev, KERN_DEBUG, __builtin_return_address(0), NULL, &vaf);
va_end(args);
}
EXPORT_SYMBOL(__drm_dev_dbg);
-void ___drm_dbg(struct _ddebug *desc, enum drm_debug_category category, const char *format, ...)
-{
- struct va_format vaf;
- va_list args;
-
- if (!__drm_debug_enabled(category))
- return;
-
- va_start(args, format);
- vaf.fmt = format;
- vaf.va = &args;
-
- printk(KERN_DEBUG "[" DRM_NAME ":%ps] %pV",
- __builtin_return_address(0), &vaf);
-
- va_end(args);
-}
-EXPORT_SYMBOL(___drm_dbg);
-
void __drm_err(const char *format, ...)
{
struct va_format vaf;
@@ -351,8 +340,7 @@ void __drm_err(const char *format, ...)
vaf.fmt = format;
vaf.va = &args;
- printk(KERN_ERR "[" DRM_NAME ":%ps] *ERROR* %pV",
- __builtin_return_address(0), &vaf);
+ __drm_dev_vprintk(NULL, KERN_ERR, __builtin_return_address(0), "*ERROR*", &vaf);
va_end(args);
}
diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
index 4f75a1cfd820..bb49d552e671 100644
--- a/drivers/gpu/drm/drm_probe_helper.c
+++ b/drivers/gpu/drm/drm_probe_helper.c
@@ -474,6 +474,10 @@ static int __drm_helper_update_and_validate(struct drm_connector *connector,
if (mode->status != MODE_OK)
continue;
+ mode->status = drm_mode_validate_ycbcr420(mode, connector);
+ if (mode->status != MODE_OK)
+ continue;
+
ret = drm_mode_validate_pipeline(mode, connector, ctx,
&mode->status);
if (ret) {
@@ -486,10 +490,6 @@ static int __drm_helper_update_and_validate(struct drm_connector *connector,
else
return -EDEADLK;
}
-
- if (mode->status != MODE_OK)
- continue;
- mode->status = drm_mode_validate_ycbcr420(mode, connector);
}
return 0;
@@ -1259,8 +1259,9 @@ int drm_connector_helper_tv_get_modes(struct drm_connector *connector)
for (i = 0; i < tv_mode_property->num_values; i++)
supported_tv_modes |= BIT(tv_mode_property->values[i]);
- if ((supported_tv_modes & ntsc_modes) &&
- (supported_tv_modes & pal_modes)) {
+ if (((supported_tv_modes & ntsc_modes) &&
+ (supported_tv_modes & pal_modes)) ||
+ (supported_tv_modes & BIT(DRM_MODE_TV_MODE_MONOCHROME))) {
uint64_t default_mode;
if (drm_object_property_get_default_value(&connector->base,
diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c
index 270523ae36d4..250819fbc5ce 100644
--- a/drivers/gpu/drm/drm_simple_kms_helper.c
+++ b/drivers/gpu/drm/drm_simple_kms_helper.c
@@ -453,4 +453,5 @@ int drm_simple_display_pipe_init(struct drm_device *dev,
}
EXPORT_SYMBOL(drm_simple_display_pipe_init);
+MODULE_DESCRIPTION("Helpers for drivers for simple display hardware");
MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
index bd9b8ab4f82b..fb3bbb6adcd1 100644
--- a/drivers/gpu/drm/drm_sysfs.c
+++ b/drivers/gpu/drm/drm_sysfs.c
@@ -266,29 +266,9 @@ static ssize_t edid_show(struct file *filp, struct kobject *kobj,
{
struct device *connector_dev = kobj_to_dev(kobj);
struct drm_connector *connector = to_drm_connector(connector_dev);
- unsigned char *edid;
- size_t size;
- ssize_t ret = 0;
+ ssize_t ret;
- mutex_lock(&connector->dev->mode_config.mutex);
- if (!connector->edid_blob_ptr)
- goto unlock;
-
- edid = connector->edid_blob_ptr->data;
- size = connector->edid_blob_ptr->length;
- if (!edid)
- goto unlock;
-
- if (off >= size)
- goto unlock;
-
- if (off + count > size)
- count = size - off;
- memcpy(buf, edid + off, count);
-
- ret = count;
-unlock:
- mutex_unlock(&connector->dev->mode_config.mutex);
+ ret = drm_edid_connector_property_show(connector, buf, off, count);
return ret;
}
diff --git a/drivers/gpu/drm/etnaviv/cmdstream.xml.h b/drivers/gpu/drm/etnaviv/cmdstream.xml.h
index 65f1ba1099bd..a96597a27ae2 100644
--- a/drivers/gpu/drm/etnaviv/cmdstream.xml.h
+++ b/drivers/gpu/drm/etnaviv/cmdstream.xml.h
@@ -8,11 +8,11 @@ http://0x04.net/cgit/index.cgi/rules-ng-ng
git clone git://0x04.net/rules-ng-ng
The rules-ng-ng source files this header was generated from are:
-- cmdstream.xml ( 14094 bytes, from 2016-11-11 06:55:14)
-- copyright.xml ( 1597 bytes, from 2016-10-29 07:29:22)
-- common.xml ( 23344 bytes, from 2016-11-10 15:14:07)
+- cmdstream.xml ( 16933 bytes, from 2023-12-11 15:50:17)
+- copyright.xml ( 1597 bytes, from 2016-11-10 13:58:32)
+- common.xml ( 35664 bytes, from 2023-12-06 10:55:32)
-Copyright (C) 2012-2016 by the following authors:
+Copyright (C) 2012-2023 by the following authors:
- Wladimir J. van der Laan <laanwj@gmail.com>
- Christian Gmeiner <christian.gmeiner@gmail.com>
- Lucas Stach <l.stach@pengutronix.de>
@@ -52,6 +52,9 @@ DEALINGS IN THE SOFTWARE.
#define FE_OPCODE_RETURN 0x0000000b
#define FE_OPCODE_DRAW_INSTANCED 0x0000000c
#define FE_OPCODE_CHIP_SELECT 0x0000000d
+#define FE_OPCODE_WAIT_FENCE 0x0000000f
+#define FE_OPCODE_DRAW_INDIRECT 0x00000010
+#define FE_OPCODE_SNAP_PAGES 0x00000013
#define PRIMITIVE_TYPE_POINTS 0x00000001
#define PRIMITIVE_TYPE_LINES 0x00000002
#define PRIMITIVE_TYPE_LINE_STRIP 0x00000003
@@ -192,6 +195,9 @@ DEALINGS IN THE SOFTWARE.
#define VIV_FE_STALL_TOKEN_TO__MASK 0x00001f00
#define VIV_FE_STALL_TOKEN_TO__SHIFT 8
#define VIV_FE_STALL_TOKEN_TO(x) (((x) << VIV_FE_STALL_TOKEN_TO__SHIFT) & VIV_FE_STALL_TOKEN_TO__MASK)
+#define VIV_FE_STALL_TOKEN_UNK28__MASK 0x30000000
+#define VIV_FE_STALL_TOKEN_UNK28__SHIFT 28
+#define VIV_FE_STALL_TOKEN_UNK28(x) (((x) << VIV_FE_STALL_TOKEN_UNK28__SHIFT) & VIV_FE_STALL_TOKEN_UNK28__MASK)
#define VIV_FE_CALL 0x00000000
@@ -266,5 +272,43 @@ DEALINGS IN THE SOFTWARE.
#define VIV_FE_DRAW_INSTANCED_START_INDEX__SHIFT 0
#define VIV_FE_DRAW_INSTANCED_START_INDEX(x) (((x) << VIV_FE_DRAW_INSTANCED_START_INDEX__SHIFT) & VIV_FE_DRAW_INSTANCED_START_INDEX__MASK)
+#define VIV_FE_WAIT_FENCE 0x00000000
+
+#define VIV_FE_WAIT_FENCE_HEADER 0x00000000
+#define VIV_FE_WAIT_FENCE_HEADER_OP__MASK 0xf8000000
+#define VIV_FE_WAIT_FENCE_HEADER_OP__SHIFT 27
+#define VIV_FE_WAIT_FENCE_HEADER_OP_WAIT_FENCE 0x78000000
+#define VIV_FE_WAIT_FENCE_HEADER_UNK16__MASK 0x00030000
+#define VIV_FE_WAIT_FENCE_HEADER_UNK16__SHIFT 16
+#define VIV_FE_WAIT_FENCE_HEADER_UNK16(x) (((x) << VIV_FE_WAIT_FENCE_HEADER_UNK16__SHIFT) & VIV_FE_WAIT_FENCE_HEADER_UNK16__MASK)
+#define VIV_FE_WAIT_FENCE_HEADER_WAITCOUNT__MASK 0x0000ffff
+#define VIV_FE_WAIT_FENCE_HEADER_WAITCOUNT__SHIFT 0
+#define VIV_FE_WAIT_FENCE_HEADER_WAITCOUNT(x) (((x) << VIV_FE_WAIT_FENCE_HEADER_WAITCOUNT__SHIFT) & VIV_FE_WAIT_FENCE_HEADER_WAITCOUNT__MASK)
+
+#define VIV_FE_WAIT_FENCE_ADDRESS 0x00000004
+
+#define VIV_FE_DRAW_INDIRECT 0x00000000
+
+#define VIV_FE_DRAW_INDIRECT_HEADER 0x00000000
+#define VIV_FE_DRAW_INDIRECT_HEADER_OP__MASK 0xf8000000
+#define VIV_FE_DRAW_INDIRECT_HEADER_OP__SHIFT 27
+#define VIV_FE_DRAW_INDIRECT_HEADER_OP_DRAW_INDIRECT 0x80000000
+#define VIV_FE_DRAW_INDIRECT_HEADER_INDEXED 0x00000100
+#define VIV_FE_DRAW_INDIRECT_HEADER_TYPE__MASK 0x0000000f
+#define VIV_FE_DRAW_INDIRECT_HEADER_TYPE__SHIFT 0
+#define VIV_FE_DRAW_INDIRECT_HEADER_TYPE(x) (((x) << VIV_FE_DRAW_INDIRECT_HEADER_TYPE__SHIFT) & VIV_FE_DRAW_INDIRECT_HEADER_TYPE__MASK)
+
+#define VIV_FE_DRAW_INDIRECT_ADDRESS 0x00000004
+
+#define VIV_FE_SNAP_PAGES 0x00000000
+
+#define VIV_FE_SNAP_PAGES_HEADER 0x00000000
+#define VIV_FE_SNAP_PAGES_HEADER_OP__MASK 0xf8000000
+#define VIV_FE_SNAP_PAGES_HEADER_OP__SHIFT 27
+#define VIV_FE_SNAP_PAGES_HEADER_OP_SNAP_PAGES 0x98000000
+#define VIV_FE_SNAP_PAGES_HEADER_UNK0__MASK 0x0000001f
+#define VIV_FE_SNAP_PAGES_HEADER_UNK0__SHIFT 0
+#define VIV_FE_SNAP_PAGES_HEADER_UNK0(x) (((x) << VIV_FE_SNAP_PAGES_HEADER_UNK0__SHIFT) & VIV_FE_SNAP_PAGES_HEADER_UNK0__MASK)
+
#endif /* CMDSTREAM_XML */
diff --git a/drivers/gpu/drm/etnaviv/common.xml.h b/drivers/gpu/drm/etnaviv/common.xml.h
index 001faea80fef..07c0bf47d89f 100644
--- a/drivers/gpu/drm/etnaviv/common.xml.h
+++ b/drivers/gpu/drm/etnaviv/common.xml.h
@@ -8,12 +8,12 @@ http://0x04.net/cgit/index.cgi/rules-ng-ng
git clone git://0x04.net/rules-ng-ng
The rules-ng-ng source files this header was generated from are:
-- texdesc_3d.xml ( 3183 bytes, from 2017-12-18 16:51:59)
-- copyright.xml ( 1597 bytes, from 2016-12-08 16:37:56)
-- common.xml ( 35468 bytes, from 2018-01-22 13:48:54)
-- common_3d.xml ( 14615 bytes, from 2017-12-18 16:51:59)
+- texdesc_3d.xml ( 3183 bytes, from 2022-11-18 09:38:25)
+- copyright.xml ( 1597 bytes, from 2016-11-10 13:58:32)
+- common.xml ( 35664 bytes, from 2023-12-06 10:55:32)
+- common_3d.xml ( 15069 bytes, from 2023-11-22 10:05:24)
-Copyright (C) 2012-2018 by the following authors:
+Copyright (C) 2012-2023 by the following authors:
- Wladimir J. van der Laan <laanwj@gmail.com>
- Christian Gmeiner <christian.gmeiner@gmail.com>
- Lucas Stach <l.stach@pengutronix.de>
@@ -65,6 +65,7 @@ DEALINGS IN THE SOFTWARE.
#define chipModel_GC520 0x00000520
#define chipModel_GC530 0x00000530
#define chipModel_GC600 0x00000600
+#define chipModel_GC620 0x00000620
#define chipModel_GC700 0x00000700
#define chipModel_GC800 0x00000800
#define chipModel_GC860 0x00000860
@@ -481,5 +482,6 @@ DEALINGS IN THE SOFTWARE.
#define chipMinorFeatures11_NN_INTERLEVE8 0x00000008
#define chipMinorFeatures11_TP_REORDER 0x00000010
#define chipMinorFeatures11_PE_DEPTH_ONLY_OQFIX 0x00000020
+#define chipMinorFeatures12_G2D_DEC400EX 0x00000020
#endif /* COMMON_XML */
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_dump.c b/drivers/gpu/drm/etnaviv/etnaviv_dump.c
index 898f84a0fc30..2cd223461eba 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_dump.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_dump.c
@@ -159,8 +159,7 @@ void etnaviv_core_dump(struct etnaviv_gem_submit *submit)
file_size += sizeof(*iter.hdr) * n_obj;
/* Allocate the file in vmalloc memory, it's likely to be big */
- iter.start = __vmalloc(file_size, GFP_KERNEL | __GFP_NOWARN |
- __GFP_NORETRY);
+ iter.start = __vmalloc(file_size, GFP_NOWAIT);
if (!iter.start) {
mutex_unlock(&submit->mmu_context->lock);
dev_warn(gpu->dev, "failed to allocate devcoredump file\n");
@@ -230,5 +229,5 @@ void etnaviv_core_dump(struct etnaviv_gem_submit *submit)
etnaviv_core_dump_header(&iter, ETDUMP_BUF_END, iter.data);
- dev_coredumpv(gpu->dev, iter.start, iter.data - iter.start, GFP_KERNEL);
+ dev_coredumpv(gpu->dev, iter.start, iter.data - iter.start, GFP_NOWAIT);
}
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c b/drivers/gpu/drm/etnaviv/etnaviv_gem.c
index 71a6d2b1c80f..5c0c9d4e3be1 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c
@@ -355,9 +355,11 @@ static void *etnaviv_gem_vmap_impl(struct etnaviv_gem_object *obj)
static inline enum dma_data_direction etnaviv_op_to_dma_dir(u32 op)
{
- if (op & ETNA_PREP_READ)
+ op &= ETNA_PREP_READ | ETNA_PREP_WRITE;
+
+ if (op == ETNA_PREP_READ)
return DMA_FROM_DEVICE;
- else if (op & ETNA_PREP_WRITE)
+ else if (op == ETNA_PREP_WRITE)
return DMA_TO_DEVICE;
else
return DMA_BIDIRECTIONAL;
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
index a9bf426f69b3..7c7f97793ddd 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
@@ -172,10 +172,12 @@ int etnaviv_gpu_get_param(struct etnaviv_gpu *gpu, u32 param, u64 *value)
return 0;
}
+static inline bool etnaviv_is_model_rev(struct etnaviv_gpu *gpu, u32 model, u32 revision)
+{
+ return gpu->identity.model == model &&
+ gpu->identity.revision == revision;
+}
-#define etnaviv_is_model_rev(gpu, mod, rev) \
- ((gpu)->identity.model == chipModel_##mod && \
- (gpu)->identity.revision == rev)
#define etnaviv_field(val, field) \
(((val) & field##__MASK) >> field##__SHIFT)
@@ -281,7 +283,7 @@ static void etnaviv_hw_specs(struct etnaviv_gpu *gpu)
switch (gpu->identity.instruction_count) {
case 0:
- if (etnaviv_is_model_rev(gpu, GC2000, 0x5108) ||
+ if (etnaviv_is_model_rev(gpu, 0x2000, 0x5108) ||
gpu->identity.model == chipModel_GC880)
gpu->identity.instruction_count = 512;
else
@@ -315,17 +317,17 @@ static void etnaviv_hw_specs(struct etnaviv_gpu *gpu)
* For some cores, two varyings are consumed for position, so the
* maximum varying count needs to be reduced by one.
*/
- if (etnaviv_is_model_rev(gpu, GC5000, 0x5434) ||
- etnaviv_is_model_rev(gpu, GC4000, 0x5222) ||
- etnaviv_is_model_rev(gpu, GC4000, 0x5245) ||
- etnaviv_is_model_rev(gpu, GC4000, 0x5208) ||
- etnaviv_is_model_rev(gpu, GC3000, 0x5435) ||
- etnaviv_is_model_rev(gpu, GC2200, 0x5244) ||
- etnaviv_is_model_rev(gpu, GC2100, 0x5108) ||
- etnaviv_is_model_rev(gpu, GC2000, 0x5108) ||
- etnaviv_is_model_rev(gpu, GC1500, 0x5246) ||
- etnaviv_is_model_rev(gpu, GC880, 0x5107) ||
- etnaviv_is_model_rev(gpu, GC880, 0x5106))
+ if (etnaviv_is_model_rev(gpu, 0x5000, 0x5434) ||
+ etnaviv_is_model_rev(gpu, 0x4000, 0x5222) ||
+ etnaviv_is_model_rev(gpu, 0x4000, 0x5245) ||
+ etnaviv_is_model_rev(gpu, 0x4000, 0x5208) ||
+ etnaviv_is_model_rev(gpu, 0x3000, 0x5435) ||
+ etnaviv_is_model_rev(gpu, 0x2200, 0x5244) ||
+ etnaviv_is_model_rev(gpu, 0x2100, 0x5108) ||
+ etnaviv_is_model_rev(gpu, 0x2000, 0x5108) ||
+ etnaviv_is_model_rev(gpu, 0x1500, 0x5246) ||
+ etnaviv_is_model_rev(gpu, 0x880, 0x5107) ||
+ etnaviv_is_model_rev(gpu, 0x880, 0x5106))
gpu->identity.varyings_count -= 1;
}
@@ -351,7 +353,7 @@ static void etnaviv_hw_identify(struct etnaviv_gpu *gpu)
* Reading these two registers on GC600 rev 0x19 result in a
* unhandled fault: external abort on non-linefetch
*/
- if (!etnaviv_is_model_rev(gpu, GC600, 0x19)) {
+ if (!etnaviv_is_model_rev(gpu, 0x600, 0x19)) {
gpu->identity.product_id = gpu_read(gpu, VIVS_HI_CHIP_PRODUCT_ID);
gpu->identity.eco_id = gpu_read(gpu, VIVS_HI_CHIP_ECO_ID);
}
@@ -368,7 +370,7 @@ static void etnaviv_hw_identify(struct etnaviv_gpu *gpu)
}
/* Another special case */
- if (etnaviv_is_model_rev(gpu, GC300, 0x2201)) {
+ if (etnaviv_is_model_rev(gpu, 0x300, 0x2201)) {
u32 chipTime = gpu_read(gpu, VIVS_HI_CHIP_TIME);
if (chipDate == 0x20080814 && chipTime == 0x12051100) {
@@ -387,15 +389,15 @@ static void etnaviv_hw_identify(struct etnaviv_gpu *gpu)
* Fix model/rev here, so all other places can refer to this
* core by its real identity.
*/
- if (etnaviv_is_model_rev(gpu, GC2000, 0xffff5450)) {
+ if (etnaviv_is_model_rev(gpu, 0x2000, 0xffff5450)) {
gpu->identity.model = chipModel_GC3000;
gpu->identity.revision &= 0xffff;
}
- if (etnaviv_is_model_rev(gpu, GC1000, 0x5037) && (chipDate == 0x20120617))
+ if (etnaviv_is_model_rev(gpu, 0x1000, 0x5037) && (chipDate == 0x20120617))
gpu->identity.eco_id = 1;
- if (etnaviv_is_model_rev(gpu, GC320, 0x5303) && (chipDate == 0x20140511))
+ if (etnaviv_is_model_rev(gpu, 0x320, 0x5303) && (chipDate == 0x20140511))
gpu->identity.eco_id = 1;
}
@@ -641,17 +643,23 @@ static void etnaviv_gpu_enable_mlcg(struct etnaviv_gpu *gpu)
pmc |= BIT(15); /* Unknown bit */
/* Disable TX clock gating on affected core revisions. */
- if (etnaviv_is_model_rev(gpu, GC4000, 0x5222) ||
- etnaviv_is_model_rev(gpu, GC2000, 0x5108) ||
- etnaviv_is_model_rev(gpu, GC7000, 0x6202) ||
- etnaviv_is_model_rev(gpu, GC7000, 0x6203))
+ if (etnaviv_is_model_rev(gpu, 0x4000, 0x5222) ||
+ etnaviv_is_model_rev(gpu, 0x2000, 0x5108) ||
+ etnaviv_is_model_rev(gpu, 0x7000, 0x6202) ||
+ etnaviv_is_model_rev(gpu, 0x7000, 0x6203))
pmc |= VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_TX;
/* Disable SE and RA clock gating on affected core revisions. */
- if (etnaviv_is_model_rev(gpu, GC7000, 0x6202))
+ if (etnaviv_is_model_rev(gpu, 0x7000, 0x6202))
pmc |= VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_SE |
VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_RA;
+ /* Disable SH_EU clock gating on affected core revisions. */
+ if (etnaviv_is_model_rev(gpu, 0x8000, 0x7200) ||
+ etnaviv_is_model_rev(gpu, 0x8000, 0x8002) ||
+ etnaviv_is_model_rev(gpu, 0x9200, 0x6304))
+ pmc |= VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_SH_EU;
+
pmc |= VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_RA_HZ;
pmc |= VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_RA_EZ;
@@ -701,14 +709,14 @@ static void etnaviv_gpu_setup_pulse_eater(struct etnaviv_gpu *gpu)
*/
u32 pulse_eater = 0x01590880;
- if (etnaviv_is_model_rev(gpu, GC4000, 0x5208) ||
- etnaviv_is_model_rev(gpu, GC4000, 0x5222)) {
+ if (etnaviv_is_model_rev(gpu, 0x4000, 0x5208) ||
+ etnaviv_is_model_rev(gpu, 0x4000, 0x5222)) {
pulse_eater |= BIT(23);
}
- if (etnaviv_is_model_rev(gpu, GC1000, 0x5039) ||
- etnaviv_is_model_rev(gpu, GC1000, 0x5040)) {
+ if (etnaviv_is_model_rev(gpu, 0x1000, 0x5039) ||
+ etnaviv_is_model_rev(gpu, 0x1000, 0x5040)) {
pulse_eater &= ~BIT(16);
pulse_eater |= BIT(17);
}
@@ -729,8 +737,8 @@ static void etnaviv_gpu_hw_init(struct etnaviv_gpu *gpu)
WARN_ON(!(gpu->state == ETNA_GPU_STATE_IDENTIFIED ||
gpu->state == ETNA_GPU_STATE_RESET));
- if ((etnaviv_is_model_rev(gpu, GC320, 0x5007) ||
- etnaviv_is_model_rev(gpu, GC320, 0x5220)) &&
+ if ((etnaviv_is_model_rev(gpu, 0x320, 0x5007) ||
+ etnaviv_is_model_rev(gpu, 0x320, 0x5220)) &&
gpu_read(gpu, VIVS_HI_CHIP_TIME) != 0x2062400) {
u32 mc_memory_debug;
@@ -756,7 +764,7 @@ static void etnaviv_gpu_hw_init(struct etnaviv_gpu *gpu)
VIVS_HI_AXI_CONFIG_ARCACHE(2));
/* GC2000 rev 5108 needs a special bus config */
- if (etnaviv_is_model_rev(gpu, GC2000, 0x5108)) {
+ if (etnaviv_is_model_rev(gpu, 0x2000, 0x5108)) {
u32 bus_config = gpu_read(gpu, VIVS_MC_BUS_CONFIG);
bus_config &= ~(VIVS_MC_BUS_CONFIG_FE_BUS_CONFIG__MASK |
VIVS_MC_BUS_CONFIG_TX_BUS_CONFIG__MASK);
@@ -855,12 +863,15 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
*
* On MC1.0 cores the linear window offset is ignored by the TS engine,
* leading to inconsistent memory views. Avoid using the offset on those
- * cores if possible, otherwise disable the TS feature.
+ * cores if possible, otherwise disable the TS feature. MMUv2 doesn't
+ * expose this issue, as all TS accesses are MMU translated, so the
+ * linear window offset won't be used.
*/
cmdbuf_paddr = ALIGN_DOWN(etnaviv_cmdbuf_get_pa(&gpu->buffer), SZ_128M);
if (!(gpu->identity.features & chipFeatures_PIPE_3D) ||
- (gpu->identity.minor_features0 & chipMinorFeatures0_MC20)) {
+ (gpu->identity.minor_features0 & chipMinorFeatures0_MC20) ||
+ (gpu->identity.minor_features1 & chipMinorFeatures1_MMU_VERSION)) {
if (cmdbuf_paddr >= SZ_2G)
priv->mmu_global->memory_base = SZ_2G;
else
@@ -1537,6 +1548,7 @@ static irqreturn_t irq_handler(int irq, void *data)
u32 intr = gpu_read(gpu, VIVS_HI_INTR_ACKNOWLEDGE);
if (intr != 0) {
+ ktime_t now = ktime_get();
int event;
pm_runtime_mark_last_busy(gpu->dev);
@@ -1586,7 +1598,7 @@ static irqreturn_t irq_handler(int irq, void *data)
*/
if (fence_after(fence->seqno, gpu->completed_fence))
gpu->completed_fence = fence->seqno;
- dma_fence_signal(fence);
+ dma_fence_signal_timestamp(fence, now);
event_free(gpu, event);
}
@@ -1975,7 +1987,6 @@ static const struct dev_pm_ops etnaviv_gpu_pm_ops = {
struct platform_driver etnaviv_gpu_driver = {
.driver = {
.name = "etnaviv-gpu",
- .owner = THIS_MODULE,
.pm = pm_ptr(&etnaviv_gpu_pm_ops),
.of_match_table = etnaviv_gpu_match,
},
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
index 197e0037732e..31322195b9e4 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
@@ -11,6 +11,7 @@
#include "etnaviv_mmu.h"
#include "etnaviv_drv.h"
#include "common.xml.h"
+#include "state.xml.h"
struct etnaviv_gem_submit;
struct etnaviv_vram_mapping;
@@ -170,6 +171,13 @@ static inline void gpu_write(struct etnaviv_gpu *gpu, u32 reg, u32 data)
static inline u32 gpu_read(struct etnaviv_gpu *gpu, u32 reg)
{
+ /* On some variants, such as the GC7000r6009, some FE registers
+ * need two reads to be consistent. Do that extra read here and
+ * throw away the result.
+ */
+ if (reg >= VIVS_FE_DMA_STATUS && reg <= VIVS_FE_AUTO_FLUSH)
+ readl(gpu->mmio + reg);
+
return readl(gpu->mmio + reg);
}
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_sched.c b/drivers/gpu/drm/etnaviv/etnaviv_sched.c
index c4b04b0dee16..62dcfdc7894d 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_sched.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_sched.c
@@ -38,9 +38,6 @@ static enum drm_gpu_sched_stat etnaviv_sched_timedout_job(struct drm_sched_job
u32 dma_addr;
int change;
- /* block scheduler */
- drm_sched_stop(&gpu->sched, sched_job);
-
/*
* If the GPU managed to complete this jobs fence, the timout is
* spurious. Bail out.
@@ -63,6 +60,9 @@ static enum drm_gpu_sched_stat etnaviv_sched_timedout_job(struct drm_sched_job
goto out_no_timeout;
}
+ /* block scheduler */
+ drm_sched_stop(&gpu->sched, sched_job);
+
if(sched_job)
drm_sched_increase_karma(sched_job);
@@ -76,8 +76,7 @@ static enum drm_gpu_sched_stat etnaviv_sched_timedout_job(struct drm_sched_job
return DRM_GPU_SCHED_STAT_NOMINAL;
out_no_timeout:
- /* restart scheduler after GPU is usable again */
- drm_sched_start(&gpu->sched, true);
+ list_add(&sched_job->list, &sched_job->sched->pending_list);
return DRM_GPU_SCHED_STAT_NOMINAL;
}
diff --git a/drivers/gpu/drm/etnaviv/state.xml.h b/drivers/gpu/drm/etnaviv/state.xml.h
index 421cb7cc0053..573e39489a27 100644
--- a/drivers/gpu/drm/etnaviv/state.xml.h
+++ b/drivers/gpu/drm/etnaviv/state.xml.h
@@ -8,17 +8,17 @@ http://0x04.net/cgit/index.cgi/rules-ng-ng
git clone git://0x04.net/rules-ng-ng
The rules-ng-ng source files this header was generated from are:
-- state.xml ( 26087 bytes, from 2017-12-18 16:51:59)
-- common.xml ( 35468 bytes, from 2018-01-22 13:48:54)
-- common_3d.xml ( 14615 bytes, from 2017-12-18 16:51:59)
-- state_hi.xml ( 30232 bytes, from 2018-02-15 15:48:01)
-- copyright.xml ( 1597 bytes, from 2016-12-08 16:37:56)
-- state_2d.xml ( 51552 bytes, from 2016-12-08 16:37:56)
-- state_3d.xml ( 79992 bytes, from 2017-12-18 16:51:59)
-- state_blt.xml ( 13405 bytes, from 2017-12-18 16:51:59)
-- state_vg.xml ( 5975 bytes, from 2016-12-08 16:37:56)
-
-Copyright (C) 2012-2017 by the following authors:
+- state.xml ( 29355 bytes, from 2024-01-19 10:18:54)
+- common.xml ( 35664 bytes, from 2023-12-06 10:55:32)
+- common_3d.xml ( 15069 bytes, from 2023-11-22 10:05:24)
+- state_hi.xml ( 35854 bytes, from 2023-12-11 15:50:17)
+- copyright.xml ( 1597 bytes, from 2016-11-10 13:58:32)
+- state_2d.xml ( 52271 bytes, from 2023-06-02 12:35:03)
+- state_3d.xml ( 89522 bytes, from 2024-01-19 10:18:54)
+- state_blt.xml ( 14592 bytes, from 2023-11-22 10:05:09)
+- state_vg.xml ( 5975 bytes, from 2016-11-10 13:58:32)
+
+Copyright (C) 2012-2024 by the following authors:
- Wladimir J. van der Laan <laanwj@gmail.com>
- Christian Gmeiner <christian.gmeiner@gmail.com>
- Lucas Stach <l.stach@pengutronix.de>
@@ -55,6 +55,8 @@ DEALINGS IN THE SOFTWARE.
#define FE_DATA_TYPE_UNSIGNED_SHORT 0x00000003
#define FE_DATA_TYPE_INT 0x00000004
#define FE_DATA_TYPE_UNSIGNED_INT 0x00000005
+#define FE_DATA_TYPE_INT_2_10_10_10_REV 0x00000006
+#define FE_DATA_TYPE_UNSIGNED_INT_2_10_10_10_REV 0x00000007
#define FE_DATA_TYPE_FLOAT 0x00000008
#define FE_DATA_TYPE_HALF_FLOAT 0x00000009
#define FE_DATA_TYPE_FIXED 0x0000000b
@@ -89,6 +91,7 @@ DEALINGS IN THE SOFTWARE.
#define VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE__MASK 0x0000c000
#define VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE__SHIFT 14
#define VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE_OFF 0x00000000
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE_SIGN_EXTEND 0x00004000
#define VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE_ON 0x00008000
#define VIVS_FE_VERTEX_ELEMENT_CONFIG_START__MASK 0x00ff0000
#define VIVS_FE_VERTEX_ELEMENT_CONFIG_START__SHIFT 16
@@ -209,7 +212,15 @@ DEALINGS IN THE SOFTWARE.
#define VIVS_FE_GENERIC_ATTRIB_SCALE(i0) (0x00000780 + 0x4*(i0))
-#define VIVS_FE_HALTI5_UNK007C4 0x000007c4
+#define VIVS_FE_HALTI5_ID_CONFIG 0x000007c4
+#define VIVS_FE_HALTI5_ID_CONFIG_VERTEX_ID_ENABLE 0x00000001
+#define VIVS_FE_HALTI5_ID_CONFIG_INSTANCE_ID_ENABLE 0x00000002
+#define VIVS_FE_HALTI5_ID_CONFIG_VERTEX_ID_REG__MASK 0x0000ff00
+#define VIVS_FE_HALTI5_ID_CONFIG_VERTEX_ID_REG__SHIFT 8
+#define VIVS_FE_HALTI5_ID_CONFIG_VERTEX_ID_REG(x) (((x) << VIVS_FE_HALTI5_ID_CONFIG_VERTEX_ID_REG__SHIFT) & VIVS_FE_HALTI5_ID_CONFIG_VERTEX_ID_REG__MASK)
+#define VIVS_FE_HALTI5_ID_CONFIG_INSTANCE_ID_REG__MASK 0x00ff0000
+#define VIVS_FE_HALTI5_ID_CONFIG_INSTANCE_ID_REG__SHIFT 16
+#define VIVS_FE_HALTI5_ID_CONFIG_INSTANCE_ID_REG(x) (((x) << VIVS_FE_HALTI5_ID_CONFIG_INSTANCE_ID_REG__SHIFT) & VIVS_FE_HALTI5_ID_CONFIG_INSTANCE_ID_REG__MASK)
#define VIVS_FE_HALTI5_UNK007D0(i0) (0x000007d0 + 0x4*(i0))
#define VIVS_FE_HALTI5_UNK007D0__ESIZE 0x00000004
@@ -232,6 +243,8 @@ DEALINGS IN THE SOFTWARE.
#define VIVS_FE_ROBUSTNESS_UNK007F8 0x000007f8
+#define VIVS_FE_MULTI_CLUSTER_UNK007FC 0x000007fc
+
#define VIVS_GL 0x00000000
#define VIVS_GL_PIPE_SELECT 0x00003800
@@ -273,6 +286,7 @@ DEALINGS IN THE SOFTWARE.
#define VIVS_GL_FLUSH_CACHE_UNK11 0x00000800
#define VIVS_GL_FLUSH_CACHE_DESCRIPTOR_UNK12 0x00001000
#define VIVS_GL_FLUSH_CACHE_DESCRIPTOR_UNK13 0x00002000
+#define VIVS_GL_FLUSH_CACHE_UNK14 0x00004000
#define VIVS_GL_FLUSH_MMU 0x00003810
#define VIVS_GL_FLUSH_MMU_FLUSH_FEMMU 0x00000001
@@ -282,6 +296,8 @@ DEALINGS IN THE SOFTWARE.
#define VIVS_GL_FLUSH_MMU_FLUSH_UNK4 0x00000010
#define VIVS_GL_VERTEX_ELEMENT_CONFIG 0x00003814
+#define VIVS_GL_VERTEX_ELEMENT_CONFIG_UNK0 0x00000001
+#define VIVS_GL_VERTEX_ELEMENT_CONFIG_REUSE 0x00000010
#define VIVS_GL_MULTI_SAMPLE_CONFIG 0x00003818
#define VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES__MASK 0x00000003
@@ -368,7 +384,7 @@ DEALINGS IN THE SOFTWARE.
#define VIVS_GL_OCCLUSION_QUERY_CONTROL 0x00003830
-#define VIVS_GL_UNK03834 0x00003834
+#define VIVS_GL_VARYING_NUM_COMPONENTS2 0x00003834
#define VIVS_GL_UNK03838 0x00003838
@@ -387,7 +403,16 @@ DEALINGS IN THE SOFTWARE.
#define VIVS_GL_FENCE_OUT_DATA_LOW 0x0000386c
-#define VIVS_GL_HALTI5_UNK03884 0x00003884
+#define VIVS_GL_USC_CONTROL 0x00003884
+#define VIVS_GL_USC_CONTROL_L1_CACHE_RATIO__MASK 0x00000007
+#define VIVS_GL_USC_CONTROL_L1_CACHE_RATIO__SHIFT 0
+#define VIVS_GL_USC_CONTROL_L1_CACHE_RATIO(x) (((x) << VIVS_GL_USC_CONTROL_L1_CACHE_RATIO__SHIFT) & VIVS_GL_USC_CONTROL_L1_CACHE_RATIO__MASK)
+#define VIVS_GL_USC_CONTROL_ATTRIB_CACHE_RATIO__MASK 0x00000f00
+#define VIVS_GL_USC_CONTROL_ATTRIB_CACHE_RATIO__SHIFT 8
+#define VIVS_GL_USC_CONTROL_ATTRIB_CACHE_RATIO(x) (((x) << VIVS_GL_USC_CONTROL_ATTRIB_CACHE_RATIO__SHIFT) & VIVS_GL_USC_CONTROL_ATTRIB_CACHE_RATIO__MASK)
+#define VIVS_GL_USC_CONTROL_UNK16__MASK 0x001f0000
+#define VIVS_GL_USC_CONTROL_UNK16__SHIFT 16
+#define VIVS_GL_USC_CONTROL_UNK16(x) (((x) << VIVS_GL_USC_CONTROL_UNK16__SHIFT) & VIVS_GL_USC_CONTROL_UNK16__MASK)
#define VIVS_GL_HALTI5_SH_SPECIALS 0x00003888
#define VIVS_GL_HALTI5_SH_SPECIALS_VS_PSIZE_OUT__MASK 0x0000007f
@@ -421,7 +446,48 @@ DEALINGS IN THE SOFTWARE.
#define VIVS_GL_SECURITY_UNK3904 0x00003904
+#define VIVS_GL_MULTI_CLUSTER_UNK3908 0x00003908
+#define VIVS_GL_MULTI_CLUSTER_UNK3908_UNK0__MASK 0x00000007
+#define VIVS_GL_MULTI_CLUSTER_UNK3908_UNK0__SHIFT 0
+#define VIVS_GL_MULTI_CLUSTER_UNK3908_UNK0(x) (((x) << VIVS_GL_MULTI_CLUSTER_UNK3908_UNK0__SHIFT) & VIVS_GL_MULTI_CLUSTER_UNK3908_UNK0__MASK)
+
+#define VIVS_GL_MULTI_CLUSTER_UNK3910(i0) (0x00003910 + 0x4*(i0))
+#define VIVS_GL_MULTI_CLUSTER_UNK3910__ESIZE 0x00000004
+#define VIVS_GL_MULTI_CLUSTER_UNK3910__LEN 0x00000004
+#define VIVS_GL_MULTI_CLUSTER_UNK3910_CLUSTER_ALIVE_MASK__MASK 0x000000ff
+#define VIVS_GL_MULTI_CLUSTER_UNK3910_CLUSTER_ALIVE_MASK__SHIFT 0
+#define VIVS_GL_MULTI_CLUSTER_UNK3910_CLUSTER_ALIVE_MASK(x) (((x) << VIVS_GL_MULTI_CLUSTER_UNK3910_CLUSTER_ALIVE_MASK__SHIFT) & VIVS_GL_MULTI_CLUSTER_UNK3910_CLUSTER_ALIVE_MASK__MASK)
+
+#define VIVS_GL_NN_CONFIG 0x00003930
+#define VIVS_GL_NN_CONFIG_UNK0__MASK 0x00000003
+#define VIVS_GL_NN_CONFIG_UNK0__SHIFT 0
+#define VIVS_GL_NN_CONFIG_UNK0(x) (((x) << VIVS_GL_NN_CONFIG_UNK0__SHIFT) & VIVS_GL_NN_CONFIG_UNK0__MASK)
+#define VIVS_GL_NN_CONFIG_DISABLE_ZDPN 0x00000004
+#define VIVS_GL_NN_CONFIG_DISABLE_SWTILING 0x00000008
+#define VIVS_GL_NN_CONFIG_SMALL_BATCH 0x00000010
+#define VIVS_GL_NN_CONFIG_DDR_BURST_SIZE__MASK 0x00000060
+#define VIVS_GL_NN_CONFIG_DDR_BURST_SIZE__SHIFT 5
+#define VIVS_GL_NN_CONFIG_DDR_BURST_SIZE(x) (((x) << VIVS_GL_NN_CONFIG_DDR_BURST_SIZE__SHIFT) & VIVS_GL_NN_CONFIG_DDR_BURST_SIZE__MASK)
+#define VIVS_GL_NN_CONFIG_UNK7 0x00000080
+#define VIVS_GL_NN_CONFIG_NN_CORE_COUNT__MASK 0x00000f00
+#define VIVS_GL_NN_CONFIG_NN_CORE_COUNT__SHIFT 8
+#define VIVS_GL_NN_CONFIG_NN_CORE_COUNT(x) (((x) << VIVS_GL_NN_CONFIG_NN_CORE_COUNT__SHIFT) & VIVS_GL_NN_CONFIG_NN_CORE_COUNT__MASK)
+#define VIVS_GL_NN_CONFIG_UNK12 0x00001000
+
+#define VIVS_GL_SRAM_REMAP_ADDRESS 0x00003938
+
+#define VIVS_GL_OCB_REMAP_START 0x0000393c
+
+#define VIVS_GL_OCB_REMAP_END 0x00003940
+
+#define VIVS_GL_TP_CONFIG 0x0000394c
+
+#define VIVS_GL_UNK03950 0x00003950
+
#define VIVS_GL_UNK03A00 0x00003a00
+#define VIVS_GL_UNK03A00_UNK0__MASK 0x00000007
+#define VIVS_GL_UNK03A00_UNK0__SHIFT 0
+#define VIVS_GL_UNK03A00_UNK0(x) (((x) << VIVS_GL_UNK03A00_UNK0__SHIFT) & VIVS_GL_UNK03A00_UNK0__MASK)
#define VIVS_GL_UNK03A04 0x00003a04
@@ -451,7 +517,7 @@ DEALINGS IN THE SOFTWARE.
#define VIVS_NFE_VERTEX_STREAMS_CONTROL(i0) (0x00014640 + 0x4*(i0))
-#define VIVS_NFE_VERTEX_STREAMS_UNK14680(i0) (0x00014680 + 0x4*(i0))
+#define VIVS_NFE_VERTEX_STREAMS_VERTEX_DIVISOR(i0) (0x00014680 + 0x4*(i0))
#define VIVS_NFE_VERTEX_STREAMS_ROBUSTNESS_UNK146C0(i0) (0x000146c0 + 0x4*(i0))
@@ -498,5 +564,12 @@ DEALINGS IN THE SOFTWARE.
#define VIVS_DUMMY_DUMMY 0x0003fffc
+#define VIVS_WD 0x00000000
+
+#define VIVS_WD_UNK18404 0x00018404
+#define VIVS_WD_UNK18404_UNK0__MASK 0x00000003
+#define VIVS_WD_UNK18404_UNK0__SHIFT 0
+#define VIVS_WD_UNK18404_UNK0(x) (((x) << VIVS_WD_UNK18404_UNK0__SHIFT) & VIVS_WD_UNK18404_UNK0__MASK)
+
#endif /* STATE_XML */
diff --git a/drivers/gpu/drm/etnaviv/state_blt.xml.h b/drivers/gpu/drm/etnaviv/state_blt.xml.h
index 0e8bcf9dcc93..380d3533d645 100644
--- a/drivers/gpu/drm/etnaviv/state_blt.xml.h
+++ b/drivers/gpu/drm/etnaviv/state_blt.xml.h
@@ -8,17 +8,17 @@ http://0x04.net/cgit/index.cgi/rules-ng-ng
git clone git://0x04.net/rules-ng-ng
The rules-ng-ng source files this header was generated from are:
-- state.xml ( 26087 bytes, from 2017-12-18 16:51:59)
-- common.xml ( 35468 bytes, from 2018-01-22 13:48:54)
-- common_3d.xml ( 14615 bytes, from 2017-12-18 16:51:59)
-- state_hi.xml ( 30232 bytes, from 2018-02-15 15:48:01)
-- copyright.xml ( 1597 bytes, from 2016-12-08 16:37:56)
-- state_2d.xml ( 51552 bytes, from 2016-12-08 16:37:56)
-- state_3d.xml ( 79992 bytes, from 2017-12-18 16:51:59)
-- state_blt.xml ( 13405 bytes, from 2017-12-18 16:51:59)
-- state_vg.xml ( 5975 bytes, from 2016-12-08 16:37:56)
-
-Copyright (C) 2012-2017 by the following authors:
+- state.xml ( 29355 bytes, from 2024-01-19 10:18:54)
+- common.xml ( 35664 bytes, from 2023-12-06 10:55:32)
+- common_3d.xml ( 15069 bytes, from 2023-11-22 10:05:24)
+- state_hi.xml ( 35854 bytes, from 2023-12-11 15:50:17)
+- copyright.xml ( 1597 bytes, from 2016-11-10 13:58:32)
+- state_2d.xml ( 52271 bytes, from 2023-06-02 12:35:03)
+- state_3d.xml ( 89522 bytes, from 2024-01-19 10:18:54)
+- state_blt.xml ( 14592 bytes, from 2023-11-22 10:05:09)
+- state_vg.xml ( 5975 bytes, from 2016-11-10 13:58:32)
+
+Copyright (C) 2012-2023 by the following authors:
- Wladimir J. van der Laan <laanwj@gmail.com>
- Christian Gmeiner <christian.gmeiner@gmail.com>
- Lucas Stach <l.stach@pengutronix.de>
diff --git a/drivers/gpu/drm/etnaviv/state_hi.xml.h b/drivers/gpu/drm/etnaviv/state_hi.xml.h
index 94d5f33b1fd6..829bc528e618 100644
--- a/drivers/gpu/drm/etnaviv/state_hi.xml.h
+++ b/drivers/gpu/drm/etnaviv/state_hi.xml.h
@@ -8,17 +8,17 @@ http://0x04.net/cgit/index.cgi/rules-ng-ng
git clone git://0x04.net/rules-ng-ng
The rules-ng-ng source files this header was generated from are:
-- state.xml ( 27198 bytes, from 2022-04-22 10:35:24)
-- common.xml ( 35468 bytes, from 2020-10-28 12:56:03)
-- common_3d.xml ( 15058 bytes, from 2020-10-28 12:56:03)
-- state_hi.xml ( 34804 bytes, from 2022-12-02 09:06:28)
-- copyright.xml ( 1597 bytes, from 2020-10-28 12:56:03)
-- state_2d.xml ( 51552 bytes, from 2020-10-28 12:56:03)
-- state_3d.xml ( 84445 bytes, from 2022-11-15 15:59:38)
-- state_blt.xml ( 14424 bytes, from 2022-11-07 11:18:41)
-- state_vg.xml ( 5975 bytes, from 2020-10-28 12:56:03)
-
-Copyright (C) 2012-2022 by the following authors:
+- state.xml ( 29355 bytes, from 2024-01-19 10:18:54)
+- common.xml ( 35664 bytes, from 2023-12-06 10:55:32)
+- common_3d.xml ( 15069 bytes, from 2023-11-22 10:05:24)
+- state_hi.xml ( 35854 bytes, from 2023-12-11 15:50:17)
+- copyright.xml ( 1597 bytes, from 2016-11-10 13:58:32)
+- state_2d.xml ( 52271 bytes, from 2023-06-02 12:35:03)
+- state_3d.xml ( 89522 bytes, from 2024-01-19 10:18:54)
+- state_blt.xml ( 14592 bytes, from 2023-11-22 10:05:09)
+- state_vg.xml ( 5975 bytes, from 2016-11-10 13:58:32)
+
+Copyright (C) 2012-2023 by the following authors:
- Wladimir J. van der Laan <laanwj@gmail.com>
- Christian Gmeiner <christian.gmeiner@gmail.com>
- Lucas Stach <l.stach@pengutronix.de>
@@ -275,8 +275,10 @@ DEALINGS IN THE SOFTWARE.
#define VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_SE 0x00000020
#define VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_RA 0x00000040
#define VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_TX 0x00000080
+#define VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_SH_EU 0x00000400
#define VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_RA_EZ 0x00010000
#define VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_RA_HZ 0x00020000
+#define VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_NN 0x00400000
#define VIVS_PM_MODULE_STATUS 0x00000108
#define VIVS_PM_MODULE_STATUS_MODULE_CLOCK_GATED_FE 0x00000001
@@ -620,5 +622,11 @@ DEALINGS IN THE SOFTWARE.
#define VIVS_MC_MC_AXI_SAMPLE_COUNT 0x00000574
+#define VIVS_DEC400EX 0x00000000
+
+#define VIVS_DEC400EX_UNK00800 0x00000800
+
+#define VIVS_DEC400EX_UNK00808 0x00000808
+
#endif /* STATE_HI_XML */
diff --git a/drivers/gpu/drm/exynos/exynos_dp.c b/drivers/gpu/drm/exynos/exynos_dp.c
index f48c4343f469..22142b293279 100644
--- a/drivers/gpu/drm/exynos/exynos_dp.c
+++ b/drivers/gpu/drm/exynos/exynos_dp.c
@@ -233,7 +233,7 @@ static int exynos_dp_probe(struct platform_device *pdev)
/* The remote port can be either a panel or a bridge */
dp->plat_data.panel = panel;
dp->plat_data.dev_type = EXYNOS_DP;
- dp->plat_data.power_on_start = exynos_dp_poweron;
+ dp->plat_data.power_on = exynos_dp_poweron;
dp->plat_data.power_off = exynos_dp_poweroff;
dp->plat_data.attach = exynos_dp_bridge_attach;
dp->plat_data.get_modes = exynos_dp_get_modes;
@@ -251,10 +251,7 @@ out:
static void exynos_dp_remove(struct platform_device *pdev)
{
- struct exynos_dp_device *dp = platform_get_drvdata(pdev);
-
component_del(&pdev->dev, &exynos_dp_ops);
- analogix_dp_remove(dp->adp);
}
static int exynos_dp_suspend(struct device *dev)
@@ -285,7 +282,6 @@ struct platform_driver dp_driver = {
.remove_new = exynos_dp_remove,
.driver = {
.name = "exynos-dp",
- .owner = THIS_MODULE,
.pm = pm_ptr(&exynos_dp_pm_ops),
.of_match_table = exynos_dp_match,
},
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
index fab135308b70..6de0cced6c9d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -41,7 +41,7 @@ struct vidi_context {
struct exynos_drm_crtc *crtc;
struct drm_connector connector;
struct exynos_drm_plane planes[WINDOWS_NR];
- struct edid *raw_edid;
+ const struct drm_edid *raw_edid;
unsigned int clkdiv;
unsigned int connected;
bool suspended;
@@ -195,12 +195,11 @@ static ssize_t vidi_store_connection(struct device *dev,
if (ctx->connected > 1)
return -EINVAL;
- /* use fake edid data for test. */
- if (!ctx->raw_edid)
- ctx->raw_edid = (struct edid *)fake_edid_info;
-
- /* if raw_edid isn't same as fake data then it can't be tested. */
- if (ctx->raw_edid != (struct edid *)fake_edid_info) {
+ /*
+ * Use fake edid data for test. If raw_edid is set then it can't be
+ * tested.
+ */
+ if (ctx->raw_edid) {
DRM_DEV_DEBUG_KMS(dev, "edid data is not fake data.\n");
return -EINVAL;
}
@@ -246,30 +245,28 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data,
}
if (vidi->connection) {
- struct edid *raw_edid;
+ const struct drm_edid *drm_edid;
+ const struct edid *raw_edid;
+ size_t size;
+
+ raw_edid = (const struct edid *)(unsigned long)vidi->edid;
+ size = (raw_edid->extensions + 1) * EDID_LENGTH;
+
+ drm_edid = drm_edid_alloc(raw_edid, size);
+ if (!drm_edid)
+ return -ENOMEM;
- raw_edid = (struct edid *)(unsigned long)vidi->edid;
- if (!drm_edid_is_valid(raw_edid)) {
+ if (!drm_edid_valid(drm_edid)) {
+ drm_edid_free(drm_edid);
DRM_DEV_DEBUG_KMS(ctx->dev,
"edid data is invalid.\n");
return -EINVAL;
}
- ctx->raw_edid = drm_edid_duplicate(raw_edid);
- if (!ctx->raw_edid) {
- DRM_DEV_DEBUG_KMS(ctx->dev,
- "failed to allocate raw_edid.\n");
- return -ENOMEM;
- }
+ ctx->raw_edid = drm_edid;
} else {
- /*
- * with connection = 0, free raw_edid
- * only if raw edid data isn't same as fake data.
- */
- if (ctx->raw_edid && ctx->raw_edid !=
- (struct edid *)fake_edid_info) {
- kfree(ctx->raw_edid);
- ctx->raw_edid = NULL;
- }
+ /* with connection = 0, free raw_edid */
+ drm_edid_free(ctx->raw_edid);
+ ctx->raw_edid = NULL;
}
ctx->connected = vidi->connection;
@@ -307,28 +304,24 @@ static const struct drm_connector_funcs vidi_connector_funcs = {
static int vidi_get_modes(struct drm_connector *connector)
{
struct vidi_context *ctx = ctx_from_connector(connector);
- struct edid *edid;
- int edid_len;
+ const struct drm_edid *drm_edid;
+ int count;
- /*
- * the edid data comes from user side and it would be set
- * to ctx->raw_edid through specific ioctl.
- */
- if (!ctx->raw_edid) {
- DRM_DEV_DEBUG_KMS(ctx->dev, "raw_edid is null.\n");
- return 0;
- }
+ if (ctx->raw_edid)
+ drm_edid = drm_edid_dup(ctx->raw_edid);
+ else
+ drm_edid = drm_edid_alloc(fake_edid_info, sizeof(fake_edid_info));
- edid_len = (1 + ctx->raw_edid->extensions) * EDID_LENGTH;
- edid = kmemdup(ctx->raw_edid, edid_len, GFP_KERNEL);
- if (!edid) {
- DRM_DEV_DEBUG_KMS(ctx->dev, "failed to allocate edid\n");
+ if (!drm_edid)
return 0;
- }
- drm_connector_update_edid_property(connector, edid);
+ drm_edid_connector_update(connector, drm_edid);
+
+ count = drm_edid_connector_add_modes(connector);
+
+ drm_edid_free(drm_edid);
- return drm_add_edid_modes(connector, edid);
+ return count;
}
static const struct drm_connector_helper_funcs vidi_connector_helper_funcs = {
@@ -466,10 +459,8 @@ static void vidi_remove(struct platform_device *pdev)
{
struct vidi_context *ctx = platform_get_drvdata(pdev);
- if (ctx->raw_edid != (struct edid *)fake_edid_info) {
- kfree(ctx->raw_edid);
- ctx->raw_edid = NULL;
- }
+ drm_edid_free(ctx->raw_edid);
+ ctx->raw_edid = NULL;
component_del(&pdev->dev, &vidi_component_ops);
}
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index e968824a4c72..1e26cd4f8347 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -887,11 +887,11 @@ static int hdmi_get_modes(struct drm_connector *connector)
int ret;
if (!hdata->ddc_adpt)
- return 0;
+ goto no_edid;
edid = drm_get_edid(connector, hdata->ddc_adpt);
if (!edid)
- return 0;
+ goto no_edid;
hdata->dvi_mode = !connector->display_info.is_hdmi;
DRM_DEV_DEBUG_KMS(hdata->dev, "%s : width[%d] x height[%d]\n",
@@ -906,6 +906,9 @@ static int hdmi_get_modes(struct drm_connector *connector)
kfree(edid);
return ret;
+
+no_edid:
+ return drm_add_modes_noedid(connector, 640, 480);
}
static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock)
diff --git a/drivers/gpu/drm/gma500/cdv_intel_dp.c b/drivers/gpu/drm/gma500/cdv_intel_dp.c
index dd1eb7e9877d..cc2ed9b3fd2d 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_dp.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_dp.c
@@ -1547,7 +1547,7 @@ cdv_intel_dp_start_link_train(struct gma_encoder *encoder)
}
if (!clock_recovery) {
- DRM_DEBUG_KMS("failure in DP patter 1 training, train set %x\n", intel_dp->train_set[0]);
+ DRM_DEBUG_KMS("failure in DP pattern 1 training, train set %x\n", intel_dp->train_set[0]);
}
intel_dp->DP = DP;
diff --git a/drivers/gpu/drm/gma500/cdv_intel_lvds.c b/drivers/gpu/drm/gma500/cdv_intel_lvds.c
index f08a6803dc18..3adc2c9ab72d 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_lvds.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_lvds.c
@@ -311,6 +311,9 @@ static int cdv_intel_lvds_get_modes(struct drm_connector *connector)
if (mode_dev->panel_fixed_mode != NULL) {
struct drm_display_mode *mode =
drm_mode_duplicate(dev, mode_dev->panel_fixed_mode);
+ if (!mode)
+ return 0;
+
drm_mode_probed_add(connector, mode);
return 1;
}
diff --git a/drivers/gpu/drm/gma500/psb_intel_lvds.c b/drivers/gpu/drm/gma500/psb_intel_lvds.c
index 8486de230ec9..8d1be94a443b 100644
--- a/drivers/gpu/drm/gma500/psb_intel_lvds.c
+++ b/drivers/gpu/drm/gma500/psb_intel_lvds.c
@@ -504,6 +504,9 @@ static int psb_intel_lvds_get_modes(struct drm_connector *connector)
if (mode_dev->panel_fixed_mode != NULL) {
struct drm_display_mode *mode =
drm_mode_duplicate(dev, mode_dev->panel_fixed_mode);
+ if (!mode)
+ return 0;
+
drm_mode_probed_add(connector, mode);
return 1;
}
diff --git a/drivers/gpu/drm/gud/gud_drv.c b/drivers/gpu/drm/gud/gud_drv.c
index 9d7bf8ee45f1..ac6bbf920c72 100644
--- a/drivers/gpu/drm/gud/gud_drv.c
+++ b/drivers/gpu/drm/gud/gud_drv.c
@@ -18,7 +18,7 @@
#include <drm/drm_damage_helper.h>
#include <drm/drm_debugfs.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_shmem.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
@@ -622,7 +622,7 @@ static int gud_probe(struct usb_interface *intf, const struct usb_device_id *id)
drm_kms_helper_poll_init(drm);
- drm_fbdev_generic_setup(drm, 0);
+ drm_fbdev_shmem_setup(drm, 0);
return 0;
}
@@ -678,4 +678,5 @@ static struct usb_driver gud_usb_driver = {
module_usb_driver(gud_usb_driver);
MODULE_AUTHOR("Noralf Trønnes");
+MODULE_DESCRIPTION("GUD USB Display driver");
MODULE_LICENSE("Dual MIT/GPL");
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
index 57c21ec452b7..9f9b19ea0587 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
@@ -17,7 +17,7 @@
#include <drm/drm_aperture.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_ttm.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_gem_vram_helper.h>
#include <drm/drm_managed.h>
@@ -339,7 +339,7 @@ static int hibmc_pci_probe(struct pci_dev *pdev,
goto err_unload;
}
- drm_fbdev_generic_setup(dev, 32);
+ drm_fbdev_ttm_setup(dev, 32);
return 0;
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
index 94e2c573a7af..409c551c92af 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
@@ -24,14 +24,16 @@
static int hibmc_connector_get_modes(struct drm_connector *connector)
{
- int count;
- void *edid;
struct hibmc_connector *hibmc_connector = to_hibmc_connector(connector);
+ const struct drm_edid *drm_edid;
+ int count;
+
+ drm_edid = drm_edid_read_ddc(connector, &hibmc_connector->adapter);
- edid = drm_get_edid(connector, &hibmc_connector->adapter);
- if (edid) {
- drm_connector_update_edid_property(connector, edid);
- count = drm_add_edid_modes(connector, edid);
+ drm_edid_connector_update(connector, drm_edid);
+
+ if (drm_edid) {
+ count = drm_edid_connector_add_modes(connector);
if (count)
goto out;
}
@@ -42,7 +44,8 @@ static int hibmc_connector_get_modes(struct drm_connector *connector)
drm_set_preferred_mode(connector, 1024, 768);
out:
- kfree(edid);
+ drm_edid_free(drm_edid);
+
return count;
}
diff --git a/drivers/gpu/drm/hisilicon/kirin/Kconfig b/drivers/gpu/drm/hisilicon/kirin/Kconfig
index c5265675bf0c..0772f79567ef 100644
--- a/drivers/gpu/drm/hisilicon/kirin/Kconfig
+++ b/drivers/gpu/drm/hisilicon/kirin/Kconfig
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
config DRM_HISI_KIRIN
tristate "DRM Support for Hisilicon Kirin series SoCs Platform"
- depends on DRM && OF && ARM64
+ depends on DRM && OF && (ARM64 || COMPILE_TEST)
select DRM_KMS_HELPER
select DRM_GEM_DMA_HELPER
select DRM_MIPI_DSI
diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
index 566de4658719..a39cc549c20b 100644
--- a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
+++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
@@ -157,8 +157,8 @@ static u32 dsi_calc_phy_rate(u32 req_kHz, struct mipi_phy_params *phy)
q_pll = 0x10 >> (7 - phy->hstx_ckg_sel);
temp = f_kHz * (u64)q_pll * (u64)ref_clk_ps;
- m_n_int = temp / (u64)1000000000;
- m_n = (temp % (u64)1000000000) / (u64)100000000;
+ m_n_int = div64_u64_rem(temp, 1000000000, &temp);
+ m_n = div_u64(temp, 100000000);
if (m_n_int % 2 == 0) {
if (m_n * 6 >= 50) {
@@ -229,9 +229,8 @@ static u32 dsi_calc_phy_rate(u32 req_kHz, struct mipi_phy_params *phy)
phy->pll_fbd_div5f = 1;
}
- f_kHz = (u64)1000000000 * (u64)m_pll /
- ((u64)ref_clk_ps * (u64)n_pll * (u64)q_pll);
-
+ f_kHz = div64_u64((u64)1000000000 * (u64)m_pll,
+ (u64)ref_clk_ps * (u64)n_pll * (u64)q_pll);
if (f_kHz >= req_kHz)
break;
@@ -490,7 +489,7 @@ static void dsi_set_mode_timing(void __iomem *base,
hsa_time = (hsw * lane_byte_clk_kHz) / pixel_clk_kHz;
hbp_time = (hbp * lane_byte_clk_kHz) / pixel_clk_kHz;
tmp = (u64)htot * (u64)lane_byte_clk_kHz;
- hline_time = DIV_ROUND_UP(tmp, pixel_clk_kHz);
+ hline_time = DIV_ROUND_UP_ULL(tmp, pixel_clk_kHz);
/* all specified in byte-lane clocks */
writel(hsa_time, base + VID_HSA_TIME);
diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_dsi_reg.h b/drivers/gpu/drm/hisilicon/kirin/dw_dsi_reg.h
index d79fc031e53d..a87d1135856f 100644
--- a/drivers/gpu/drm/hisilicon/kirin/dw_dsi_reg.h
+++ b/drivers/gpu/drm/hisilicon/kirin/dw_dsi_reg.h
@@ -7,6 +7,8 @@
#ifndef __DW_DSI_REG_H__
#define __DW_DSI_REG_H__
+#include <linux/io.h>
+
#define MASK(x) (BIT(x) - 1)
/*
diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_ade_reg.h b/drivers/gpu/drm/hisilicon/kirin/kirin_ade_reg.h
index be9e789c2d04..36f923cc7594 100644
--- a/drivers/gpu/drm/hisilicon/kirin/kirin_ade_reg.h
+++ b/drivers/gpu/drm/hisilicon/kirin/kirin_ade_reg.h
@@ -10,7 +10,7 @@
/*
* ADE Registers
*/
-#define MASK(x) (BIT(x) - 1)
+#define MASK(x) (BIT_ULL(x) - 1)
#define ADE_CTRL 0x0004
#define FRM_END_START_OFST 0
diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
index 75292a2f4644..12666985686b 100644
--- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
@@ -19,7 +19,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_dma.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_module.h>
@@ -237,7 +237,7 @@ static int kirin_drm_bind(struct device *dev)
if (ret)
goto err_kms_cleanup;
- drm_fbdev_generic_setup(drm_dev, 32);
+ drm_fbdev_dma_setup(drm_dev, 32);
return 0;
diff --git a/drivers/gpu/drm/hyperv/hyperv_drm_drv.c b/drivers/gpu/drm/hyperv/hyperv_drm_drv.c
index cff85086f2d6..ff93e08d5036 100644
--- a/drivers/gpu/drm/hyperv/hyperv_drm_drv.c
+++ b/drivers/gpu/drm/hyperv/hyperv_drm_drv.c
@@ -11,7 +11,7 @@
#include <drm/drm_aperture.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_shmem.h>
#include <drm/drm_gem_shmem_helper.h>
#include <drm/drm_simple_kms_helper.h>
@@ -149,7 +149,7 @@ static int hyperv_vmbus_probe(struct hv_device *hdev,
goto err_free_mmio;
}
- drm_fbdev_generic_setup(dev, 0);
+ drm_fbdev_shmem_setup(dev, 0);
return 0;
diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
index d8d7de18dd65..2160f05bbd16 100644
--- a/drivers/gpu/drm/i2c/tda998x_drv.c
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -1283,7 +1283,7 @@ static int read_edid_block(void *data, u8 *buf, unsigned int blk, size_t length)
static int tda998x_connector_get_modes(struct drm_connector *connector)
{
struct tda998x_priv *priv = conn_to_tda998x_priv(connector);
- struct edid *edid;
+ const struct drm_edid *drm_edid;
int n;
/*
@@ -1297,25 +1297,26 @@ static int tda998x_connector_get_modes(struct drm_connector *connector)
if (priv->rev == TDA19988)
reg_clear(priv, REG_TX4, TX4_PD_RAM);
- edid = drm_do_get_edid(connector, read_edid_block, priv);
+ drm_edid = drm_edid_read_custom(connector, read_edid_block, priv);
if (priv->rev == TDA19988)
reg_set(priv, REG_TX4, TX4_PD_RAM);
- if (!edid) {
+ drm_edid_connector_update(connector, drm_edid);
+ cec_notifier_set_phys_addr(priv->cec_notify,
+ connector->display_info.source_physical_address);
+
+ if (!drm_edid) {
dev_warn(&priv->hdmi->dev, "failed to read EDID\n");
return 0;
}
- drm_connector_update_edid_property(connector, edid);
- cec_notifier_set_phys_addr_from_edid(priv->cec_notify, edid);
-
mutex_lock(&priv->audio_mutex);
- n = drm_add_edid_modes(connector, edid);
- priv->sink_has_audio = drm_detect_monitor_audio(edid);
+ n = drm_edid_connector_add_modes(connector);
+ priv->sink_has_audio = connector->display_info.has_audio;
mutex_unlock(&priv->audio_mutex);
- kfree(edid);
+ drm_edid_free(drm_edid);
return n;
}
diff --git a/drivers/gpu/drm/i915/Kconfig.debug b/drivers/gpu/drm/i915/Kconfig.debug
index d8397065c3f0..1852e0804942 100644
--- a/drivers/gpu/drm/i915/Kconfig.debug
+++ b/drivers/gpu/drm/i915/Kconfig.debug
@@ -16,6 +16,23 @@ config DRM_I915_WERROR
If in doubt, say "N".
+config DRM_I915_REPLAY_GPU_HANGS_API
+ bool "Enable GPU hang replay userspace API"
+ depends on DRM_I915
+ depends on EXPERT
+ default n
+ help
+ Choose this option if you want to enable special and unstable
+ userspace API used for replaying GPU hangs on a running system.
+
+ This API is intended to be used by userspace graphics stack developers
+ and provides no stability guarantees.
+
+ The API needs to be activated at boot time using the
+ enable_debug_only_api module parameter.
+
+ If in doubt, say "N".
+
config DRM_I915_DEBUG
bool "Enable additional driver debugging"
depends on DRM_I915
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c
index 81f65cab1330..c0543c35cd6a 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c
@@ -78,6 +78,7 @@
#include "gt/intel_engine_user.h"
#include "gt/intel_gpu_commands.h"
#include "gt/intel_ring.h"
+#include "gt/shmem_utils.h"
#include "pxp/intel_pxp.h"
@@ -957,6 +958,7 @@ static int set_proto_ctx_param(struct drm_i915_file_private *fpriv,
case I915_CONTEXT_PARAM_NO_ZEROMAP:
case I915_CONTEXT_PARAM_BAN_PERIOD:
case I915_CONTEXT_PARAM_RINGSIZE:
+ case I915_CONTEXT_PARAM_CONTEXT_IMAGE:
default:
ret = -EINVAL;
break;
@@ -2104,6 +2106,95 @@ static int get_protected(struct i915_gem_context *ctx,
return 0;
}
+static int set_context_image(struct i915_gem_context *ctx,
+ struct drm_i915_gem_context_param *args)
+{
+ struct i915_gem_context_param_context_image user;
+ struct intel_context *ce;
+ struct file *shmem_state;
+ unsigned long lookup;
+ void *state;
+ int ret = 0;
+
+ if (!IS_ENABLED(CONFIG_DRM_I915_REPLAY_GPU_HANGS_API))
+ return -EINVAL;
+
+ if (!ctx->i915->params.enable_debug_only_api)
+ return -EINVAL;
+
+ if (args->size < sizeof(user))
+ return -EINVAL;
+
+ if (copy_from_user(&user, u64_to_user_ptr(args->value), sizeof(user)))
+ return -EFAULT;
+
+ if (user.mbz)
+ return -EINVAL;
+
+ if (user.flags & ~(I915_CONTEXT_IMAGE_FLAG_ENGINE_INDEX))
+ return -EINVAL;
+
+ lookup = 0;
+ if (user.flags & I915_CONTEXT_IMAGE_FLAG_ENGINE_INDEX)
+ lookup |= LOOKUP_USER_INDEX;
+
+ ce = lookup_user_engine(ctx, lookup, &user.engine);
+ if (IS_ERR(ce))
+ return PTR_ERR(ce);
+
+ if (user.size < ce->engine->context_size) {
+ ret = -EINVAL;
+ goto out_ce;
+ }
+
+ if (drm_WARN_ON_ONCE(&ctx->i915->drm,
+ test_bit(CONTEXT_ALLOC_BIT, &ce->flags))) {
+ /*
+ * This is racy but for a debug only API, if userspace is keen
+ * to create and configure contexts, while simultaneously using
+ * them from a second thread, let them suffer by potentially not
+ * executing with the context image they just raced to apply.
+ */
+ ret = -EBUSY;
+ goto out_ce;
+ }
+
+ state = kmalloc(ce->engine->context_size, GFP_KERNEL);
+ if (!state) {
+ ret = -ENOMEM;
+ goto out_ce;
+ }
+
+ if (copy_from_user(state, u64_to_user_ptr(user.image),
+ ce->engine->context_size)) {
+ ret = -EFAULT;
+ goto out_state;
+ }
+
+ shmem_state = shmem_create_from_data(ce->engine->name,
+ state, ce->engine->context_size);
+ if (IS_ERR(shmem_state)) {
+ ret = PTR_ERR(shmem_state);
+ goto out_state;
+ }
+
+ if (intel_context_set_own_state(ce)) {
+ ret = -EBUSY;
+ fput(shmem_state);
+ goto out_state;
+ }
+
+ ce->default_state = shmem_state;
+
+ args->size = sizeof(user);
+
+out_state:
+ kfree(state);
+out_ce:
+ intel_context_put(ce);
+ return ret;
+}
+
static int ctx_setparam(struct drm_i915_file_private *fpriv,
struct i915_gem_context *ctx,
struct drm_i915_gem_context_param *args)
@@ -2156,6 +2247,10 @@ static int ctx_setparam(struct drm_i915_file_private *fpriv,
ret = set_persistence(ctx, args);
break;
+ case I915_CONTEXT_PARAM_CONTEXT_IMAGE:
+ ret = set_context_image(ctx, args);
+ break;
+
case I915_CONTEXT_PARAM_PROTECTED_CONTENT:
case I915_CONTEXT_PARAM_NO_ZEROMAP:
case I915_CONTEXT_PARAM_BAN_PERIOD:
@@ -2500,6 +2595,7 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data,
case I915_CONTEXT_PARAM_BAN_PERIOD:
case I915_CONTEXT_PARAM_ENGINES:
case I915_CONTEXT_PARAM_RINGSIZE:
+ case I915_CONTEXT_PARAM_CONTEXT_IMAGE:
default:
ret = -EINVAL;
break;
@@ -2612,5 +2708,22 @@ int __init i915_gem_context_module_init(void)
if (!slab_luts)
return -ENOMEM;
+ if (IS_ENABLED(CONFIG_DRM_I915_REPLAY_GPU_HANGS_API)) {
+ pr_notice("**************************************************************\n");
+ pr_notice("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **\n");
+ pr_notice("** **\n");
+ if (i915_modparams.enable_debug_only_api)
+ pr_notice("** i915.enable_debug_only_api is intended to be set **\n");
+ else
+ pr_notice("** CONFIG_DRM_I915_REPLAY_GPU_HANGS_API builds are intended **\n");
+ pr_notice("** for specific userspace graphics stack developers only! **\n");
+ pr_notice("** **\n");
+ pr_notice("** If you are seeing this message please report this to the **\n");
+ pr_notice("** provider of your kernel build. **\n");
+ pr_notice("** **\n");
+ pr_notice("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **\n");
+ pr_notice("**************************************************************\n");
+ }
+
return 0;
}
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
index 090724fa766c..d54162ce0f99 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
@@ -340,7 +340,7 @@ static int eb_create(struct i915_execbuffer *eb)
* Without a 1:1 association between relocation handles and
* the execobject[] index, we instead create a hashtable.
* We size it dynamically based on available memory, starting
- * first with 1:1 assocative hash and scaling back until
+ * first with 1:1 associative hash and scaling back until
* the allocation succeeds.
*
* Later on we use a positive lut_size to indicate we are
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c
index 30595b2b63e1..d29005980806 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c
@@ -936,8 +936,12 @@ i915_gem_stolen_lmem_setup(struct drm_i915_private *i915, u16 type,
} else {
/* Use DSM base address instead for stolen memory */
dsm_base = intel_uncore_read64(uncore, GEN6_DSMBASE) & GEN11_BDSM_MASK;
- if (WARN_ON(lmem_size < dsm_base))
- return ERR_PTR(-ENODEV);
+ if (lmem_size < dsm_base) {
+ drm_dbg(&i915->drm,
+ "Disabling stolen memory support due to OOB placement: lmem_size = %pa vs dsm_base = %pa\n",
+ &lmem_size, &dsm_base);
+ return NULL;
+ }
dsm_size = ALIGN_DOWN(lmem_size - dsm_base, SZ_1M);
}
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c
index 7078af2f8f79..03b00a03a634 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c
@@ -155,7 +155,7 @@ void i915_ttm_adjust_gem_after_move(struct drm_i915_gem_object *obj)
* @bo: The ttm buffer object.
*
* This function prepares an object for move by removing all GPU bindings,
- * removing all CPU mapings and finally releasing the pages sg-table.
+ * removing all CPU mappings and finally releasing the pages sg-table.
*
* Return: 0 if successful, negative error code on error.
*/
diff --git a/drivers/gpu/drm/i915/gt/intel_context.c b/drivers/gpu/drm/i915/gt/intel_context.c
index a2f1245741bb..b1b8695ba7c9 100644
--- a/drivers/gpu/drm/i915/gt/intel_context.c
+++ b/drivers/gpu/drm/i915/gt/intel_context.c
@@ -27,6 +27,8 @@ static void rcu_context_free(struct rcu_head *rcu)
struct intel_context *ce = container_of(rcu, typeof(*ce), rcu);
trace_intel_context_free(ce);
+ if (intel_context_has_own_state(ce))
+ fput(ce->default_state);
kmem_cache_free(slab_ce, ce);
}
diff --git a/drivers/gpu/drm/i915/gt/intel_context.h b/drivers/gpu/drm/i915/gt/intel_context.h
index 25564c01507e..9f523999acd1 100644
--- a/drivers/gpu/drm/i915/gt/intel_context.h
+++ b/drivers/gpu/drm/i915/gt/intel_context.h
@@ -375,6 +375,28 @@ intel_context_clear_nopreempt(struct intel_context *ce)
clear_bit(CONTEXT_NOPREEMPT, &ce->flags);
}
+#if IS_ENABLED(CONFIG_DRM_I915_REPLAY_GPU_HANGS_API)
+static inline bool intel_context_has_own_state(const struct intel_context *ce)
+{
+ return test_bit(CONTEXT_OWN_STATE, &ce->flags);
+}
+
+static inline bool intel_context_set_own_state(struct intel_context *ce)
+{
+ return test_and_set_bit(CONTEXT_OWN_STATE, &ce->flags);
+}
+#else
+static inline bool intel_context_has_own_state(const struct intel_context *ce)
+{
+ return false;
+}
+
+static inline bool intel_context_set_own_state(struct intel_context *ce)
+{
+ return true;
+}
+#endif
+
u64 intel_context_get_total_runtime_ns(struct intel_context *ce);
u64 intel_context_get_avg_runtime_ns(struct intel_context *ce);
diff --git a/drivers/gpu/drm/i915/gt/intel_context_types.h b/drivers/gpu/drm/i915/gt/intel_context_types.h
index ed95a7b57cbb..98c7f6052069 100644
--- a/drivers/gpu/drm/i915/gt/intel_context_types.h
+++ b/drivers/gpu/drm/i915/gt/intel_context_types.h
@@ -99,6 +99,8 @@ struct intel_context {
struct i915_address_space *vm;
struct i915_gem_context __rcu *gem_context;
+ struct file *default_state;
+
/*
* @signal_lock protects the list of requests that need signaling,
* @signals. While there are any requests that need signaling,
@@ -131,6 +133,7 @@ struct intel_context {
#define CONTEXT_IS_PARKING 12
#define CONTEXT_EXITING 13
#define CONTEXT_LOW_LATENCY 14
+#define CONTEXT_OWN_STATE 15
struct {
u64 timeout_us;
diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
index 21829439e686..72090f52fb85 100644
--- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
+++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
@@ -3315,11 +3315,7 @@ static void remove_from_engine(struct i915_request *rq)
static bool can_preempt(struct intel_engine_cs *engine)
{
- if (GRAPHICS_VER(engine->i915) > 8)
- return true;
-
- /* GPGPU on bdw requires extra w/a; not implemented */
- return engine->class != RENDER_CLASS;
+ return GRAPHICS_VER(engine->i915) > 8;
}
static void kick_execlists(const struct i915_request *rq, int prio)
diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c b/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c
index 40371b8a9bbb..93bc1cc1ee7e 100644
--- a/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c
+++ b/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c
@@ -298,6 +298,7 @@ void i915_vma_revoke_fence(struct i915_vma *vma)
return;
GEM_BUG_ON(fence->vma != vma);
+ i915_active_wait(&fence->active);
GEM_BUG_ON(!i915_active_is_idle(&fence->active));
GEM_BUG_ON(atomic_read(&fence->pin_count));
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c b/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c
index c1ce6258e55c..8d08b38874ef 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c
@@ -71,6 +71,8 @@ static int fw_domains_show(struct seq_file *m, void *data)
struct intel_uncore_forcewake_domain *fw_domain;
unsigned int tmp;
+ spin_lock_irq(&uncore->lock);
+
seq_printf(m, "user.bypass_count = %u\n",
uncore->user_forcewake_count);
@@ -79,6 +81,8 @@ static int fw_domains_show(struct seq_file *m, void *data)
intel_uncore_forcewake_domain_to_str(fw_domain->id),
READ_ONCE(fw_domain->wake_count));
+ spin_unlock_irq(&uncore->lock);
+
return 0;
}
DEFINE_INTEL_GT_DEBUGFS_ATTRIBUTE(fw_domains);
diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c
index b387146ede98..7bd5d2c29056 100644
--- a/drivers/gpu/drm/i915/gt/intel_lrc.c
+++ b/drivers/gpu/drm/i915/gt/intel_lrc.c
@@ -1017,9 +1017,8 @@ void lrc_init_state(struct intel_context *ce,
set_redzone(state, engine);
- if (engine->default_state) {
- shmem_read(engine->default_state, 0,
- state, engine->context_size);
+ if (ce->default_state) {
+ shmem_read(ce->default_state, 0, state, engine->context_size);
__set_bit(CONTEXT_VALID_BIT, &ce->flags);
inhibit = false;
}
@@ -1131,6 +1130,9 @@ int lrc_alloc(struct intel_context *ce, struct intel_engine_cs *engine)
GEM_BUG_ON(ce->state);
+ if (!intel_context_has_own_state(ce))
+ ce->default_state = engine->default_state;
+
vma = __lrc_alloc_state(ce, engine);
if (IS_ERR(vma))
return PTR_ERR(vma);
diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c
index 6161f7a3ff70..735cd23a43c6 100644
--- a/drivers/gpu/drm/i915/gt/intel_reset.c
+++ b/drivers/gpu/drm/i915/gt/intel_reset.c
@@ -1025,7 +1025,7 @@ void intel_gt_set_wedged(struct intel_gt *gt)
if (GEM_SHOW_DEBUG()) {
struct drm_printer p = drm_dbg_printer(&gt->i915->drm,
- DRM_UT_DRIVER, __func__);
+ DRM_UT_DRIVER, NULL);
struct intel_engine_cs *engine;
enum intel_engine_id id;
diff --git a/drivers/gpu/drm/i915/gt/intel_ring_submission.c b/drivers/gpu/drm/i915/gt/intel_ring_submission.c
index 92085ffd23de..72277bc8322e 100644
--- a/drivers/gpu/drm/i915/gt/intel_ring_submission.c
+++ b/drivers/gpu/drm/i915/gt/intel_ring_submission.c
@@ -474,8 +474,7 @@ static int ring_context_init_default_state(struct intel_context *ce,
if (IS_ERR(vaddr))
return PTR_ERR(vaddr);
- shmem_read(ce->engine->default_state, 0,
- vaddr, ce->engine->context_size);
+ shmem_read(ce->default_state, 0, vaddr, ce->engine->context_size);
i915_gem_object_flush_map(obj);
__i915_gem_object_release_map(obj);
@@ -491,7 +490,7 @@ static int ring_context_pre_pin(struct intel_context *ce,
struct i915_address_space *vm;
int err = 0;
- if (ce->engine->default_state &&
+ if (ce->default_state &&
!test_bit(CONTEXT_VALID_BIT, &ce->flags)) {
err = ring_context_init_default_state(ce, ww);
if (err)
@@ -570,6 +569,9 @@ static int ring_context_alloc(struct intel_context *ce)
{
struct intel_engine_cs *engine = ce->engine;
+ if (!intel_context_has_own_state(ce))
+ ce->default_state = engine->default_state;
+
/* One ringbuffer to rule them all */
GEM_BUG_ON(!engine->legacy.ring);
ce->ring = engine->legacy.ring;
diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c
index 5a0f1b279a80..09a287c1aedd 100644
--- a/drivers/gpu/drm/i915/gt/intel_workarounds.c
+++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c
@@ -1590,6 +1590,14 @@ xelpmp_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal)
*/
wa_write_or(wal, XELPMP_GSC_MOD_CTRL, FORCE_MISS_FTLB);
+ /*
+ * Wa_14018575942
+ *
+ * Issue is seen on media KPI test running on VDBOX engine
+ * especially VP9 encoding WLs
+ */
+ wa_write_or(wal, XELPMP_VDBX_MOD_CTRL, FORCE_MISS_FTLB);
+
/* Wa_22016670082 */
wa_write_or(wal, GEN12_SQCNT1, GEN12_STRICT_RAR_ENABLE);
diff --git a/drivers/gpu/drm/i915/gt/selftest_context.c b/drivers/gpu/drm/i915/gt/selftest_context.c
index 12eca750f7d0..5eb46700dc4e 100644
--- a/drivers/gpu/drm/i915/gt/selftest_context.c
+++ b/drivers/gpu/drm/i915/gt/selftest_context.c
@@ -286,7 +286,7 @@ out_engine:
if (intel_engine_pm_is_awake(engine)) {
struct drm_printer p = drm_dbg_printer(&engine->i915->drm,
- DRM_UT_DRIVER, __func__);
+ DRM_UT_DRIVER, NULL);
intel_engine_dump(engine, &p,
"%s is still awake:%d after idle-barriers\n",
diff --git a/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c b/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c
index ef014df4c4fc..9e4f0e417b3b 100644
--- a/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c
+++ b/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c
@@ -193,115 +193,6 @@ static int live_idle_pulse(void *arg)
return err;
}
-static int cmp_u32(const void *_a, const void *_b)
-{
- const u32 *a = _a, *b = _b;
-
- return *a - *b;
-}
-
-static int __live_heartbeat_fast(struct intel_engine_cs *engine)
-{
- const unsigned int error_threshold = max(20000u, jiffies_to_usecs(6));
- struct intel_context *ce;
- struct i915_request *rq;
- ktime_t t0, t1;
- u32 times[5];
- int err;
- int i;
-
- ce = intel_context_create(engine);
- if (IS_ERR(ce))
- return PTR_ERR(ce);
-
- intel_engine_pm_get(engine);
-
- err = intel_engine_set_heartbeat(engine, 1);
- if (err)
- goto err_pm;
-
- for (i = 0; i < ARRAY_SIZE(times); i++) {
- do {
- /* Manufacture a tick */
- intel_engine_park_heartbeat(engine);
- GEM_BUG_ON(engine->heartbeat.systole);
- engine->serial++; /* pretend we are not idle! */
- intel_engine_unpark_heartbeat(engine);
-
- flush_delayed_work(&engine->heartbeat.work);
- if (!delayed_work_pending(&engine->heartbeat.work)) {
- pr_err("%s: heartbeat %d did not start\n",
- engine->name, i);
- err = -EINVAL;
- goto err_pm;
- }
-
- rcu_read_lock();
- rq = READ_ONCE(engine->heartbeat.systole);
- if (rq)
- rq = i915_request_get_rcu(rq);
- rcu_read_unlock();
- } while (!rq);
-
- t0 = ktime_get();
- while (rq == READ_ONCE(engine->heartbeat.systole))
- yield(); /* work is on the local cpu! */
- t1 = ktime_get();
-
- i915_request_put(rq);
- times[i] = ktime_us_delta(t1, t0);
- }
-
- sort(times, ARRAY_SIZE(times), sizeof(times[0]), cmp_u32, NULL);
-
- pr_info("%s: Heartbeat delay: %uus [%u, %u]\n",
- engine->name,
- times[ARRAY_SIZE(times) / 2],
- times[0],
- times[ARRAY_SIZE(times) - 1]);
-
- /*
- * Ideally, the upper bound on min work delay would be something like
- * 2 * 2 (worst), +1 for scheduling, +1 for slack. In practice, we
- * are, even with system_wq_highpri, at the mercy of the CPU scheduler
- * and may be stuck behind some slow work for many millisecond. Such
- * as our very own display workers.
- */
- if (times[ARRAY_SIZE(times) / 2] > error_threshold) {
- pr_err("%s: Heartbeat delay was %uus, expected less than %dus\n",
- engine->name,
- times[ARRAY_SIZE(times) / 2],
- error_threshold);
- err = -EINVAL;
- }
-
- reset_heartbeat(engine);
-err_pm:
- intel_engine_pm_put(engine);
- intel_context_put(ce);
- return err;
-}
-
-static int live_heartbeat_fast(void *arg)
-{
- struct intel_gt *gt = arg;
- struct intel_engine_cs *engine;
- enum intel_engine_id id;
- int err = 0;
-
- /* Check that the heartbeat ticks at the desired rate. */
- if (!CONFIG_DRM_I915_HEARTBEAT_INTERVAL)
- return 0;
-
- for_each_engine(engine, gt, id) {
- err = __live_heartbeat_fast(engine);
- if (err)
- break;
- }
-
- return err;
-}
-
static int __live_heartbeat_off(struct intel_engine_cs *engine)
{
int err;
@@ -372,7 +263,6 @@ int intel_heartbeat_live_selftests(struct drm_i915_private *i915)
static const struct i915_subtest tests[] = {
SUBTEST(live_idle_flush),
SUBTEST(live_idle_pulse),
- SUBTEST(live_heartbeat_fast),
SUBTEST(live_heartbeat_off),
};
int saved_hangcheck;
diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h
index 525587cfe1af..37ff539a6963 100644
--- a/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h
+++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h
@@ -106,6 +106,7 @@ enum {
*/
enum {
GUC_WORKAROUND_KLV_SERIALIZED_RA_MODE = 0x9001,
+ GUC_WORKAROUND_KLV_BLOCK_INTERRUPTS_WHEN_MGSR_BLOCKED = 0x9002,
};
#endif /* _ABI_GUC_KLVS_ABI_H */
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
index c606bb5e3b7b..7995f059f30d 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
@@ -815,23 +815,23 @@ engine_instance_list:
return PAGE_ALIGN(total_size);
}
-/* Wa_14019159160 */
-static u32 guc_waklv_ra_mode(struct intel_guc *guc, u32 offset, u32 remain)
+static void guc_waklv_enable_simple(struct intel_guc *guc,
+ u32 klv_id, u32 *offset, u32 *remain)
{
u32 size;
u32 klv_entry[] = {
/* 16:16 key/length */
- FIELD_PREP(GUC_KLV_0_KEY, GUC_WORKAROUND_KLV_SERIALIZED_RA_MODE) |
+ FIELD_PREP(GUC_KLV_0_KEY, klv_id) |
FIELD_PREP(GUC_KLV_0_LEN, 0),
/* 0 dwords data */
};
size = sizeof(klv_entry);
- GEM_BUG_ON(remain < size);
+ GEM_BUG_ON(*remain < size);
- iosys_map_memcpy_to(&guc->ads_map, offset, klv_entry, size);
-
- return size;
+ iosys_map_memcpy_to(&guc->ads_map, *offset, klv_entry, size);
+ *offset += size;
+ *remain -= size;
}
static void guc_waklv_init(struct intel_guc *guc)
@@ -850,11 +850,19 @@ static void guc_waklv_init(struct intel_guc *guc)
remain = guc_ads_waklv_size(guc);
/* Wa_14019159160 */
- if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71))) {
- size = guc_waklv_ra_mode(guc, offset, remain);
- offset += size;
- remain -= size;
- }
+ if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71)))
+ guc_waklv_enable_simple(guc,
+ GUC_WORKAROUND_KLV_SERIALIZED_RA_MODE,
+ &offset, &remain);
+
+ /* Wa_16021333562 */
+ if ((GUC_FIRMWARE_VER(guc) >= MAKE_GUC_VER(70, 21, 1)) &&
+ (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 74)) ||
+ IS_MEDIA_GT_IP_RANGE(gt, IP_VER(13, 0), IP_VER(13, 0)) ||
+ IS_DG2(gt->i915)))
+ guc_waklv_enable_simple(guc,
+ GUC_WORKAROUND_KLV_BLOCK_INTERRUPTS_WHEN_MGSR_BLOCKED,
+ &offset, &remain);
size = guc_ads_waklv_size(guc) - remain;
if (!size)
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
index 14797e80bc92..263c9c3f6a03 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
@@ -295,7 +295,7 @@ struct guc_update_scheduling_policy_header {
} __packed;
/*
- * Can't dynmically allocate memory for the scheduling policy KLV because
+ * Can't dynamically allocate memory for the scheduling policy KLV because
* it will be sent from within the reset path. Need a fixed size lump on
* the stack instead :(.
*
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
index 0eaa1064242c..9400d0eb682b 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
@@ -4267,20 +4267,25 @@ static void guc_bump_inflight_request_prio(struct i915_request *rq,
u8 new_guc_prio = map_i915_prio_to_guc_prio(prio);
/* Short circuit function */
- if (prio < I915_PRIORITY_NORMAL ||
- rq->guc_prio == GUC_PRIO_FINI ||
- (rq->guc_prio != GUC_PRIO_INIT &&
- !new_guc_prio_higher(rq->guc_prio, new_guc_prio)))
+ if (prio < I915_PRIORITY_NORMAL)
return;
spin_lock(&ce->guc_state.lock);
- if (rq->guc_prio != GUC_PRIO_FINI) {
- if (rq->guc_prio != GUC_PRIO_INIT)
- sub_context_inflight_prio(ce, rq->guc_prio);
- rq->guc_prio = new_guc_prio;
- add_context_inflight_prio(ce, rq->guc_prio);
- update_context_prio(ce);
- }
+
+ if (rq->guc_prio == GUC_PRIO_FINI)
+ goto exit;
+
+ if (!new_guc_prio_higher(rq->guc_prio, new_guc_prio))
+ goto exit;
+
+ if (rq->guc_prio != GUC_PRIO_INIT)
+ sub_context_inflight_prio(ce, rq->guc_prio);
+
+ rq->guc_prio = new_guc_prio;
+ add_context_inflight_prio(ce, rq->guc_prio);
+ update_context_prio(ce);
+
+exit:
spin_unlock(&ce->guc_state.lock);
}
diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
index 4f74d867fe1a..38830818c120 100644
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -1985,5 +1985,6 @@ static void __exit kvmgt_exit(void)
module_init(kvmgt_init);
module_exit(kvmgt_exit);
+MODULE_DESCRIPTION("Intel mediated pass-through framework for KVM");
MODULE_LICENSE("GPL and additional rights");
MODULE_AUTHOR("Intel Corporation");
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index bef3c5b0551f..94f7f6cc444c 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -721,8 +721,8 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
*/
#define HAS_64K_PAGES(i915) (INTEL_INFO(i915)->has_64k_pages)
-#define HAS_REGION(i915, i) (INTEL_INFO(i915)->memory_regions & (i))
-#define HAS_LMEM(i915) HAS_REGION(i915, REGION_LMEM)
+#define HAS_REGION(i915, id) (INTEL_INFO(i915)->memory_regions & BIT(id))
+#define HAS_LMEM(i915) HAS_REGION(i915, INTEL_REGION_LMEM_0)
#define HAS_EXTRA_GT_LIST(i915) (INTEL_INFO(i915)->extra_gt_list)
diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
index 8c00169e3ab7..316e55f3e87b 100644
--- a/drivers/gpu/drm/i915/i915_params.c
+++ b/drivers/gpu/drm/i915/i915_params.c
@@ -131,6 +131,11 @@ i915_param_named_unsafe(lmem_size, uint, 0400,
i915_param_named_unsafe(lmem_bar_size, uint, 0400,
"Set the lmem bar size(in MiB).");
+#if IS_ENABLED(CONFIG_DRM_I915_REPLAY_GPU_HANGS_API)
+i915_param_named(enable_debug_only_api, bool, 0400,
+ "Enable support for unstable debug only userspace API. (default:false)");
+#endif
+
static void _param_print_bool(struct drm_printer *p, const char *name,
bool val)
{
diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h
index 2eb3f2115ff2..0fbcb5b6d7bf 100644
--- a/drivers/gpu/drm/i915/i915_params.h
+++ b/drivers/gpu/drm/i915/i915_params.h
@@ -63,7 +63,8 @@ struct drm_printer;
/* leave bools at the end to not create holes */ \
param(bool, enable_hangcheck, true, 0600) \
param(bool, error_capture, true, IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) ? 0600 : 0) \
- param(bool, enable_gvt, false, IS_ENABLED(CONFIG_DRM_I915_GVT) ? 0400 : 0)
+ param(bool, enable_gvt, false, IS_ENABLED(CONFIG_DRM_I915_GVT) ? 0400 : 0) \
+ param(bool, enable_debug_only_api, false, IS_ENABLED(CONFIG_DRM_I915_REPLAY_GPU_HANGS_API) ? 0400 : 0)
#define MEMBER(T, member, ...) T member;
struct i915_params {
diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c
index 7058efa75324..ce4dfd65fafa 100644
--- a/drivers/gpu/drm/i915/i915_pci.c
+++ b/drivers/gpu/drm/i915/i915_pci.c
@@ -76,7 +76,7 @@ __diag_ignore_all("-Woverride-init", "Allow field initialization overrides for d
.__runtime.page_sizes = I915_GTT_PAGE_SIZE_4K
#define GEN_DEFAULT_REGIONS \
- .memory_regions = REGION_SMEM | REGION_STOLEN_SMEM
+ .memory_regions = BIT(INTEL_REGION_SMEM) | BIT(INTEL_REGION_STOLEN_SMEM)
#define I830_FEATURES \
GEN(2), \
@@ -655,7 +655,7 @@ static const struct intel_device_info rkl_info = {
};
#define DGFX_FEATURES \
- .memory_regions = REGION_SMEM | REGION_LMEM | REGION_STOLEN_LMEM, \
+ .memory_regions = BIT(INTEL_REGION_SMEM) | BIT(INTEL_REGION_LMEM_0) | BIT(INTEL_REGION_STOLEN_LMEM), \
.has_llc = 0, \
.has_pxp = 0, \
.has_snoop = 1, \
@@ -781,7 +781,7 @@ static const struct intel_device_info mtl_info = {
.has_snoop = 1,
.max_pat_index = 4,
.has_pxp = 1,
- .memory_regions = REGION_SMEM | REGION_STOLEN_LMEM,
+ .memory_regions = BIT(INTEL_REGION_SMEM) | BIT(INTEL_REGION_STOLEN_LMEM),
.platform_engine_mask = BIT(RCS0) | BIT(BCS0) | BIT(CCS0),
MTL_CACHELEVEL,
};
diff --git a/drivers/gpu/drm/i915/i915_scatterlist.c b/drivers/gpu/drm/i915/i915_scatterlist.c
index e93d2538f298..4d830740946d 100644
--- a/drivers/gpu/drm/i915/i915_scatterlist.c
+++ b/drivers/gpu/drm/i915/i915_scatterlist.c
@@ -90,7 +90,7 @@ struct i915_refct_sgt *i915_rsgt_from_mm_node(const struct drm_mm_node *node,
GEM_BUG_ON(!max_segment);
- rsgt = kmalloc(sizeof(*rsgt), GFP_KERNEL);
+ rsgt = kmalloc(sizeof(*rsgt), GFP_KERNEL | __GFP_NOWARN);
if (!rsgt)
return ERR_PTR(-ENOMEM);
@@ -104,7 +104,7 @@ struct i915_refct_sgt *i915_rsgt_from_mm_node(const struct drm_mm_node *node,
}
if (sg_alloc_table(st, DIV_ROUND_UP_ULL(node->size, segment_pages),
- GFP_KERNEL)) {
+ GFP_KERNEL | __GFP_NOWARN)) {
i915_refct_sgt_put(rsgt);
return ERR_PTR(-ENOMEM);
}
@@ -178,7 +178,7 @@ struct i915_refct_sgt *i915_rsgt_from_buddy_resource(struct ttm_resource *res,
GEM_BUG_ON(list_empty(blocks));
GEM_BUG_ON(!max_segment);
- rsgt = kmalloc(sizeof(*rsgt), GFP_KERNEL);
+ rsgt = kmalloc(sizeof(*rsgt), GFP_KERNEL | __GFP_NOWARN);
if (!rsgt)
return ERR_PTR(-ENOMEM);
@@ -190,7 +190,7 @@ struct i915_refct_sgt *i915_rsgt_from_buddy_resource(struct ttm_resource *res,
return ERR_PTR(-E2BIG);
}
- if (sg_alloc_table(st, PFN_UP(res->size), GFP_KERNEL)) {
+ if (sg_alloc_table(st, PFN_UP(res->size), GFP_KERNEL | __GFP_NOWARN)) {
i915_refct_sgt_put(rsgt);
return ERR_PTR(-ENOMEM);
}
diff --git a/drivers/gpu/drm/i915/intel_memory_region.c b/drivers/gpu/drm/i915/intel_memory_region.c
index 52d998e5c21a..d40ee1b42110 100644
--- a/drivers/gpu/drm/i915/intel_memory_region.c
+++ b/drivers/gpu/drm/i915/intel_memory_region.c
@@ -332,7 +332,7 @@ int intel_memory_regions_hw_probe(struct drm_i915_private *i915)
struct intel_memory_region *mem = ERR_PTR(-ENODEV);
u16 type, instance;
- if (!HAS_REGION(i915, BIT(i)))
+ if (!HAS_REGION(i915, i))
continue;
type = intel_region_map[i].class;
@@ -368,8 +368,10 @@ int intel_memory_regions_hw_probe(struct drm_i915_private *i915)
goto out_cleanup;
}
- mem->id = i;
- i915->mm.regions[i] = mem;
+ if (mem) { /* Skip on non-fatal errors */
+ mem->id = i;
+ i915->mm.regions[i] = mem;
+ }
}
for (i = 0; i < ARRAY_SIZE(i915->mm.regions); i++) {
diff --git a/drivers/gpu/drm/i915/intel_memory_region.h b/drivers/gpu/drm/i915/intel_memory_region.h
index 8c927e303c4a..5973b6fe13cf 100644
--- a/drivers/gpu/drm/i915/intel_memory_region.h
+++ b/drivers/gpu/drm/i915/intel_memory_region.h
@@ -38,11 +38,6 @@ enum intel_region_id {
INTEL_REGION_UNKNOWN, /* Should be last */
};
-#define REGION_SMEM BIT(INTEL_REGION_SMEM)
-#define REGION_LMEM BIT(INTEL_REGION_LMEM_0)
-#define REGION_STOLEN_SMEM BIT(INTEL_REGION_STOLEN_SMEM)
-#define REGION_STOLEN_LMEM BIT(INTEL_REGION_STOLEN_LMEM)
-
#define I915_ALLOC_CONTIGUOUS BIT(0)
#define for_each_memory_region(mr, i915, id) \
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index 729409a4bada..2eba289d88ad 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -2614,12 +2614,19 @@ void intel_uncore_prune_engine_fw_domains(struct intel_uncore *uncore,
static void driver_initiated_flr(struct intel_uncore *uncore)
{
struct drm_i915_private *i915 = uncore->i915;
- const unsigned int flr_timeout_ms = 3000; /* specs recommend a 3s wait */
+ unsigned int flr_timeout_ms;
int ret;
drm_dbg(&i915->drm, "Triggering Driver-FLR\n");
/*
+ * The specification recommends a 3 seconds FLR reset timeout. To be
+ * cautious, we will extend this to 9 seconds, three times the specified
+ * timeout.
+ */
+ flr_timeout_ms = 9000;
+
+ /*
* Make sure any pending FLR requests have cleared by waiting for the
* FLR trigger bit to go to zero. Also clear GU_DEBUG's DRIVERFLR_STATUS
* to make sure it's not still set from a prior attempt (it's a write to
diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c
index af349fd9abc2..0bd29846873b 100644
--- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c
+++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c
@@ -122,7 +122,7 @@ static const struct intel_device_info mock_info = {
.__runtime.page_sizes = (I915_GTT_PAGE_SIZE_4K |
I915_GTT_PAGE_SIZE_64K |
I915_GTT_PAGE_SIZE_2M),
- .memory_regions = REGION_SMEM,
+ .memory_regions = BIT(INTEL_REGION_SMEM),
.platform_engine_mask = BIT(0),
/* simply use legacy cache level for mock device */
diff --git a/drivers/gpu/drm/imagination/pvr_drv.c b/drivers/gpu/drm/imagination/pvr_drv.c
index 5c3b2d58d766..1a0cb7aa9cea 100644
--- a/drivers/gpu/drm/imagination/pvr_drv.c
+++ b/drivers/gpu/drm/imagination/pvr_drv.c
@@ -1451,8 +1451,7 @@ err_context_fini:
return err;
}
-static int
-pvr_remove(struct platform_device *plat_dev)
+static void pvr_remove(struct platform_device *plat_dev)
{
struct drm_device *drm_dev = platform_get_drvdata(plat_dev);
struct pvr_device *pvr_dev = to_pvr_device(drm_dev);
@@ -1469,8 +1468,6 @@ pvr_remove(struct platform_device *plat_dev)
pvr_watchdog_fini(pvr_dev);
pvr_queue_device_fini(pvr_dev);
pvr_context_device_fini(pvr_dev);
-
- return 0;
}
static const struct of_device_id dt_match[] = {
@@ -1485,7 +1482,7 @@ static const struct dev_pm_ops pvr_pm_ops = {
static struct platform_driver pvr_driver = {
.probe = pvr_probe,
- .remove = pvr_remove,
+ .remove_new = pvr_remove,
.driver = {
.name = PVR_DRIVER_NAME,
.pm = &pvr_pm_ops,
diff --git a/drivers/gpu/drm/imx/ipuv3/imx-ldb.c b/drivers/gpu/drm/imx/ipuv3/imx-ldb.c
index 71d70194fcbd..793dfb1a3ed0 100644
--- a/drivers/gpu/drm/imx/ipuv3/imx-ldb.c
+++ b/drivers/gpu/drm/imx/ipuv3/imx-ldb.c
@@ -72,7 +72,7 @@ struct imx_ldb_channel {
struct device_node *child;
struct i2c_adapter *ddc;
int chno;
- void *edid;
+ const struct drm_edid *drm_edid;
struct drm_display_mode mode;
int mode_valid;
u32 bus_format;
@@ -142,15 +142,15 @@ static int imx_ldb_connector_get_modes(struct drm_connector *connector)
if (num_modes > 0)
return num_modes;
- if (!imx_ldb_ch->edid && imx_ldb_ch->ddc)
- imx_ldb_ch->edid = drm_get_edid(connector, imx_ldb_ch->ddc);
-
- if (imx_ldb_ch->edid) {
- drm_connector_update_edid_property(connector,
- imx_ldb_ch->edid);
- num_modes = drm_add_edid_modes(connector, imx_ldb_ch->edid);
+ if (!imx_ldb_ch->drm_edid && imx_ldb_ch->ddc) {
+ imx_ldb_ch->drm_edid = drm_edid_read_ddc(connector,
+ imx_ldb_ch->ddc);
+ drm_edid_connector_update(connector, imx_ldb_ch->drm_edid);
}
+ if (imx_ldb_ch->drm_edid)
+ num_modes = drm_edid_connector_add_modes(connector);
+
if (imx_ldb_ch->mode_valid) {
struct drm_display_mode *mode;
@@ -553,7 +553,6 @@ static int imx_ldb_panel_ddc(struct device *dev,
struct imx_ldb_channel *channel, struct device_node *child)
{
struct device_node *ddc_node;
- const u8 *edidp;
int ret;
ddc_node = of_parse_phandle(child, "ddc-i2c-bus", 0);
@@ -567,6 +566,7 @@ static int imx_ldb_panel_ddc(struct device *dev,
}
if (!channel->ddc) {
+ const void *edidp;
int edid_len;
/* if no DDC available, fallback to hardcoded EDID */
@@ -574,8 +574,8 @@ static int imx_ldb_panel_ddc(struct device *dev,
edidp = of_get_property(child, "edid", &edid_len);
if (edidp) {
- channel->edid = kmemdup(edidp, edid_len, GFP_KERNEL);
- if (!channel->edid)
+ channel->drm_edid = drm_edid_alloc(edidp, edid_len);
+ if (!channel->drm_edid)
return -ENOMEM;
} else if (!channel->panel) {
/* fallback to display-timings node */
@@ -744,7 +744,7 @@ static void imx_ldb_remove(struct platform_device *pdev)
for (i = 0; i < 2; i++) {
struct imx_ldb_channel *channel = &imx_ldb->channel[i];
- kfree(channel->edid);
+ drm_edid_free(channel->drm_edid);
i2c_put_adapter(channel->ddc);
}
diff --git a/drivers/gpu/drm/imx/ipuv3/imx-tve.c b/drivers/gpu/drm/imx/ipuv3/imx-tve.c
index b49bddb85535..29f494bfff67 100644
--- a/drivers/gpu/drm/imx/ipuv3/imx-tve.c
+++ b/drivers/gpu/drm/imx/ipuv3/imx-tve.c
@@ -201,18 +201,16 @@ static int tve_setup_vga(struct imx_tve *tve)
static int imx_tve_connector_get_modes(struct drm_connector *connector)
{
struct imx_tve *tve = con_to_tve(connector);
- struct edid *edid;
- int ret = 0;
+ const struct drm_edid *drm_edid;
+ int ret;
if (!tve->ddc)
return 0;
- edid = drm_get_edid(connector, tve->ddc);
- if (edid) {
- drm_connector_update_edid_property(connector, edid);
- ret = drm_add_edid_modes(connector, edid);
- kfree(edid);
- }
+ drm_edid = drm_edid_read_ddc(connector, tve->ddc);
+ drm_edid_connector_update(connector, drm_edid);
+ ret = drm_edid_connector_add_modes(connector);
+ drm_edid_free(drm_edid);
return ret;
}
diff --git a/drivers/gpu/drm/imx/lcdc/imx-lcdc.c b/drivers/gpu/drm/imx/lcdc/imx-lcdc.c
index 43ddf3a9810b..36668455aee8 100644
--- a/drivers/gpu/drm/imx/lcdc/imx-lcdc.c
+++ b/drivers/gpu/drm/imx/lcdc/imx-lcdc.c
@@ -5,7 +5,7 @@
#include <drm/drm_bridge_connector.h>
#include <drm/drm_damage_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_dma.h>
#include <drm/drm_fb_dma_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
@@ -501,7 +501,7 @@ static int imx_lcdc_probe(struct platform_device *pdev)
if (ret)
return dev_err_probe(dev, ret, "Cannot register device\n");
- drm_fbdev_generic_setup(drm, 0);
+ drm_fbdev_dma_setup(drm, 0);
return 0;
}
diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
index 0751235007a7..39fa291f43dd 100644
--- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
+++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
@@ -31,7 +31,7 @@
#include <drm/drm_encoder.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_fb_dma_helper.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_dma.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_atomic_helper.h>
@@ -1399,7 +1399,7 @@ static int ingenic_drm_bind(struct device *dev, bool has_components)
goto err_clk_notifier_unregister;
}
- drm_fbdev_generic_setup(drm, 32);
+ drm_fbdev_dma_setup(drm, 32);
return 0;
diff --git a/drivers/gpu/drm/lima/lima_drv.c b/drivers/gpu/drm/lima/lima_drv.c
index 739c865b556f..10bce18b7c31 100644
--- a/drivers/gpu/drm/lima/lima_drv.c
+++ b/drivers/gpu/drm/lima/lima_drv.c
@@ -501,3 +501,4 @@ module_platform_driver(lima_platform_driver);
MODULE_AUTHOR("Lima Project Developers");
MODULE_DESCRIPTION("Lima DRM Driver");
MODULE_LICENSE("GPL v2");
+MODULE_SOFTDEP("pre: governor_simpleondemand");
diff --git a/drivers/gpu/drm/loongson/Kconfig b/drivers/gpu/drm/loongson/Kconfig
index 8e59753e532d..9ed463a76ae2 100644
--- a/drivers/gpu/drm/loongson/Kconfig
+++ b/drivers/gpu/drm/loongson/Kconfig
@@ -6,6 +6,7 @@ config DRM_LOONGSON
depends on LOONGARCH || MIPS || COMPILE_TEST
select DRM_KMS_HELPER
select DRM_TTM
+ select DRM_TTM_HELPER
select I2C
select I2C_ALGOBIT
help
diff --git a/drivers/gpu/drm/loongson/lsdc_drv.c b/drivers/gpu/drm/loongson/lsdc_drv.c
index d8ff60b46abe..adc7344d2f80 100644
--- a/drivers/gpu/drm/loongson/lsdc_drv.c
+++ b/drivers/gpu/drm/loongson/lsdc_drv.c
@@ -10,7 +10,7 @@
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_ttm.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_ioctl.h>
#include <drm/drm_modeset_helper.h>
@@ -314,7 +314,7 @@ static int lsdc_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (ret)
return ret;
- drm_fbdev_generic_setup(ddev, 32);
+ drm_fbdev_ttm_setup(ddev, 32);
return 0;
}
diff --git a/drivers/gpu/drm/loongson/lsdc_output_7a1000.c b/drivers/gpu/drm/loongson/lsdc_output_7a1000.c
index 6fc8dd1c7d9a..600ed4fb0884 100644
--- a/drivers/gpu/drm/loongson/lsdc_output_7a1000.c
+++ b/drivers/gpu/drm/loongson/lsdc_output_7a1000.c
@@ -40,16 +40,15 @@
static int ls7a1000_dpi_connector_get_modes(struct drm_connector *conn)
{
- unsigned int num = 0;
- struct edid *edid;
+ int num;
if (conn->ddc) {
- edid = drm_get_edid(conn, conn->ddc);
- if (edid) {
- drm_connector_update_edid_property(conn, edid);
- num = drm_add_edid_modes(conn, edid);
- kfree(edid);
- }
+ const struct drm_edid *drm_edid;
+
+ drm_edid = drm_edid_read(conn);
+ drm_edid_connector_update(conn, drm_edid);
+ num = drm_edid_connector_add_modes(conn);
+ drm_edid_free(drm_edid);
return num;
}
diff --git a/drivers/gpu/drm/loongson/lsdc_output_7a2000.c b/drivers/gpu/drm/loongson/lsdc_output_7a2000.c
index ce3dabec887e..2bd797a9b9ff 100644
--- a/drivers/gpu/drm/loongson/lsdc_output_7a2000.c
+++ b/drivers/gpu/drm/loongson/lsdc_output_7a2000.c
@@ -44,16 +44,15 @@
static int ls7a2000_connector_get_modes(struct drm_connector *connector)
{
- unsigned int num = 0;
- struct edid *edid;
+ int num;
if (connector->ddc) {
- edid = drm_get_edid(connector, connector->ddc);
- if (edid) {
- drm_connector_update_edid_property(connector, edid);
- num = drm_add_edid_modes(connector, edid);
- kfree(edid);
- }
+ const struct drm_edid *drm_edid;
+
+ drm_edid = drm_edid_read(connector);
+ drm_edid_connector_update(connector, drm_edid);
+ num = drm_edid_connector_add_modes(connector);
+ drm_edid_free(drm_edid);
return num;
}
diff --git a/drivers/gpu/drm/mediatek/Kconfig b/drivers/gpu/drm/mediatek/Kconfig
index 96cbe020f493..d6449ebae838 100644
--- a/drivers/gpu/drm/mediatek/Kconfig
+++ b/drivers/gpu/drm/mediatek/Kconfig
@@ -7,6 +7,7 @@ config DRM_MEDIATEK
depends on HAVE_ARM_SMCCC
depends on OF
depends on MTK_MMSYS
+ select DRM_GEM_DMA_HELPER if DRM_FBDEV_EMULATION
select DRM_KMS_HELPER
select DRM_MIPI_DSI
select DRM_PANEL
diff --git a/drivers/gpu/drm/mediatek/mtk_cec.c b/drivers/gpu/drm/mediatek/mtk_cec.c
index 8519e9bade36..2de248443147 100644
--- a/drivers/gpu/drm/mediatek/mtk_cec.c
+++ b/drivers/gpu/drm/mediatek/mtk_cec.c
@@ -195,18 +195,14 @@ static int mtk_cec_probe(struct platform_device *pdev)
spin_lock_init(&cec->lock);
cec->regs = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(cec->regs)) {
- ret = PTR_ERR(cec->regs);
- dev_err(dev, "Failed to ioremap cec: %d\n", ret);
- return ret;
- }
+ if (IS_ERR(cec->regs))
+ return dev_err_probe(dev, PTR_ERR(cec->regs),
+ "Failed to ioremap cec\n");
cec->clk = devm_clk_get(dev, NULL);
- if (IS_ERR(cec->clk)) {
- ret = PTR_ERR(cec->clk);
- dev_err(dev, "Failed to get cec clock: %d\n", ret);
- return ret;
- }
+ if (IS_ERR(cec->clk))
+ return dev_err_probe(dev, PTR_ERR(cec->clk),
+ "Failed to get cec clock\n");
cec->irq = platform_get_irq(pdev, 0);
if (cec->irq < 0)
@@ -216,16 +212,12 @@ static int mtk_cec_probe(struct platform_device *pdev)
mtk_cec_htplg_isr_thread,
IRQF_SHARED | IRQF_TRIGGER_LOW |
IRQF_ONESHOT, "hdmi hpd", dev);
- if (ret) {
- dev_err(dev, "Failed to register cec irq: %d\n", ret);
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to register cec irq\n");
ret = clk_prepare_enable(cec->clk);
- if (ret) {
- dev_err(dev, "Failed to enable cec clock: %d\n", ret);
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to enable cec clock\n");
mtk_cec_htplg_irq_init(cec);
mtk_cec_htplg_irq_enable(cec);
diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
index 17b036411292..be66d94be361 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
@@ -514,29 +514,42 @@ static bool mtk_ddp_comp_find(struct device *dev,
return false;
}
-static unsigned int mtk_ddp_comp_find_in_route(struct device *dev,
- const struct mtk_drm_route *routes,
- unsigned int num_routes,
- struct mtk_ddp_comp *ddp_comp)
+static int mtk_ddp_comp_find_in_route(struct device *dev,
+ const struct mtk_drm_route *routes,
+ unsigned int num_routes,
+ struct mtk_ddp_comp *ddp_comp)
{
- int ret;
unsigned int i;
- if (!routes) {
- ret = -EINVAL;
- goto err;
- }
+ if (!routes)
+ return -EINVAL;
for (i = 0; i < num_routes; i++)
if (dev == ddp_comp[routes[i].route_ddp].dev)
return BIT(routes[i].crtc_id);
- ret = -ENODEV;
-err:
+ return -ENODEV;
+}
- DRM_INFO("Failed to find comp in ddp table, ret = %d\n", ret);
+static bool mtk_ddp_path_available(const unsigned int *path,
+ unsigned int path_len,
+ struct device_node **comp_node)
+{
+ unsigned int i;
- return 0;
+ if (!path || !path_len)
+ return false;
+
+ for (i = 0U; i < path_len; i++) {
+ /* OVL_ADAPTOR doesn't have a device node */
+ if (path[i] == DDP_COMPONENT_DRM_OVL_ADAPTOR)
+ continue;
+
+ if (!comp_node[path[i]])
+ return false;
+ }
+
+ return true;
}
int mtk_ddp_comp_get_id(struct device_node *node,
@@ -554,31 +567,53 @@ int mtk_ddp_comp_get_id(struct device_node *node,
return -EINVAL;
}
-unsigned int mtk_find_possible_crtcs(struct drm_device *drm, struct device *dev)
+int mtk_find_possible_crtcs(struct drm_device *drm, struct device *dev)
{
struct mtk_drm_private *private = drm->dev_private;
- unsigned int ret = 0;
-
- if (mtk_ddp_comp_find(dev,
- private->data->main_path,
- private->data->main_len,
- private->ddp_comp))
- ret = BIT(0);
- else if (mtk_ddp_comp_find(dev,
- private->data->ext_path,
- private->data->ext_len,
- private->ddp_comp))
- ret = BIT(1);
- else if (mtk_ddp_comp_find(dev,
- private->data->third_path,
- private->data->third_len,
- private->ddp_comp))
- ret = BIT(2);
- else
- ret = mtk_ddp_comp_find_in_route(dev,
- private->data->conn_routes,
- private->data->num_conn_routes,
- private->ddp_comp);
+ const struct mtk_mmsys_driver_data *data;
+ struct mtk_drm_private *priv_n;
+ int i = 0, j;
+ int ret;
+
+ for (j = 0; j < private->data->mmsys_dev_num; j++) {
+ priv_n = private->all_drm_private[j];
+ data = priv_n->data;
+
+ if (mtk_ddp_path_available(data->main_path, data->main_len,
+ priv_n->comp_node)) {
+ if (mtk_ddp_comp_find(dev, data->main_path,
+ data->main_len,
+ priv_n->ddp_comp))
+ return BIT(i);
+ i++;
+ }
+
+ if (mtk_ddp_path_available(data->ext_path, data->ext_len,
+ priv_n->comp_node)) {
+ if (mtk_ddp_comp_find(dev, data->ext_path,
+ data->ext_len,
+ priv_n->ddp_comp))
+ return BIT(i);
+ i++;
+ }
+
+ if (mtk_ddp_path_available(data->third_path, data->third_len,
+ priv_n->comp_node)) {
+ if (mtk_ddp_comp_find(dev, data->third_path,
+ data->third_len,
+ priv_n->ddp_comp))
+ return BIT(i);
+ i++;
+ }
+ }
+
+ ret = mtk_ddp_comp_find_in_route(dev,
+ private->data->conn_routes,
+ private->data->num_conn_routes,
+ private->ddp_comp);
+
+ if (ret < 0)
+ DRM_INFO("Failed to find comp in ddp table, ret = %d\n", ret);
return ret;
}
@@ -593,7 +628,7 @@ int mtk_ddp_comp_init(struct device_node *node, struct mtk_ddp_comp *comp,
int ret;
#endif
- if (comp_id < 0 || comp_id >= DDP_COMPONENT_DRM_ID_MAX)
+ if (comp_id >= DDP_COMPONENT_DRM_ID_MAX)
return -EINVAL;
type = mtk_ddp_matches[comp_id].type;
diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
index 26236691ce4c..ecf6dc283cd7 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
@@ -192,7 +192,11 @@ unsigned int mtk_ddp_comp_supported_rotations(struct mtk_ddp_comp *comp)
if (comp->funcs && comp->funcs->supported_rotations)
return comp->funcs->supported_rotations(comp->dev);
- return 0;
+ /*
+ * In order to pass IGT tests, DRM_MODE_ROTATE_0 is required when
+ * rotation is not supported.
+ */
+ return DRM_MODE_ROTATE_0;
}
static inline unsigned int mtk_ddp_comp_layer_nr(struct mtk_ddp_comp *comp)
@@ -326,7 +330,7 @@ static inline void mtk_ddp_comp_encoder_index_set(struct mtk_ddp_comp *comp)
int mtk_ddp_comp_get_id(struct device_node *node,
enum mtk_ddp_comp_type comp_type);
-unsigned int mtk_find_possible_crtcs(struct drm_device *drm, struct device *dev);
+int mtk_find_possible_crtcs(struct drm_device *drm, struct device *dev);
int mtk_ddp_comp_init(struct device_node *comp_node, struct mtk_ddp_comp *comp,
unsigned int comp_id);
enum mtk_ddp_comp_type mtk_ddp_comp_get_type(unsigned int comp_id);
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_aal.c b/drivers/gpu/drm/mediatek/mtk_disp_aal.c
index 3ce8f32b06d5..59fb9a08d54b 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_aal.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_aal.c
@@ -175,16 +175,14 @@ static int mtk_disp_aal_probe(struct platform_device *pdev)
return -ENOMEM;
priv->clk = devm_clk_get(dev, NULL);
- if (IS_ERR(priv->clk)) {
- dev_err(dev, "failed to get aal clk\n");
- return PTR_ERR(priv->clk);
- }
+ if (IS_ERR(priv->clk))
+ return dev_err_probe(dev, PTR_ERR(priv->clk),
+ "failed to get aal clk\n");
priv->regs = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(priv->regs)) {
- dev_err(dev, "failed to ioremap aal\n");
- return PTR_ERR(priv->regs);
- }
+ if (IS_ERR(priv->regs))
+ return dev_err_probe(dev, PTR_ERR(priv->regs),
+ "failed to ioremap aal\n");
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
ret = cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0);
@@ -197,9 +195,9 @@ static int mtk_disp_aal_probe(struct platform_device *pdev)
ret = component_add(dev, &mtk_disp_aal_component_ops);
if (ret)
- dev_err(dev, "Failed to add component: %d\n", ret);
+ return dev_err_probe(dev, ret, "Failed to add component\n");
- return ret;
+ return 0;
}
static void mtk_disp_aal_remove(struct platform_device *pdev)
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ccorr.c b/drivers/gpu/drm/mediatek/mtk_disp_ccorr.c
index df35e90dd25f..9b75727e0861 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ccorr.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ccorr.c
@@ -160,16 +160,14 @@ static int mtk_disp_ccorr_probe(struct platform_device *pdev)
return -ENOMEM;
priv->clk = devm_clk_get(dev, NULL);
- if (IS_ERR(priv->clk)) {
- dev_err(dev, "failed to get ccorr clk\n");
- return PTR_ERR(priv->clk);
- }
+ if (IS_ERR(priv->clk))
+ return dev_err_probe(dev, PTR_ERR(priv->clk),
+ "failed to get ccorr clk\n");
priv->regs = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(priv->regs)) {
- dev_err(dev, "failed to ioremap ccorr\n");
- return PTR_ERR(priv->regs);
- }
+ if (IS_ERR(priv->regs))
+ return dev_err_probe(dev, PTR_ERR(priv->regs),
+ "failed to ioremap ccorr\n");
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
ret = cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0);
@@ -182,9 +180,9 @@ static int mtk_disp_ccorr_probe(struct platform_device *pdev)
ret = component_add(dev, &mtk_disp_ccorr_component_ops);
if (ret)
- dev_err(dev, "Failed to add component: %d\n", ret);
+ return dev_err_probe(dev, ret, "Failed to add component\n");
- return ret;
+ return 0;
}
static void mtk_disp_ccorr_remove(struct platform_device *pdev)
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_color.c b/drivers/gpu/drm/mediatek/mtk_disp_color.c
index 7f0085be5671..2fd5e7dc9e24 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_color.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_color.c
@@ -104,17 +104,15 @@ static int mtk_disp_color_probe(struct platform_device *pdev)
return -ENOMEM;
priv->clk = devm_clk_get(dev, NULL);
- if (IS_ERR(priv->clk)) {
- dev_err(dev, "failed to get color clk\n");
- return PTR_ERR(priv->clk);
- }
+ if (IS_ERR(priv->clk))
+ return dev_err_probe(dev, PTR_ERR(priv->clk),
+ "failed to get color clk\n");
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->regs = devm_ioremap_resource(dev, res);
- if (IS_ERR(priv->regs)) {
- dev_err(dev, "failed to ioremap color\n");
- return PTR_ERR(priv->regs);
- }
+ if (IS_ERR(priv->regs))
+ return dev_err_probe(dev, PTR_ERR(priv->regs),
+ "failed to ioremap color\n");
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
ret = cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0);
if (ret)
@@ -126,9 +124,9 @@ static int mtk_disp_color_probe(struct platform_device *pdev)
ret = component_add(dev, &mtk_disp_color_component_ops);
if (ret)
- dev_err(dev, "Failed to add component: %d\n", ret);
+ return dev_err_probe(dev, ret, "Failed to add component\n");
- return ret;
+ return 0;
}
static void mtk_disp_color_remove(struct platform_device *pdev)
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_gamma.c b/drivers/gpu/drm/mediatek/mtk_disp_gamma.c
index ca8d1f3aca03..f0b38817ba6c 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_gamma.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_gamma.c
@@ -264,17 +264,15 @@ static int mtk_disp_gamma_probe(struct platform_device *pdev)
return -ENOMEM;
priv->clk = devm_clk_get(dev, NULL);
- if (IS_ERR(priv->clk)) {
- dev_err(dev, "failed to get gamma clk\n");
- return PTR_ERR(priv->clk);
- }
+ if (IS_ERR(priv->clk))
+ return dev_err_probe(dev, PTR_ERR(priv->clk),
+ "failed to get gamma clk\n");
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->regs = devm_ioremap_resource(dev, res);
- if (IS_ERR(priv->regs)) {
- dev_err(dev, "failed to ioremap gamma\n");
- return PTR_ERR(priv->regs);
- }
+ if (IS_ERR(priv->regs))
+ return dev_err_probe(dev, PTR_ERR(priv->regs),
+ "failed to ioremap gamma\n");
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
ret = cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0);
@@ -287,9 +285,9 @@ static int mtk_disp_gamma_probe(struct platform_device *pdev)
ret = component_add(dev, &mtk_disp_gamma_component_ops);
if (ret)
- dev_err(dev, "Failed to add component: %d\n", ret);
+ return dev_err_probe(dev, ret, "Failed to add component\n");
- return ret;
+ return 0;
}
static void mtk_disp_gamma_remove(struct platform_device *pdev)
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_merge.c b/drivers/gpu/drm/mediatek/mtk_disp_merge.c
index 77c057e0e671..435e5d9c8520 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_merge.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_merge.c
@@ -316,22 +316,19 @@ static int mtk_disp_merge_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->regs = devm_ioremap_resource(dev, res);
- if (IS_ERR(priv->regs)) {
- dev_err(dev, "failed to ioremap merge\n");
- return PTR_ERR(priv->regs);
- }
+ if (IS_ERR(priv->regs))
+ return dev_err_probe(dev, PTR_ERR(priv->regs),
+ "failed to ioremap merge\n");
priv->clk = devm_clk_get(dev, NULL);
- if (IS_ERR(priv->clk)) {
- dev_err(dev, "failed to get merge clk\n");
- return PTR_ERR(priv->clk);
- }
+ if (IS_ERR(priv->clk))
+ return dev_err_probe(dev, PTR_ERR(priv->clk),
+ "failed to get merge clk\n");
priv->async_clk = devm_clk_get_optional(dev, "merge_async");
- if (IS_ERR(priv->async_clk)) {
- dev_err(dev, "failed to get merge async clock\n");
- return PTR_ERR(priv->async_clk);
- }
+ if (IS_ERR(priv->async_clk))
+ return dev_err_probe(dev, PTR_ERR(priv->async_clk),
+ "failed to get merge async clock\n");
if (priv->async_clk) {
priv->reset_ctl = devm_reset_control_get_optional_exclusive(dev, NULL);
@@ -354,9 +351,9 @@ static int mtk_disp_merge_probe(struct platform_device *pdev)
ret = component_add(dev, &mtk_disp_merge_component_ops);
if (ret != 0)
- dev_err(dev, "Failed to add component: %d\n", ret);
+ return dev_err_probe(dev, ret, "Failed to add component\n");
- return ret;
+ return 0;
}
static void mtk_disp_merge_remove(struct platform_device *pdev)
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
index b552a02d7eae..9d6d9fd8342e 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
@@ -38,10 +38,15 @@
#define DISP_REG_OVL_PITCH_MSB(n) (0x0040 + 0x20 * (n))
#define OVL_PITCH_MSB_2ND_SUBBUF BIT(16)
#define DISP_REG_OVL_PITCH(n) (0x0044 + 0x20 * (n))
+#define OVL_CONST_BLEND BIT(28)
#define DISP_REG_OVL_RDMA_CTRL(n) (0x00c0 + 0x20 * (n))
#define DISP_REG_OVL_RDMA_GMC(n) (0x00c8 + 0x20 * (n))
#define DISP_REG_OVL_ADDR_MT2701 0x0040
-#define DISP_REG_OVL_CLRFMT_EXT 0x02D0
+#define DISP_REG_OVL_CLRFMT_EXT 0x02d0
+#define OVL_CON_CLRFMT_BIT_DEPTH_MASK(n) (GENMASK(1, 0) << (4 * (n)))
+#define OVL_CON_CLRFMT_BIT_DEPTH(depth, n) ((depth) << (4 * (n)))
+#define OVL_CON_CLRFMT_8_BIT (0)
+#define OVL_CON_CLRFMT_10_BIT (1)
#define DISP_REG_OVL_ADDR_MT8173 0x0f40
#define DISP_REG_OVL_ADDR(ovl, n) ((ovl)->data->addr + 0x20 * (n))
#define DISP_REG_OVL_HDR_ADDR(ovl, n) ((ovl)->data->addr + 0x20 * (n) + 0x04)
@@ -54,23 +59,39 @@
#define OVL_CON_BYTE_SWAP BIT(24)
#define OVL_CON_MTX_YUV_TO_RGB (6 << 16)
#define OVL_CON_CLRFMT_RGB (1 << 12)
-#define OVL_CON_CLRFMT_RGBA8888 (2 << 12)
-#define OVL_CON_CLRFMT_ARGB8888 (3 << 12)
+#define OVL_CON_CLRFMT_ARGB8888 (2 << 12)
+#define OVL_CON_CLRFMT_RGBA8888 (3 << 12)
+#define OVL_CON_CLRFMT_ABGR8888 (OVL_CON_CLRFMT_RGBA8888 | OVL_CON_BYTE_SWAP)
+#define OVL_CON_CLRFMT_BGRA8888 (OVL_CON_CLRFMT_ARGB8888 | OVL_CON_BYTE_SWAP)
#define OVL_CON_CLRFMT_UYVY (4 << 12)
#define OVL_CON_CLRFMT_YUYV (5 << 12)
#define OVL_CON_CLRFMT_RGB565(ovl) ((ovl)->data->fmt_rgb565_is_0 ? \
0 : OVL_CON_CLRFMT_RGB)
#define OVL_CON_CLRFMT_RGB888(ovl) ((ovl)->data->fmt_rgb565_is_0 ? \
OVL_CON_CLRFMT_RGB : 0)
-#define OVL_CON_CLRFMT_BIT_DEPTH_MASK(ovl) (0xFF << 4 * (ovl))
-#define OVL_CON_CLRFMT_BIT_DEPTH(depth, ovl) (depth << 4 * (ovl))
-#define OVL_CON_CLRFMT_8_BIT 0x00
-#define OVL_CON_CLRFMT_10_BIT 0x01
#define OVL_CON_AEN BIT(8)
#define OVL_CON_ALPHA 0xff
#define OVL_CON_VIRT_FLIP BIT(9)
#define OVL_CON_HORZ_FLIP BIT(10)
+#define OVL_COLOR_ALPHA GENMASK(31, 24)
+
+static inline bool is_10bit_rgb(u32 fmt)
+{
+ switch (fmt) {
+ case DRM_FORMAT_XRGB2101010:
+ case DRM_FORMAT_ARGB2101010:
+ case DRM_FORMAT_RGBX1010102:
+ case DRM_FORMAT_RGBA1010102:
+ case DRM_FORMAT_XBGR2101010:
+ case DRM_FORMAT_ABGR2101010:
+ case DRM_FORMAT_BGRX1010102:
+ case DRM_FORMAT_BGRA1010102:
+ return true;
+ }
+ return false;
+}
+
static const u32 mt8173_formats[] = {
DRM_FORMAT_XRGB8888,
DRM_FORMAT_ARGB8888,
@@ -88,12 +109,20 @@ static const u32 mt8173_formats[] = {
static const u32 mt8195_formats[] = {
DRM_FORMAT_XRGB8888,
DRM_FORMAT_ARGB8888,
+ DRM_FORMAT_XRGB2101010,
DRM_FORMAT_ARGB2101010,
DRM_FORMAT_BGRX8888,
DRM_FORMAT_BGRA8888,
+ DRM_FORMAT_BGRX1010102,
DRM_FORMAT_BGRA1010102,
DRM_FORMAT_ABGR8888,
DRM_FORMAT_XBGR8888,
+ DRM_FORMAT_XBGR2101010,
+ DRM_FORMAT_ABGR2101010,
+ DRM_FORMAT_RGBX8888,
+ DRM_FORMAT_RGBA8888,
+ DRM_FORMAT_RGBX1010102,
+ DRM_FORMAT_RGBA1010102,
DRM_FORMAT_RGB888,
DRM_FORMAT_BGR888,
DRM_FORMAT_RGB565,
@@ -244,24 +273,17 @@ static void mtk_ovl_set_bit_depth(struct device *dev, int idx, u32 format,
struct cmdq_pkt *cmdq_pkt)
{
struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
- unsigned int reg;
unsigned int bit_depth = OVL_CON_CLRFMT_8_BIT;
if (!ovl->data->supports_clrfmt_ext)
return;
- reg = readl(ovl->regs + DISP_REG_OVL_CLRFMT_EXT);
- reg &= ~OVL_CON_CLRFMT_BIT_DEPTH_MASK(idx);
-
- if (format == DRM_FORMAT_RGBA1010102 ||
- format == DRM_FORMAT_BGRA1010102 ||
- format == DRM_FORMAT_ARGB2101010)
+ if (is_10bit_rgb(format))
bit_depth = OVL_CON_CLRFMT_10_BIT;
- reg |= OVL_CON_CLRFMT_BIT_DEPTH(bit_depth, idx);
-
- mtk_ddp_write(cmdq_pkt, reg, &ovl->cmdq_reg,
- ovl->regs, DISP_REG_OVL_CLRFMT_EXT);
+ mtk_ddp_write_mask(cmdq_pkt, OVL_CON_CLRFMT_BIT_DEPTH(bit_depth, idx),
+ &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_CLRFMT_EXT,
+ OVL_CON_CLRFMT_BIT_DEPTH_MASK(idx));
}
void mtk_ovl_config(struct device *dev, unsigned int w,
@@ -273,7 +295,13 @@ void mtk_ovl_config(struct device *dev, unsigned int w,
if (w != 0 && h != 0)
mtk_ddp_write_relaxed(cmdq_pkt, h << 16 | w, &ovl->cmdq_reg, ovl->regs,
DISP_REG_OVL_ROI_SIZE);
- mtk_ddp_write_relaxed(cmdq_pkt, 0x0, &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_ROI_BGCLR);
+
+ /*
+ * The background color must be opaque black (ARGB),
+ * otherwise the alpha blending will have no effect
+ */
+ mtk_ddp_write_relaxed(cmdq_pkt, OVL_COLOR_ALPHA, &ovl->cmdq_reg,
+ ovl->regs, DISP_REG_OVL_ROI_BGCLR);
mtk_ddp_write(cmdq_pkt, 0x1, &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_RST);
mtk_ddp_write(cmdq_pkt, 0x0, &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_RST);
@@ -296,27 +324,20 @@ int mtk_ovl_layer_check(struct device *dev, unsigned int idx,
struct mtk_plane_state *mtk_state)
{
struct drm_plane_state *state = &mtk_state->base;
- unsigned int rotation = 0;
- rotation = drm_rotation_simplify(state->rotation,
- DRM_MODE_ROTATE_0 |
- DRM_MODE_REFLECT_X |
- DRM_MODE_REFLECT_Y);
- rotation &= ~DRM_MODE_ROTATE_0;
-
- /* We can only do reflection, not rotation */
- if ((rotation & DRM_MODE_ROTATE_MASK) != 0)
+ /* check if any unsupported rotation is set */
+ if (state->rotation & ~mtk_ovl_supported_rotations(dev))
return -EINVAL;
/*
* TODO: Rotating/reflecting YUV buffers is not supported at this time.
* Only RGB[AX] variants are supported.
+ * Since DRM_MODE_ROTATE_0 means "no rotation", we should not
+ * reject layers with this property.
*/
- if (state->fb->format->is_yuv && rotation != 0)
+ if (state->fb->format->is_yuv && (state->rotation & ~DRM_MODE_ROTATE_0))
return -EINVAL;
- state->rotation = rotation;
-
return 0;
}
@@ -375,18 +396,24 @@ static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl, unsigned int fmt)
return OVL_CON_CLRFMT_RGB888(ovl) | OVL_CON_BYTE_SWAP;
case DRM_FORMAT_RGBX8888:
case DRM_FORMAT_RGBA8888:
- return OVL_CON_CLRFMT_ARGB8888;
+ case DRM_FORMAT_RGBX1010102:
+ case DRM_FORMAT_RGBA1010102:
+ return OVL_CON_CLRFMT_RGBA8888;
case DRM_FORMAT_BGRX8888:
case DRM_FORMAT_BGRA8888:
+ case DRM_FORMAT_BGRX1010102:
case DRM_FORMAT_BGRA1010102:
- return OVL_CON_CLRFMT_ARGB8888 | OVL_CON_BYTE_SWAP;
+ return OVL_CON_CLRFMT_BGRA8888;
case DRM_FORMAT_XRGB8888:
case DRM_FORMAT_ARGB8888:
+ case DRM_FORMAT_XRGB2101010:
case DRM_FORMAT_ARGB2101010:
- return OVL_CON_CLRFMT_RGBA8888;
+ return OVL_CON_CLRFMT_ARGB8888;
case DRM_FORMAT_XBGR8888:
case DRM_FORMAT_ABGR8888:
- return OVL_CON_CLRFMT_RGBA8888 | OVL_CON_BYTE_SWAP;
+ case DRM_FORMAT_XBGR2101010:
+ case DRM_FORMAT_ABGR2101010:
+ return OVL_CON_CLRFMT_ABGR8888;
case DRM_FORMAT_UYVY:
return OVL_CON_CLRFMT_UYVY | OVL_CON_MTX_YUV_TO_RGB;
case DRM_FORMAT_YUYV:
@@ -407,6 +434,7 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
unsigned int fmt = pending->format;
unsigned int offset = (pending->y << 16) | pending->x;
unsigned int src_size = (pending->height << 16) | pending->width;
+ unsigned int ignore_pixel_alpha = 0;
unsigned int con;
bool is_afbc = pending->modifier != DRM_FORMAT_MOD_LINEAR;
union overlay_pitch {
@@ -425,8 +453,18 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
}
con = ovl_fmt_convert(ovl, fmt);
- if (state->base.fb && state->base.fb->format->has_alpha)
- con |= OVL_CON_AEN | OVL_CON_ALPHA;
+ if (state->base.fb) {
+ con |= OVL_CON_AEN;
+ con |= state->base.alpha & OVL_CON_ALPHA;
+ }
+
+ /* CONST_BLD must be enabled for XRGB formats although the alpha channel
+ * can be ignored, or OVL will still read the value from memory.
+ * For RGB888 related formats, whether CONST_BLD is enabled or not won't
+ * affect the result. Therefore we use !has_alpha as the condition.
+ */
+ if (state->base.fb && !state->base.fb->format->has_alpha)
+ ignore_pixel_alpha = OVL_CONST_BLEND;
if (pending->rotation & DRM_MODE_REFLECT_Y) {
con |= OVL_CON_VIRT_FLIP;
@@ -443,8 +481,8 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
mtk_ddp_write_relaxed(cmdq_pkt, con, &ovl->cmdq_reg, ovl->regs,
DISP_REG_OVL_CON(idx));
- mtk_ddp_write_relaxed(cmdq_pkt, overlay_pitch.split_pitch.lsb, &ovl->cmdq_reg, ovl->regs,
- DISP_REG_OVL_PITCH(idx));
+ mtk_ddp_write_relaxed(cmdq_pkt, overlay_pitch.split_pitch.lsb | ignore_pixel_alpha,
+ &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_PITCH(idx));
mtk_ddp_write_relaxed(cmdq_pkt, src_size, &ovl->cmdq_reg, ovl->regs,
DISP_REG_OVL_SRC_SIZE(idx));
mtk_ddp_write_relaxed(cmdq_pkt, offset, &ovl->cmdq_reg, ovl->regs,
@@ -523,17 +561,15 @@ static int mtk_disp_ovl_probe(struct platform_device *pdev)
return irq;
priv->clk = devm_clk_get(dev, NULL);
- if (IS_ERR(priv->clk)) {
- dev_err(dev, "failed to get ovl clk\n");
- return PTR_ERR(priv->clk);
- }
+ if (IS_ERR(priv->clk))
+ return dev_err_probe(dev, PTR_ERR(priv->clk),
+ "failed to get ovl clk\n");
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->regs = devm_ioremap_resource(dev, res);
- if (IS_ERR(priv->regs)) {
- dev_err(dev, "failed to ioremap ovl\n");
- return PTR_ERR(priv->regs);
- }
+ if (IS_ERR(priv->regs))
+ return dev_err_probe(dev, PTR_ERR(priv->regs),
+ "failed to ioremap ovl\n");
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
ret = cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0);
if (ret)
@@ -545,20 +581,18 @@ static int mtk_disp_ovl_probe(struct platform_device *pdev)
ret = devm_request_irq(dev, irq, mtk_disp_ovl_irq_handler,
IRQF_TRIGGER_NONE, dev_name(dev), priv);
- if (ret < 0) {
- dev_err(dev, "Failed to request irq %d: %d\n", irq, ret);
- return ret;
- }
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "Failed to request irq %d\n", irq);
pm_runtime_enable(dev);
ret = component_add(dev, &mtk_disp_ovl_component_ops);
if (ret) {
pm_runtime_disable(dev);
- dev_err(dev, "Failed to add component: %d\n", ret);
+ return dev_err_probe(dev, ret, "Failed to add component\n");
}
- return ret;
+ return 0;
}
static void mtk_disp_ovl_remove(struct platform_device *pdev)
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c
index 02dd7dcdfedb..1a2a73757370 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c
@@ -158,7 +158,7 @@ void mtk_ovl_adaptor_layer_config(struct device *dev, unsigned int idx,
merge = ovl_adaptor->ovl_adaptor_comp[OVL_ADAPTOR_MERGE0 + idx];
ethdr = ovl_adaptor->ovl_adaptor_comp[OVL_ADAPTOR_ETHDR0];
- if (!pending->enable) {
+ if (!pending->enable || !pending->width || !pending->height) {
mtk_merge_stop_cmdq(merge, cmdq_pkt);
mtk_mdp_rdma_stop(rdma_l, cmdq_pkt);
mtk_mdp_rdma_stop(rdma_r, cmdq_pkt);
@@ -612,10 +612,10 @@ static int mtk_disp_ovl_adaptor_probe(struct platform_device *pdev)
ret = component_add(dev, &mtk_disp_ovl_adaptor_comp_ops);
if (ret != 0) {
pm_runtime_disable(dev);
- dev_err(dev, "Failed to add component: %d\n", ret);
+ return dev_err_probe(dev, ret, "Failed to add component\n");
}
- return ret;
+ return 0;
}
static void mtk_disp_ovl_adaptor_remove(struct platform_device *pdev)
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
index 7b1a6e631200..634bbba5d43f 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
@@ -326,17 +326,15 @@ static int mtk_disp_rdma_probe(struct platform_device *pdev)
return irq;
priv->clk = devm_clk_get(dev, NULL);
- if (IS_ERR(priv->clk)) {
- dev_err(dev, "failed to get rdma clk\n");
- return PTR_ERR(priv->clk);
- }
+ if (IS_ERR(priv->clk))
+ return dev_err_probe(dev, PTR_ERR(priv->clk),
+ "failed to get rdma clk\n");
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->regs = devm_ioremap_resource(dev, res);
- if (IS_ERR(priv->regs)) {
- dev_err(dev, "failed to ioremap rdma\n");
- return PTR_ERR(priv->regs);
- }
+ if (IS_ERR(priv->regs))
+ return dev_err_probe(dev, PTR_ERR(priv->regs),
+ "failed to ioremap rdma\n");
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
ret = cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0);
if (ret)
@@ -347,10 +345,9 @@ static int mtk_disp_rdma_probe(struct platform_device *pdev)
ret = of_property_read_u32(dev->of_node,
"mediatek,rdma-fifo-size",
&priv->fifo_size);
- if (ret) {
- dev_err(dev, "Failed to get rdma fifo size\n");
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to get rdma fifo size\n");
}
/* Disable and clear pending interrupts */
@@ -359,10 +356,8 @@ static int mtk_disp_rdma_probe(struct platform_device *pdev)
ret = devm_request_irq(dev, irq, mtk_disp_rdma_irq_handler,
IRQF_TRIGGER_NONE, dev_name(dev), priv);
- if (ret < 0) {
- dev_err(dev, "Failed to request irq %d: %d\n", irq, ret);
- return ret;
- }
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "Failed to request irq %d\n", irq);
priv->data = of_device_get_match_data(dev);
@@ -373,10 +368,10 @@ static int mtk_disp_rdma_probe(struct platform_device *pdev)
ret = component_add(dev, &mtk_disp_rdma_component_ops);
if (ret) {
pm_runtime_disable(dev);
- dev_err(dev, "Failed to add component: %d\n", ret);
+ return dev_err_probe(dev, ret, "Failed to add component\n");
}
- return ret;
+ return 0;
}
static void mtk_disp_rdma_remove(struct platform_device *pdev)
diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c
index 536366956447..d8796a904eca 100644
--- a/drivers/gpu/drm/mediatek/mtk_dp.c
+++ b/drivers/gpu/drm/mediatek/mtk_dp.c
@@ -2073,9 +2073,15 @@ static const struct drm_edid *mtk_dp_edid_read(struct drm_bridge *bridge,
*/
const struct edid *edid = drm_edid_raw(drm_edid);
struct cea_sad *sads;
+ int ret;
- audio_caps->sad_count = drm_edid_to_sad(edid, &sads);
- kfree(sads);
+ ret = drm_edid_to_sad(edid, &sads);
+ /* Ignore any errors */
+ if (ret < 0)
+ ret = 0;
+ if (ret)
+ kfree(sads);
+ audio_caps->sad_count = ret;
/*
* FIXME: This should use connector->display_info.has_audio from
@@ -2655,11 +2661,9 @@ static int mtk_dp_probe(struct platform_device *pdev)
mutex_init(&mtk_dp->update_plugged_status_lock);
ret = mtk_dp_register_audio_driver(dev);
- if (ret) {
- dev_err(dev, "Failed to register audio driver: %d\n",
- ret);
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to register audio driver\n");
}
ret = mtk_dp_register_phy(mtk_dp);
diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
index bfe8653005db..a08d20654954 100644
--- a/drivers/gpu/drm/mediatek/mtk_dpi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
@@ -805,7 +805,10 @@ static int mtk_dpi_bind(struct device *dev, struct device *master, void *data)
return ret;
}
- dpi->encoder.possible_crtcs = mtk_find_possible_crtcs(drm_dev, dpi->dev);
+ ret = mtk_find_possible_crtcs(drm_dev, dpi->dev);
+ if (ret < 0)
+ goto err_cleanup;
+ dpi->encoder.possible_crtcs = ret;
ret = drm_bridge_attach(&dpi->encoder, &dpi->bridge, NULL,
DRM_BRIDGE_ATTACH_NO_CONNECTOR);
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index b5f605751b0a..ae5c6ec24a1e 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -15,7 +15,7 @@
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_dma.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_gem.h>
#include <drm/drm_gem_framebuffer_helper.h>
@@ -294,6 +294,9 @@ static const struct mtk_mmsys_driver_data mt8188_vdosys0_driver_data = {
.conn_routes = mt8188_mtk_ddp_main_routes,
.num_conn_routes = ARRAY_SIZE(mt8188_mtk_ddp_main_routes),
.mmsys_dev_num = 2,
+ .max_width = 8191,
+ .min_width = 1,
+ .min_height = 1,
};
static const struct mtk_mmsys_driver_data mt8192_mmsys_driver_data = {
@@ -308,6 +311,9 @@ static const struct mtk_mmsys_driver_data mt8195_vdosys0_driver_data = {
.main_path = mt8195_mtk_ddp_main,
.main_len = ARRAY_SIZE(mt8195_mtk_ddp_main),
.mmsys_dev_num = 2,
+ .max_width = 8191,
+ .min_width = 1,
+ .min_height = 1,
};
static const struct mtk_mmsys_driver_data mt8195_vdosys1_driver_data = {
@@ -315,6 +321,9 @@ static const struct mtk_mmsys_driver_data mt8195_vdosys1_driver_data = {
.ext_len = ARRAY_SIZE(mt8195_mtk_ddp_ext),
.mmsys_id = 1,
.mmsys_dev_num = 2,
+ .max_width = 8191,
+ .min_width = 2, /* 2-pixel align when ethdr is bypassed */
+ .min_height = 1,
};
static const struct of_device_id mtk_drm_of_ids[] = {
@@ -493,6 +502,15 @@ static int mtk_drm_kms_init(struct drm_device *drm)
for (j = 0; j < private->data->mmsys_dev_num; j++) {
priv_n = private->all_drm_private[j];
+ if (priv_n->data->max_width)
+ drm->mode_config.max_width = priv_n->data->max_width;
+
+ if (priv_n->data->min_width)
+ drm->mode_config.min_width = priv_n->data->min_width;
+
+ if (priv_n->data->min_height)
+ drm->mode_config.min_height = priv_n->data->min_height;
+
if (i == CRTC_MAIN && priv_n->data->main_len) {
ret = mtk_crtc_create(drm, priv_n->data->main_path,
priv_n->data->main_len, j,
@@ -520,6 +538,10 @@ static int mtk_drm_kms_init(struct drm_device *drm)
}
}
+ /* IGT will check if the cursor size is configured */
+ drm->mode_config.cursor_width = drm->mode_config.max_width;
+ drm->mode_config.cursor_height = drm->mode_config.max_height;
+
/* Use OVL device for all DMA memory allocations */
crtc = drm_crtc_from_index(drm, 0);
if (crtc)
@@ -644,7 +666,7 @@ static int mtk_drm_bind(struct device *dev)
if (ret < 0)
goto err_deinit;
- drm_fbdev_generic_setup(drm, 32);
+ drm_fbdev_dma_setup(drm, 32);
return 0;
@@ -743,6 +765,8 @@ static const struct of_device_id mtk_ddp_comp_dt_ids[] = {
.data = (void *)MTK_DISP_OVL },
{ .compatible = "mediatek,mt8192-disp-ovl",
.data = (void *)MTK_DISP_OVL },
+ { .compatible = "mediatek,mt8195-disp-ovl",
+ .data = (void *)MTK_DISP_OVL },
{ .compatible = "mediatek,mt8183-disp-ovl-2l",
.data = (void *)MTK_DISP_OVL_2L },
{ .compatible = "mediatek,mt8192-disp-ovl-2l",
@@ -952,6 +976,13 @@ static void mtk_drm_remove(struct platform_device *pdev)
of_node_put(private->comp_node[i]);
}
+static void mtk_drm_shutdown(struct platform_device *pdev)
+{
+ struct mtk_drm_private *private = platform_get_drvdata(pdev);
+
+ drm_atomic_helper_shutdown(private->drm);
+}
+
static int mtk_drm_sys_prepare(struct device *dev)
{
struct mtk_drm_private *private = dev_get_drvdata(dev);
@@ -983,6 +1014,7 @@ static const struct dev_pm_ops mtk_drm_pm_ops = {
static struct platform_driver mtk_drm_platform_driver = {
.probe = mtk_drm_probe,
.remove_new = mtk_drm_remove,
+ .shutdown = mtk_drm_shutdown,
.driver = {
.name = "mediatek-drm",
.pm = &mtk_drm_pm_ops,
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
index 78d698ede1bf..ce897984de51 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
@@ -46,6 +46,10 @@ struct mtk_mmsys_driver_data {
bool shadow_register;
unsigned int mmsys_id;
unsigned int mmsys_dev_num;
+
+ u16 max_width;
+ u16 min_width;
+ u16 min_height;
};
struct mtk_drm_private {
diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
index c255559cc56e..b6e3c011a12d 100644
--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
@@ -837,7 +837,10 @@ static int mtk_dsi_encoder_init(struct drm_device *drm, struct mtk_dsi *dsi)
return ret;
}
- dsi->encoder.possible_crtcs = mtk_find_possible_crtcs(drm, dsi->host.dev);
+ ret = mtk_find_possible_crtcs(drm, dsi->host.dev);
+ if (ret < 0)
+ goto err_cleanup_encoder;
+ dsi->encoder.possible_crtcs = ret;
ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL,
DRM_BRIDGE_ATTACH_NO_CONNECTOR);
diff --git a/drivers/gpu/drm/mediatek/mtk_ethdr.c b/drivers/gpu/drm/mediatek/mtk_ethdr.c
index 156c6ff547e8..9dfd13d32dfa 100644
--- a/drivers/gpu/drm/mediatek/mtk_ethdr.c
+++ b/drivers/gpu/drm/mediatek/mtk_ethdr.c
@@ -50,7 +50,6 @@
#define MIXER_INX_MODE_BYPASS 0
#define MIXER_INX_MODE_EVEN_EXTEND 1
-#define DEFAULT_9BIT_ALPHA 0x100
#define MIXER_ALPHA_AEN BIT(8)
#define MIXER_ALPHA 0xff
#define ETHDR_CLK_NUM 13
@@ -154,22 +153,38 @@ void mtk_ethdr_layer_config(struct device *dev, unsigned int idx,
unsigned int offset = (pending->x & 1) << 31 | pending->y << 16 | pending->x;
unsigned int align_width = ALIGN_DOWN(pending->width, 2);
unsigned int alpha_con = 0;
+ bool replace_src_a = false;
dev_dbg(dev, "%s+ idx:%d", __func__, idx);
if (idx >= 4)
return;
- if (!pending->enable) {
+ if (!pending->enable || !pending->width || !pending->height) {
+ /*
+ * instead of disabling layer with MIX_SRC_CON directly
+ * set the size to 0 to avoid screen shift due to mixer
+ * mode switch (hardware behavior)
+ */
mtk_ddp_write(cmdq_pkt, 0, &mixer->cmdq_base, mixer->regs, MIX_L_SRC_SIZE(idx));
return;
}
- if (state->base.fb && state->base.fb->format->has_alpha)
- alpha_con = MIXER_ALPHA_AEN | MIXER_ALPHA;
+ if (state->base.fb) {
+ alpha_con |= MIXER_ALPHA_AEN;
+ alpha_con |= state->base.alpha & MIXER_ALPHA;
+ }
+
+ if (state->base.fb && !state->base.fb->format->has_alpha) {
+ /*
+ * Mixer doesn't support CONST_BLD mode,
+ * use a trick to make the output equivalent
+ */
+ replace_src_a = true;
+ }
- mtk_mmsys_mixer_in_config(priv->mmsys_dev, idx + 1, alpha_con ? false : true,
- DEFAULT_9BIT_ALPHA,
+ mtk_mmsys_mixer_in_config(priv->mmsys_dev, idx + 1, replace_src_a,
+ MIXER_ALPHA,
pending->x & 1 ? MIXER_INX_MODE_EVEN_EXTEND :
MIXER_INX_MODE_BYPASS, align_width / 2 - 1, cmdq_pkt);
@@ -325,25 +340,24 @@ static int mtk_ethdr_probe(struct platform_device *pdev)
if (priv->irq) {
ret = devm_request_irq(dev, priv->irq, mtk_ethdr_irq_handler,
IRQF_TRIGGER_NONE, dev_name(dev), priv);
- if (ret < 0) {
- dev_err(dev, "Failed to request irq %d: %d\n", priv->irq, ret);
- return ret;
- }
+ if (ret < 0)
+ return dev_err_probe(dev, ret,
+ "Failed to request irq %d\n",
+ priv->irq);
}
priv->reset_ctl = devm_reset_control_array_get_optional_exclusive(dev);
- if (IS_ERR(priv->reset_ctl)) {
- dev_err_probe(dev, PTR_ERR(priv->reset_ctl), "cannot get ethdr reset control\n");
- return PTR_ERR(priv->reset_ctl);
- }
+ if (IS_ERR(priv->reset_ctl))
+ return dev_err_probe(dev, PTR_ERR(priv->reset_ctl),
+ "cannot get ethdr reset control\n");
platform_set_drvdata(pdev, priv);
ret = component_add(dev, &mtk_ethdr_component_ops);
if (ret)
- dev_notice(dev, "Failed to add component: %d\n", ret);
+ return dev_err_probe(dev, ret, "Failed to add component\n");
- return ret;
+ return 0;
}
static void mtk_ethdr_remove(struct platform_device *pdev)
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
index 6e1cca97a654..7687f673964e 100644
--- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
@@ -1208,22 +1208,11 @@ mtk_hdmi_bridge_mode_valid(struct drm_bridge *bridge,
const struct drm_display_mode *mode)
{
struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge);
- struct drm_bridge *next_bridge;
dev_dbg(hdmi->dev, "xres=%d, yres=%d, refresh=%d, intl=%d clock=%d\n",
mode->hdisplay, mode->vdisplay, drm_mode_vrefresh(mode),
!!(mode->flags & DRM_MODE_FLAG_INTERLACE), mode->clock * 1000);
- next_bridge = drm_bridge_get_next_bridge(&hdmi->bridge);
- if (next_bridge) {
- struct drm_display_mode adjusted_mode;
-
- drm_mode_init(&adjusted_mode, mode);
- if (!drm_bridge_chain_mode_fixup(next_bridge, mode,
- &adjusted_mode))
- return MODE_BAD;
- }
-
if (hdmi->conf) {
if (hdmi->conf->cea_modes_only && !drm_match_cea_mode(mode))
return MODE_BAD;
@@ -1713,26 +1702,22 @@ static int mtk_hdmi_probe(struct platform_device *pdev)
return ret;
hdmi->phy = devm_phy_get(dev, "hdmi");
- if (IS_ERR(hdmi->phy)) {
- ret = PTR_ERR(hdmi->phy);
- dev_err(dev, "Failed to get HDMI PHY: %d\n", ret);
- return ret;
- }
+ if (IS_ERR(hdmi->phy))
+ return dev_err_probe(dev, PTR_ERR(hdmi->phy),
+ "Failed to get HDMI PHY\n");
mutex_init(&hdmi->update_plugged_status_lock);
platform_set_drvdata(pdev, hdmi);
ret = mtk_hdmi_output_init(hdmi);
- if (ret) {
- dev_err(dev, "Failed to initialize hdmi output\n");
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to initialize hdmi output\n");
ret = mtk_hdmi_register_audio_driver(dev);
- if (ret) {
- dev_err(dev, "Failed to register audio driver: %d\n", ret);
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to register audio driver\n");
hdmi->bridge.funcs = &mtk_hdmi_bridge_funcs;
hdmi->bridge.of_node = pdev->dev.of_node;
@@ -1743,15 +1728,12 @@ static int mtk_hdmi_probe(struct platform_device *pdev)
ret = mtk_hdmi_clk_enable_audio(hdmi);
if (ret) {
- dev_err(dev, "Failed to enable audio clocks: %d\n", ret);
- goto err_bridge_remove;
+ drm_bridge_remove(&hdmi->bridge);
+ return dev_err_probe(dev, ret,
+ "Failed to enable audio clocks\n");
}
return 0;
-
-err_bridge_remove:
- drm_bridge_remove(&hdmi->bridge);
- return ret;
}
static void mtk_hdmi_remove(struct platform_device *pdev)
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c b/drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c
index 52d55861f954..8e60631d4cd2 100644
--- a/drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c
@@ -279,20 +279,17 @@ static int mtk_hdmi_ddc_probe(struct platform_device *pdev)
return -ENOMEM;
ddc->clk = devm_clk_get(dev, "ddc-i2c");
- if (IS_ERR(ddc->clk)) {
- dev_err(dev, "get ddc_clk failed: %p ,\n", ddc->clk);
- return PTR_ERR(ddc->clk);
- }
+ if (IS_ERR(ddc->clk))
+ return dev_err_probe(dev, PTR_ERR(ddc->clk),
+ "get ddc_clk failed\n");
ddc->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &mem);
if (IS_ERR(ddc->regs))
return PTR_ERR(ddc->regs);
ret = clk_prepare_enable(ddc->clk);
- if (ret) {
- dev_err(dev, "enable ddc clk failed!\n");
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "enable ddc clk failed!\n");
strscpy(ddc->adap.name, "mediatek-hdmi-ddc", sizeof(ddc->adap.name));
ddc->adap.owner = THIS_MODULE;
@@ -304,8 +301,8 @@ static int mtk_hdmi_ddc_probe(struct platform_device *pdev)
ret = i2c_add_adapter(&ddc->adap);
if (ret < 0) {
- dev_err(dev, "failed to add bus to i2c core\n");
- goto err_clk_disable;
+ clk_disable_unprepare(ddc->clk);
+ return dev_err_probe(dev, ret, "failed to add bus to i2c core\n");
}
platform_set_drvdata(pdev, ddc);
@@ -316,10 +313,6 @@ static int mtk_hdmi_ddc_probe(struct platform_device *pdev)
&mem->end);
return 0;
-
-err_clk_disable:
- clk_disable_unprepare(ddc->clk);
- return ret;
}
static void mtk_hdmi_ddc_remove(struct platform_device *pdev)
diff --git a/drivers/gpu/drm/mediatek/mtk_mdp_rdma.c b/drivers/gpu/drm/mediatek/mtk_mdp_rdma.c
index 925cbb7471ec..7c1a8c796833 100644
--- a/drivers/gpu/drm/mediatek/mtk_mdp_rdma.c
+++ b/drivers/gpu/drm/mediatek/mtk_mdp_rdma.c
@@ -301,16 +301,14 @@ static int mtk_mdp_rdma_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->regs = devm_ioremap_resource(dev, res);
- if (IS_ERR(priv->regs)) {
- dev_err(dev, "failed to ioremap rdma\n");
- return PTR_ERR(priv->regs);
- }
+ if (IS_ERR(priv->regs))
+ return dev_err_probe(dev, PTR_ERR(priv->regs),
+ "failed to ioremap rdma\n");
priv->clk = devm_clk_get(dev, NULL);
- if (IS_ERR(priv->clk)) {
- dev_err(dev, "failed to get rdma clk\n");
- return PTR_ERR(priv->clk);
- }
+ if (IS_ERR(priv->clk))
+ return dev_err_probe(dev, PTR_ERR(priv->clk),
+ "failed to get rdma clk\n");
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
ret = cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0);
@@ -324,9 +322,9 @@ static int mtk_mdp_rdma_probe(struct platform_device *pdev)
ret = component_add(dev, &mtk_mdp_rdma_component_ops);
if (ret != 0) {
pm_runtime_disable(dev);
- dev_err(dev, "Failed to add component: %d\n", ret);
+ return dev_err_probe(dev, ret, "Failed to add component\n");
}
- return ret;
+ return 0;
}
static void mtk_mdp_rdma_remove(struct platform_device *pdev)
diff --git a/drivers/gpu/drm/mediatek/mtk_padding.c b/drivers/gpu/drm/mediatek/mtk_padding.c
index 85bc6768b6bc..4bebd13a07bd 100644
--- a/drivers/gpu/drm/mediatek/mtk_padding.c
+++ b/drivers/gpu/drm/mediatek/mtk_padding.c
@@ -103,23 +103,19 @@ static int mtk_padding_probe(struct platform_device *pdev)
return -ENOMEM;
priv->clk = devm_clk_get(dev, NULL);
- if (IS_ERR(priv->clk)) {
- dev_err(dev, "failed to get clk\n");
- return PTR_ERR(priv->clk);
- }
+ if (IS_ERR(priv->clk))
+ return dev_err_probe(dev, PTR_ERR(priv->clk),
+ "failed to get clk\n");
priv->reg = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
- if (IS_ERR(priv->reg)) {
- dev_err(dev, "failed to do ioremap\n");
- return PTR_ERR(priv->reg);
- }
+ if (IS_ERR(priv->reg))
+ return dev_err_probe(dev, PTR_ERR(priv->reg),
+ "failed to do ioremap\n");
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
ret = cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0);
- if (ret) {
- dev_err(dev, "failed to get gce client reg\n");
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to get gce client reg\n");
#endif
platform_set_drvdata(pdev, priv);
@@ -137,10 +133,9 @@ static int mtk_padding_probe(struct platform_device *pdev)
return 0;
}
-static int mtk_padding_remove(struct platform_device *pdev)
+static void mtk_padding_remove(struct platform_device *pdev)
{
component_del(&pdev->dev, &mtk_padding_component_ops);
- return 0;
}
static const struct of_device_id mtk_padding_driver_dt_match[] = {
@@ -151,7 +146,7 @@ MODULE_DEVICE_TABLE(of, mtk_padding_driver_dt_match);
struct platform_driver mtk_padding_driver = {
.probe = mtk_padding_probe,
- .remove = mtk_padding_remove,
+ .remove_new = mtk_padding_remove,
.driver = {
.name = "mediatek-disp-padding",
.of_match_table = mtk_padding_driver_dt_match,
diff --git a/drivers/gpu/drm/mediatek/mtk_plane.c b/drivers/gpu/drm/mediatek/mtk_plane.c
index 4625deb21d40..1723d4333f37 100644
--- a/drivers/gpu/drm/mediatek/mtk_plane.c
+++ b/drivers/gpu/drm/mediatek/mtk_plane.c
@@ -227,6 +227,8 @@ static void mtk_plane_atomic_async_update(struct drm_plane *plane,
plane->state->src_y = new_state->src_y;
plane->state->src_h = new_state->src_h;
plane->state->src_w = new_state->src_w;
+ plane->state->dst.x1 = new_state->dst.x1;
+ plane->state->dst.y1 = new_state->dst.y1;
mtk_plane_update_new_state(new_state, new_plane_state);
swap(plane->state->fb, new_state->fb);
@@ -336,7 +338,7 @@ int mtk_plane_init(struct drm_device *dev, struct drm_plane *plane,
return err;
}
- if (supported_rotations & ~DRM_MODE_ROTATE_0) {
+ if (supported_rotations) {
err = drm_plane_create_rotation_property(plane,
DRM_MODE_ROTATE_0,
supported_rotations);
diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c
index 17a5cca007e2..4bd0baa2a4f5 100644
--- a/drivers/gpu/drm/meson/meson_drv.c
+++ b/drivers/gpu/drm/meson/meson_drv.c
@@ -250,29 +250,20 @@ static int meson_drv_bind_master(struct device *dev, bool has_components)
if (ret)
goto free_drm;
ret = meson_canvas_alloc(priv->canvas, &priv->canvas_id_vd1_0);
- if (ret) {
- meson_canvas_free(priv->canvas, priv->canvas_id_osd1);
- goto free_drm;
- }
+ if (ret)
+ goto free_canvas_osd1;
ret = meson_canvas_alloc(priv->canvas, &priv->canvas_id_vd1_1);
- if (ret) {
- meson_canvas_free(priv->canvas, priv->canvas_id_osd1);
- meson_canvas_free(priv->canvas, priv->canvas_id_vd1_0);
- goto free_drm;
- }
+ if (ret)
+ goto free_canvas_vd1_0;
ret = meson_canvas_alloc(priv->canvas, &priv->canvas_id_vd1_2);
- if (ret) {
- meson_canvas_free(priv->canvas, priv->canvas_id_osd1);
- meson_canvas_free(priv->canvas, priv->canvas_id_vd1_0);
- meson_canvas_free(priv->canvas, priv->canvas_id_vd1_1);
- goto free_drm;
- }
+ if (ret)
+ goto free_canvas_vd1_1;
priv->vsync_irq = platform_get_irq(pdev, 0);
ret = drm_vblank_init(drm, 1);
if (ret)
- goto free_drm;
+ goto free_canvas_vd1_2;
/* Assign limits per soc revision/package */
for (i = 0 ; i < ARRAY_SIZE(meson_drm_soc_attrs) ; ++i) {
@@ -288,11 +279,11 @@ static int meson_drv_bind_master(struct device *dev, bool has_components)
*/
ret = drm_aperture_remove_framebuffers(&meson_driver);
if (ret)
- goto free_drm;
+ goto free_canvas_vd1_2;
ret = drmm_mode_config_init(drm);
if (ret)
- goto free_drm;
+ goto free_canvas_vd1_2;
drm->mode_config.max_width = 3840;
drm->mode_config.max_height = 2160;
drm->mode_config.funcs = &meson_mode_config_funcs;
@@ -307,7 +298,7 @@ static int meson_drv_bind_master(struct device *dev, bool has_components)
if (priv->afbcd.ops) {
ret = priv->afbcd.ops->init(priv);
if (ret)
- goto free_drm;
+ goto free_canvas_vd1_2;
}
/* Encoder Initialization */
@@ -371,6 +362,14 @@ uninstall_irq:
exit_afbcd:
if (priv->afbcd.ops)
priv->afbcd.ops->exit(priv);
+free_canvas_vd1_2:
+ meson_canvas_free(priv->canvas, priv->canvas_id_vd1_2);
+free_canvas_vd1_1:
+ meson_canvas_free(priv->canvas, priv->canvas_id_vd1_1);
+free_canvas_vd1_0:
+ meson_canvas_free(priv->canvas, priv->canvas_id_vd1_0);
+free_canvas_osd1:
+ meson_canvas_free(priv->canvas, priv->canvas_id_osd1);
free_drm:
drm_dev_put(drm);
diff --git a/drivers/gpu/drm/meson/meson_plane.c b/drivers/gpu/drm/meson/meson_plane.c
index 815dfe30492b..b43ac61201f3 100644
--- a/drivers/gpu/drm/meson/meson_plane.c
+++ b/drivers/gpu/drm/meson/meson_plane.c
@@ -534,6 +534,7 @@ int meson_plane_create(struct meson_drm *priv)
struct meson_plane *meson_plane;
struct drm_plane *plane;
const uint64_t *format_modifiers = format_modifiers_default;
+ int ret;
meson_plane = devm_kzalloc(priv->drm->dev, sizeof(*meson_plane),
GFP_KERNEL);
@@ -548,12 +549,16 @@ int meson_plane_create(struct meson_drm *priv)
else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
format_modifiers = format_modifiers_afbc_g12a;
- drm_universal_plane_init(priv->drm, plane, 0xFF,
- &meson_plane_funcs,
- supported_drm_formats,
- ARRAY_SIZE(supported_drm_formats),
- format_modifiers,
- DRM_PLANE_TYPE_PRIMARY, "meson_primary_plane");
+ ret = drm_universal_plane_init(priv->drm, plane, 0xFF,
+ &meson_plane_funcs,
+ supported_drm_formats,
+ ARRAY_SIZE(supported_drm_formats),
+ format_modifiers,
+ DRM_PLANE_TYPE_PRIMARY, "meson_primary_plane");
+ if (ret) {
+ devm_kfree(priv->drm->dev, meson_plane);
+ return ret;
+ }
drm_plane_helper_add(plane, &meson_plane_helper_funcs);
diff --git a/drivers/gpu/drm/mgag200/Kconfig b/drivers/gpu/drm/mgag200/Kconfig
index 5e4d48df4854..3096944a8f0a 100644
--- a/drivers/gpu/drm/mgag200/Kconfig
+++ b/drivers/gpu/drm/mgag200/Kconfig
@@ -12,14 +12,12 @@ config DRM_MGAG200
of the modesetting userspace driver, and a version of mga driver
that will fail on KMS enabled devices.
-config DRM_MGAG200_IOBURST_WORKAROUND
- bool "Disable buffer caching"
- depends on DRM_MGAG200 && PREEMPT_RT && X86
+config DRM_MGAG200_DISABLE_WRITECOMBINE
+ bool "Disable Write Combine mapping of VRAM"
+ depends on DRM_MGAG200 && PREEMPT_RT
help
- Enable a workaround to avoid I/O bursts within the mgag200 driver at
- the expense of overall display performance.
- It restores the <v5.10 behavior, by mapping the framebuffer in system
- RAM as Write-Combining, and flushing the cache after each write.
- This is only useful on x86_64 if you want to run processes with
- deterministic latency.
- If unsure, say N.
+ The VRAM of the G200 is mapped with Write-Combine to improve
+ performances. This can interfere with real-time tasks; even if they
+ are running on other CPU cores than the graphics output.
+ Enable this option only if you run realtime tasks on a server with a
+ Matrox G200. \ No newline at end of file
diff --git a/drivers/gpu/drm/mgag200/Makefile b/drivers/gpu/drm/mgag200/Makefile
index 182e224c460d..d1b25f9f6586 100644
--- a/drivers/gpu/drm/mgag200/Makefile
+++ b/drivers/gpu/drm/mgag200/Makefile
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
mgag200-y := \
mgag200_bmc.o \
+ mgag200_ddc.o \
mgag200_drv.o \
mgag200_g200.o \
mgag200_g200eh.o \
@@ -10,7 +11,7 @@ mgag200-y := \
mgag200_g200ew3.o \
mgag200_g200se.o \
mgag200_g200wb.o \
- mgag200_i2c.o \
- mgag200_mode.o
+ mgag200_mode.o \
+ mgag200_vga.o
obj-$(CONFIG_DRM_MGAG200) += mgag200.o
diff --git a/drivers/gpu/drm/mgag200/mgag200_bmc.c b/drivers/gpu/drm/mgag200/mgag200_bmc.c
index 2ba2e3c5086a..23ef85aa7e37 100644
--- a/drivers/gpu/drm/mgag200/mgag200_bmc.c
+++ b/drivers/gpu/drm/mgag200/mgag200_bmc.c
@@ -2,8 +2,18 @@
#include <linux/delay.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_managed.h>
+#include <drm/drm_probe_helper.h>
+
#include "mgag200_drv.h"
+static struct mgag200_bmc_connector *to_mgag200_bmc_connector(struct drm_connector *connector)
+{
+ return container_of(connector, struct mgag200_bmc_connector, base);
+}
+
void mgag200_bmc_disable_vidrst(struct mga_device *mdev)
{
u8 tmp;
@@ -97,3 +107,100 @@ void mgag200_bmc_enable_vidrst(struct mga_device *mdev)
tmp &= ~0x10;
WREG_DAC(MGA1064_GEN_IO_DATA, tmp);
}
+
+static const struct drm_encoder_funcs mgag200_bmc_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
+static int mgag200_bmc_connector_helper_detect_ctx(struct drm_connector *connector,
+ struct drm_modeset_acquire_ctx *ctx,
+ bool force)
+{
+ struct mgag200_bmc_connector *bmc_connector = to_mgag200_bmc_connector(connector);
+ struct drm_connector *physical_connector = bmc_connector->physical_connector;
+
+ /*
+ * Most user-space compositors cannot handle more than one connected
+ * connector per CRTC. Hence, we only mark the BMC as connected if the
+ * physical connector is disconnected. If the physical connector's status
+ * is connected or unknown, the BMC remains disconnected. This has no
+ * effect on the output of the BMC.
+ *
+ * FIXME: Remove this logic once user-space compositors can handle more
+ * than one connector per CRTC. The BMC should always be connected.
+ */
+
+ if (physical_connector && physical_connector->status == connector_status_disconnected)
+ return connector_status_connected;
+
+ return connector_status_disconnected;
+}
+
+static int mgag200_bmc_connector_helper_get_modes(struct drm_connector *connector)
+{
+ struct drm_device *dev = connector->dev;
+ struct mga_device *mdev = to_mga_device(dev);
+ const struct mgag200_device_info *minfo = mdev->info;
+
+ return drm_add_modes_noedid(connector, minfo->max_hdisplay, minfo->max_vdisplay);
+}
+
+static const struct drm_connector_helper_funcs mgag200_bmc_connector_helper_funcs = {
+ .get_modes = mgag200_bmc_connector_helper_get_modes,
+ .detect_ctx = mgag200_bmc_connector_helper_detect_ctx,
+};
+
+static const struct drm_connector_funcs mgag200_bmc_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,
+};
+
+static int mgag200_bmc_connector_init(struct drm_device *dev,
+ struct mgag200_bmc_connector *bmc_connector,
+ struct drm_connector *physical_connector)
+{
+ struct drm_connector *connector = &bmc_connector->base;
+ int ret;
+
+ ret = drm_connector_init(dev, connector, &mgag200_bmc_connector_funcs,
+ DRM_MODE_CONNECTOR_VIRTUAL);
+ if (ret)
+ return ret;
+ drm_connector_helper_add(connector, &mgag200_bmc_connector_helper_funcs);
+
+ bmc_connector->physical_connector = physical_connector;
+
+ return 0;
+}
+
+int mgag200_bmc_output_init(struct mga_device *mdev, struct drm_connector *physical_connector)
+{
+ struct drm_device *dev = &mdev->base;
+ struct drm_crtc *crtc = &mdev->crtc;
+ struct drm_encoder *encoder;
+ struct mgag200_bmc_connector *bmc_connector;
+ struct drm_connector *connector;
+ int ret;
+
+ encoder = &mdev->output.bmc.encoder;
+ ret = drm_encoder_init(dev, encoder, &mgag200_bmc_encoder_funcs,
+ DRM_MODE_ENCODER_VIRTUAL, NULL);
+ if (ret)
+ return ret;
+ encoder->possible_crtcs = drm_crtc_mask(crtc);
+
+ bmc_connector = &mdev->output.bmc.bmc_connector;
+ ret = mgag200_bmc_connector_init(dev, bmc_connector, physical_connector);
+ if (ret)
+ return ret;
+ connector = &bmc_connector->base;
+
+ ret = drm_connector_attach_encoder(connector, encoder);
+ if (ret)
+ return ret;
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/mgag200/mgag200_ddc.c b/drivers/gpu/drm/mgag200/mgag200_ddc.c
new file mode 100644
index 000000000000..6d81ea8931e8
--- /dev/null
+++ b/drivers/gpu/drm/mgag200/mgag200_ddc.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2012 Red Hat 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, sub license, 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 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ */
+/*
+ * Authors: Dave Airlie <airlied@redhat.com>
+ */
+
+#include <linux/export.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/i2c.h>
+#include <linux/pci.h>
+
+#include <drm/drm_managed.h>
+
+#include "mgag200_ddc.h"
+#include "mgag200_drv.h"
+
+struct mgag200_ddc {
+ struct mga_device *mdev;
+
+ int data;
+ int clock;
+
+ struct i2c_algo_bit_data bit;
+ struct i2c_adapter adapter;
+};
+
+static int mga_i2c_read_gpio(struct mga_device *mdev)
+{
+ WREG8(DAC_INDEX, MGA1064_GEN_IO_DATA);
+ return RREG8(DAC_DATA);
+}
+
+static void mga_i2c_set_gpio(struct mga_device *mdev, int mask, int val)
+{
+ int tmp;
+
+ WREG8(DAC_INDEX, MGA1064_GEN_IO_CTL);
+ tmp = (RREG8(DAC_DATA) & mask) | val;
+ WREG_DAC(MGA1064_GEN_IO_CTL, tmp);
+ WREG_DAC(MGA1064_GEN_IO_DATA, 0);
+}
+
+static inline void mga_i2c_set(struct mga_device *mdev, int mask, int state)
+{
+ if (state)
+ state = 0;
+ else
+ state = mask;
+ mga_i2c_set_gpio(mdev, ~mask, state);
+}
+
+static void mgag200_ddc_algo_bit_data_setsda(void *data, int state)
+{
+ struct mgag200_ddc *ddc = data;
+
+ mga_i2c_set(ddc->mdev, ddc->data, state);
+}
+
+static void mgag200_ddc_algo_bit_data_setscl(void *data, int state)
+{
+ struct mgag200_ddc *ddc = data;
+
+ mga_i2c_set(ddc->mdev, ddc->clock, state);
+}
+
+static int mgag200_ddc_algo_bit_data_getsda(void *data)
+{
+ struct mgag200_ddc *ddc = data;
+
+ return (mga_i2c_read_gpio(ddc->mdev) & ddc->data) ? 1 : 0;
+}
+
+static int mgag200_ddc_algo_bit_data_getscl(void *data)
+{
+ struct mgag200_ddc *ddc = data;
+
+ return (mga_i2c_read_gpio(ddc->mdev) & ddc->clock) ? 1 : 0;
+}
+
+static int mgag200_ddc_algo_bit_data_pre_xfer(struct i2c_adapter *adapter)
+{
+ struct mgag200_ddc *ddc = i2c_get_adapdata(adapter);
+ struct mga_device *mdev = ddc->mdev;
+
+ /*
+ * Protect access to I/O registers from concurrent modesetting
+ * by acquiring the I/O-register lock.
+ */
+ mutex_lock(&mdev->rmmio_lock);
+
+ return 0;
+}
+
+static void mgag200_ddc_algo_bit_data_post_xfer(struct i2c_adapter *adapter)
+{
+ struct mgag200_ddc *ddc = i2c_get_adapdata(adapter);
+ struct mga_device *mdev = ddc->mdev;
+
+ mutex_unlock(&mdev->rmmio_lock);
+}
+
+static void mgag200_ddc_release(struct drm_device *dev, void *res)
+{
+ struct mgag200_ddc *ddc = res;
+
+ i2c_del_adapter(&ddc->adapter);
+}
+
+struct i2c_adapter *mgag200_ddc_create(struct mga_device *mdev)
+{
+ struct drm_device *dev = &mdev->base;
+ const struct mgag200_device_info *info = mdev->info;
+ struct mgag200_ddc *ddc;
+ struct i2c_algo_bit_data *bit;
+ struct i2c_adapter *adapter;
+ int ret;
+
+ ddc = drmm_kzalloc(dev, sizeof(*ddc), GFP_KERNEL);
+ if (!ddc)
+ return ERR_PTR(-ENOMEM);
+
+ WREG_DAC(MGA1064_GEN_IO_CTL2, 1);
+ WREG_DAC(MGA1064_GEN_IO_DATA, 0xff);
+ WREG_DAC(MGA1064_GEN_IO_CTL, 0);
+
+ ddc->mdev = mdev;
+ ddc->data = BIT(info->i2c.data_bit);
+ ddc->clock = BIT(info->i2c.clock_bit);
+
+ bit = &ddc->bit;
+ bit->data = ddc;
+ bit->setsda = mgag200_ddc_algo_bit_data_setsda;
+ bit->setscl = mgag200_ddc_algo_bit_data_setscl;
+ bit->getsda = mgag200_ddc_algo_bit_data_getsda;
+ bit->getscl = mgag200_ddc_algo_bit_data_getscl;
+ bit->pre_xfer = mgag200_ddc_algo_bit_data_pre_xfer;
+ bit->post_xfer = mgag200_ddc_algo_bit_data_post_xfer;
+ bit->udelay = 10;
+ bit->timeout = usecs_to_jiffies(2200);
+
+ adapter = &ddc->adapter;
+ adapter->owner = THIS_MODULE;
+ adapter->algo_data = bit;
+ adapter->dev.parent = dev->dev;
+ snprintf(adapter->name, sizeof(adapter->name), "Matrox DDC bus");
+ i2c_set_adapdata(adapter, ddc);
+
+ ret = i2c_bit_add_bus(adapter);
+ if (ret)
+ return ERR_PTR(ret);
+
+ ret = drmm_add_action_or_reset(dev, mgag200_ddc_release, ddc);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return adapter;
+}
diff --git a/drivers/gpu/drm/mgag200/mgag200_ddc.h b/drivers/gpu/drm/mgag200/mgag200_ddc.h
new file mode 100644
index 000000000000..fa21d197cc78
--- /dev/null
+++ b/drivers/gpu/drm/mgag200/mgag200_ddc.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __MGAG200_DDC_H__
+#define __MGAG200_DDC_H__
+
+struct i2c_adapter;
+struct mga_device;
+
+struct i2c_adapter *mgag200_ddc_create(struct mga_device *mdev);
+
+#endif
diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c
index 573dbe256aa8..62080cf0f2da 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.c
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.c
@@ -12,7 +12,7 @@
#include <drm/drm_aperture.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_shmem.h>
#include <drm/drm_file.h>
#include <drm/drm_ioctl.h>
#include <drm/drm_managed.h>
@@ -84,20 +84,6 @@ resource_size_t mgag200_probe_vram(void __iomem *mem, resource_size_t size)
return offset - 65536;
}
-#if defined(CONFIG_DRM_MGAG200_IOBURST_WORKAROUND)
-static struct drm_gem_object *mgag200_create_object(struct drm_device *dev, size_t size)
-{
- struct drm_gem_shmem_object *shmem;
-
- shmem = kzalloc(sizeof(*shmem), GFP_KERNEL);
- if (!shmem)
- return NULL;
-
- shmem->map_wc = true;
- return &shmem->base;
-}
-#endif
-
/*
* DRM driver
*/
@@ -113,9 +99,6 @@ static const struct drm_driver mgag200_driver = {
.major = DRIVER_MAJOR,
.minor = DRIVER_MINOR,
.patchlevel = DRIVER_PATCHLEVEL,
-#if defined(CONFIG_DRM_MGAG200_IOBURST_WORKAROUND)
- .gem_create_object = mgag200_create_object,
-#endif
DRM_GEM_SHMEM_DRIVER_OPS,
};
@@ -163,12 +146,18 @@ int mgag200_device_preinit(struct mga_device *mdev)
}
mdev->vram_res = res;
+#if defined(CONFIG_DRM_MGAG200_DISABLE_WRITECOMBINE)
+ mdev->vram = devm_ioremap(dev->dev, res->start, resource_size(res));
+ if (!mdev->vram)
+ return -ENOMEM;
+#else
mdev->vram = devm_ioremap_wc(dev->dev, res->start, resource_size(res));
if (!mdev->vram)
return -ENOMEM;
/* Don't fail on errors, but performance might be reduced. */
devm_arch_phys_wc_add(dev->dev, res->start, resource_size(res));
+#endif
return 0;
}
@@ -285,7 +274,7 @@ mgag200_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
* FIXME: A 24-bit color depth does not work with 24 bpp on
* G200ER. Force 32 bpp.
*/
- drm_fbdev_generic_setup(dev, 32);
+ drm_fbdev_shmem_setup(dev, 32);
return 0;
}
diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h
index 58a0e62eaf18..7f7dfbd0f013 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.h
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
@@ -10,9 +10,6 @@
#ifndef __MGAG200_DRV_H__
#define __MGAG200_DRV_H__
-#include <linux/i2c-algo-bit.h>
-#include <linux/i2c.h>
-
#include <video/vga.h>
#include <drm/drm_connector.h>
@@ -189,11 +186,9 @@ static inline struct mgag200_crtc_state *to_mgag200_crtc_state(struct drm_crtc_s
return container_of(base, struct mgag200_crtc_state, base);
}
-struct mga_i2c_chan {
- struct i2c_adapter adapter;
- struct drm_device *dev;
- struct i2c_algo_bit_data bit;
- int data, clock;
+struct mgag200_bmc_connector {
+ struct drm_connector base;
+ struct drm_connector *physical_connector;
};
enum mga_type {
@@ -293,9 +288,16 @@ struct mga_device {
struct drm_plane primary_plane;
struct drm_crtc crtc;
- struct drm_encoder encoder;
- struct mga_i2c_chan i2c;
- struct drm_connector connector;
+ struct {
+ struct {
+ struct drm_encoder encoder;
+ struct drm_connector connector;
+ } vga;
+ struct {
+ struct drm_encoder encoder;
+ struct mgag200_bmc_connector bmc_connector;
+ } bmc;
+ } output;
};
static inline struct mga_device *to_mga_device(struct drm_device *dev)
@@ -428,32 +430,18 @@ void mgag200_crtc_atomic_destroy_state(struct drm_crtc *crtc, struct drm_crtc_st
.atomic_duplicate_state = mgag200_crtc_atomic_duplicate_state, \
.atomic_destroy_state = mgag200_crtc_atomic_destroy_state
-#define MGAG200_DAC_ENCODER_FUNCS \
- .destroy = drm_encoder_cleanup
-
-int mgag200_vga_connector_helper_get_modes(struct drm_connector *connector);
-
-#define MGAG200_VGA_CONNECTOR_HELPER_FUNCS \
- .get_modes = mgag200_vga_connector_helper_get_modes
-
-#define MGAG200_VGA_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
-
void mgag200_set_mode_regs(struct mga_device *mdev, const struct drm_display_mode *mode);
void mgag200_set_format_regs(struct mga_device *mdev, const struct drm_format_info *format);
void mgag200_enable_display(struct mga_device *mdev);
void mgag200_init_registers(struct mga_device *mdev);
int mgag200_mode_config_init(struct mga_device *mdev, resource_size_t vram_available);
+/* mgag200_vga.c */
+int mgag200_vga_output_init(struct mga_device *mdev);
+
/* mgag200_bmc.c */
void mgag200_bmc_disable_vidrst(struct mga_device *mdev);
void mgag200_bmc_enable_vidrst(struct mga_device *mdev);
-
- /* mgag200_i2c.c */
-int mgag200_i2c_init(struct mga_device *mdev, struct mga_i2c_chan *i2c);
+int mgag200_bmc_output_init(struct mga_device *mdev, struct drm_connector *physical_connector);
#endif /* __MGAG200_DRV_H__ */
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200.c b/drivers/gpu/drm/mgag200/mgag200_g200.c
index bf5d7fe525a3..f874e2949840 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200.c
@@ -183,26 +183,11 @@ static const struct drm_crtc_funcs mgag200_g200_crtc_funcs = {
MGAG200_CRTC_FUNCS,
};
-static const struct drm_encoder_funcs mgag200_g200_dac_encoder_funcs = {
- MGAG200_DAC_ENCODER_FUNCS,
-};
-
-static const struct drm_connector_helper_funcs mgag200_g200_vga_connector_helper_funcs = {
- MGAG200_VGA_CONNECTOR_HELPER_FUNCS,
-};
-
-static const struct drm_connector_funcs mgag200_g200_vga_connector_funcs = {
- MGAG200_VGA_CONNECTOR_FUNCS,
-};
-
static int mgag200_g200_pipeline_init(struct mga_device *mdev)
{
struct drm_device *dev = &mdev->base;
struct drm_plane *primary_plane = &mdev->primary_plane;
struct drm_crtc *crtc = &mdev->crtc;
- struct drm_encoder *encoder = &mdev->encoder;
- struct mga_i2c_chan *i2c = &mdev->i2c;
- struct drm_connector *connector = &mdev->connector;
int ret;
ret = drm_universal_plane_init(dev, primary_plane, 0,
@@ -230,35 +215,9 @@ static int mgag200_g200_pipeline_init(struct mga_device *mdev)
drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);
drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);
- encoder->possible_crtcs = drm_crtc_mask(crtc);
- ret = drm_encoder_init(dev, encoder, &mgag200_g200_dac_encoder_funcs,
- DRM_MODE_ENCODER_DAC, NULL);
- if (ret) {
- drm_err(dev, "drm_encoder_init() failed: %d\n", ret);
- return ret;
- }
-
- ret = mgag200_i2c_init(mdev, i2c);
- if (ret) {
- drm_err(dev, "failed to add DDC bus: %d\n", ret);
- return ret;
- }
-
- ret = drm_connector_init_with_ddc(dev, connector,
- &mgag200_g200_vga_connector_funcs,
- DRM_MODE_CONNECTOR_VGA,
- &i2c->adapter);
- if (ret) {
- drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
- return ret;
- }
- drm_connector_helper_add(connector, &mgag200_g200_vga_connector_helper_funcs);
-
- ret = drm_connector_attach_encoder(connector, encoder);
- if (ret) {
- drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret);
+ ret = mgag200_vga_output_init(mdev);
+ if (ret)
return ret;
- }
return 0;
}
@@ -442,6 +401,7 @@ struct mga_device *mgag200_g200_device_create(struct pci_dev *pdev, const struct
return ERR_PTR(ret);
drm_mode_config_reset(dev);
+ drm_kms_helper_poll_init(dev);
return mdev;
}
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200eh.c b/drivers/gpu/drm/mgag200/mgag200_g200eh.c
index fad62453a91d..52bf49ead5c5 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200eh.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200eh.c
@@ -182,26 +182,11 @@ static const struct drm_crtc_funcs mgag200_g200eh_crtc_funcs = {
MGAG200_CRTC_FUNCS,
};
-static const struct drm_encoder_funcs mgag200_g200eh_dac_encoder_funcs = {
- MGAG200_DAC_ENCODER_FUNCS,
-};
-
-static const struct drm_connector_helper_funcs mgag200_g200eh_vga_connector_helper_funcs = {
- MGAG200_VGA_CONNECTOR_HELPER_FUNCS,
-};
-
-static const struct drm_connector_funcs mgag200_g200eh_vga_connector_funcs = {
- MGAG200_VGA_CONNECTOR_FUNCS,
-};
-
static int mgag200_g200eh_pipeline_init(struct mga_device *mdev)
{
struct drm_device *dev = &mdev->base;
struct drm_plane *primary_plane = &mdev->primary_plane;
struct drm_crtc *crtc = &mdev->crtc;
- struct drm_encoder *encoder = &mdev->encoder;
- struct mga_i2c_chan *i2c = &mdev->i2c;
- struct drm_connector *connector = &mdev->connector;
int ret;
ret = drm_universal_plane_init(dev, primary_plane, 0,
@@ -229,35 +214,13 @@ static int mgag200_g200eh_pipeline_init(struct mga_device *mdev)
drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);
drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);
- encoder->possible_crtcs = drm_crtc_mask(crtc);
- ret = drm_encoder_init(dev, encoder, &mgag200_g200eh_dac_encoder_funcs,
- DRM_MODE_ENCODER_DAC, NULL);
- if (ret) {
- drm_err(dev, "drm_encoder_init() failed: %d\n", ret);
- return ret;
- }
-
- ret = mgag200_i2c_init(mdev, i2c);
- if (ret) {
- drm_err(dev, "failed to add DDC bus: %d\n", ret);
- return ret;
- }
-
- ret = drm_connector_init_with_ddc(dev, connector,
- &mgag200_g200eh_vga_connector_funcs,
- DRM_MODE_CONNECTOR_VGA,
- &i2c->adapter);
- if (ret) {
- drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
+ ret = mgag200_vga_output_init(mdev);
+ if (ret)
return ret;
- }
- drm_connector_helper_add(connector, &mgag200_g200eh_vga_connector_helper_funcs);
- ret = drm_connector_attach_encoder(connector, encoder);
- if (ret) {
- drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret);
+ ret = mgag200_bmc_output_init(mdev, &mdev->output.vga.connector);
+ if (ret)
return ret;
- }
return 0;
}
@@ -314,6 +277,7 @@ struct mga_device *mgag200_g200eh_device_create(struct pci_dev *pdev, const stru
return ERR_PTR(ret);
drm_mode_config_reset(dev);
+ drm_kms_helper_poll_init(dev);
return mdev;
}
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200eh3.c b/drivers/gpu/drm/mgag200/mgag200_g200eh3.c
index 0f7d8112cd49..e7f89b2a59fd 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200eh3.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200eh3.c
@@ -86,26 +86,11 @@ static const struct drm_crtc_funcs mgag200_g200eh3_crtc_funcs = {
MGAG200_CRTC_FUNCS,
};
-static const struct drm_encoder_funcs mgag200_g200eh3_dac_encoder_funcs = {
- MGAG200_DAC_ENCODER_FUNCS,
-};
-
-static const struct drm_connector_helper_funcs mgag200_g200eh3_vga_connector_helper_funcs = {
- MGAG200_VGA_CONNECTOR_HELPER_FUNCS,
-};
-
-static const struct drm_connector_funcs mgag200_g200eh3_vga_connector_funcs = {
- MGAG200_VGA_CONNECTOR_FUNCS,
-};
-
static int mgag200_g200eh3_pipeline_init(struct mga_device *mdev)
{
struct drm_device *dev = &mdev->base;
struct drm_plane *primary_plane = &mdev->primary_plane;
struct drm_crtc *crtc = &mdev->crtc;
- struct drm_encoder *encoder = &mdev->encoder;
- struct mga_i2c_chan *i2c = &mdev->i2c;
- struct drm_connector *connector = &mdev->connector;
int ret;
ret = drm_universal_plane_init(dev, primary_plane, 0,
@@ -133,35 +118,13 @@ static int mgag200_g200eh3_pipeline_init(struct mga_device *mdev)
drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);
drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);
- encoder->possible_crtcs = drm_crtc_mask(crtc);
- ret = drm_encoder_init(dev, encoder, &mgag200_g200eh3_dac_encoder_funcs,
- DRM_MODE_ENCODER_DAC, NULL);
- if (ret) {
- drm_err(dev, "drm_encoder_init() failed: %d\n", ret);
- return ret;
- }
-
- ret = mgag200_i2c_init(mdev, i2c);
- if (ret) {
- drm_err(dev, "failed to add DDC bus: %d\n", ret);
- return ret;
- }
-
- ret = drm_connector_init_with_ddc(dev, connector,
- &mgag200_g200eh3_vga_connector_funcs,
- DRM_MODE_CONNECTOR_VGA,
- &i2c->adapter);
- if (ret) {
- drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
+ ret = mgag200_vga_output_init(mdev);
+ if (ret)
return ret;
- }
- drm_connector_helper_add(connector, &mgag200_g200eh3_vga_connector_helper_funcs);
- ret = drm_connector_attach_encoder(connector, encoder);
- if (ret) {
- drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret);
+ ret = mgag200_bmc_output_init(mdev, &mdev->output.vga.connector);
+ if (ret)
return ret;
- }
return 0;
}
@@ -219,6 +182,7 @@ struct mga_device *mgag200_g200eh3_device_create(struct pci_dev *pdev,
return ERR_PTR(ret);
drm_mode_config_reset(dev);
+ drm_kms_helper_poll_init(dev);
return mdev;
}
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200er.c b/drivers/gpu/drm/mgag200/mgag200_g200er.c
index 8d4538b71047..4e8a1756138d 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200er.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200er.c
@@ -225,26 +225,11 @@ static const struct drm_crtc_funcs mgag200_g200er_crtc_funcs = {
MGAG200_CRTC_FUNCS,
};
-static const struct drm_encoder_funcs mgag200_g200er_dac_encoder_funcs = {
- MGAG200_DAC_ENCODER_FUNCS,
-};
-
-static const struct drm_connector_helper_funcs mgag200_g200er_vga_connector_helper_funcs = {
- MGAG200_VGA_CONNECTOR_HELPER_FUNCS,
-};
-
-static const struct drm_connector_funcs mgag200_g200er_vga_connector_funcs = {
- MGAG200_VGA_CONNECTOR_FUNCS,
-};
-
static int mgag200_g200er_pipeline_init(struct mga_device *mdev)
{
struct drm_device *dev = &mdev->base;
struct drm_plane *primary_plane = &mdev->primary_plane;
struct drm_crtc *crtc = &mdev->crtc;
- struct drm_encoder *encoder = &mdev->encoder;
- struct mga_i2c_chan *i2c = &mdev->i2c;
- struct drm_connector *connector = &mdev->connector;
int ret;
ret = drm_universal_plane_init(dev, primary_plane, 0,
@@ -272,35 +257,13 @@ static int mgag200_g200er_pipeline_init(struct mga_device *mdev)
drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);
drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);
- encoder->possible_crtcs = drm_crtc_mask(crtc);
- ret = drm_encoder_init(dev, encoder, &mgag200_g200er_dac_encoder_funcs,
- DRM_MODE_ENCODER_DAC, NULL);
- if (ret) {
- drm_err(dev, "drm_encoder_init() failed: %d\n", ret);
- return ret;
- }
-
- ret = mgag200_i2c_init(mdev, i2c);
- if (ret) {
- drm_err(dev, "failed to add DDC bus: %d\n", ret);
- return ret;
- }
-
- ret = drm_connector_init_with_ddc(dev, connector,
- &mgag200_g200er_vga_connector_funcs,
- DRM_MODE_CONNECTOR_VGA,
- &i2c->adapter);
- if (ret) {
- drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
+ ret = mgag200_vga_output_init(mdev);
+ if (ret)
return ret;
- }
- drm_connector_helper_add(connector, &mgag200_g200er_vga_connector_helper_funcs);
- ret = drm_connector_attach_encoder(connector, encoder);
- if (ret) {
- drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret);
+ ret = mgag200_bmc_output_init(mdev, &mdev->output.vga.connector);
+ if (ret)
return ret;
- }
return 0;
}
@@ -353,6 +316,7 @@ struct mga_device *mgag200_g200er_device_create(struct pci_dev *pdev, const stru
return ERR_PTR(ret);
drm_mode_config_reset(dev);
+ drm_kms_helper_poll_init(dev);
return mdev;
}
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ev.c b/drivers/gpu/drm/mgag200/mgag200_g200ev.c
index 56e6f986bff3..d884f3cb0ec7 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200ev.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200ev.c
@@ -226,26 +226,11 @@ static const struct drm_crtc_funcs mgag200_g200ev_crtc_funcs = {
MGAG200_CRTC_FUNCS,
};
-static const struct drm_encoder_funcs mgag200_g200ev_dac_encoder_funcs = {
- MGAG200_DAC_ENCODER_FUNCS,
-};
-
-static const struct drm_connector_helper_funcs mgag200_g200ev_vga_connector_helper_funcs = {
- MGAG200_VGA_CONNECTOR_HELPER_FUNCS,
-};
-
-static const struct drm_connector_funcs mgag200_g200ev_vga_connector_funcs = {
- MGAG200_VGA_CONNECTOR_FUNCS,
-};
-
static int mgag200_g200ev_pipeline_init(struct mga_device *mdev)
{
struct drm_device *dev = &mdev->base;
struct drm_plane *primary_plane = &mdev->primary_plane;
struct drm_crtc *crtc = &mdev->crtc;
- struct drm_encoder *encoder = &mdev->encoder;
- struct mga_i2c_chan *i2c = &mdev->i2c;
- struct drm_connector *connector = &mdev->connector;
int ret;
ret = drm_universal_plane_init(dev, primary_plane, 0,
@@ -273,35 +258,13 @@ static int mgag200_g200ev_pipeline_init(struct mga_device *mdev)
drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);
drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);
- encoder->possible_crtcs = drm_crtc_mask(crtc);
- ret = drm_encoder_init(dev, encoder, &mgag200_g200ev_dac_encoder_funcs,
- DRM_MODE_ENCODER_DAC, NULL);
- if (ret) {
- drm_err(dev, "drm_encoder_init() failed: %d\n", ret);
- return ret;
- }
-
- ret = mgag200_i2c_init(mdev, i2c);
- if (ret) {
- drm_err(dev, "failed to add DDC bus: %d\n", ret);
- return ret;
- }
-
- ret = drm_connector_init_with_ddc(dev, connector,
- &mgag200_g200ev_vga_connector_funcs,
- DRM_MODE_CONNECTOR_VGA,
- &i2c->adapter);
- if (ret) {
- drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
+ ret = mgag200_vga_output_init(mdev);
+ if (ret)
return ret;
- }
- drm_connector_helper_add(connector, &mgag200_g200ev_vga_connector_helper_funcs);
- ret = drm_connector_attach_encoder(connector, encoder);
- if (ret) {
- drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret);
+ ret = mgag200_bmc_output_init(mdev, &mdev->output.vga.connector);
+ if (ret)
return ret;
- }
return 0;
}
@@ -358,6 +321,7 @@ struct mga_device *mgag200_g200ev_device_create(struct pci_dev *pdev, const stru
return ERR_PTR(ret);
drm_mode_config_reset(dev);
+ drm_kms_helper_poll_init(dev);
return mdev;
}
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
index 170934414d7d..839401e8b465 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
@@ -95,26 +95,11 @@ static const struct drm_crtc_funcs mgag200_g200ew3_crtc_funcs = {
MGAG200_CRTC_FUNCS,
};
-static const struct drm_encoder_funcs mgag200_g200ew3_dac_encoder_funcs = {
- MGAG200_DAC_ENCODER_FUNCS,
-};
-
-static const struct drm_connector_helper_funcs mgag200_g200ew3_vga_connector_helper_funcs = {
- MGAG200_VGA_CONNECTOR_HELPER_FUNCS,
-};
-
-static const struct drm_connector_funcs mgag200_g200ew3_vga_connector_funcs = {
- MGAG200_VGA_CONNECTOR_FUNCS,
-};
-
static int mgag200_g200ew3_pipeline_init(struct mga_device *mdev)
{
struct drm_device *dev = &mdev->base;
struct drm_plane *primary_plane = &mdev->primary_plane;
struct drm_crtc *crtc = &mdev->crtc;
- struct drm_encoder *encoder = &mdev->encoder;
- struct mga_i2c_chan *i2c = &mdev->i2c;
- struct drm_connector *connector = &mdev->connector;
int ret;
ret = drm_universal_plane_init(dev, primary_plane, 0,
@@ -142,35 +127,13 @@ static int mgag200_g200ew3_pipeline_init(struct mga_device *mdev)
drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);
drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);
- encoder->possible_crtcs = drm_crtc_mask(crtc);
- ret = drm_encoder_init(dev, encoder, &mgag200_g200ew3_dac_encoder_funcs,
- DRM_MODE_ENCODER_DAC, NULL);
- if (ret) {
- drm_err(dev, "drm_encoder_init() failed: %d\n", ret);
- return ret;
- }
-
- ret = mgag200_i2c_init(mdev, i2c);
- if (ret) {
- drm_err(dev, "failed to add DDC bus: %d\n", ret);
- return ret;
- }
-
- ret = drm_connector_init_with_ddc(dev, connector,
- &mgag200_g200ew3_vga_connector_funcs,
- DRM_MODE_CONNECTOR_VGA,
- &i2c->adapter);
- if (ret) {
- drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
+ ret = mgag200_vga_output_init(mdev);
+ if (ret)
return ret;
- }
- drm_connector_helper_add(connector, &mgag200_g200ew3_vga_connector_helper_funcs);
- ret = drm_connector_attach_encoder(connector, encoder);
- if (ret) {
- drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret);
+ ret = mgag200_bmc_output_init(mdev, &mdev->output.vga.connector);
+ if (ret)
return ret;
- }
return 0;
}
@@ -239,6 +202,7 @@ struct mga_device *mgag200_g200ew3_device_create(struct pci_dev *pdev,
return ERR_PTR(ret);
drm_mode_config_reset(dev);
+ drm_kms_helper_poll_init(dev);
return mdev;
}
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200se.c b/drivers/gpu/drm/mgag200/mgag200_g200se.c
index ff2b3c6622e7..a824bb8ad579 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200se.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200se.c
@@ -357,26 +357,11 @@ static const struct drm_crtc_funcs mgag200_g200se_crtc_funcs = {
MGAG200_CRTC_FUNCS,
};
-static const struct drm_encoder_funcs mgag200_g200se_dac_encoder_funcs = {
- MGAG200_DAC_ENCODER_FUNCS,
-};
-
-static const struct drm_connector_helper_funcs mgag200_g200se_vga_connector_helper_funcs = {
- MGAG200_VGA_CONNECTOR_HELPER_FUNCS,
-};
-
-static const struct drm_connector_funcs mgag200_g200se_vga_connector_funcs = {
- MGAG200_VGA_CONNECTOR_FUNCS,
-};
-
static int mgag200_g200se_pipeline_init(struct mga_device *mdev)
{
struct drm_device *dev = &mdev->base;
struct drm_plane *primary_plane = &mdev->primary_plane;
struct drm_crtc *crtc = &mdev->crtc;
- struct drm_encoder *encoder = &mdev->encoder;
- struct mga_i2c_chan *i2c = &mdev->i2c;
- struct drm_connector *connector = &mdev->connector;
int ret;
ret = drm_universal_plane_init(dev, primary_plane, 0,
@@ -404,35 +389,13 @@ static int mgag200_g200se_pipeline_init(struct mga_device *mdev)
drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);
drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);
- encoder->possible_crtcs = drm_crtc_mask(crtc);
- ret = drm_encoder_init(dev, encoder, &mgag200_g200se_dac_encoder_funcs,
- DRM_MODE_ENCODER_DAC, NULL);
- if (ret) {
- drm_err(dev, "drm_encoder_init() failed: %d\n", ret);
- return ret;
- }
-
- ret = mgag200_i2c_init(mdev, i2c);
- if (ret) {
- drm_err(dev, "failed to add DDC bus: %d\n", ret);
- return ret;
- }
-
- ret = drm_connector_init_with_ddc(dev, connector,
- &mgag200_g200se_vga_connector_funcs,
- DRM_MODE_CONNECTOR_VGA,
- &i2c->adapter);
- if (ret) {
- drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
+ ret = mgag200_vga_output_init(mdev);
+ if (ret)
return ret;
- }
- drm_connector_helper_add(connector, &mgag200_g200se_vga_connector_helper_funcs);
- ret = drm_connector_attach_encoder(connector, encoder);
- if (ret) {
- drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret);
+ ret = mgag200_bmc_output_init(mdev, &mdev->output.vga.connector);
+ if (ret)
return ret;
- }
return 0;
}
@@ -558,6 +521,7 @@ struct mga_device *mgag200_g200se_device_create(struct pci_dev *pdev, const stru
return ERR_PTR(ret);
drm_mode_config_reset(dev);
+ drm_kms_helper_poll_init(dev);
return mdev;
}
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200wb.c b/drivers/gpu/drm/mgag200/mgag200_g200wb.c
index 9baa727ac6f9..835df0f4fc13 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200wb.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200wb.c
@@ -229,26 +229,11 @@ static const struct drm_crtc_funcs mgag200_g200wb_crtc_funcs = {
MGAG200_CRTC_FUNCS,
};
-static const struct drm_encoder_funcs mgag200_g200wb_dac_encoder_funcs = {
- MGAG200_DAC_ENCODER_FUNCS,
-};
-
-static const struct drm_connector_helper_funcs mgag200_g200wb_vga_connector_helper_funcs = {
- MGAG200_VGA_CONNECTOR_HELPER_FUNCS,
-};
-
-static const struct drm_connector_funcs mgag200_g200wb_vga_connector_funcs = {
- MGAG200_VGA_CONNECTOR_FUNCS,
-};
-
static int mgag200_g200wb_pipeline_init(struct mga_device *mdev)
{
struct drm_device *dev = &mdev->base;
struct drm_plane *primary_plane = &mdev->primary_plane;
struct drm_crtc *crtc = &mdev->crtc;
- struct drm_encoder *encoder = &mdev->encoder;
- struct mga_i2c_chan *i2c = &mdev->i2c;
- struct drm_connector *connector = &mdev->connector;
int ret;
ret = drm_universal_plane_init(dev, primary_plane, 0,
@@ -276,35 +261,13 @@ static int mgag200_g200wb_pipeline_init(struct mga_device *mdev)
drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);
drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);
- encoder->possible_crtcs = drm_crtc_mask(crtc);
- ret = drm_encoder_init(dev, encoder, &mgag200_g200wb_dac_encoder_funcs,
- DRM_MODE_ENCODER_DAC, NULL);
- if (ret) {
- drm_err(dev, "drm_encoder_init() failed: %d\n", ret);
- return ret;
- }
-
- ret = mgag200_i2c_init(mdev, i2c);
- if (ret) {
- drm_err(dev, "failed to add DDC bus: %d\n", ret);
- return ret;
- }
-
- ret = drm_connector_init_with_ddc(dev, connector,
- &mgag200_g200wb_vga_connector_funcs,
- DRM_MODE_CONNECTOR_VGA,
- &i2c->adapter);
- if (ret) {
- drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
+ ret = mgag200_vga_output_init(mdev);
+ if (ret)
return ret;
- }
- drm_connector_helper_add(connector, &mgag200_g200wb_vga_connector_helper_funcs);
- ret = drm_connector_attach_encoder(connector, encoder);
- if (ret) {
- drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret);
+ ret = mgag200_bmc_output_init(mdev, &mdev->output.vga.connector);
+ if (ret)
return ret;
- }
return 0;
}
@@ -363,6 +326,7 @@ struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const stru
return ERR_PTR(ret);
drm_mode_config_reset(dev);
+ drm_kms_helper_poll_init(dev);
return mdev;
}
diff --git a/drivers/gpu/drm/mgag200/mgag200_i2c.c b/drivers/gpu/drm/mgag200/mgag200_i2c.c
deleted file mode 100644
index 423eb302be7e..000000000000
--- a/drivers/gpu/drm/mgag200/mgag200_i2c.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright 2012 Red Hat 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, sub license, 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 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 NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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.
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- */
-/*
- * Authors: Dave Airlie <airlied@redhat.com>
- */
-
-#include <linux/export.h>
-#include <linux/i2c-algo-bit.h>
-#include <linux/i2c.h>
-#include <linux/pci.h>
-
-#include "mgag200_drv.h"
-
-static int mga_i2c_read_gpio(struct mga_device *mdev)
-{
- WREG8(DAC_INDEX, MGA1064_GEN_IO_DATA);
- return RREG8(DAC_DATA);
-}
-
-static void mga_i2c_set_gpio(struct mga_device *mdev, int mask, int val)
-{
- int tmp;
-
- WREG8(DAC_INDEX, MGA1064_GEN_IO_CTL);
- tmp = (RREG8(DAC_DATA) & mask) | val;
- WREG_DAC(MGA1064_GEN_IO_CTL, tmp);
- WREG_DAC(MGA1064_GEN_IO_DATA, 0);
-}
-
-static inline void mga_i2c_set(struct mga_device *mdev, int mask, int state)
-{
- if (state)
- state = 0;
- else
- state = mask;
- mga_i2c_set_gpio(mdev, ~mask, state);
-}
-
-static void mga_gpio_setsda(void *data, int state)
-{
- struct mga_i2c_chan *i2c = data;
- struct mga_device *mdev = to_mga_device(i2c->dev);
- mga_i2c_set(mdev, i2c->data, state);
-}
-
-static void mga_gpio_setscl(void *data, int state)
-{
- struct mga_i2c_chan *i2c = data;
- struct mga_device *mdev = to_mga_device(i2c->dev);
- mga_i2c_set(mdev, i2c->clock, state);
-}
-
-static int mga_gpio_getsda(void *data)
-{
- struct mga_i2c_chan *i2c = data;
- struct mga_device *mdev = to_mga_device(i2c->dev);
- return (mga_i2c_read_gpio(mdev) & i2c->data) ? 1 : 0;
-}
-
-static int mga_gpio_getscl(void *data)
-{
- struct mga_i2c_chan *i2c = data;
- struct mga_device *mdev = to_mga_device(i2c->dev);
- return (mga_i2c_read_gpio(mdev) & i2c->clock) ? 1 : 0;
-}
-
-static void mgag200_i2c_release(void *res)
-{
- struct mga_i2c_chan *i2c = res;
-
- i2c_del_adapter(&i2c->adapter);
-}
-
-int mgag200_i2c_init(struct mga_device *mdev, struct mga_i2c_chan *i2c)
-{
- struct drm_device *dev = &mdev->base;
- const struct mgag200_device_info *info = mdev->info;
- int ret;
-
- WREG_DAC(MGA1064_GEN_IO_CTL2, 1);
- WREG_DAC(MGA1064_GEN_IO_DATA, 0xff);
- WREG_DAC(MGA1064_GEN_IO_CTL, 0);
-
- i2c->data = BIT(info->i2c.data_bit);
- i2c->clock = BIT(info->i2c.clock_bit);
- i2c->adapter.owner = THIS_MODULE;
- i2c->adapter.dev.parent = dev->dev;
- i2c->dev = dev;
- i2c_set_adapdata(&i2c->adapter, i2c);
- snprintf(i2c->adapter.name, sizeof(i2c->adapter.name), "mga i2c");
-
- i2c->adapter.algo_data = &i2c->bit;
-
- i2c->bit.udelay = 10;
- i2c->bit.timeout = 2;
- i2c->bit.data = i2c;
- i2c->bit.setsda = mga_gpio_setsda;
- i2c->bit.setscl = mga_gpio_setscl;
- i2c->bit.getsda = mga_gpio_getsda;
- i2c->bit.getscl = mga_gpio_getscl;
-
- ret = i2c_bit_add_bus(&i2c->adapter);
- if (ret)
- return ret;
-
- return devm_add_action_or_reset(dev->dev, mgag200_i2c_release, i2c);
-}
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index fc54851d3384..d4550e4b3b01 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -13,7 +13,6 @@
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
-#include <drm/drm_cache.h>
#include <drm/drm_damage_helper.h>
#include <drm/drm_edid.h>
#include <drm/drm_format_helper.h>
@@ -24,6 +23,7 @@
#include <drm/drm_panic.h>
#include <drm/drm_print.h>
+#include "mgag200_ddc.h"
#include "mgag200_drv.h"
/*
@@ -111,12 +111,12 @@ static inline void mga_wait_vsync(struct mga_device *mdev)
unsigned int status = 0;
do {
- status = RREG32(MGAREG_Status);
+ status = RREG32(MGAREG_STATUS);
} while ((status & 0x08) && time_before(jiffies, timeout));
timeout = jiffies + HZ/10;
status = 0;
do {
- status = RREG32(MGAREG_Status);
+ status = RREG32(MGAREG_STATUS);
} while (!(status & 0x08) && time_before(jiffies, timeout));
}
@@ -125,7 +125,7 @@ static inline void mga_wait_busy(struct mga_device *mdev)
unsigned long timeout = jiffies + HZ;
unsigned int status = 0;
do {
- status = RREG8(MGAREG_Status + 2);
+ status = RREG8(MGAREG_STATUS + 2);
} while ((status & 0x01) && time_before(jiffies, timeout));
}
@@ -438,13 +438,6 @@ static void mgag200_handle_damage(struct mga_device *mdev, const struct iosys_ma
iosys_map_incr(&dst, drm_fb_clip_offset(fb->pitches[0], fb->format, clip));
drm_fb_memcpy(&dst, fb->pitches, vmap, fb, clip);
-
- /* Flushing the cache greatly improves latency on x86_64 */
-#if defined(CONFIG_DRM_MGAG200_IOBURST_WORKAROUND)
- if (!vmap->is_iomem)
- drm_clflush_virt_range(vmap->vaddr + clip->y1 * fb->pitches[0],
- drm_rect_height(clip) * fb->pitches[0]);
-#endif
}
/*
@@ -737,32 +730,6 @@ void mgag200_crtc_atomic_destroy_state(struct drm_crtc *crtc, struct drm_crtc_st
}
/*
- * Connector
- */
-
-int mgag200_vga_connector_helper_get_modes(struct drm_connector *connector)
-{
- struct mga_device *mdev = to_mga_device(connector->dev);
- const struct drm_edid *drm_edid;
- int count;
-
- /*
- * Protect access to I/O registers from concurrent modesetting
- * by acquiring the I/O-register lock.
- */
- mutex_lock(&mdev->rmmio_lock);
-
- drm_edid = drm_edid_read(connector);
- drm_edid_connector_update(connector, drm_edid);
- count = drm_edid_connector_add_modes(connector);
- drm_edid_free(drm_edid);
-
- mutex_unlock(&mdev->rmmio_lock);
-
- return count;
-}
-
-/*
* Mode config
*/
diff --git a/drivers/gpu/drm/mgag200/mgag200_reg.h b/drivers/gpu/drm/mgag200/mgag200_reg.h
index 1019ffd6c260..aa73463674e4 100644
--- a/drivers/gpu/drm/mgag200/mgag200_reg.h
+++ b/drivers/gpu/drm/mgag200/mgag200_reg.h
@@ -102,7 +102,7 @@
#define MGAREG_EXEC 0x0100
#define MGAREG_FIFOSTATUS 0x1e10
-#define MGAREG_Status 0x1e14
+#define MGAREG_STATUS 0x1e14
#define MGAREG_CACHEFLUSH 0x1fff
#define MGAREG_ICLEAR 0x1e18
#define MGAREG_IEN 0x1e1c
diff --git a/drivers/gpu/drm/mgag200/mgag200_vga.c b/drivers/gpu/drm/mgag200/mgag200_vga.c
new file mode 100644
index 000000000000..60568f32736d
--- /dev/null
+++ b/drivers/gpu/drm/mgag200/mgag200_vga.c
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_probe_helper.h>
+
+#include "mgag200_ddc.h"
+#include "mgag200_drv.h"
+
+static const struct drm_encoder_funcs mgag200_dac_encoder_funcs = {
+ .destroy = drm_encoder_cleanup
+};
+
+static const struct drm_connector_helper_funcs mgag200_vga_connector_helper_funcs = {
+ .get_modes = drm_connector_helper_get_modes,
+ .detect_ctx = drm_connector_helper_detect_from_ddc
+};
+
+static const struct drm_connector_funcs mgag200_vga_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
+};
+
+int mgag200_vga_output_init(struct mga_device *mdev)
+{
+ struct drm_device *dev = &mdev->base;
+ struct drm_crtc *crtc = &mdev->crtc;
+ struct drm_encoder *encoder;
+ struct drm_connector *connector;
+ struct i2c_adapter *ddc;
+ int ret;
+
+ encoder = &mdev->output.vga.encoder;
+ ret = drm_encoder_init(dev, encoder, &mgag200_dac_encoder_funcs,
+ DRM_MODE_ENCODER_DAC, NULL);
+ if (ret) {
+ drm_err(dev, "drm_encoder_init() failed: %d\n", ret);
+ return ret;
+ }
+ encoder->possible_crtcs = drm_crtc_mask(crtc);
+
+ ddc = mgag200_ddc_create(mdev);
+ if (IS_ERR(ddc)) {
+ ret = PTR_ERR(ddc);
+ drm_err(dev, "failed to add DDC bus: %d\n", ret);
+ return ret;
+ }
+
+ connector = &mdev->output.vga.connector;
+ ret = drm_connector_init_with_ddc(dev, connector,
+ &mgag200_vga_connector_funcs,
+ DRM_MODE_CONNECTOR_VGA, ddc);
+ if (ret) {
+ drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
+ return ret;
+ }
+ drm_connector_helper_add(connector, &mgag200_vga_connector_helper_funcs);
+
+ connector->polled = DRM_CONNECTOR_POLL_CONNECT |
+ DRM_CONNECTOR_POLL_DISCONNECT;
+
+ ret = drm_connector_attach_encoder(connector, encoder);
+ if (ret) {
+ drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig
index 1931ecf73e32..26a4c71da63a 100644
--- a/drivers/gpu/drm/msm/Kconfig
+++ b/drivers/gpu/drm/msm/Kconfig
@@ -33,6 +33,7 @@ config DRM_MSM
select PM_OPP
select NVMEM
select PM_GENERIC_DOMAINS
+ select TRACE_GPU_MEM
help
DRM/KMS driver for MSM/snapdragon.
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index eb788921ff4f..f5e2838c6a76 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -8,13 +8,18 @@ ccflags-$(CONFIG_DRM_MSM_DP) += -I $(src)/dp
adreno-y := \
adreno/adreno_device.o \
adreno/adreno_gpu.o \
+ adreno/a2xx_catalog.o \
adreno/a2xx_gpu.o \
adreno/a2xx_gpummu.o \
+ adreno/a3xx_catalog.o \
adreno/a3xx_gpu.o \
+ adreno/a4xx_catalog.o \
adreno/a4xx_gpu.o \
+ adreno/a5xx_catalog.o \
adreno/a5xx_gpu.o \
adreno/a5xx_power.o \
adreno/a5xx_preempt.o \
+ adreno/a6xx_catalog.o \
adreno/a6xx_gpu.o \
adreno/a6xx_gmu.o \
adreno/a6xx_hfi.o \
diff --git a/drivers/gpu/drm/msm/adreno/a2xx_catalog.c b/drivers/gpu/drm/msm/adreno/a2xx_catalog.c
new file mode 100644
index 000000000000..9ddb7b31fd98
--- /dev/null
+++ b/drivers/gpu/drm/msm/adreno/a2xx_catalog.c
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2013-2014 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ *
+ * Copyright (c) 2014,2017 The Linux Foundation. All rights reserved.
+ */
+
+#include "adreno_gpu.h"
+
+static const struct adreno_info a2xx_gpus[] = {
+ {
+ .chip_ids = ADRENO_CHIP_IDS(0x02000000),
+ .family = ADRENO_2XX_GEN1,
+ .revn = 200,
+ .fw = {
+ [ADRENO_FW_PM4] = "yamato_pm4.fw",
+ [ADRENO_FW_PFP] = "yamato_pfp.fw",
+ },
+ .gmem = SZ_256K,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
+ .init = a2xx_gpu_init,
+ }, { /* a200 on i.mx51 has only 128kib gmem */
+ .chip_ids = ADRENO_CHIP_IDS(0x02000001),
+ .family = ADRENO_2XX_GEN1,
+ .revn = 201,
+ .fw = {
+ [ADRENO_FW_PM4] = "yamato_pm4.fw",
+ [ADRENO_FW_PFP] = "yamato_pfp.fw",
+ },
+ .gmem = SZ_128K,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
+ .init = a2xx_gpu_init,
+ }, {
+ .chip_ids = ADRENO_CHIP_IDS(0x02020000),
+ .family = ADRENO_2XX_GEN2,
+ .revn = 220,
+ .fw = {
+ [ADRENO_FW_PM4] = "leia_pm4_470.fw",
+ [ADRENO_FW_PFP] = "leia_pfp_470.fw",
+ },
+ .gmem = SZ_512K,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
+ .init = a2xx_gpu_init,
+ }
+};
+DECLARE_ADRENO_GPULIST(a2xx);
+
+MODULE_FIRMWARE("qcom/leia_pfp_470.fw");
+MODULE_FIRMWARE("qcom/leia_pm4_470.fw");
+MODULE_FIRMWARE("qcom/yamato_pfp.fw");
+MODULE_FIRMWARE("qcom/yamato_pm4.fw");
diff --git a/drivers/gpu/drm/msm/adreno/a3xx_catalog.c b/drivers/gpu/drm/msm/adreno/a3xx_catalog.c
new file mode 100644
index 000000000000..0de8465b6cf0
--- /dev/null
+++ b/drivers/gpu/drm/msm/adreno/a3xx_catalog.c
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2013-2014 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ *
+ * Copyright (c) 2014,2017 The Linux Foundation. All rights reserved.
+ */
+
+#include "adreno_gpu.h"
+
+static const struct adreno_info a3xx_gpus[] = {
+ {
+ .chip_ids = ADRENO_CHIP_IDS(0x03000512),
+ .family = ADRENO_3XX,
+ .fw = {
+ [ADRENO_FW_PM4] = "a330_pm4.fw",
+ [ADRENO_FW_PFP] = "a330_pfp.fw",
+ },
+ .gmem = SZ_128K,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
+ .init = a3xx_gpu_init,
+ }, {
+ .chip_ids = ADRENO_CHIP_IDS(0x03000520),
+ .family = ADRENO_3XX,
+ .revn = 305,
+ .fw = {
+ [ADRENO_FW_PM4] = "a300_pm4.fw",
+ [ADRENO_FW_PFP] = "a300_pfp.fw",
+ },
+ .gmem = SZ_256K,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
+ .init = a3xx_gpu_init,
+ }, {
+ .chip_ids = ADRENO_CHIP_IDS(0x03000600),
+ .family = ADRENO_3XX,
+ .revn = 307, /* because a305c is revn==306 */
+ .fw = {
+ [ADRENO_FW_PM4] = "a300_pm4.fw",
+ [ADRENO_FW_PFP] = "a300_pfp.fw",
+ },
+ .gmem = SZ_128K,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
+ .init = a3xx_gpu_init,
+ }, {
+ .chip_ids = ADRENO_CHIP_IDS(
+ 0x03020000,
+ 0x03020001,
+ 0x03020002
+ ),
+ .family = ADRENO_3XX,
+ .revn = 320,
+ .fw = {
+ [ADRENO_FW_PM4] = "a300_pm4.fw",
+ [ADRENO_FW_PFP] = "a300_pfp.fw",
+ },
+ .gmem = SZ_512K,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
+ .init = a3xx_gpu_init,
+ }, {
+ .chip_ids = ADRENO_CHIP_IDS(
+ 0x03030000,
+ 0x03030001,
+ 0x03030002
+ ),
+ .family = ADRENO_3XX,
+ .revn = 330,
+ .fw = {
+ [ADRENO_FW_PM4] = "a330_pm4.fw",
+ [ADRENO_FW_PFP] = "a330_pfp.fw",
+ },
+ .gmem = SZ_1M,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
+ .init = a3xx_gpu_init,
+ }
+};
+DECLARE_ADRENO_GPULIST(a3xx);
+
+MODULE_FIRMWARE("qcom/a300_pm4.fw");
+MODULE_FIRMWARE("qcom/a300_pfp.fw");
+MODULE_FIRMWARE("qcom/a330_pm4.fw");
+MODULE_FIRMWARE("qcom/a330_pfp.fw");
diff --git a/drivers/gpu/drm/msm/adreno/a4xx_catalog.c b/drivers/gpu/drm/msm/adreno/a4xx_catalog.c
new file mode 100644
index 000000000000..93519f807f87
--- /dev/null
+++ b/drivers/gpu/drm/msm/adreno/a4xx_catalog.c
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2013-2014 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ *
+ * Copyright (c) 2014,2017 The Linux Foundation. All rights reserved.
+ */
+
+#include "adreno_gpu.h"
+
+static const struct adreno_info a4xx_gpus[] = {
+ {
+ .chip_ids = ADRENO_CHIP_IDS(0x04000500),
+ .family = ADRENO_4XX,
+ .revn = 405,
+ .fw = {
+ [ADRENO_FW_PM4] = "a420_pm4.fw",
+ [ADRENO_FW_PFP] = "a420_pfp.fw",
+ },
+ .gmem = SZ_256K,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
+ .init = a4xx_gpu_init,
+ }, {
+ .chip_ids = ADRENO_CHIP_IDS(0x04020000),
+ .family = ADRENO_4XX,
+ .revn = 420,
+ .fw = {
+ [ADRENO_FW_PM4] = "a420_pm4.fw",
+ [ADRENO_FW_PFP] = "a420_pfp.fw",
+ },
+ .gmem = (SZ_1M + SZ_512K),
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
+ .init = a4xx_gpu_init,
+ }, {
+ .chip_ids = ADRENO_CHIP_IDS(0x04030002),
+ .family = ADRENO_4XX,
+ .revn = 430,
+ .fw = {
+ [ADRENO_FW_PM4] = "a420_pm4.fw",
+ [ADRENO_FW_PFP] = "a420_pfp.fw",
+ },
+ .gmem = (SZ_1M + SZ_512K),
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
+ .init = a4xx_gpu_init,
+ }
+};
+DECLARE_ADRENO_GPULIST(a4xx);
+
+MODULE_FIRMWARE("qcom/a420_pm4.fw");
+MODULE_FIRMWARE("qcom/a420_pfp.fw");
diff --git a/drivers/gpu/drm/msm/adreno/a5xx_catalog.c b/drivers/gpu/drm/msm/adreno/a5xx_catalog.c
new file mode 100644
index 000000000000..633f31539162
--- /dev/null
+++ b/drivers/gpu/drm/msm/adreno/a5xx_catalog.c
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2013-2014 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ *
+ * Copyright (c) 2014,2017 The Linux Foundation. All rights reserved.
+ */
+
+#include "adreno_gpu.h"
+
+static const struct adreno_info a5xx_gpus[] = {
+ {
+ .chip_ids = ADRENO_CHIP_IDS(0x05000500),
+ .family = ADRENO_5XX,
+ .revn = 505,
+ .fw = {
+ [ADRENO_FW_PM4] = "a530_pm4.fw",
+ [ADRENO_FW_PFP] = "a530_pfp.fw",
+ },
+ .gmem = (SZ_128K + SZ_8K),
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
+ .quirks = ADRENO_QUIRK_TWO_PASS_USE_WFI |
+ ADRENO_QUIRK_LMLOADKILL_DISABLE,
+ .init = a5xx_gpu_init,
+ }, {
+ .chip_ids = ADRENO_CHIP_IDS(0x05000600),
+ .family = ADRENO_5XX,
+ .revn = 506,
+ .fw = {
+ [ADRENO_FW_PM4] = "a530_pm4.fw",
+ [ADRENO_FW_PFP] = "a530_pfp.fw",
+ },
+ .gmem = (SZ_128K + SZ_8K),
+ /*
+ * Increase inactive period to 250 to avoid bouncing
+ * the GDSC which appears to make it grumpy
+ */
+ .inactive_period = 250,
+ .quirks = ADRENO_QUIRK_TWO_PASS_USE_WFI |
+ ADRENO_QUIRK_LMLOADKILL_DISABLE,
+ .init = a5xx_gpu_init,
+ .zapfw = "a506_zap.mdt",
+ }, {
+ .chip_ids = ADRENO_CHIP_IDS(0x05000800),
+ .family = ADRENO_5XX,
+ .revn = 508,
+ .fw = {
+ [ADRENO_FW_PM4] = "a530_pm4.fw",
+ [ADRENO_FW_PFP] = "a530_pfp.fw",
+ },
+ .gmem = (SZ_128K + SZ_8K),
+ /*
+ * Increase inactive period to 250 to avoid bouncing
+ * the GDSC which appears to make it grumpy
+ */
+ .inactive_period = 250,
+ .quirks = ADRENO_QUIRK_LMLOADKILL_DISABLE,
+ .init = a5xx_gpu_init,
+ .zapfw = "a508_zap.mdt",
+ }, {
+ .chip_ids = ADRENO_CHIP_IDS(0x05000900),
+ .family = ADRENO_5XX,
+ .revn = 509,
+ .fw = {
+ [ADRENO_FW_PM4] = "a530_pm4.fw",
+ [ADRENO_FW_PFP] = "a530_pfp.fw",
+ },
+ .gmem = (SZ_256K + SZ_16K),
+ /*
+ * Increase inactive period to 250 to avoid bouncing
+ * the GDSC which appears to make it grumpy
+ */
+ .inactive_period = 250,
+ .quirks = ADRENO_QUIRK_LMLOADKILL_DISABLE,
+ .init = a5xx_gpu_init,
+ /* Adreno 509 uses the same ZAP as 512 */
+ .zapfw = "a512_zap.mdt",
+ }, {
+ .chip_ids = ADRENO_CHIP_IDS(0x05010000),
+ .family = ADRENO_5XX,
+ .revn = 510,
+ .fw = {
+ [ADRENO_FW_PM4] = "a530_pm4.fw",
+ [ADRENO_FW_PFP] = "a530_pfp.fw",
+ },
+ .gmem = SZ_256K,
+ /*
+ * Increase inactive period to 250 to avoid bouncing
+ * the GDSC which appears to make it grumpy
+ */
+ .inactive_period = 250,
+ .init = a5xx_gpu_init,
+ }, {
+ .chip_ids = ADRENO_CHIP_IDS(0x05010200),
+ .family = ADRENO_5XX,
+ .revn = 512,
+ .fw = {
+ [ADRENO_FW_PM4] = "a530_pm4.fw",
+ [ADRENO_FW_PFP] = "a530_pfp.fw",
+ },
+ .gmem = (SZ_256K + SZ_16K),
+ /*
+ * Increase inactive period to 250 to avoid bouncing
+ * the GDSC which appears to make it grumpy
+ */
+ .inactive_period = 250,
+ .quirks = ADRENO_QUIRK_LMLOADKILL_DISABLE,
+ .init = a5xx_gpu_init,
+ .zapfw = "a512_zap.mdt",
+ }, {
+ .chip_ids = ADRENO_CHIP_IDS(
+ 0x05030002,
+ 0x05030004
+ ),
+ .family = ADRENO_5XX,
+ .revn = 530,
+ .fw = {
+ [ADRENO_FW_PM4] = "a530_pm4.fw",
+ [ADRENO_FW_PFP] = "a530_pfp.fw",
+ [ADRENO_FW_GPMU] = "a530v3_gpmu.fw2",
+ },
+ .gmem = SZ_1M,
+ /*
+ * Increase inactive period to 250 to avoid bouncing
+ * the GDSC which appears to make it grumpy
+ */
+ .inactive_period = 250,
+ .quirks = ADRENO_QUIRK_TWO_PASS_USE_WFI |
+ ADRENO_QUIRK_FAULT_DETECT_MASK,
+ .init = a5xx_gpu_init,
+ .zapfw = "a530_zap.mdt",
+ }, {
+ .chip_ids = ADRENO_CHIP_IDS(0x05040001),
+ .family = ADRENO_5XX,
+ .revn = 540,
+ .fw = {
+ [ADRENO_FW_PM4] = "a530_pm4.fw",
+ [ADRENO_FW_PFP] = "a530_pfp.fw",
+ [ADRENO_FW_GPMU] = "a540_gpmu.fw2",
+ },
+ .gmem = SZ_1M,
+ /*
+ * Increase inactive period to 250 to avoid bouncing
+ * the GDSC which appears to make it grumpy
+ */
+ .inactive_period = 250,
+ .quirks = ADRENO_QUIRK_LMLOADKILL_DISABLE,
+ .init = a5xx_gpu_init,
+ .zapfw = "a540_zap.mdt",
+ }
+};
+DECLARE_ADRENO_GPULIST(a5xx);
+
+MODULE_FIRMWARE("qcom/a530_pm4.fw");
+MODULE_FIRMWARE("qcom/a530_pfp.fw");
+MODULE_FIRMWARE("qcom/a530v3_gpmu.fw2");
+MODULE_FIRMWARE("qcom/a530_zap.mdt");
+MODULE_FIRMWARE("qcom/a530_zap.b00");
+MODULE_FIRMWARE("qcom/a530_zap.b01");
+MODULE_FIRMWARE("qcom/a530_zap.b02");
+MODULE_FIRMWARE("qcom/a540_gpmu.fw2");
diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
index c003f970189b..c0b5373e90d7 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
@@ -439,7 +439,8 @@ void a5xx_set_hwcg(struct msm_gpu *gpu, bool state)
const struct adreno_five_hwcg_regs *regs;
unsigned int i, sz;
- if (adreno_is_a506(adreno_gpu) || adreno_is_a508(adreno_gpu)) {
+ if (adreno_is_a505(adreno_gpu) || adreno_is_a506(adreno_gpu) ||
+ adreno_is_a508(adreno_gpu)) {
regs = a50x_hwcg;
sz = ARRAY_SIZE(a50x_hwcg);
} else if (adreno_is_a509(adreno_gpu) || adreno_is_a512(adreno_gpu)) {
@@ -483,7 +484,8 @@ static int a5xx_me_init(struct msm_gpu *gpu)
OUT_RING(ring, 0x00000000);
/* Specify workarounds for various microcode issues */
- if (adreno_is_a506(adreno_gpu) || adreno_is_a530(adreno_gpu)) {
+ if (adreno_is_a505(adreno_gpu) || adreno_is_a506(adreno_gpu) ||
+ adreno_is_a530(adreno_gpu)) {
/* Workaround for token end syncs
* Force a WFI after every direct-render 3D mode draw and every
* 2D mode 3 draw
@@ -752,10 +754,11 @@ static int a5xx_hw_init(struct msm_gpu *gpu)
0x00100000 + adreno_gpu->info->gmem - 1);
gpu_write(gpu, REG_A5XX_UCHE_GMEM_RANGE_MAX_HI, 0x00000000);
- if (adreno_is_a506(adreno_gpu) || adreno_is_a508(adreno_gpu) ||
- adreno_is_a510(adreno_gpu)) {
+ if (adreno_is_a505(adreno_gpu) || adreno_is_a506(adreno_gpu) ||
+ adreno_is_a508(adreno_gpu) || adreno_is_a510(adreno_gpu)) {
gpu_write(gpu, REG_A5XX_CP_MEQ_THRESHOLDS, 0x20);
- if (adreno_is_a506(adreno_gpu) || adreno_is_a508(adreno_gpu))
+ if (adreno_is_a505(adreno_gpu) || adreno_is_a506(adreno_gpu) ||
+ adreno_is_a508(adreno_gpu))
gpu_write(gpu, REG_A5XX_CP_MERCIU_SIZE, 0x400);
else
gpu_write(gpu, REG_A5XX_CP_MERCIU_SIZE, 0x20);
@@ -771,7 +774,8 @@ static int a5xx_hw_init(struct msm_gpu *gpu)
gpu_write(gpu, REG_A5XX_CP_ROQ_THRESHOLDS_1, 0x40201B16);
}
- if (adreno_is_a506(adreno_gpu) || adreno_is_a508(adreno_gpu))
+ if (adreno_is_a505(adreno_gpu) || adreno_is_a506(adreno_gpu) ||
+ adreno_is_a508(adreno_gpu))
gpu_write(gpu, REG_A5XX_PC_DBG_ECO_CNTL,
(0x100 << 11 | 0x100 << 22));
else if (adreno_is_a509(adreno_gpu) || adreno_is_a510(adreno_gpu) ||
@@ -789,8 +793,9 @@ static int a5xx_hw_init(struct msm_gpu *gpu)
* Disable the RB sampler datapath DP2 clock gating optimization
* for 1-SP GPUs, as it is enabled by default.
*/
- if (adreno_is_a506(adreno_gpu) || adreno_is_a508(adreno_gpu) ||
- adreno_is_a509(adreno_gpu) || adreno_is_a512(adreno_gpu))
+ if (adreno_is_a505(adreno_gpu) || adreno_is_a506(adreno_gpu) ||
+ adreno_is_a508(adreno_gpu) || adreno_is_a509(adreno_gpu) ||
+ adreno_is_a512(adreno_gpu))
gpu_rmw(gpu, REG_A5XX_RB_DBG_ECO_CNTL, 0, (1 << 9));
/* Disable UCHE global filter as SP can invalidate/flush independently */
@@ -1345,7 +1350,7 @@ static int a5xx_pm_resume(struct msm_gpu *gpu)
if (ret)
return ret;
- /* Adreno 506, 508, 509, 510, 512 needs manual RBBM sus/res control */
+ /* Adreno 505, 506, 508, 509, 510, 512 needs manual RBBM sus/res control */
if (!(adreno_is_a530(adreno_gpu) || adreno_is_a540(adreno_gpu))) {
/* Halt the sp_input_clk at HM level */
gpu_write(gpu, REG_A5XX_RBBM_CLOCK_CNTL, 0x00000055);
@@ -1388,9 +1393,9 @@ static int a5xx_pm_suspend(struct msm_gpu *gpu)
u32 mask = 0xf;
int i, ret;
- /* A506, A508, A510 have 3 XIN ports in VBIF */
- if (adreno_is_a506(adreno_gpu) || adreno_is_a508(adreno_gpu) ||
- adreno_is_a510(adreno_gpu))
+ /* A505, A506, A508, A510 have 3 XIN ports in VBIF */
+ if (adreno_is_a505(adreno_gpu) || adreno_is_a506(adreno_gpu) ||
+ adreno_is_a508(adreno_gpu) || adreno_is_a510(adreno_gpu))
mask = 0x7;
/* Clear the VBIF pipe before shutting down */
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_catalog.c b/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
new file mode 100644
index 000000000000..68ba9aed5506
--- /dev/null
+++ b/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
@@ -0,0 +1,1259 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2013-2014 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ *
+ * Copyright (c) 2014,2017 The Linux Foundation. All rights reserved.
+ */
+
+#include "adreno_gpu.h"
+#include "a6xx_gpu.h"
+#include "a6xx.xml.h"
+#include "a6xx_gmu.xml.h"
+
+static const struct adreno_reglist a612_hwcg[] = {
+ {REG_A6XX_RBBM_CLOCK_CNTL_SP0, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_SP0, 0x02222220},
+ {REG_A6XX_RBBM_CLOCK_DELAY_SP0, 0x00000081},
+ {REG_A6XX_RBBM_CLOCK_HYST_SP0, 0x0000f3cf},
+ {REG_A6XX_RBBM_CLOCK_CNTL_TP0, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL3_TP0, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL4_TP0, 0x00022222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_TP0, 0x11111111},
+ {REG_A6XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111},
+ {REG_A6XX_RBBM_CLOCK_DELAY3_TP0, 0x11111111},
+ {REG_A6XX_RBBM_CLOCK_DELAY4_TP0, 0x00011111},
+ {REG_A6XX_RBBM_CLOCK_HYST_TP0, 0x77777777},
+ {REG_A6XX_RBBM_CLOCK_HYST2_TP0, 0x77777777},
+ {REG_A6XX_RBBM_CLOCK_HYST3_TP0, 0x77777777},
+ {REG_A6XX_RBBM_CLOCK_HYST4_TP0, 0x00077777},
+ {REG_A6XX_RBBM_CLOCK_CNTL_RB0, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_RB0, 0x01202222},
+ {REG_A6XX_RBBM_CLOCK_CNTL_CCU0, 0x00002220},
+ {REG_A6XX_RBBM_CLOCK_HYST_RB_CCU0, 0x00040f00},
+ {REG_A6XX_RBBM_CLOCK_CNTL_RAC, 0x05522022},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_RAC, 0x00005555},
+ {REG_A6XX_RBBM_CLOCK_DELAY_RAC, 0x00000011},
+ {REG_A6XX_RBBM_CLOCK_HYST_RAC, 0x00445044},
+ {REG_A6XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222},
+ {REG_A6XX_RBBM_CLOCK_MODE_VFD, 0x00002222},
+ {REG_A6XX_RBBM_CLOCK_MODE_GPC, 0x02222222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_HLSQ_2, 0x00000002},
+ {REG_A6XX_RBBM_CLOCK_MODE_HLSQ, 0x00002222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00004000},
+ {REG_A6XX_RBBM_CLOCK_DELAY_VFD, 0x00002222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_GPC, 0x00000200},
+ {REG_A6XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_HYST_VFD, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_HYST_GPC, 0x04104004},
+ {REG_A6XX_RBBM_CLOCK_HYST_HLSQ, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_HYST_UCHE, 0x00000004},
+ {REG_A6XX_RBBM_CLOCK_DELAY_UCHE, 0x00000002},
+ {REG_A6XX_RBBM_ISDB_CNT, 0x00000182},
+ {REG_A6XX_RBBM_RAC_THRESHOLD_CNT, 0x00000000},
+ {REG_A6XX_RBBM_SP_HYST_CNT, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_CNTL_GMU_GX, 0x00000222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_GMU_GX, 0x00000111},
+ {REG_A6XX_RBBM_CLOCK_HYST_GMU_GX, 0x00000555},
+ {},
+};
+
+/* For a615 family (a615, a616, a618 and a619) */
+static const struct adreno_reglist a615_hwcg[] = {
+ {REG_A6XX_RBBM_CLOCK_CNTL_SP0, 0x02222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_SP0, 0x02222220},
+ {REG_A6XX_RBBM_CLOCK_DELAY_SP0, 0x00000080},
+ {REG_A6XX_RBBM_CLOCK_HYST_SP0, 0x0000F3CF},
+ {REG_A6XX_RBBM_CLOCK_CNTL_TP0, 0x02222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL_TP1, 0x02222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_TP1, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL3_TP0, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL3_TP1, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL4_TP0, 0x00022222},
+ {REG_A6XX_RBBM_CLOCK_CNTL4_TP1, 0x00022222},
+ {REG_A6XX_RBBM_CLOCK_HYST_TP0, 0x77777777},
+ {REG_A6XX_RBBM_CLOCK_HYST_TP1, 0x77777777},
+ {REG_A6XX_RBBM_CLOCK_HYST2_TP0, 0x77777777},
+ {REG_A6XX_RBBM_CLOCK_HYST2_TP1, 0x77777777},
+ {REG_A6XX_RBBM_CLOCK_HYST3_TP0, 0x77777777},
+ {REG_A6XX_RBBM_CLOCK_HYST3_TP1, 0x77777777},
+ {REG_A6XX_RBBM_CLOCK_HYST4_TP0, 0x00077777},
+ {REG_A6XX_RBBM_CLOCK_HYST4_TP1, 0x00077777},
+ {REG_A6XX_RBBM_CLOCK_DELAY_TP0, 0x11111111},
+ {REG_A6XX_RBBM_CLOCK_DELAY_TP1, 0x11111111},
+ {REG_A6XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111},
+ {REG_A6XX_RBBM_CLOCK_DELAY2_TP1, 0x11111111},
+ {REG_A6XX_RBBM_CLOCK_DELAY3_TP0, 0x11111111},
+ {REG_A6XX_RBBM_CLOCK_DELAY3_TP1, 0x11111111},
+ {REG_A6XX_RBBM_CLOCK_DELAY4_TP0, 0x00011111},
+ {REG_A6XX_RBBM_CLOCK_DELAY4_TP1, 0x00011111},
+ {REG_A6XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_UCHE, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL3_UCHE, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL4_UCHE, 0x00222222},
+ {REG_A6XX_RBBM_CLOCK_HYST_UCHE, 0x00000004},
+ {REG_A6XX_RBBM_CLOCK_DELAY_UCHE, 0x00000002},
+ {REG_A6XX_RBBM_CLOCK_CNTL_RB0, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_RB0, 0x00002222},
+ {REG_A6XX_RBBM_CLOCK_CNTL_CCU0, 0x00002020},
+ {REG_A6XX_RBBM_CLOCK_CNTL_CCU1, 0x00002220},
+ {REG_A6XX_RBBM_CLOCK_CNTL_CCU2, 0x00002220},
+ {REG_A6XX_RBBM_CLOCK_CNTL_CCU3, 0x00002220},
+ {REG_A6XX_RBBM_CLOCK_HYST_RB_CCU0, 0x00040F00},
+ {REG_A6XX_RBBM_CLOCK_HYST_RB_CCU1, 0x00040F00},
+ {REG_A6XX_RBBM_CLOCK_HYST_RB_CCU2, 0x00040F00},
+ {REG_A6XX_RBBM_CLOCK_HYST_RB_CCU3, 0x00040F00},
+ {REG_A6XX_RBBM_CLOCK_CNTL_RAC, 0x05022022},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_RAC, 0x00005555},
+ {REG_A6XX_RBBM_CLOCK_DELAY_RAC, 0x00000011},
+ {REG_A6XX_RBBM_CLOCK_HYST_RAC, 0x00445044},
+ {REG_A6XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222},
+ {REG_A6XX_RBBM_CLOCK_MODE_GPC, 0x00222222},
+ {REG_A6XX_RBBM_CLOCK_MODE_VFD, 0x00002222},
+ {REG_A6XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_HYST_GPC, 0x04104004},
+ {REG_A6XX_RBBM_CLOCK_HYST_VFD, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00004000},
+ {REG_A6XX_RBBM_CLOCK_DELAY_GPC, 0x00000200},
+ {REG_A6XX_RBBM_CLOCK_DELAY_VFD, 0x00002222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_HLSQ_2, 0x00000002},
+ {REG_A6XX_RBBM_CLOCK_MODE_HLSQ, 0x00002222},
+ {REG_A6XX_RBBM_CLOCK_CNTL_GMU_GX, 0x00000222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_GMU_GX, 0x00000111},
+ {REG_A6XX_RBBM_CLOCK_HYST_GMU_GX, 0x00000555},
+ {},
+};
+
+static const struct adreno_reglist a630_hwcg[] = {
+ {REG_A6XX_RBBM_CLOCK_CNTL_SP0, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL_SP1, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL_SP2, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL_SP3, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_SP0, 0x02022220},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_SP1, 0x02022220},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_SP2, 0x02022220},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_SP3, 0x02022220},
+ {REG_A6XX_RBBM_CLOCK_DELAY_SP0, 0x00000080},
+ {REG_A6XX_RBBM_CLOCK_DELAY_SP1, 0x00000080},
+ {REG_A6XX_RBBM_CLOCK_DELAY_SP2, 0x00000080},
+ {REG_A6XX_RBBM_CLOCK_DELAY_SP3, 0x00000080},
+ {REG_A6XX_RBBM_CLOCK_HYST_SP0, 0x0000f3cf},
+ {REG_A6XX_RBBM_CLOCK_HYST_SP1, 0x0000f3cf},
+ {REG_A6XX_RBBM_CLOCK_HYST_SP2, 0x0000f3cf},
+ {REG_A6XX_RBBM_CLOCK_HYST_SP3, 0x0000f3cf},
+ {REG_A6XX_RBBM_CLOCK_CNTL_TP0, 0x02222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL_TP1, 0x02222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL_TP2, 0x02222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL_TP3, 0x02222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_TP1, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_TP2, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_TP3, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL3_TP0, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL3_TP1, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL3_TP2, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL3_TP3, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL4_TP0, 0x00022222},
+ {REG_A6XX_RBBM_CLOCK_CNTL4_TP1, 0x00022222},
+ {REG_A6XX_RBBM_CLOCK_CNTL4_TP2, 0x00022222},
+ {REG_A6XX_RBBM_CLOCK_CNTL4_TP3, 0x00022222},
+ {REG_A6XX_RBBM_CLOCK_HYST_TP0, 0x77777777},
+ {REG_A6XX_RBBM_CLOCK_HYST_TP1, 0x77777777},
+ {REG_A6XX_RBBM_CLOCK_HYST_TP2, 0x77777777},
+ {REG_A6XX_RBBM_CLOCK_HYST_TP3, 0x77777777},
+ {REG_A6XX_RBBM_CLOCK_HYST2_TP0, 0x77777777},
+ {REG_A6XX_RBBM_CLOCK_HYST2_TP1, 0x77777777},
+ {REG_A6XX_RBBM_CLOCK_HYST2_TP2, 0x77777777},
+ {REG_A6XX_RBBM_CLOCK_HYST2_TP3, 0x77777777},
+ {REG_A6XX_RBBM_CLOCK_HYST3_TP0, 0x77777777},
+ {REG_A6XX_RBBM_CLOCK_HYST3_TP1, 0x77777777},
+ {REG_A6XX_RBBM_CLOCK_HYST3_TP2, 0x77777777},
+ {REG_A6XX_RBBM_CLOCK_HYST3_TP3, 0x77777777},
+ {REG_A6XX_RBBM_CLOCK_HYST4_TP0, 0x00077777},
+ {REG_A6XX_RBBM_CLOCK_HYST4_TP1, 0x00077777},
+ {REG_A6XX_RBBM_CLOCK_HYST4_TP2, 0x00077777},
+ {REG_A6XX_RBBM_CLOCK_HYST4_TP3, 0x00077777},
+ {REG_A6XX_RBBM_CLOCK_DELAY_TP0, 0x11111111},
+ {REG_A6XX_RBBM_CLOCK_DELAY_TP1, 0x11111111},
+ {REG_A6XX_RBBM_CLOCK_DELAY_TP2, 0x11111111},
+ {REG_A6XX_RBBM_CLOCK_DELAY_TP3, 0x11111111},
+ {REG_A6XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111},
+ {REG_A6XX_RBBM_CLOCK_DELAY2_TP1, 0x11111111},
+ {REG_A6XX_RBBM_CLOCK_DELAY2_TP2, 0x11111111},
+ {REG_A6XX_RBBM_CLOCK_DELAY2_TP3, 0x11111111},
+ {REG_A6XX_RBBM_CLOCK_DELAY3_TP0, 0x11111111},
+ {REG_A6XX_RBBM_CLOCK_DELAY3_TP1, 0x11111111},
+ {REG_A6XX_RBBM_CLOCK_DELAY3_TP2, 0x11111111},
+ {REG_A6XX_RBBM_CLOCK_DELAY3_TP3, 0x11111111},
+ {REG_A6XX_RBBM_CLOCK_DELAY4_TP0, 0x00011111},
+ {REG_A6XX_RBBM_CLOCK_DELAY4_TP1, 0x00011111},
+ {REG_A6XX_RBBM_CLOCK_DELAY4_TP2, 0x00011111},
+ {REG_A6XX_RBBM_CLOCK_DELAY4_TP3, 0x00011111},
+ {REG_A6XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_UCHE, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL3_UCHE, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL4_UCHE, 0x00222222},
+ {REG_A6XX_RBBM_CLOCK_HYST_UCHE, 0x00000004},
+ {REG_A6XX_RBBM_CLOCK_DELAY_UCHE, 0x00000002},
+ {REG_A6XX_RBBM_CLOCK_CNTL_RB0, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL_RB1, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL_RB2, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL_RB3, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_RB0, 0x00002222},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_RB1, 0x00002222},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_RB2, 0x00002222},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_RB3, 0x00002222},
+ {REG_A6XX_RBBM_CLOCK_CNTL_CCU0, 0x00002220},
+ {REG_A6XX_RBBM_CLOCK_CNTL_CCU1, 0x00002220},
+ {REG_A6XX_RBBM_CLOCK_CNTL_CCU2, 0x00002220},
+ {REG_A6XX_RBBM_CLOCK_CNTL_CCU3, 0x00002220},
+ {REG_A6XX_RBBM_CLOCK_HYST_RB_CCU0, 0x00040f00},
+ {REG_A6XX_RBBM_CLOCK_HYST_RB_CCU1, 0x00040f00},
+ {REG_A6XX_RBBM_CLOCK_HYST_RB_CCU2, 0x00040f00},
+ {REG_A6XX_RBBM_CLOCK_HYST_RB_CCU3, 0x00040f00},
+ {REG_A6XX_RBBM_CLOCK_CNTL_RAC, 0x05022022},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_RAC, 0x00005555},
+ {REG_A6XX_RBBM_CLOCK_DELAY_RAC, 0x00000011},
+ {REG_A6XX_RBBM_CLOCK_HYST_RAC, 0x00445044},
+ {REG_A6XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222},
+ {REG_A6XX_RBBM_CLOCK_MODE_GPC, 0x00222222},
+ {REG_A6XX_RBBM_CLOCK_MODE_VFD, 0x00002222},
+ {REG_A6XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_HYST_GPC, 0x04104004},
+ {REG_A6XX_RBBM_CLOCK_HYST_VFD, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00004000},
+ {REG_A6XX_RBBM_CLOCK_DELAY_GPC, 0x00000200},
+ {REG_A6XX_RBBM_CLOCK_DELAY_VFD, 0x00002222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_HLSQ_2, 0x00000002},
+ {REG_A6XX_RBBM_CLOCK_MODE_HLSQ, 0x00002222},
+ {REG_A6XX_RBBM_CLOCK_CNTL_GMU_GX, 0x00000222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_GMU_GX, 0x00000111},
+ {REG_A6XX_RBBM_CLOCK_HYST_GMU_GX, 0x00000555},
+ {},
+};
+
+static const struct adreno_reglist a640_hwcg[] = {
+ {REG_A6XX_RBBM_CLOCK_CNTL_SP0, 0x02222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_SP0, 0x02222220},
+ {REG_A6XX_RBBM_CLOCK_DELAY_SP0, 0x00000080},
+ {REG_A6XX_RBBM_CLOCK_HYST_SP0, 0x0000F3CF},
+ {REG_A6XX_RBBM_CLOCK_CNTL_TP0, 0x02222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL3_TP0, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL4_TP0, 0x00022222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_TP0, 0x11111111},
+ {REG_A6XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111},
+ {REG_A6XX_RBBM_CLOCK_DELAY3_TP0, 0x11111111},
+ {REG_A6XX_RBBM_CLOCK_DELAY4_TP0, 0x00011111},
+ {REG_A6XX_RBBM_CLOCK_HYST_TP0, 0x77777777},
+ {REG_A6XX_RBBM_CLOCK_HYST2_TP0, 0x77777777},
+ {REG_A6XX_RBBM_CLOCK_HYST3_TP0, 0x77777777},
+ {REG_A6XX_RBBM_CLOCK_HYST4_TP0, 0x00077777},
+ {REG_A6XX_RBBM_CLOCK_CNTL_RB0, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_RB0, 0x01002222},
+ {REG_A6XX_RBBM_CLOCK_CNTL_CCU0, 0x00002220},
+ {REG_A6XX_RBBM_CLOCK_HYST_RB_CCU0, 0x00040F00},
+ {REG_A6XX_RBBM_CLOCK_CNTL_RAC, 0x05222022},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_RAC, 0x00005555},
+ {REG_A6XX_RBBM_CLOCK_DELAY_RAC, 0x00000011},
+ {REG_A6XX_RBBM_CLOCK_HYST_RAC, 0x00445044},
+ {REG_A6XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222},
+ {REG_A6XX_RBBM_CLOCK_MODE_VFD, 0x00002222},
+ {REG_A6XX_RBBM_CLOCK_MODE_GPC, 0x00222222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_HLSQ_2, 0x00000002},
+ {REG_A6XX_RBBM_CLOCK_MODE_HLSQ, 0x00002222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00004000},
+ {REG_A6XX_RBBM_CLOCK_DELAY_VFD, 0x00002222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_GPC, 0x00000200},
+ {REG_A6XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_HYST_VFD, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_HYST_GPC, 0x04104004},
+ {REG_A6XX_RBBM_CLOCK_HYST_HLSQ, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_CNTL_TEX_FCHE, 0x00000222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_TEX_FCHE, 0x00000111},
+ {REG_A6XX_RBBM_CLOCK_HYST_TEX_FCHE, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_HYST_UCHE, 0x00000004},
+ {REG_A6XX_RBBM_CLOCK_DELAY_UCHE, 0x00000002},
+ {REG_A6XX_RBBM_ISDB_CNT, 0x00000182},
+ {REG_A6XX_RBBM_RAC_THRESHOLD_CNT, 0x00000000},
+ {REG_A6XX_RBBM_SP_HYST_CNT, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_CNTL_GMU_GX, 0x00000222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_GMU_GX, 0x00000111},
+ {REG_A6XX_RBBM_CLOCK_HYST_GMU_GX, 0x00000555},
+ {},
+};
+
+static const struct adreno_reglist a650_hwcg[] = {
+ {REG_A6XX_RBBM_CLOCK_CNTL_SP0, 0x02222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_SP0, 0x02222220},
+ {REG_A6XX_RBBM_CLOCK_DELAY_SP0, 0x00000080},
+ {REG_A6XX_RBBM_CLOCK_HYST_SP0, 0x0000F3CF},
+ {REG_A6XX_RBBM_CLOCK_CNTL_TP0, 0x02222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL3_TP0, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL4_TP0, 0x00022222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_TP0, 0x11111111},
+ {REG_A6XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111},
+ {REG_A6XX_RBBM_CLOCK_DELAY3_TP0, 0x11111111},
+ {REG_A6XX_RBBM_CLOCK_DELAY4_TP0, 0x00011111},
+ {REG_A6XX_RBBM_CLOCK_HYST_TP0, 0x77777777},
+ {REG_A6XX_RBBM_CLOCK_HYST2_TP0, 0x77777777},
+ {REG_A6XX_RBBM_CLOCK_HYST3_TP0, 0x77777777},
+ {REG_A6XX_RBBM_CLOCK_HYST4_TP0, 0x00077777},
+ {REG_A6XX_RBBM_CLOCK_CNTL_RB0, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_RB0, 0x01002222},
+ {REG_A6XX_RBBM_CLOCK_CNTL_CCU0, 0x00002220},
+ {REG_A6XX_RBBM_CLOCK_HYST_RB_CCU0, 0x00040F00},
+ {REG_A6XX_RBBM_CLOCK_CNTL_RAC, 0x25222022},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_RAC, 0x00005555},
+ {REG_A6XX_RBBM_CLOCK_DELAY_RAC, 0x00000011},
+ {REG_A6XX_RBBM_CLOCK_HYST_RAC, 0x00445044},
+ {REG_A6XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222},
+ {REG_A6XX_RBBM_CLOCK_MODE_VFD, 0x00002222},
+ {REG_A6XX_RBBM_CLOCK_MODE_GPC, 0x00222222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_HLSQ_2, 0x00000002},
+ {REG_A6XX_RBBM_CLOCK_MODE_HLSQ, 0x00002222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00004000},
+ {REG_A6XX_RBBM_CLOCK_DELAY_VFD, 0x00002222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_GPC, 0x00000200},
+ {REG_A6XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_HYST_VFD, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_HYST_GPC, 0x04104004},
+ {REG_A6XX_RBBM_CLOCK_HYST_HLSQ, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_CNTL_TEX_FCHE, 0x00000222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_TEX_FCHE, 0x00000111},
+ {REG_A6XX_RBBM_CLOCK_HYST_TEX_FCHE, 0x00000777},
+ {REG_A6XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_HYST_UCHE, 0x00000004},
+ {REG_A6XX_RBBM_CLOCK_DELAY_UCHE, 0x00000002},
+ {REG_A6XX_RBBM_ISDB_CNT, 0x00000182},
+ {REG_A6XX_RBBM_RAC_THRESHOLD_CNT, 0x00000000},
+ {REG_A6XX_RBBM_SP_HYST_CNT, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_CNTL_GMU_GX, 0x00000222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_GMU_GX, 0x00000111},
+ {REG_A6XX_RBBM_CLOCK_HYST_GMU_GX, 0x00000555},
+ {},
+};
+
+static const struct adreno_reglist a660_hwcg[] = {
+ {REG_A6XX_RBBM_CLOCK_CNTL_SP0, 0x02222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_SP0, 0x02222220},
+ {REG_A6XX_RBBM_CLOCK_DELAY_SP0, 0x00000080},
+ {REG_A6XX_RBBM_CLOCK_HYST_SP0, 0x0000F3CF},
+ {REG_A6XX_RBBM_CLOCK_CNTL_TP0, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL3_TP0, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL4_TP0, 0x00022222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_TP0, 0x11111111},
+ {REG_A6XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111},
+ {REG_A6XX_RBBM_CLOCK_DELAY3_TP0, 0x11111111},
+ {REG_A6XX_RBBM_CLOCK_DELAY4_TP0, 0x00011111},
+ {REG_A6XX_RBBM_CLOCK_HYST_TP0, 0x77777777},
+ {REG_A6XX_RBBM_CLOCK_HYST2_TP0, 0x77777777},
+ {REG_A6XX_RBBM_CLOCK_HYST3_TP0, 0x77777777},
+ {REG_A6XX_RBBM_CLOCK_HYST4_TP0, 0x00077777},
+ {REG_A6XX_RBBM_CLOCK_CNTL_RB0, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_RB0, 0x01002222},
+ {REG_A6XX_RBBM_CLOCK_CNTL_CCU0, 0x00002220},
+ {REG_A6XX_RBBM_CLOCK_HYST_RB_CCU0, 0x00040F00},
+ {REG_A6XX_RBBM_CLOCK_CNTL_RAC, 0x25222022},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_RAC, 0x00005555},
+ {REG_A6XX_RBBM_CLOCK_DELAY_RAC, 0x00000011},
+ {REG_A6XX_RBBM_CLOCK_HYST_RAC, 0x00445044},
+ {REG_A6XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222},
+ {REG_A6XX_RBBM_CLOCK_MODE_VFD, 0x00002222},
+ {REG_A6XX_RBBM_CLOCK_MODE_GPC, 0x00222222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_HLSQ_2, 0x00000002},
+ {REG_A6XX_RBBM_CLOCK_MODE_HLSQ, 0x00002222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00004000},
+ {REG_A6XX_RBBM_CLOCK_DELAY_VFD, 0x00002222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_GPC, 0x00000200},
+ {REG_A6XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_HYST_VFD, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_HYST_GPC, 0x04104004},
+ {REG_A6XX_RBBM_CLOCK_HYST_HLSQ, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_CNTL_TEX_FCHE, 0x00000222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_TEX_FCHE, 0x00000111},
+ {REG_A6XX_RBBM_CLOCK_HYST_TEX_FCHE, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_HYST_UCHE, 0x00000004},
+ {REG_A6XX_RBBM_CLOCK_DELAY_UCHE, 0x00000002},
+ {REG_A6XX_RBBM_ISDB_CNT, 0x00000182},
+ {REG_A6XX_RBBM_RAC_THRESHOLD_CNT, 0x00000000},
+ {REG_A6XX_RBBM_SP_HYST_CNT, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_CNTL_GMU_GX, 0x00000222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_GMU_GX, 0x00000111},
+ {REG_A6XX_RBBM_CLOCK_HYST_GMU_GX, 0x00000555},
+ {},
+};
+
+static const struct adreno_reglist a690_hwcg[] = {
+ {REG_A6XX_RBBM_CLOCK_CNTL_SP0, 0x02222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_SP0, 0x02222220},
+ {REG_A6XX_RBBM_CLOCK_DELAY_SP0, 0x00000080},
+ {REG_A6XX_RBBM_CLOCK_HYST_SP0, 0x0000F3CF},
+ {REG_A6XX_RBBM_CLOCK_CNTL_TP0, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL3_TP0, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL4_TP0, 0x00022222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_TP0, 0x11111111},
+ {REG_A6XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111},
+ {REG_A6XX_RBBM_CLOCK_DELAY3_TP0, 0x11111111},
+ {REG_A6XX_RBBM_CLOCK_DELAY4_TP0, 0x00011111},
+ {REG_A6XX_RBBM_CLOCK_HYST_TP0, 0x77777777},
+ {REG_A6XX_RBBM_CLOCK_HYST2_TP0, 0x77777777},
+ {REG_A6XX_RBBM_CLOCK_HYST3_TP0, 0x77777777},
+ {REG_A6XX_RBBM_CLOCK_HYST4_TP0, 0x00077777},
+ {REG_A6XX_RBBM_CLOCK_CNTL_RB0, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_RB0, 0x01002222},
+ {REG_A6XX_RBBM_CLOCK_CNTL_CCU0, 0x00002220},
+ {REG_A6XX_RBBM_CLOCK_HYST_RB_CCU0, 0x00040F00},
+ {REG_A6XX_RBBM_CLOCK_CNTL_RAC, 0x25222022},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_RAC, 0x00005555},
+ {REG_A6XX_RBBM_CLOCK_DELAY_RAC, 0x00000011},
+ {REG_A6XX_RBBM_CLOCK_HYST_RAC, 0x00445044},
+ {REG_A6XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222},
+ {REG_A6XX_RBBM_CLOCK_MODE_VFD, 0x00002222},
+ {REG_A6XX_RBBM_CLOCK_MODE_GPC, 0x00222222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_HLSQ_2, 0x00000002},
+ {REG_A6XX_RBBM_CLOCK_MODE_HLSQ, 0x00002222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00004000},
+ {REG_A6XX_RBBM_CLOCK_DELAY_VFD, 0x00002222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_GPC, 0x00000200},
+ {REG_A6XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_HYST_VFD, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_HYST_GPC, 0x04104004},
+ {REG_A6XX_RBBM_CLOCK_HYST_HLSQ, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_CNTL_TEX_FCHE, 0x00000222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_TEX_FCHE, 0x00000111},
+ {REG_A6XX_RBBM_CLOCK_HYST_TEX_FCHE, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_HYST_UCHE, 0x00000004},
+ {REG_A6XX_RBBM_CLOCK_DELAY_UCHE, 0x00000002},
+ {REG_A6XX_RBBM_CLOCK_CNTL, 0x8AA8AA82},
+ {REG_A6XX_RBBM_ISDB_CNT, 0x00000182},
+ {REG_A6XX_RBBM_RAC_THRESHOLD_CNT, 0x00000000},
+ {REG_A6XX_RBBM_SP_HYST_CNT, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_CNTL_GMU_GX, 0x00000222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_GMU_GX, 0x00000111},
+ {REG_A6XX_RBBM_CLOCK_HYST_GMU_GX, 0x00000555},
+ {REG_A6XX_GPU_GMU_AO_GMU_CGC_MODE_CNTL, 0x20200},
+ {REG_A6XX_GPU_GMU_AO_GMU_CGC_DELAY_CNTL, 0x10111},
+ {REG_A6XX_GPU_GMU_AO_GMU_CGC_HYST_CNTL, 0x5555},
+ {}
+};
+
+/* For a615, a616, a618, a619, a630, a640 and a680 */
+static const u32 a630_protect_regs[] = {
+ A6XX_PROTECT_RDONLY(0x00000, 0x04ff),
+ A6XX_PROTECT_RDONLY(0x00501, 0x0005),
+ A6XX_PROTECT_RDONLY(0x0050b, 0x02f4),
+ A6XX_PROTECT_NORDWR(0x0050e, 0x0000),
+ A6XX_PROTECT_NORDWR(0x00510, 0x0000),
+ A6XX_PROTECT_NORDWR(0x00534, 0x0000),
+ A6XX_PROTECT_NORDWR(0x00800, 0x0082),
+ A6XX_PROTECT_NORDWR(0x008a0, 0x0008),
+ A6XX_PROTECT_NORDWR(0x008ab, 0x0024),
+ A6XX_PROTECT_RDONLY(0x008de, 0x00ae),
+ A6XX_PROTECT_NORDWR(0x00900, 0x004d),
+ A6XX_PROTECT_NORDWR(0x0098d, 0x0272),
+ A6XX_PROTECT_NORDWR(0x00e00, 0x0001),
+ A6XX_PROTECT_NORDWR(0x00e03, 0x000c),
+ A6XX_PROTECT_NORDWR(0x03c00, 0x00c3),
+ A6XX_PROTECT_RDONLY(0x03cc4, 0x1fff),
+ A6XX_PROTECT_NORDWR(0x08630, 0x01cf),
+ A6XX_PROTECT_NORDWR(0x08e00, 0x0000),
+ A6XX_PROTECT_NORDWR(0x08e08, 0x0000),
+ A6XX_PROTECT_NORDWR(0x08e50, 0x001f),
+ A6XX_PROTECT_NORDWR(0x09624, 0x01db),
+ A6XX_PROTECT_NORDWR(0x09e70, 0x0001),
+ A6XX_PROTECT_NORDWR(0x09e78, 0x0187),
+ A6XX_PROTECT_NORDWR(0x0a630, 0x01cf),
+ A6XX_PROTECT_NORDWR(0x0ae02, 0x0000),
+ A6XX_PROTECT_NORDWR(0x0ae50, 0x032f),
+ A6XX_PROTECT_NORDWR(0x0b604, 0x0000),
+ A6XX_PROTECT_NORDWR(0x0be02, 0x0001),
+ A6XX_PROTECT_NORDWR(0x0be20, 0x17df),
+ A6XX_PROTECT_NORDWR(0x0f000, 0x0bff),
+ A6XX_PROTECT_RDONLY(0x0fc00, 0x1fff),
+ A6XX_PROTECT_NORDWR(0x11c00, 0x0000), /* note: infinite range */
+};
+DECLARE_ADRENO_PROTECT(a630_protect, 32);
+
+/* These are for a620 and a650 */
+static const u32 a650_protect_regs[] = {
+ A6XX_PROTECT_RDONLY(0x00000, 0x04ff),
+ A6XX_PROTECT_RDONLY(0x00501, 0x0005),
+ A6XX_PROTECT_RDONLY(0x0050b, 0x02f4),
+ A6XX_PROTECT_NORDWR(0x0050e, 0x0000),
+ A6XX_PROTECT_NORDWR(0x00510, 0x0000),
+ A6XX_PROTECT_NORDWR(0x00534, 0x0000),
+ A6XX_PROTECT_NORDWR(0x00800, 0x0082),
+ A6XX_PROTECT_NORDWR(0x008a0, 0x0008),
+ A6XX_PROTECT_NORDWR(0x008ab, 0x0024),
+ A6XX_PROTECT_RDONLY(0x008de, 0x00ae),
+ A6XX_PROTECT_NORDWR(0x00900, 0x004d),
+ A6XX_PROTECT_NORDWR(0x0098d, 0x0272),
+ A6XX_PROTECT_NORDWR(0x00e00, 0x0001),
+ A6XX_PROTECT_NORDWR(0x00e03, 0x000c),
+ A6XX_PROTECT_NORDWR(0x03c00, 0x00c3),
+ A6XX_PROTECT_RDONLY(0x03cc4, 0x1fff),
+ A6XX_PROTECT_NORDWR(0x08630, 0x01cf),
+ A6XX_PROTECT_NORDWR(0x08e00, 0x0000),
+ A6XX_PROTECT_NORDWR(0x08e08, 0x0000),
+ A6XX_PROTECT_NORDWR(0x08e50, 0x001f),
+ A6XX_PROTECT_NORDWR(0x08e80, 0x027f),
+ A6XX_PROTECT_NORDWR(0x09624, 0x01db),
+ A6XX_PROTECT_NORDWR(0x09e60, 0x0011),
+ A6XX_PROTECT_NORDWR(0x09e78, 0x0187),
+ A6XX_PROTECT_NORDWR(0x0a630, 0x01cf),
+ A6XX_PROTECT_NORDWR(0x0ae02, 0x0000),
+ A6XX_PROTECT_NORDWR(0x0ae50, 0x032f),
+ A6XX_PROTECT_NORDWR(0x0b604, 0x0000),
+ A6XX_PROTECT_NORDWR(0x0b608, 0x0007),
+ A6XX_PROTECT_NORDWR(0x0be02, 0x0001),
+ A6XX_PROTECT_NORDWR(0x0be20, 0x17df),
+ A6XX_PROTECT_NORDWR(0x0f000, 0x0bff),
+ A6XX_PROTECT_RDONLY(0x0fc00, 0x1fff),
+ A6XX_PROTECT_NORDWR(0x18400, 0x1fff),
+ A6XX_PROTECT_NORDWR(0x1a800, 0x1fff),
+ A6XX_PROTECT_NORDWR(0x1f400, 0x0443),
+ A6XX_PROTECT_RDONLY(0x1f844, 0x007b),
+ A6XX_PROTECT_NORDWR(0x1f887, 0x001b),
+ A6XX_PROTECT_NORDWR(0x1f8c0, 0x0000), /* note: infinite range */
+};
+DECLARE_ADRENO_PROTECT(a650_protect, 48);
+
+/* These are for a635 and a660 */
+static const u32 a660_protect_regs[] = {
+ A6XX_PROTECT_RDONLY(0x00000, 0x04ff),
+ A6XX_PROTECT_RDONLY(0x00501, 0x0005),
+ A6XX_PROTECT_RDONLY(0x0050b, 0x02f4),
+ A6XX_PROTECT_NORDWR(0x0050e, 0x0000),
+ A6XX_PROTECT_NORDWR(0x00510, 0x0000),
+ A6XX_PROTECT_NORDWR(0x00534, 0x0000),
+ A6XX_PROTECT_NORDWR(0x00800, 0x0082),
+ A6XX_PROTECT_NORDWR(0x008a0, 0x0008),
+ A6XX_PROTECT_NORDWR(0x008ab, 0x0024),
+ A6XX_PROTECT_RDONLY(0x008de, 0x00ae),
+ A6XX_PROTECT_NORDWR(0x00900, 0x004d),
+ A6XX_PROTECT_NORDWR(0x0098d, 0x0272),
+ A6XX_PROTECT_NORDWR(0x00e00, 0x0001),
+ A6XX_PROTECT_NORDWR(0x00e03, 0x000c),
+ A6XX_PROTECT_NORDWR(0x03c00, 0x00c3),
+ A6XX_PROTECT_RDONLY(0x03cc4, 0x1fff),
+ A6XX_PROTECT_NORDWR(0x08630, 0x01cf),
+ A6XX_PROTECT_NORDWR(0x08e00, 0x0000),
+ A6XX_PROTECT_NORDWR(0x08e08, 0x0000),
+ A6XX_PROTECT_NORDWR(0x08e50, 0x001f),
+ A6XX_PROTECT_NORDWR(0x08e80, 0x027f),
+ A6XX_PROTECT_NORDWR(0x09624, 0x01db),
+ A6XX_PROTECT_NORDWR(0x09e60, 0x0011),
+ A6XX_PROTECT_NORDWR(0x09e78, 0x0187),
+ A6XX_PROTECT_NORDWR(0x0a630, 0x01cf),
+ A6XX_PROTECT_NORDWR(0x0ae02, 0x0000),
+ A6XX_PROTECT_NORDWR(0x0ae50, 0x012f),
+ A6XX_PROTECT_NORDWR(0x0b604, 0x0000),
+ A6XX_PROTECT_NORDWR(0x0b608, 0x0006),
+ A6XX_PROTECT_NORDWR(0x0be02, 0x0001),
+ A6XX_PROTECT_NORDWR(0x0be20, 0x015f),
+ A6XX_PROTECT_NORDWR(0x0d000, 0x05ff),
+ A6XX_PROTECT_NORDWR(0x0f000, 0x0bff),
+ A6XX_PROTECT_RDONLY(0x0fc00, 0x1fff),
+ A6XX_PROTECT_NORDWR(0x18400, 0x1fff),
+ A6XX_PROTECT_NORDWR(0x1a400, 0x1fff),
+ A6XX_PROTECT_NORDWR(0x1f400, 0x0443),
+ A6XX_PROTECT_RDONLY(0x1f844, 0x007b),
+ A6XX_PROTECT_NORDWR(0x1f860, 0x0000),
+ A6XX_PROTECT_NORDWR(0x1f887, 0x001b),
+ A6XX_PROTECT_NORDWR(0x1f8c0, 0x0000), /* note: infinite range */
+};
+DECLARE_ADRENO_PROTECT(a660_protect, 48);
+
+/* These are for a690 */
+static const u32 a690_protect_regs[] = {
+ A6XX_PROTECT_RDONLY(0x00000, 0x004ff),
+ A6XX_PROTECT_RDONLY(0x00501, 0x00001),
+ A6XX_PROTECT_RDONLY(0x0050b, 0x002f4),
+ A6XX_PROTECT_NORDWR(0x0050e, 0x00000),
+ A6XX_PROTECT_NORDWR(0x00510, 0x00000),
+ A6XX_PROTECT_NORDWR(0x00534, 0x00000),
+ A6XX_PROTECT_NORDWR(0x00800, 0x00082),
+ A6XX_PROTECT_NORDWR(0x008a0, 0x00008),
+ A6XX_PROTECT_NORDWR(0x008ab, 0x00024),
+ A6XX_PROTECT_RDONLY(0x008de, 0x000ae),
+ A6XX_PROTECT_NORDWR(0x00900, 0x0004d),
+ A6XX_PROTECT_NORDWR(0x0098d, 0x00272),
+ A6XX_PROTECT_NORDWR(0x00e00, 0x00001),
+ A6XX_PROTECT_NORDWR(0x00e03, 0x0000c),
+ A6XX_PROTECT_NORDWR(0x03c00, 0x000c3),
+ A6XX_PROTECT_RDONLY(0x03cc4, 0x01fff),
+ A6XX_PROTECT_NORDWR(0x08630, 0x001cf),
+ A6XX_PROTECT_NORDWR(0x08e00, 0x00000),
+ A6XX_PROTECT_NORDWR(0x08e08, 0x00007),
+ A6XX_PROTECT_NORDWR(0x08e50, 0x0001f),
+ A6XX_PROTECT_NORDWR(0x08e80, 0x0027f),
+ A6XX_PROTECT_NORDWR(0x09624, 0x001db),
+ A6XX_PROTECT_NORDWR(0x09e60, 0x00011),
+ A6XX_PROTECT_NORDWR(0x09e78, 0x00187),
+ A6XX_PROTECT_NORDWR(0x0a630, 0x001cf),
+ A6XX_PROTECT_NORDWR(0x0ae02, 0x00000),
+ A6XX_PROTECT_NORDWR(0x0ae50, 0x0012f),
+ A6XX_PROTECT_NORDWR(0x0b604, 0x00000),
+ A6XX_PROTECT_NORDWR(0x0b608, 0x00006),
+ A6XX_PROTECT_NORDWR(0x0be02, 0x00001),
+ A6XX_PROTECT_NORDWR(0x0be20, 0x0015f),
+ A6XX_PROTECT_NORDWR(0x0d000, 0x005ff),
+ A6XX_PROTECT_NORDWR(0x0f000, 0x00bff),
+ A6XX_PROTECT_RDONLY(0x0fc00, 0x01fff),
+ A6XX_PROTECT_NORDWR(0x11c00, 0x00000), /*note: infiite range */
+};
+DECLARE_ADRENO_PROTECT(a690_protect, 48);
+
+static const struct adreno_info a6xx_gpus[] = {
+ {
+ .chip_ids = ADRENO_CHIP_IDS(0x06010000),
+ .family = ADRENO_6XX_GEN1,
+ .revn = 610,
+ .fw = {
+ [ADRENO_FW_SQE] = "a630_sqe.fw",
+ },
+ .gmem = (SZ_128K + SZ_4K),
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
+ .init = a6xx_gpu_init,
+ .zapfw = "a610_zap.mdt",
+ .a6xx = &(const struct a6xx_info) {
+ .hwcg = a612_hwcg,
+ .protect = &a630_protect,
+ },
+ /*
+ * There are (at least) three SoCs implementing A610: SM6125
+ * (trinket), SM6115 (bengal) and SM6225 (khaje). Trinket does
+ * not have speedbinning, as only a single SKU exists and we
+ * don't support khaje upstream yet. Hence, this matching
+ * table is only valid for bengal.
+ */
+ .speedbins = ADRENO_SPEEDBINS(
+ { 0, 0 },
+ { 206, 1 },
+ { 200, 2 },
+ { 157, 3 },
+ { 127, 4 },
+ ),
+ }, {
+ .machine = "qcom,sm7150",
+ .chip_ids = ADRENO_CHIP_IDS(0x06010800),
+ .family = ADRENO_6XX_GEN1,
+ .fw = {
+ [ADRENO_FW_SQE] = "a630_sqe.fw",
+ [ADRENO_FW_GMU] = "a630_gmu.bin",
+ },
+ .gmem = SZ_512K,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
+ .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT,
+ .init = a6xx_gpu_init,
+ .zapfw = "a615_zap.mbn",
+ .a6xx = &(const struct a6xx_info) {
+ .hwcg = a615_hwcg,
+ .protect = &a630_protect,
+ },
+ .speedbins = ADRENO_SPEEDBINS(
+ { 0, 0 },
+ { 128, 1 },
+ { 146, 2 },
+ { 167, 3 },
+ { 172, 4 },
+ ),
+ }, {
+ .chip_ids = ADRENO_CHIP_IDS(0x06010800),
+ .family = ADRENO_6XX_GEN1,
+ .revn = 618,
+ .fw = {
+ [ADRENO_FW_SQE] = "a630_sqe.fw",
+ [ADRENO_FW_GMU] = "a630_gmu.bin",
+ },
+ .gmem = SZ_512K,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
+ .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT,
+ .init = a6xx_gpu_init,
+ .a6xx = &(const struct a6xx_info) {
+ .protect = &a630_protect,
+ },
+ .speedbins = ADRENO_SPEEDBINS(
+ { 0, 0 },
+ { 169, 1 },
+ { 174, 2 },
+ ),
+ }, {
+ .machine = "qcom,sm4350",
+ .chip_ids = ADRENO_CHIP_IDS(0x06010900),
+ .family = ADRENO_6XX_GEN1,
+ .revn = 619,
+ .fw = {
+ [ADRENO_FW_SQE] = "a630_sqe.fw",
+ [ADRENO_FW_GMU] = "a619_gmu.bin",
+ },
+ .gmem = SZ_512K,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
+ .init = a6xx_gpu_init,
+ .zapfw = "a615_zap.mdt",
+ .a6xx = &(const struct a6xx_info) {
+ .hwcg = a615_hwcg,
+ .protect = &a630_protect,
+ },
+ .speedbins = ADRENO_SPEEDBINS(
+ { 0, 0 },
+ { 138, 1 },
+ { 92, 2 },
+ ),
+ }, {
+ .machine = "qcom,sm6375",
+ .chip_ids = ADRENO_CHIP_IDS(0x06010901),
+ .family = ADRENO_6XX_GEN1,
+ .revn = 619,
+ .fw = {
+ [ADRENO_FW_SQE] = "a630_sqe.fw",
+ [ADRENO_FW_GMU] = "a619_gmu.bin",
+ },
+ .gmem = SZ_512K,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
+ .init = a6xx_gpu_init,
+ .zapfw = "a615_zap.mdt",
+ .a6xx = &(const struct a6xx_info) {
+ .hwcg = a615_hwcg,
+ .protect = &a630_protect,
+ },
+ .speedbins = ADRENO_SPEEDBINS(
+ { 0, 0 },
+ { 190, 1 },
+ { 177, 2 },
+ ),
+ }, {
+ .chip_ids = ADRENO_CHIP_IDS(0x06010900),
+ .family = ADRENO_6XX_GEN1,
+ .revn = 619,
+ .fw = {
+ [ADRENO_FW_SQE] = "a630_sqe.fw",
+ [ADRENO_FW_GMU] = "a619_gmu.bin",
+ },
+ .gmem = SZ_512K,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
+ .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT,
+ .init = a6xx_gpu_init,
+ .zapfw = "a615_zap.mdt",
+ .a6xx = &(const struct a6xx_info) {
+ .hwcg = a615_hwcg,
+ .protect = &a630_protect,
+ },
+ .speedbins = ADRENO_SPEEDBINS(
+ { 0, 0 },
+ { 120, 4 },
+ { 138, 3 },
+ { 169, 2 },
+ { 180, 1 },
+ ),
+ }, {
+ .chip_ids = ADRENO_CHIP_IDS(
+ 0x06030001,
+ 0x06030002
+ ),
+ .family = ADRENO_6XX_GEN1,
+ .revn = 630,
+ .fw = {
+ [ADRENO_FW_SQE] = "a630_sqe.fw",
+ [ADRENO_FW_GMU] = "a630_gmu.bin",
+ },
+ .gmem = SZ_1M,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
+ .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT,
+ .init = a6xx_gpu_init,
+ .zapfw = "a630_zap.mdt",
+ .a6xx = &(const struct a6xx_info) {
+ .hwcg = a630_hwcg,
+ .protect = &a630_protect,
+ },
+ }, {
+ .chip_ids = ADRENO_CHIP_IDS(0x06040001),
+ .family = ADRENO_6XX_GEN2,
+ .revn = 640,
+ .fw = {
+ [ADRENO_FW_SQE] = "a630_sqe.fw",
+ [ADRENO_FW_GMU] = "a640_gmu.bin",
+ },
+ .gmem = SZ_1M,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
+ .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT,
+ .init = a6xx_gpu_init,
+ .zapfw = "a640_zap.mdt",
+ .a6xx = &(const struct a6xx_info) {
+ .hwcg = a640_hwcg,
+ .protect = &a630_protect,
+ },
+ .speedbins = ADRENO_SPEEDBINS(
+ { 0, 0 },
+ { 1, 1 },
+ ),
+ }, {
+ .chip_ids = ADRENO_CHIP_IDS(0x06050002),
+ .family = ADRENO_6XX_GEN3,
+ .revn = 650,
+ .fw = {
+ [ADRENO_FW_SQE] = "a650_sqe.fw",
+ [ADRENO_FW_GMU] = "a650_gmu.bin",
+ },
+ .gmem = SZ_1M + SZ_128K,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
+ .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT |
+ ADRENO_QUIRK_HAS_HW_APRIV,
+ .init = a6xx_gpu_init,
+ .zapfw = "a650_zap.mdt",
+ .a6xx = &(const struct a6xx_info) {
+ .hwcg = a650_hwcg,
+ .protect = &a650_protect,
+ },
+ .address_space_size = SZ_16G,
+ .speedbins = ADRENO_SPEEDBINS(
+ { 0, 0 },
+ { 1, 1 },
+ { 2, 3 }, /* Yep, 2 and 3 are swapped! :/ */
+ { 3, 2 },
+ ),
+ }, {
+ .chip_ids = ADRENO_CHIP_IDS(0x06060001),
+ .family = ADRENO_6XX_GEN4,
+ .revn = 660,
+ .fw = {
+ [ADRENO_FW_SQE] = "a660_sqe.fw",
+ [ADRENO_FW_GMU] = "a660_gmu.bin",
+ },
+ .gmem = SZ_1M + SZ_512K,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
+ .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT |
+ ADRENO_QUIRK_HAS_HW_APRIV,
+ .init = a6xx_gpu_init,
+ .zapfw = "a660_zap.mdt",
+ .a6xx = &(const struct a6xx_info) {
+ .hwcg = a660_hwcg,
+ .protect = &a660_protect,
+ },
+ .address_space_size = SZ_16G,
+ }, {
+ .chip_ids = ADRENO_CHIP_IDS(0x06030500),
+ .family = ADRENO_6XX_GEN4,
+ .fw = {
+ [ADRENO_FW_SQE] = "a660_sqe.fw",
+ [ADRENO_FW_GMU] = "a660_gmu.bin",
+ },
+ .gmem = SZ_512K,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
+ .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT |
+ ADRENO_QUIRK_HAS_HW_APRIV,
+ .init = a6xx_gpu_init,
+ .zapfw = "a660_zap.mbn",
+ .a6xx = &(const struct a6xx_info) {
+ .hwcg = a660_hwcg,
+ .protect = &a660_protect,
+ },
+ .address_space_size = SZ_16G,
+ .speedbins = ADRENO_SPEEDBINS(
+ { 0, 0 },
+ { 117, 0 },
+ { 172, 2 }, /* Called speedbin 1 downstream, but let's not break things! */
+ { 190, 1 },
+ ),
+ }, {
+ .chip_ids = ADRENO_CHIP_IDS(0x06080001),
+ .family = ADRENO_6XX_GEN2,
+ .revn = 680,
+ .fw = {
+ [ADRENO_FW_SQE] = "a630_sqe.fw",
+ [ADRENO_FW_GMU] = "a640_gmu.bin",
+ },
+ .gmem = SZ_2M,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
+ .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT,
+ .init = a6xx_gpu_init,
+ .zapfw = "a640_zap.mdt",
+ .a6xx = &(const struct a6xx_info) {
+ .hwcg = a640_hwcg,
+ .protect = &a630_protect,
+ },
+ }, {
+ .chip_ids = ADRENO_CHIP_IDS(0x06090000),
+ .family = ADRENO_6XX_GEN4,
+ .fw = {
+ [ADRENO_FW_SQE] = "a660_sqe.fw",
+ [ADRENO_FW_GMU] = "a660_gmu.bin",
+ },
+ .gmem = SZ_4M,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
+ .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT |
+ ADRENO_QUIRK_HAS_HW_APRIV,
+ .init = a6xx_gpu_init,
+ .zapfw = "a690_zap.mdt",
+ .a6xx = &(const struct a6xx_info) {
+ .hwcg = a690_hwcg,
+ .protect = &a690_protect,
+ },
+ .address_space_size = SZ_16G,
+ }
+};
+DECLARE_ADRENO_GPULIST(a6xx);
+
+MODULE_FIRMWARE("qcom/a615_zap.mbn");
+MODULE_FIRMWARE("qcom/a619_gmu.bin");
+MODULE_FIRMWARE("qcom/a630_sqe.fw");
+MODULE_FIRMWARE("qcom/a630_gmu.bin");
+MODULE_FIRMWARE("qcom/a630_zap.mbn");
+MODULE_FIRMWARE("qcom/a640_gmu.bin");
+MODULE_FIRMWARE("qcom/a650_gmu.bin");
+MODULE_FIRMWARE("qcom/a650_sqe.fw");
+MODULE_FIRMWARE("qcom/a660_gmu.bin");
+MODULE_FIRMWARE("qcom/a660_sqe.fw");
+
+static const struct adreno_reglist a702_hwcg[] = {
+ { REG_A6XX_RBBM_CLOCK_CNTL_SP0, 0x22222222 },
+ { REG_A6XX_RBBM_CLOCK_CNTL2_SP0, 0x02222220 },
+ { REG_A6XX_RBBM_CLOCK_DELAY_SP0, 0x00000081 },
+ { REG_A6XX_RBBM_CLOCK_HYST_SP0, 0x0000f3cf },
+ { REG_A6XX_RBBM_CLOCK_CNTL_TP0, 0x22222222 },
+ { REG_A6XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222 },
+ { REG_A6XX_RBBM_CLOCK_CNTL3_TP0, 0x22222222 },
+ { REG_A6XX_RBBM_CLOCK_CNTL4_TP0, 0x00022222 },
+ { REG_A6XX_RBBM_CLOCK_DELAY_TP0, 0x11111111 },
+ { REG_A6XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111 },
+ { REG_A6XX_RBBM_CLOCK_DELAY3_TP0, 0x11111111 },
+ { REG_A6XX_RBBM_CLOCK_DELAY4_TP0, 0x00011111 },
+ { REG_A6XX_RBBM_CLOCK_HYST_TP0, 0x77777777 },
+ { REG_A6XX_RBBM_CLOCK_HYST2_TP0, 0x77777777 },
+ { REG_A6XX_RBBM_CLOCK_HYST3_TP0, 0x77777777 },
+ { REG_A6XX_RBBM_CLOCK_HYST4_TP0, 0x00077777 },
+ { REG_A6XX_RBBM_CLOCK_CNTL_RB0, 0x22222222 },
+ { REG_A6XX_RBBM_CLOCK_CNTL2_RB0, 0x01202222 },
+ { REG_A6XX_RBBM_CLOCK_CNTL_CCU0, 0x00002220 },
+ { REG_A6XX_RBBM_CLOCK_HYST_RB_CCU0, 0x00040f00 },
+ { REG_A6XX_RBBM_CLOCK_CNTL_RAC, 0x05522022 },
+ { REG_A6XX_RBBM_CLOCK_CNTL2_RAC, 0x00005555 },
+ { REG_A6XX_RBBM_CLOCK_DELAY_RAC, 0x00000011 },
+ { REG_A6XX_RBBM_CLOCK_HYST_RAC, 0x00445044 },
+ { REG_A6XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222 },
+ { REG_A6XX_RBBM_CLOCK_MODE_VFD, 0x00002222 },
+ { REG_A6XX_RBBM_CLOCK_MODE_GPC, 0x02222222 },
+ { REG_A6XX_RBBM_CLOCK_DELAY_HLSQ_2, 0x00000002 },
+ { REG_A6XX_RBBM_CLOCK_MODE_HLSQ, 0x00002222 },
+ { REG_A6XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00004000 },
+ { REG_A6XX_RBBM_CLOCK_DELAY_VFD, 0x00002222 },
+ { REG_A6XX_RBBM_CLOCK_DELAY_GPC, 0x00000200 },
+ { REG_A6XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000 },
+ { REG_A6XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000 },
+ { REG_A6XX_RBBM_CLOCK_HYST_VFD, 0x00000000 },
+ { REG_A6XX_RBBM_CLOCK_HYST_GPC, 0x04104004 },
+ { REG_A6XX_RBBM_CLOCK_HYST_HLSQ, 0x00000000 },
+ { REG_A6XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222 },
+ { REG_A6XX_RBBM_CLOCK_HYST_UCHE, 0x00000004 },
+ { REG_A6XX_RBBM_CLOCK_DELAY_UCHE, 0x00000002 },
+ { REG_A6XX_RBBM_ISDB_CNT, 0x00000182 },
+ { REG_A6XX_RBBM_RAC_THRESHOLD_CNT, 0x00000000 },
+ { REG_A6XX_RBBM_SP_HYST_CNT, 0x00000000 },
+ { REG_A6XX_RBBM_CLOCK_CNTL_GMU_GX, 0x00000222 },
+ { REG_A6XX_RBBM_CLOCK_DELAY_GMU_GX, 0x00000111 },
+ { REG_A6XX_RBBM_CLOCK_HYST_GMU_GX, 0x00000555 },
+ { REG_A6XX_RBBM_CLOCK_CNTL_FCHE, 0x00000222 },
+ { REG_A6XX_RBBM_CLOCK_DELAY_FCHE, 0x00000000 },
+ { REG_A6XX_RBBM_CLOCK_HYST_FCHE, 0x00000000 },
+ { REG_A6XX_RBBM_CLOCK_CNTL_GLC, 0x00222222 },
+ { REG_A6XX_RBBM_CLOCK_DELAY_GLC, 0x00000000 },
+ { REG_A6XX_RBBM_CLOCK_HYST_GLC, 0x00000000 },
+ { REG_A6XX_RBBM_CLOCK_CNTL_MHUB, 0x00000002 },
+ { REG_A6XX_RBBM_CLOCK_DELAY_MHUB, 0x00000000 },
+ { REG_A6XX_RBBM_CLOCK_HYST_MHUB, 0x00000000 },
+ {}
+};
+
+static const struct adreno_reglist a730_hwcg[] = {
+ { REG_A6XX_RBBM_CLOCK_CNTL_SP0, 0x02222222 },
+ { REG_A6XX_RBBM_CLOCK_CNTL2_SP0, 0x02022222 },
+ { REG_A6XX_RBBM_CLOCK_HYST_SP0, 0x0000f3cf },
+ { REG_A6XX_RBBM_CLOCK_DELAY_SP0, 0x00000080 },
+ { REG_A6XX_RBBM_CLOCK_CNTL_TP0, 0x22222220 },
+ { REG_A6XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222 },
+ { REG_A6XX_RBBM_CLOCK_CNTL3_TP0, 0x22222222 },
+ { REG_A6XX_RBBM_CLOCK_CNTL4_TP0, 0x00222222 },
+ { REG_A6XX_RBBM_CLOCK_HYST_TP0, 0x77777777 },
+ { REG_A6XX_RBBM_CLOCK_HYST2_TP0, 0x77777777 },
+ { REG_A6XX_RBBM_CLOCK_HYST3_TP0, 0x77777777 },
+ { REG_A6XX_RBBM_CLOCK_HYST4_TP0, 0x00077777 },
+ { REG_A6XX_RBBM_CLOCK_DELAY_TP0, 0x11111111 },
+ { REG_A6XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111 },
+ { REG_A6XX_RBBM_CLOCK_DELAY3_TP0, 0x11111111 },
+ { REG_A6XX_RBBM_CLOCK_DELAY4_TP0, 0x00011111 },
+ { REG_A6XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222 },
+ { REG_A6XX_RBBM_CLOCK_HYST_UCHE, 0x00000004 },
+ { REG_A6XX_RBBM_CLOCK_DELAY_UCHE, 0x00000002 },
+ { REG_A6XX_RBBM_CLOCK_CNTL_RB0, 0x22222222 },
+ { REG_A6XX_RBBM_CLOCK_CNTL2_RB0, 0x01002222 },
+ { REG_A6XX_RBBM_CLOCK_CNTL_CCU0, 0x00002220 },
+ { REG_A6XX_RBBM_CLOCK_HYST_RB_CCU0, 0x44000f00 },
+ { REG_A6XX_RBBM_CLOCK_CNTL_RAC, 0x25222022 },
+ { REG_A6XX_RBBM_CLOCK_CNTL2_RAC, 0x00555555 },
+ { REG_A6XX_RBBM_CLOCK_DELAY_RAC, 0x00000011 },
+ { REG_A6XX_RBBM_CLOCK_HYST_RAC, 0x00440044 },
+ { REG_A6XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222 },
+ { REG_A7XX_RBBM_CLOCK_MODE2_GRAS, 0x00000222 },
+ { REG_A7XX_RBBM_CLOCK_MODE_BV_GRAS, 0x00222222 },
+ { REG_A6XX_RBBM_CLOCK_MODE_GPC, 0x02222223 },
+ { REG_A6XX_RBBM_CLOCK_MODE_VFD, 0x00002222 },
+ { REG_A7XX_RBBM_CLOCK_MODE_BV_GPC, 0x00222222 },
+ { REG_A7XX_RBBM_CLOCK_MODE_BV_VFD, 0x00002222 },
+ { REG_A6XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000 },
+ { REG_A6XX_RBBM_CLOCK_HYST_GPC, 0x04104004 },
+ { REG_A6XX_RBBM_CLOCK_HYST_VFD, 0x00000000 },
+ { REG_A6XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00004000 },
+ { REG_A6XX_RBBM_CLOCK_DELAY_GPC, 0x00000200 },
+ { REG_A6XX_RBBM_CLOCK_DELAY_VFD, 0x00002222 },
+ { REG_A6XX_RBBM_CLOCK_MODE_HLSQ, 0x00002222 },
+ { REG_A6XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000 },
+ { REG_A6XX_RBBM_CLOCK_HYST_HLSQ, 0x00000000 },
+ { REG_A6XX_RBBM_CLOCK_DELAY_HLSQ_2, 0x00000002 },
+ { REG_A7XX_RBBM_CLOCK_MODE_BV_LRZ, 0x55555552 },
+ { REG_A7XX_RBBM_CLOCK_MODE_CP, 0x00000223 },
+ { REG_A6XX_RBBM_CLOCK_CNTL, 0x8aa8aa82 },
+ { REG_A6XX_RBBM_ISDB_CNT, 0x00000182 },
+ { REG_A6XX_RBBM_RAC_THRESHOLD_CNT, 0x00000000 },
+ { REG_A6XX_RBBM_SP_HYST_CNT, 0x00000000 },
+ { REG_A6XX_RBBM_CLOCK_CNTL_GMU_GX, 0x00000222 },
+ { REG_A6XX_RBBM_CLOCK_DELAY_GMU_GX, 0x00000111 },
+ { REG_A6XX_RBBM_CLOCK_HYST_GMU_GX, 0x00000555 },
+ {},
+};
+
+static const struct adreno_reglist a740_hwcg[] = {
+ { REG_A6XX_RBBM_CLOCK_CNTL_SP0, 0x02222222 },
+ { REG_A6XX_RBBM_CLOCK_CNTL2_SP0, 0x22022222 },
+ { REG_A6XX_RBBM_CLOCK_HYST_SP0, 0x003cf3cf },
+ { REG_A6XX_RBBM_CLOCK_DELAY_SP0, 0x00000080 },
+ { REG_A6XX_RBBM_CLOCK_CNTL_TP0, 0x22222220 },
+ { REG_A6XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222 },
+ { REG_A6XX_RBBM_CLOCK_CNTL3_TP0, 0x22222222 },
+ { REG_A6XX_RBBM_CLOCK_CNTL4_TP0, 0x00222222 },
+ { REG_A6XX_RBBM_CLOCK_HYST_TP0, 0x77777777 },
+ { REG_A6XX_RBBM_CLOCK_HYST2_TP0, 0x77777777 },
+ { REG_A6XX_RBBM_CLOCK_HYST3_TP0, 0x77777777 },
+ { REG_A6XX_RBBM_CLOCK_HYST4_TP0, 0x00077777 },
+ { REG_A6XX_RBBM_CLOCK_DELAY_TP0, 0x11111111 },
+ { REG_A6XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111 },
+ { REG_A6XX_RBBM_CLOCK_DELAY3_TP0, 0x11111111 },
+ { REG_A6XX_RBBM_CLOCK_DELAY4_TP0, 0x00011111 },
+ { REG_A6XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222 },
+ { REG_A6XX_RBBM_CLOCK_CNTL2_UCHE, 0x00222222 },
+ { REG_A6XX_RBBM_CLOCK_HYST_UCHE, 0x00000444 },
+ { REG_A6XX_RBBM_CLOCK_DELAY_UCHE, 0x00000222 },
+ { REG_A6XX_RBBM_CLOCK_CNTL_RB0, 0x22222222 },
+ { REG_A6XX_RBBM_CLOCK_CNTL2_RB0, 0x01002222 },
+ { REG_A6XX_RBBM_CLOCK_CNTL_CCU0, 0x00002220 },
+ { REG_A6XX_RBBM_CLOCK_HYST_RB_CCU0, 0x44000f00 },
+ { REG_A6XX_RBBM_CLOCK_CNTL_RAC, 0x25222022 },
+ { REG_A6XX_RBBM_CLOCK_CNTL2_RAC, 0x00555555 },
+ { REG_A6XX_RBBM_CLOCK_DELAY_RAC, 0x00000011 },
+ { REG_A6XX_RBBM_CLOCK_HYST_RAC, 0x00440044 },
+ { REG_A6XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222 },
+ { REG_A7XX_RBBM_CLOCK_MODE2_GRAS, 0x00000222 },
+ { REG_A7XX_RBBM_CLOCK_MODE_BV_GRAS, 0x00222222 },
+ { REG_A6XX_RBBM_CLOCK_MODE_GPC, 0x02222223 },
+ { REG_A6XX_RBBM_CLOCK_MODE_VFD, 0x00222222 },
+ { REG_A7XX_RBBM_CLOCK_MODE_BV_GPC, 0x00222222 },
+ { REG_A7XX_RBBM_CLOCK_MODE_BV_VFD, 0x00002222 },
+ { REG_A6XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000 },
+ { REG_A6XX_RBBM_CLOCK_HYST_GPC, 0x04104004 },
+ { REG_A6XX_RBBM_CLOCK_HYST_VFD, 0x00000000 },
+ { REG_A6XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00000000 },
+ { REG_A6XX_RBBM_CLOCK_DELAY_GPC, 0x00000200 },
+ { REG_A6XX_RBBM_CLOCK_DELAY_VFD, 0x00000000 },
+ { REG_A6XX_RBBM_CLOCK_MODE_HLSQ, 0x00002222 },
+ { REG_A6XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000 },
+ { REG_A6XX_RBBM_CLOCK_HYST_HLSQ, 0x00000000 },
+ { REG_A7XX_RBBM_CLOCK_MODE_BV_LRZ, 0x55555552 },
+ { REG_A7XX_RBBM_CLOCK_HYST2_VFD, 0x00000000 },
+ { REG_A7XX_RBBM_CLOCK_MODE_CP, 0x00000222 },
+ { REG_A6XX_RBBM_CLOCK_CNTL, 0x8aa8aa82 },
+ { REG_A6XX_RBBM_ISDB_CNT, 0x00000182 },
+ { REG_A6XX_RBBM_RAC_THRESHOLD_CNT, 0x00000000 },
+ { REG_A6XX_RBBM_SP_HYST_CNT, 0x00000000 },
+ { REG_A6XX_RBBM_CLOCK_CNTL_GMU_GX, 0x00000222 },
+ { REG_A6XX_RBBM_CLOCK_DELAY_GMU_GX, 0x00000111 },
+ { REG_A6XX_RBBM_CLOCK_HYST_GMU_GX, 0x00000555 },
+ {},
+};
+
+static const u32 a730_protect_regs[] = {
+ A6XX_PROTECT_RDONLY(0x00000, 0x04ff),
+ A6XX_PROTECT_RDONLY(0x0050b, 0x0058),
+ A6XX_PROTECT_NORDWR(0x0050e, 0x0000),
+ A6XX_PROTECT_NORDWR(0x00510, 0x0000),
+ A6XX_PROTECT_NORDWR(0x00534, 0x0000),
+ A6XX_PROTECT_RDONLY(0x005fb, 0x009d),
+ A6XX_PROTECT_NORDWR(0x00699, 0x01e9),
+ A6XX_PROTECT_NORDWR(0x008a0, 0x0008),
+ A6XX_PROTECT_NORDWR(0x008ab, 0x0024),
+ /* 0x008d0-0x008dd and 0x008e0-0x008e6 are unprotected on purpose for tools like perfetto */
+ A6XX_PROTECT_NORDWR(0x008de, 0x0001),
+ A6XX_PROTECT_RDONLY(0x008e7, 0x014b),
+ A6XX_PROTECT_NORDWR(0x00900, 0x004d),
+ A6XX_PROTECT_NORDWR(0x0098d, 0x00b2),
+ A6XX_PROTECT_NORDWR(0x00a41, 0x01be),
+ A6XX_PROTECT_NORDWR(0x00df0, 0x0001),
+ A6XX_PROTECT_NORDWR(0x00e01, 0x0000),
+ A6XX_PROTECT_NORDWR(0x00e07, 0x0008),
+ A6XX_PROTECT_NORDWR(0x03c00, 0x00c3),
+ A6XX_PROTECT_RDONLY(0x03cc4, 0x1fff),
+ A6XX_PROTECT_NORDWR(0x08630, 0x01cf),
+ A6XX_PROTECT_NORDWR(0x08e00, 0x0000),
+ A6XX_PROTECT_NORDWR(0x08e08, 0x0000),
+ A6XX_PROTECT_NORDWR(0x08e50, 0x001f),
+ A6XX_PROTECT_NORDWR(0x08e80, 0x0280),
+ A6XX_PROTECT_NORDWR(0x09624, 0x01db),
+ A6XX_PROTECT_NORDWR(0x09e40, 0x0000),
+ A6XX_PROTECT_NORDWR(0x09e64, 0x000d),
+ A6XX_PROTECT_NORDWR(0x09e78, 0x0187),
+ A6XX_PROTECT_NORDWR(0x0a630, 0x01cf),
+ A6XX_PROTECT_NORDWR(0x0ae02, 0x0000),
+ A6XX_PROTECT_NORDWR(0x0ae50, 0x000f),
+ A6XX_PROTECT_NORDWR(0x0ae66, 0x0003),
+ A6XX_PROTECT_NORDWR(0x0ae6f, 0x0003),
+ A6XX_PROTECT_NORDWR(0x0b604, 0x0003),
+ A6XX_PROTECT_NORDWR(0x0ec00, 0x0fff),
+ A6XX_PROTECT_RDONLY(0x0fc00, 0x1fff),
+ A6XX_PROTECT_NORDWR(0x18400, 0x0053),
+ A6XX_PROTECT_RDONLY(0x18454, 0x0004),
+ A6XX_PROTECT_NORDWR(0x18459, 0x1fff),
+ A6XX_PROTECT_NORDWR(0x1a459, 0x1fff),
+ A6XX_PROTECT_NORDWR(0x1c459, 0x1fff),
+ A6XX_PROTECT_NORDWR(0x1f400, 0x0443),
+ A6XX_PROTECT_RDONLY(0x1f844, 0x007b),
+ A6XX_PROTECT_NORDWR(0x1f860, 0x0000),
+ A6XX_PROTECT_NORDWR(0x1f878, 0x002a),
+ /* CP_PROTECT_REG[45, 46] are left untouched! */
+ 0,
+ 0,
+ A6XX_PROTECT_NORDWR(0x1f8c0, 0x00000),
+};
+DECLARE_ADRENO_PROTECT(a730_protect, 48);
+
+static const struct adreno_info a7xx_gpus[] = {
+ {
+ .chip_ids = ADRENO_CHIP_IDS(0x07000200),
+ .family = ADRENO_6XX_GEN1, /* NOT a mistake! */
+ .fw = {
+ [ADRENO_FW_SQE] = "a702_sqe.fw",
+ },
+ .gmem = SZ_128K,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
+ .quirks = ADRENO_QUIRK_HAS_HW_APRIV,
+ .init = a6xx_gpu_init,
+ .zapfw = "a702_zap.mbn",
+ .a6xx = &(const struct a6xx_info) {
+ .hwcg = a702_hwcg,
+ .protect = &a650_protect,
+ },
+ .speedbins = ADRENO_SPEEDBINS(
+ { 0, 0 },
+ { 236, 1 },
+ { 178, 2 },
+ { 142, 3 },
+ ),
+ }, {
+ .chip_ids = ADRENO_CHIP_IDS(0x07030001),
+ .family = ADRENO_7XX_GEN1,
+ .fw = {
+ [ADRENO_FW_SQE] = "a730_sqe.fw",
+ [ADRENO_FW_GMU] = "gmu_gen70000.bin",
+ },
+ .gmem = SZ_2M,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
+ .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT |
+ ADRENO_QUIRK_HAS_HW_APRIV,
+ .init = a6xx_gpu_init,
+ .zapfw = "a730_zap.mdt",
+ .a6xx = &(const struct a6xx_info) {
+ .hwcg = a730_hwcg,
+ .protect = &a730_protect,
+ },
+ .address_space_size = SZ_16G,
+ }, {
+ .chip_ids = ADRENO_CHIP_IDS(0x43050a01), /* "C510v2" */
+ .family = ADRENO_7XX_GEN2,
+ .fw = {
+ [ADRENO_FW_SQE] = "a740_sqe.fw",
+ [ADRENO_FW_GMU] = "gmu_gen70200.bin",
+ },
+ .gmem = 3 * SZ_1M,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
+ .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT |
+ ADRENO_QUIRK_HAS_HW_APRIV,
+ .init = a6xx_gpu_init,
+ .zapfw = "a740_zap.mdt",
+ .a6xx = &(const struct a6xx_info) {
+ .hwcg = a740_hwcg,
+ .protect = &a730_protect,
+ .gmu_chipid = 0x7020100,
+ },
+ .address_space_size = SZ_16G,
+ }, {
+ .chip_ids = ADRENO_CHIP_IDS(0x43050c01), /* "C512v2" */
+ .family = ADRENO_7XX_GEN2,
+ .fw = {
+ [ADRENO_FW_SQE] = "gen70500_sqe.fw",
+ [ADRENO_FW_GMU] = "gen70500_gmu.bin",
+ },
+ .gmem = 3 * SZ_1M,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
+ .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT |
+ ADRENO_QUIRK_HAS_HW_APRIV,
+ .init = a6xx_gpu_init,
+ .a6xx = &(const struct a6xx_info) {
+ .hwcg = a740_hwcg,
+ .protect = &a730_protect,
+ .gmu_chipid = 0x7050001,
+ },
+ .address_space_size = SZ_256G,
+ }, {
+ .chip_ids = ADRENO_CHIP_IDS(0x43051401), /* "C520v2" */
+ .family = ADRENO_7XX_GEN3,
+ .fw = {
+ [ADRENO_FW_SQE] = "gen70900_sqe.fw",
+ [ADRENO_FW_GMU] = "gmu_gen70900.bin",
+ },
+ .gmem = 3 * SZ_1M,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
+ .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT |
+ ADRENO_QUIRK_HAS_HW_APRIV,
+ .init = a6xx_gpu_init,
+ .zapfw = "gen70900_zap.mbn",
+ .a6xx = &(const struct a6xx_info) {
+ .protect = &a730_protect,
+ .gmu_chipid = 0x7090100,
+ },
+ .address_space_size = SZ_16G,
+ }
+};
+DECLARE_ADRENO_GPULIST(a7xx);
+
+static inline __always_unused void __build_asserts(void)
+{
+ BUILD_BUG_ON(a630_protect.count > a630_protect.count_max);
+ BUILD_BUG_ON(a650_protect.count > a650_protect.count_max);
+ 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);
+}
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index 0e3dfd4c2bc8..cb538a262d1c 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -466,9 +466,7 @@ static int a6xx_rpmh_start(struct a6xx_gmu *gmu)
int ret;
u32 val;
- gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, 1 << 1);
- /* Wait for the register to finish posting */
- wmb();
+ gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, BIT(1));
ret = gmu_poll_timeout(gmu, REG_A6XX_GMU_RSCC_CONTROL_ACK, val,
val & (1 << 1), 100, 10000);
@@ -769,8 +767,9 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state)
{
struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu);
struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
+ const struct a6xx_info *a6xx_info = adreno_gpu->info->a6xx;
u32 fence_range_lower, fence_range_upper;
- u32 chipid, chipid_min = 0;
+ u32 chipid = 0;
int ret;
/* Vote veto for FAL10 */
@@ -830,27 +829,8 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state)
*/
gmu_write(gmu, REG_A6XX_GMU_CM3_CFG, 0x4052);
- /* NOTE: A730 may also fall in this if-condition with a future GMU fw update. */
- if (adreno_is_a7xx(adreno_gpu) && !adreno_is_a730(adreno_gpu)) {
- /* A7xx GPUs have obfuscated chip IDs. Use constant maj = 7 */
- chipid = FIELD_PREP(GENMASK(31, 24), 0x7);
-
- /*
- * The min part has a 1-1 mapping for each GPU SKU.
- * This chipid that the GMU expects corresponds to the "GENX_Y_Z" naming,
- * where X = major, Y = minor, Z = patchlevel, e.g. GEN7_2_1 for prod A740.
- */
- if (adreno_is_a740(adreno_gpu))
- chipid_min = 2;
- else if (adreno_is_a750(adreno_gpu))
- chipid_min = 9;
- else
- return -EINVAL;
-
- chipid |= FIELD_PREP(GENMASK(23, 16), chipid_min);
-
- /* Get the patchid (which may vary) from the device tree */
- chipid |= FIELD_PREP(GENMASK(15, 8), adreno_patchid(adreno_gpu));
+ if (a6xx_info->gmu_chipid) {
+ chipid = a6xx_info->gmu_chipid;
} else {
/*
* Note that the GMU has a slightly different layout for
@@ -1329,7 +1309,13 @@ static int a6xx_gmu_rpmh_arc_votes_init(struct device *dev, u32 *votes,
if (!pri_count)
return -EINVAL;
- sec = cmd_db_read_aux_data("mx.lvl", &sec_count);
+ /*
+ * Some targets have a separate gfx mxc rail. So try to read that first and then fall back
+ * to regular mx rail if it is missing
+ */
+ sec = cmd_db_read_aux_data("gmxc.lvl", &sec_count);
+ if (IS_ERR(sec) && sec != ERR_PTR(-EPROBE_DEFER))
+ sec = cmd_db_read_aux_data("mx.lvl", &sec_count);
if (IS_ERR(sec))
return PTR_ERR(sec);
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index 973872ad0474..bcaec86ac67a 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -10,6 +10,7 @@
#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>
@@ -394,623 +395,6 @@ static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
a6xx_flush(gpu, ring);
}
-const struct adreno_reglist a612_hwcg[] = {
- {REG_A6XX_RBBM_CLOCK_CNTL_SP0, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL2_SP0, 0x02222220},
- {REG_A6XX_RBBM_CLOCK_DELAY_SP0, 0x00000081},
- {REG_A6XX_RBBM_CLOCK_HYST_SP0, 0x0000f3cf},
- {REG_A6XX_RBBM_CLOCK_CNTL_TP0, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL3_TP0, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL4_TP0, 0x00022222},
- {REG_A6XX_RBBM_CLOCK_DELAY_TP0, 0x11111111},
- {REG_A6XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111},
- {REG_A6XX_RBBM_CLOCK_DELAY3_TP0, 0x11111111},
- {REG_A6XX_RBBM_CLOCK_DELAY4_TP0, 0x00011111},
- {REG_A6XX_RBBM_CLOCK_HYST_TP0, 0x77777777},
- {REG_A6XX_RBBM_CLOCK_HYST2_TP0, 0x77777777},
- {REG_A6XX_RBBM_CLOCK_HYST3_TP0, 0x77777777},
- {REG_A6XX_RBBM_CLOCK_HYST4_TP0, 0x00077777},
- {REG_A6XX_RBBM_CLOCK_CNTL_RB0, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL2_RB0, 0x01202222},
- {REG_A6XX_RBBM_CLOCK_CNTL_CCU0, 0x00002220},
- {REG_A6XX_RBBM_CLOCK_HYST_RB_CCU0, 0x00040f00},
- {REG_A6XX_RBBM_CLOCK_CNTL_RAC, 0x05522022},
- {REG_A6XX_RBBM_CLOCK_CNTL2_RAC, 0x00005555},
- {REG_A6XX_RBBM_CLOCK_DELAY_RAC, 0x00000011},
- {REG_A6XX_RBBM_CLOCK_HYST_RAC, 0x00445044},
- {REG_A6XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222},
- {REG_A6XX_RBBM_CLOCK_MODE_VFD, 0x00002222},
- {REG_A6XX_RBBM_CLOCK_MODE_GPC, 0x02222222},
- {REG_A6XX_RBBM_CLOCK_DELAY_HLSQ_2, 0x00000002},
- {REG_A6XX_RBBM_CLOCK_MODE_HLSQ, 0x00002222},
- {REG_A6XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00004000},
- {REG_A6XX_RBBM_CLOCK_DELAY_VFD, 0x00002222},
- {REG_A6XX_RBBM_CLOCK_DELAY_GPC, 0x00000200},
- {REG_A6XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000},
- {REG_A6XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000},
- {REG_A6XX_RBBM_CLOCK_HYST_VFD, 0x00000000},
- {REG_A6XX_RBBM_CLOCK_HYST_GPC, 0x04104004},
- {REG_A6XX_RBBM_CLOCK_HYST_HLSQ, 0x00000000},
- {REG_A6XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_HYST_UCHE, 0x00000004},
- {REG_A6XX_RBBM_CLOCK_DELAY_UCHE, 0x00000002},
- {REG_A6XX_RBBM_ISDB_CNT, 0x00000182},
- {REG_A6XX_RBBM_RAC_THRESHOLD_CNT, 0x00000000},
- {REG_A6XX_RBBM_SP_HYST_CNT, 0x00000000},
- {REG_A6XX_RBBM_CLOCK_CNTL_GMU_GX, 0x00000222},
- {REG_A6XX_RBBM_CLOCK_DELAY_GMU_GX, 0x00000111},
- {REG_A6XX_RBBM_CLOCK_HYST_GMU_GX, 0x00000555},
- {},
-};
-
-/* For a615 family (a615, a616, a618 and a619) */
-const struct adreno_reglist a615_hwcg[] = {
- {REG_A6XX_RBBM_CLOCK_CNTL_SP0, 0x02222222},
- {REG_A6XX_RBBM_CLOCK_CNTL2_SP0, 0x02222220},
- {REG_A6XX_RBBM_CLOCK_DELAY_SP0, 0x00000080},
- {REG_A6XX_RBBM_CLOCK_HYST_SP0, 0x0000F3CF},
- {REG_A6XX_RBBM_CLOCK_CNTL_TP0, 0x02222222},
- {REG_A6XX_RBBM_CLOCK_CNTL_TP1, 0x02222222},
- {REG_A6XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL2_TP1, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL3_TP0, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL3_TP1, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL4_TP0, 0x00022222},
- {REG_A6XX_RBBM_CLOCK_CNTL4_TP1, 0x00022222},
- {REG_A6XX_RBBM_CLOCK_HYST_TP0, 0x77777777},
- {REG_A6XX_RBBM_CLOCK_HYST_TP1, 0x77777777},
- {REG_A6XX_RBBM_CLOCK_HYST2_TP0, 0x77777777},
- {REG_A6XX_RBBM_CLOCK_HYST2_TP1, 0x77777777},
- {REG_A6XX_RBBM_CLOCK_HYST3_TP0, 0x77777777},
- {REG_A6XX_RBBM_CLOCK_HYST3_TP1, 0x77777777},
- {REG_A6XX_RBBM_CLOCK_HYST4_TP0, 0x00077777},
- {REG_A6XX_RBBM_CLOCK_HYST4_TP1, 0x00077777},
- {REG_A6XX_RBBM_CLOCK_DELAY_TP0, 0x11111111},
- {REG_A6XX_RBBM_CLOCK_DELAY_TP1, 0x11111111},
- {REG_A6XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111},
- {REG_A6XX_RBBM_CLOCK_DELAY2_TP1, 0x11111111},
- {REG_A6XX_RBBM_CLOCK_DELAY3_TP0, 0x11111111},
- {REG_A6XX_RBBM_CLOCK_DELAY3_TP1, 0x11111111},
- {REG_A6XX_RBBM_CLOCK_DELAY4_TP0, 0x00011111},
- {REG_A6XX_RBBM_CLOCK_DELAY4_TP1, 0x00011111},
- {REG_A6XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL2_UCHE, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL3_UCHE, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL4_UCHE, 0x00222222},
- {REG_A6XX_RBBM_CLOCK_HYST_UCHE, 0x00000004},
- {REG_A6XX_RBBM_CLOCK_DELAY_UCHE, 0x00000002},
- {REG_A6XX_RBBM_CLOCK_CNTL_RB0, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL2_RB0, 0x00002222},
- {REG_A6XX_RBBM_CLOCK_CNTL_CCU0, 0x00002020},
- {REG_A6XX_RBBM_CLOCK_CNTL_CCU1, 0x00002220},
- {REG_A6XX_RBBM_CLOCK_CNTL_CCU2, 0x00002220},
- {REG_A6XX_RBBM_CLOCK_CNTL_CCU3, 0x00002220},
- {REG_A6XX_RBBM_CLOCK_HYST_RB_CCU0, 0x00040F00},
- {REG_A6XX_RBBM_CLOCK_HYST_RB_CCU1, 0x00040F00},
- {REG_A6XX_RBBM_CLOCK_HYST_RB_CCU2, 0x00040F00},
- {REG_A6XX_RBBM_CLOCK_HYST_RB_CCU3, 0x00040F00},
- {REG_A6XX_RBBM_CLOCK_CNTL_RAC, 0x05022022},
- {REG_A6XX_RBBM_CLOCK_CNTL2_RAC, 0x00005555},
- {REG_A6XX_RBBM_CLOCK_DELAY_RAC, 0x00000011},
- {REG_A6XX_RBBM_CLOCK_HYST_RAC, 0x00445044},
- {REG_A6XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222},
- {REG_A6XX_RBBM_CLOCK_MODE_GPC, 0x00222222},
- {REG_A6XX_RBBM_CLOCK_MODE_VFD, 0x00002222},
- {REG_A6XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000},
- {REG_A6XX_RBBM_CLOCK_HYST_GPC, 0x04104004},
- {REG_A6XX_RBBM_CLOCK_HYST_VFD, 0x00000000},
- {REG_A6XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000},
- {REG_A6XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00004000},
- {REG_A6XX_RBBM_CLOCK_DELAY_GPC, 0x00000200},
- {REG_A6XX_RBBM_CLOCK_DELAY_VFD, 0x00002222},
- {REG_A6XX_RBBM_CLOCK_DELAY_HLSQ_2, 0x00000002},
- {REG_A6XX_RBBM_CLOCK_MODE_HLSQ, 0x00002222},
- {REG_A6XX_RBBM_CLOCK_CNTL_GMU_GX, 0x00000222},
- {REG_A6XX_RBBM_CLOCK_DELAY_GMU_GX, 0x00000111},
- {REG_A6XX_RBBM_CLOCK_HYST_GMU_GX, 0x00000555},
- {},
-};
-
-const struct adreno_reglist a630_hwcg[] = {
- {REG_A6XX_RBBM_CLOCK_CNTL_SP0, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL_SP1, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL_SP2, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL_SP3, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL2_SP0, 0x02022220},
- {REG_A6XX_RBBM_CLOCK_CNTL2_SP1, 0x02022220},
- {REG_A6XX_RBBM_CLOCK_CNTL2_SP2, 0x02022220},
- {REG_A6XX_RBBM_CLOCK_CNTL2_SP3, 0x02022220},
- {REG_A6XX_RBBM_CLOCK_DELAY_SP0, 0x00000080},
- {REG_A6XX_RBBM_CLOCK_DELAY_SP1, 0x00000080},
- {REG_A6XX_RBBM_CLOCK_DELAY_SP2, 0x00000080},
- {REG_A6XX_RBBM_CLOCK_DELAY_SP3, 0x00000080},
- {REG_A6XX_RBBM_CLOCK_HYST_SP0, 0x0000f3cf},
- {REG_A6XX_RBBM_CLOCK_HYST_SP1, 0x0000f3cf},
- {REG_A6XX_RBBM_CLOCK_HYST_SP2, 0x0000f3cf},
- {REG_A6XX_RBBM_CLOCK_HYST_SP3, 0x0000f3cf},
- {REG_A6XX_RBBM_CLOCK_CNTL_TP0, 0x02222222},
- {REG_A6XX_RBBM_CLOCK_CNTL_TP1, 0x02222222},
- {REG_A6XX_RBBM_CLOCK_CNTL_TP2, 0x02222222},
- {REG_A6XX_RBBM_CLOCK_CNTL_TP3, 0x02222222},
- {REG_A6XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL2_TP1, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL2_TP2, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL2_TP3, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL3_TP0, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL3_TP1, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL3_TP2, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL3_TP3, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL4_TP0, 0x00022222},
- {REG_A6XX_RBBM_CLOCK_CNTL4_TP1, 0x00022222},
- {REG_A6XX_RBBM_CLOCK_CNTL4_TP2, 0x00022222},
- {REG_A6XX_RBBM_CLOCK_CNTL4_TP3, 0x00022222},
- {REG_A6XX_RBBM_CLOCK_HYST_TP0, 0x77777777},
- {REG_A6XX_RBBM_CLOCK_HYST_TP1, 0x77777777},
- {REG_A6XX_RBBM_CLOCK_HYST_TP2, 0x77777777},
- {REG_A6XX_RBBM_CLOCK_HYST_TP3, 0x77777777},
- {REG_A6XX_RBBM_CLOCK_HYST2_TP0, 0x77777777},
- {REG_A6XX_RBBM_CLOCK_HYST2_TP1, 0x77777777},
- {REG_A6XX_RBBM_CLOCK_HYST2_TP2, 0x77777777},
- {REG_A6XX_RBBM_CLOCK_HYST2_TP3, 0x77777777},
- {REG_A6XX_RBBM_CLOCK_HYST3_TP0, 0x77777777},
- {REG_A6XX_RBBM_CLOCK_HYST3_TP1, 0x77777777},
- {REG_A6XX_RBBM_CLOCK_HYST3_TP2, 0x77777777},
- {REG_A6XX_RBBM_CLOCK_HYST3_TP3, 0x77777777},
- {REG_A6XX_RBBM_CLOCK_HYST4_TP0, 0x00077777},
- {REG_A6XX_RBBM_CLOCK_HYST4_TP1, 0x00077777},
- {REG_A6XX_RBBM_CLOCK_HYST4_TP2, 0x00077777},
- {REG_A6XX_RBBM_CLOCK_HYST4_TP3, 0x00077777},
- {REG_A6XX_RBBM_CLOCK_DELAY_TP0, 0x11111111},
- {REG_A6XX_RBBM_CLOCK_DELAY_TP1, 0x11111111},
- {REG_A6XX_RBBM_CLOCK_DELAY_TP2, 0x11111111},
- {REG_A6XX_RBBM_CLOCK_DELAY_TP3, 0x11111111},
- {REG_A6XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111},
- {REG_A6XX_RBBM_CLOCK_DELAY2_TP1, 0x11111111},
- {REG_A6XX_RBBM_CLOCK_DELAY2_TP2, 0x11111111},
- {REG_A6XX_RBBM_CLOCK_DELAY2_TP3, 0x11111111},
- {REG_A6XX_RBBM_CLOCK_DELAY3_TP0, 0x11111111},
- {REG_A6XX_RBBM_CLOCK_DELAY3_TP1, 0x11111111},
- {REG_A6XX_RBBM_CLOCK_DELAY3_TP2, 0x11111111},
- {REG_A6XX_RBBM_CLOCK_DELAY3_TP3, 0x11111111},
- {REG_A6XX_RBBM_CLOCK_DELAY4_TP0, 0x00011111},
- {REG_A6XX_RBBM_CLOCK_DELAY4_TP1, 0x00011111},
- {REG_A6XX_RBBM_CLOCK_DELAY4_TP2, 0x00011111},
- {REG_A6XX_RBBM_CLOCK_DELAY4_TP3, 0x00011111},
- {REG_A6XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL2_UCHE, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL3_UCHE, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL4_UCHE, 0x00222222},
- {REG_A6XX_RBBM_CLOCK_HYST_UCHE, 0x00000004},
- {REG_A6XX_RBBM_CLOCK_DELAY_UCHE, 0x00000002},
- {REG_A6XX_RBBM_CLOCK_CNTL_RB0, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL_RB1, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL_RB2, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL_RB3, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL2_RB0, 0x00002222},
- {REG_A6XX_RBBM_CLOCK_CNTL2_RB1, 0x00002222},
- {REG_A6XX_RBBM_CLOCK_CNTL2_RB2, 0x00002222},
- {REG_A6XX_RBBM_CLOCK_CNTL2_RB3, 0x00002222},
- {REG_A6XX_RBBM_CLOCK_CNTL_CCU0, 0x00002220},
- {REG_A6XX_RBBM_CLOCK_CNTL_CCU1, 0x00002220},
- {REG_A6XX_RBBM_CLOCK_CNTL_CCU2, 0x00002220},
- {REG_A6XX_RBBM_CLOCK_CNTL_CCU3, 0x00002220},
- {REG_A6XX_RBBM_CLOCK_HYST_RB_CCU0, 0x00040f00},
- {REG_A6XX_RBBM_CLOCK_HYST_RB_CCU1, 0x00040f00},
- {REG_A6XX_RBBM_CLOCK_HYST_RB_CCU2, 0x00040f00},
- {REG_A6XX_RBBM_CLOCK_HYST_RB_CCU3, 0x00040f00},
- {REG_A6XX_RBBM_CLOCK_CNTL_RAC, 0x05022022},
- {REG_A6XX_RBBM_CLOCK_CNTL2_RAC, 0x00005555},
- {REG_A6XX_RBBM_CLOCK_DELAY_RAC, 0x00000011},
- {REG_A6XX_RBBM_CLOCK_HYST_RAC, 0x00445044},
- {REG_A6XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222},
- {REG_A6XX_RBBM_CLOCK_MODE_GPC, 0x00222222},
- {REG_A6XX_RBBM_CLOCK_MODE_VFD, 0x00002222},
- {REG_A6XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000},
- {REG_A6XX_RBBM_CLOCK_HYST_GPC, 0x04104004},
- {REG_A6XX_RBBM_CLOCK_HYST_VFD, 0x00000000},
- {REG_A6XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000},
- {REG_A6XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00004000},
- {REG_A6XX_RBBM_CLOCK_DELAY_GPC, 0x00000200},
- {REG_A6XX_RBBM_CLOCK_DELAY_VFD, 0x00002222},
- {REG_A6XX_RBBM_CLOCK_DELAY_HLSQ_2, 0x00000002},
- {REG_A6XX_RBBM_CLOCK_MODE_HLSQ, 0x00002222},
- {REG_A6XX_RBBM_CLOCK_CNTL_GMU_GX, 0x00000222},
- {REG_A6XX_RBBM_CLOCK_DELAY_GMU_GX, 0x00000111},
- {REG_A6XX_RBBM_CLOCK_HYST_GMU_GX, 0x00000555},
- {},
-};
-
-const struct adreno_reglist a640_hwcg[] = {
- {REG_A6XX_RBBM_CLOCK_CNTL_SP0, 0x02222222},
- {REG_A6XX_RBBM_CLOCK_CNTL2_SP0, 0x02222220},
- {REG_A6XX_RBBM_CLOCK_DELAY_SP0, 0x00000080},
- {REG_A6XX_RBBM_CLOCK_HYST_SP0, 0x0000F3CF},
- {REG_A6XX_RBBM_CLOCK_CNTL_TP0, 0x02222222},
- {REG_A6XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL3_TP0, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL4_TP0, 0x00022222},
- {REG_A6XX_RBBM_CLOCK_DELAY_TP0, 0x11111111},
- {REG_A6XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111},
- {REG_A6XX_RBBM_CLOCK_DELAY3_TP0, 0x11111111},
- {REG_A6XX_RBBM_CLOCK_DELAY4_TP0, 0x00011111},
- {REG_A6XX_RBBM_CLOCK_HYST_TP0, 0x77777777},
- {REG_A6XX_RBBM_CLOCK_HYST2_TP0, 0x77777777},
- {REG_A6XX_RBBM_CLOCK_HYST3_TP0, 0x77777777},
- {REG_A6XX_RBBM_CLOCK_HYST4_TP0, 0x00077777},
- {REG_A6XX_RBBM_CLOCK_CNTL_RB0, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL2_RB0, 0x01002222},
- {REG_A6XX_RBBM_CLOCK_CNTL_CCU0, 0x00002220},
- {REG_A6XX_RBBM_CLOCK_HYST_RB_CCU0, 0x00040F00},
- {REG_A6XX_RBBM_CLOCK_CNTL_RAC, 0x05222022},
- {REG_A6XX_RBBM_CLOCK_CNTL2_RAC, 0x00005555},
- {REG_A6XX_RBBM_CLOCK_DELAY_RAC, 0x00000011},
- {REG_A6XX_RBBM_CLOCK_HYST_RAC, 0x00445044},
- {REG_A6XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222},
- {REG_A6XX_RBBM_CLOCK_MODE_VFD, 0x00002222},
- {REG_A6XX_RBBM_CLOCK_MODE_GPC, 0x00222222},
- {REG_A6XX_RBBM_CLOCK_DELAY_HLSQ_2, 0x00000002},
- {REG_A6XX_RBBM_CLOCK_MODE_HLSQ, 0x00002222},
- {REG_A6XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00004000},
- {REG_A6XX_RBBM_CLOCK_DELAY_VFD, 0x00002222},
- {REG_A6XX_RBBM_CLOCK_DELAY_GPC, 0x00000200},
- {REG_A6XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000},
- {REG_A6XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000},
- {REG_A6XX_RBBM_CLOCK_HYST_VFD, 0x00000000},
- {REG_A6XX_RBBM_CLOCK_HYST_GPC, 0x04104004},
- {REG_A6XX_RBBM_CLOCK_HYST_HLSQ, 0x00000000},
- {REG_A6XX_RBBM_CLOCK_CNTL_TEX_FCHE, 0x00000222},
- {REG_A6XX_RBBM_CLOCK_DELAY_TEX_FCHE, 0x00000111},
- {REG_A6XX_RBBM_CLOCK_HYST_TEX_FCHE, 0x00000000},
- {REG_A6XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_HYST_UCHE, 0x00000004},
- {REG_A6XX_RBBM_CLOCK_DELAY_UCHE, 0x00000002},
- {REG_A6XX_RBBM_ISDB_CNT, 0x00000182},
- {REG_A6XX_RBBM_RAC_THRESHOLD_CNT, 0x00000000},
- {REG_A6XX_RBBM_SP_HYST_CNT, 0x00000000},
- {REG_A6XX_RBBM_CLOCK_CNTL_GMU_GX, 0x00000222},
- {REG_A6XX_RBBM_CLOCK_DELAY_GMU_GX, 0x00000111},
- {REG_A6XX_RBBM_CLOCK_HYST_GMU_GX, 0x00000555},
- {},
-};
-
-const struct adreno_reglist a650_hwcg[] = {
- {REG_A6XX_RBBM_CLOCK_CNTL_SP0, 0x02222222},
- {REG_A6XX_RBBM_CLOCK_CNTL2_SP0, 0x02222220},
- {REG_A6XX_RBBM_CLOCK_DELAY_SP0, 0x00000080},
- {REG_A6XX_RBBM_CLOCK_HYST_SP0, 0x0000F3CF},
- {REG_A6XX_RBBM_CLOCK_CNTL_TP0, 0x02222222},
- {REG_A6XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL3_TP0, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL4_TP0, 0x00022222},
- {REG_A6XX_RBBM_CLOCK_DELAY_TP0, 0x11111111},
- {REG_A6XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111},
- {REG_A6XX_RBBM_CLOCK_DELAY3_TP0, 0x11111111},
- {REG_A6XX_RBBM_CLOCK_DELAY4_TP0, 0x00011111},
- {REG_A6XX_RBBM_CLOCK_HYST_TP0, 0x77777777},
- {REG_A6XX_RBBM_CLOCK_HYST2_TP0, 0x77777777},
- {REG_A6XX_RBBM_CLOCK_HYST3_TP0, 0x77777777},
- {REG_A6XX_RBBM_CLOCK_HYST4_TP0, 0x00077777},
- {REG_A6XX_RBBM_CLOCK_CNTL_RB0, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL2_RB0, 0x01002222},
- {REG_A6XX_RBBM_CLOCK_CNTL_CCU0, 0x00002220},
- {REG_A6XX_RBBM_CLOCK_HYST_RB_CCU0, 0x00040F00},
- {REG_A6XX_RBBM_CLOCK_CNTL_RAC, 0x25222022},
- {REG_A6XX_RBBM_CLOCK_CNTL2_RAC, 0x00005555},
- {REG_A6XX_RBBM_CLOCK_DELAY_RAC, 0x00000011},
- {REG_A6XX_RBBM_CLOCK_HYST_RAC, 0x00445044},
- {REG_A6XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222},
- {REG_A6XX_RBBM_CLOCK_MODE_VFD, 0x00002222},
- {REG_A6XX_RBBM_CLOCK_MODE_GPC, 0x00222222},
- {REG_A6XX_RBBM_CLOCK_DELAY_HLSQ_2, 0x00000002},
- {REG_A6XX_RBBM_CLOCK_MODE_HLSQ, 0x00002222},
- {REG_A6XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00004000},
- {REG_A6XX_RBBM_CLOCK_DELAY_VFD, 0x00002222},
- {REG_A6XX_RBBM_CLOCK_DELAY_GPC, 0x00000200},
- {REG_A6XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000},
- {REG_A6XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000},
- {REG_A6XX_RBBM_CLOCK_HYST_VFD, 0x00000000},
- {REG_A6XX_RBBM_CLOCK_HYST_GPC, 0x04104004},
- {REG_A6XX_RBBM_CLOCK_HYST_HLSQ, 0x00000000},
- {REG_A6XX_RBBM_CLOCK_CNTL_TEX_FCHE, 0x00000222},
- {REG_A6XX_RBBM_CLOCK_DELAY_TEX_FCHE, 0x00000111},
- {REG_A6XX_RBBM_CLOCK_HYST_TEX_FCHE, 0x00000777},
- {REG_A6XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_HYST_UCHE, 0x00000004},
- {REG_A6XX_RBBM_CLOCK_DELAY_UCHE, 0x00000002},
- {REG_A6XX_RBBM_ISDB_CNT, 0x00000182},
- {REG_A6XX_RBBM_RAC_THRESHOLD_CNT, 0x00000000},
- {REG_A6XX_RBBM_SP_HYST_CNT, 0x00000000},
- {REG_A6XX_RBBM_CLOCK_CNTL_GMU_GX, 0x00000222},
- {REG_A6XX_RBBM_CLOCK_DELAY_GMU_GX, 0x00000111},
- {REG_A6XX_RBBM_CLOCK_HYST_GMU_GX, 0x00000555},
- {},
-};
-
-const struct adreno_reglist a660_hwcg[] = {
- {REG_A6XX_RBBM_CLOCK_CNTL_SP0, 0x02222222},
- {REG_A6XX_RBBM_CLOCK_CNTL2_SP0, 0x02222220},
- {REG_A6XX_RBBM_CLOCK_DELAY_SP0, 0x00000080},
- {REG_A6XX_RBBM_CLOCK_HYST_SP0, 0x0000F3CF},
- {REG_A6XX_RBBM_CLOCK_CNTL_TP0, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL3_TP0, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL4_TP0, 0x00022222},
- {REG_A6XX_RBBM_CLOCK_DELAY_TP0, 0x11111111},
- {REG_A6XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111},
- {REG_A6XX_RBBM_CLOCK_DELAY3_TP0, 0x11111111},
- {REG_A6XX_RBBM_CLOCK_DELAY4_TP0, 0x00011111},
- {REG_A6XX_RBBM_CLOCK_HYST_TP0, 0x77777777},
- {REG_A6XX_RBBM_CLOCK_HYST2_TP0, 0x77777777},
- {REG_A6XX_RBBM_CLOCK_HYST3_TP0, 0x77777777},
- {REG_A6XX_RBBM_CLOCK_HYST4_TP0, 0x00077777},
- {REG_A6XX_RBBM_CLOCK_CNTL_RB0, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL2_RB0, 0x01002222},
- {REG_A6XX_RBBM_CLOCK_CNTL_CCU0, 0x00002220},
- {REG_A6XX_RBBM_CLOCK_HYST_RB_CCU0, 0x00040F00},
- {REG_A6XX_RBBM_CLOCK_CNTL_RAC, 0x25222022},
- {REG_A6XX_RBBM_CLOCK_CNTL2_RAC, 0x00005555},
- {REG_A6XX_RBBM_CLOCK_DELAY_RAC, 0x00000011},
- {REG_A6XX_RBBM_CLOCK_HYST_RAC, 0x00445044},
- {REG_A6XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222},
- {REG_A6XX_RBBM_CLOCK_MODE_VFD, 0x00002222},
- {REG_A6XX_RBBM_CLOCK_MODE_GPC, 0x00222222},
- {REG_A6XX_RBBM_CLOCK_DELAY_HLSQ_2, 0x00000002},
- {REG_A6XX_RBBM_CLOCK_MODE_HLSQ, 0x00002222},
- {REG_A6XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00004000},
- {REG_A6XX_RBBM_CLOCK_DELAY_VFD, 0x00002222},
- {REG_A6XX_RBBM_CLOCK_DELAY_GPC, 0x00000200},
- {REG_A6XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000},
- {REG_A6XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000},
- {REG_A6XX_RBBM_CLOCK_HYST_VFD, 0x00000000},
- {REG_A6XX_RBBM_CLOCK_HYST_GPC, 0x04104004},
- {REG_A6XX_RBBM_CLOCK_HYST_HLSQ, 0x00000000},
- {REG_A6XX_RBBM_CLOCK_CNTL_TEX_FCHE, 0x00000222},
- {REG_A6XX_RBBM_CLOCK_DELAY_TEX_FCHE, 0x00000111},
- {REG_A6XX_RBBM_CLOCK_HYST_TEX_FCHE, 0x00000000},
- {REG_A6XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_HYST_UCHE, 0x00000004},
- {REG_A6XX_RBBM_CLOCK_DELAY_UCHE, 0x00000002},
- {REG_A6XX_RBBM_ISDB_CNT, 0x00000182},
- {REG_A6XX_RBBM_RAC_THRESHOLD_CNT, 0x00000000},
- {REG_A6XX_RBBM_SP_HYST_CNT, 0x00000000},
- {REG_A6XX_RBBM_CLOCK_CNTL_GMU_GX, 0x00000222},
- {REG_A6XX_RBBM_CLOCK_DELAY_GMU_GX, 0x00000111},
- {REG_A6XX_RBBM_CLOCK_HYST_GMU_GX, 0x00000555},
- {},
-};
-
-const struct adreno_reglist a690_hwcg[] = {
- {REG_A6XX_RBBM_CLOCK_CNTL_SP0, 0x02222222},
- {REG_A6XX_RBBM_CLOCK_CNTL2_SP0, 0x02222220},
- {REG_A6XX_RBBM_CLOCK_DELAY_SP0, 0x00000080},
- {REG_A6XX_RBBM_CLOCK_HYST_SP0, 0x0000F3CF},
- {REG_A6XX_RBBM_CLOCK_CNTL_TP0, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL3_TP0, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL4_TP0, 0x00022222},
- {REG_A6XX_RBBM_CLOCK_DELAY_TP0, 0x11111111},
- {REG_A6XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111},
- {REG_A6XX_RBBM_CLOCK_DELAY3_TP0, 0x11111111},
- {REG_A6XX_RBBM_CLOCK_DELAY4_TP0, 0x00011111},
- {REG_A6XX_RBBM_CLOCK_HYST_TP0, 0x77777777},
- {REG_A6XX_RBBM_CLOCK_HYST2_TP0, 0x77777777},
- {REG_A6XX_RBBM_CLOCK_HYST3_TP0, 0x77777777},
- {REG_A6XX_RBBM_CLOCK_HYST4_TP0, 0x00077777},
- {REG_A6XX_RBBM_CLOCK_CNTL_RB0, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_CNTL2_RB0, 0x01002222},
- {REG_A6XX_RBBM_CLOCK_CNTL_CCU0, 0x00002220},
- {REG_A6XX_RBBM_CLOCK_HYST_RB_CCU0, 0x00040F00},
- {REG_A6XX_RBBM_CLOCK_CNTL_RAC, 0x25222022},
- {REG_A6XX_RBBM_CLOCK_CNTL2_RAC, 0x00005555},
- {REG_A6XX_RBBM_CLOCK_DELAY_RAC, 0x00000011},
- {REG_A6XX_RBBM_CLOCK_HYST_RAC, 0x00445044},
- {REG_A6XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222},
- {REG_A6XX_RBBM_CLOCK_MODE_VFD, 0x00002222},
- {REG_A6XX_RBBM_CLOCK_MODE_GPC, 0x00222222},
- {REG_A6XX_RBBM_CLOCK_DELAY_HLSQ_2, 0x00000002},
- {REG_A6XX_RBBM_CLOCK_MODE_HLSQ, 0x00002222},
- {REG_A6XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00004000},
- {REG_A6XX_RBBM_CLOCK_DELAY_VFD, 0x00002222},
- {REG_A6XX_RBBM_CLOCK_DELAY_GPC, 0x00000200},
- {REG_A6XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000},
- {REG_A6XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000},
- {REG_A6XX_RBBM_CLOCK_HYST_VFD, 0x00000000},
- {REG_A6XX_RBBM_CLOCK_HYST_GPC, 0x04104004},
- {REG_A6XX_RBBM_CLOCK_HYST_HLSQ, 0x00000000},
- {REG_A6XX_RBBM_CLOCK_CNTL_TEX_FCHE, 0x00000222},
- {REG_A6XX_RBBM_CLOCK_DELAY_TEX_FCHE, 0x00000111},
- {REG_A6XX_RBBM_CLOCK_HYST_TEX_FCHE, 0x00000000},
- {REG_A6XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222},
- {REG_A6XX_RBBM_CLOCK_HYST_UCHE, 0x00000004},
- {REG_A6XX_RBBM_CLOCK_DELAY_UCHE, 0x00000002},
- {REG_A6XX_RBBM_CLOCK_CNTL, 0x8AA8AA82},
- {REG_A6XX_RBBM_ISDB_CNT, 0x00000182},
- {REG_A6XX_RBBM_RAC_THRESHOLD_CNT, 0x00000000},
- {REG_A6XX_RBBM_SP_HYST_CNT, 0x00000000},
- {REG_A6XX_RBBM_CLOCK_CNTL_GMU_GX, 0x00000222},
- {REG_A6XX_RBBM_CLOCK_DELAY_GMU_GX, 0x00000111},
- {REG_A6XX_RBBM_CLOCK_HYST_GMU_GX, 0x00000555},
- {REG_A6XX_GPU_GMU_AO_GMU_CGC_MODE_CNTL, 0x20200},
- {REG_A6XX_GPU_GMU_AO_GMU_CGC_DELAY_CNTL, 0x10111},
- {REG_A6XX_GPU_GMU_AO_GMU_CGC_HYST_CNTL, 0x5555},
- {}
-};
-
-const struct adreno_reglist a702_hwcg[] = {
- { REG_A6XX_RBBM_CLOCK_CNTL_SP0, 0x22222222 },
- { REG_A6XX_RBBM_CLOCK_CNTL2_SP0, 0x02222220 },
- { REG_A6XX_RBBM_CLOCK_DELAY_SP0, 0x00000081 },
- { REG_A6XX_RBBM_CLOCK_HYST_SP0, 0x0000f3cf },
- { REG_A6XX_RBBM_CLOCK_CNTL_TP0, 0x22222222 },
- { REG_A6XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222 },
- { REG_A6XX_RBBM_CLOCK_CNTL3_TP0, 0x22222222 },
- { REG_A6XX_RBBM_CLOCK_CNTL4_TP0, 0x00022222 },
- { REG_A6XX_RBBM_CLOCK_DELAY_TP0, 0x11111111 },
- { REG_A6XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111 },
- { REG_A6XX_RBBM_CLOCK_DELAY3_TP0, 0x11111111 },
- { REG_A6XX_RBBM_CLOCK_DELAY4_TP0, 0x00011111 },
- { REG_A6XX_RBBM_CLOCK_HYST_TP0, 0x77777777 },
- { REG_A6XX_RBBM_CLOCK_HYST2_TP0, 0x77777777 },
- { REG_A6XX_RBBM_CLOCK_HYST3_TP0, 0x77777777 },
- { REG_A6XX_RBBM_CLOCK_HYST4_TP0, 0x00077777 },
- { REG_A6XX_RBBM_CLOCK_CNTL_RB0, 0x22222222 },
- { REG_A6XX_RBBM_CLOCK_CNTL2_RB0, 0x01202222 },
- { REG_A6XX_RBBM_CLOCK_CNTL_CCU0, 0x00002220 },
- { REG_A6XX_RBBM_CLOCK_HYST_RB_CCU0, 0x00040f00 },
- { REG_A6XX_RBBM_CLOCK_CNTL_RAC, 0x05522022 },
- { REG_A6XX_RBBM_CLOCK_CNTL2_RAC, 0x00005555 },
- { REG_A6XX_RBBM_CLOCK_DELAY_RAC, 0x00000011 },
- { REG_A6XX_RBBM_CLOCK_HYST_RAC, 0x00445044 },
- { REG_A6XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222 },
- { REG_A6XX_RBBM_CLOCK_MODE_VFD, 0x00002222 },
- { REG_A6XX_RBBM_CLOCK_MODE_GPC, 0x02222222 },
- { REG_A6XX_RBBM_CLOCK_DELAY_HLSQ_2, 0x00000002 },
- { REG_A6XX_RBBM_CLOCK_MODE_HLSQ, 0x00002222 },
- { REG_A6XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00004000 },
- { REG_A6XX_RBBM_CLOCK_DELAY_VFD, 0x00002222 },
- { REG_A6XX_RBBM_CLOCK_DELAY_GPC, 0x00000200 },
- { REG_A6XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000 },
- { REG_A6XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000 },
- { REG_A6XX_RBBM_CLOCK_HYST_VFD, 0x00000000 },
- { REG_A6XX_RBBM_CLOCK_HYST_GPC, 0x04104004 },
- { REG_A6XX_RBBM_CLOCK_HYST_HLSQ, 0x00000000 },
- { REG_A6XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222 },
- { REG_A6XX_RBBM_CLOCK_HYST_UCHE, 0x00000004 },
- { REG_A6XX_RBBM_CLOCK_DELAY_UCHE, 0x00000002 },
- { REG_A6XX_RBBM_ISDB_CNT, 0x00000182 },
- { REG_A6XX_RBBM_RAC_THRESHOLD_CNT, 0x00000000 },
- { REG_A6XX_RBBM_SP_HYST_CNT, 0x00000000 },
- { REG_A6XX_RBBM_CLOCK_CNTL_GMU_GX, 0x00000222 },
- { REG_A6XX_RBBM_CLOCK_DELAY_GMU_GX, 0x00000111 },
- { REG_A6XX_RBBM_CLOCK_HYST_GMU_GX, 0x00000555 },
- { REG_A6XX_RBBM_CLOCK_CNTL_FCHE, 0x00000222 },
- { REG_A6XX_RBBM_CLOCK_DELAY_FCHE, 0x00000000 },
- { REG_A6XX_RBBM_CLOCK_HYST_FCHE, 0x00000000 },
- { REG_A6XX_RBBM_CLOCK_CNTL_GLC, 0x00222222 },
- { REG_A6XX_RBBM_CLOCK_DELAY_GLC, 0x00000000 },
- { REG_A6XX_RBBM_CLOCK_HYST_GLC, 0x00000000 },
- { REG_A6XX_RBBM_CLOCK_CNTL_MHUB, 0x00000002 },
- { REG_A6XX_RBBM_CLOCK_DELAY_MHUB, 0x00000000 },
- { REG_A6XX_RBBM_CLOCK_HYST_MHUB, 0x00000000 },
- {}
-};
-
-const struct adreno_reglist a730_hwcg[] = {
- { REG_A6XX_RBBM_CLOCK_CNTL_SP0, 0x02222222 },
- { REG_A6XX_RBBM_CLOCK_CNTL2_SP0, 0x02022222 },
- { REG_A6XX_RBBM_CLOCK_HYST_SP0, 0x0000f3cf },
- { REG_A6XX_RBBM_CLOCK_DELAY_SP0, 0x00000080 },
- { REG_A6XX_RBBM_CLOCK_CNTL_TP0, 0x22222220 },
- { REG_A6XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222 },
- { REG_A6XX_RBBM_CLOCK_CNTL3_TP0, 0x22222222 },
- { REG_A6XX_RBBM_CLOCK_CNTL4_TP0, 0x00222222 },
- { REG_A6XX_RBBM_CLOCK_HYST_TP0, 0x77777777 },
- { REG_A6XX_RBBM_CLOCK_HYST2_TP0, 0x77777777 },
- { REG_A6XX_RBBM_CLOCK_HYST3_TP0, 0x77777777 },
- { REG_A6XX_RBBM_CLOCK_HYST4_TP0, 0x00077777 },
- { REG_A6XX_RBBM_CLOCK_DELAY_TP0, 0x11111111 },
- { REG_A6XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111 },
- { REG_A6XX_RBBM_CLOCK_DELAY3_TP0, 0x11111111 },
- { REG_A6XX_RBBM_CLOCK_DELAY4_TP0, 0x00011111 },
- { REG_A6XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222 },
- { REG_A6XX_RBBM_CLOCK_HYST_UCHE, 0x00000004 },
- { REG_A6XX_RBBM_CLOCK_DELAY_UCHE, 0x00000002 },
- { REG_A6XX_RBBM_CLOCK_CNTL_RB0, 0x22222222 },
- { REG_A6XX_RBBM_CLOCK_CNTL2_RB0, 0x01002222 },
- { REG_A6XX_RBBM_CLOCK_CNTL_CCU0, 0x00002220 },
- { REG_A6XX_RBBM_CLOCK_HYST_RB_CCU0, 0x44000f00 },
- { REG_A6XX_RBBM_CLOCK_CNTL_RAC, 0x25222022 },
- { REG_A6XX_RBBM_CLOCK_CNTL2_RAC, 0x00555555 },
- { REG_A6XX_RBBM_CLOCK_DELAY_RAC, 0x00000011 },
- { REG_A6XX_RBBM_CLOCK_HYST_RAC, 0x00440044 },
- { REG_A6XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222 },
- { REG_A7XX_RBBM_CLOCK_MODE2_GRAS, 0x00000222 },
- { REG_A7XX_RBBM_CLOCK_MODE_BV_GRAS, 0x00222222 },
- { REG_A6XX_RBBM_CLOCK_MODE_GPC, 0x02222223 },
- { REG_A6XX_RBBM_CLOCK_MODE_VFD, 0x00002222 },
- { REG_A7XX_RBBM_CLOCK_MODE_BV_GPC, 0x00222222 },
- { REG_A7XX_RBBM_CLOCK_MODE_BV_VFD, 0x00002222 },
- { REG_A6XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000 },
- { REG_A6XX_RBBM_CLOCK_HYST_GPC, 0x04104004 },
- { REG_A6XX_RBBM_CLOCK_HYST_VFD, 0x00000000 },
- { REG_A6XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00004000 },
- { REG_A6XX_RBBM_CLOCK_DELAY_GPC, 0x00000200 },
- { REG_A6XX_RBBM_CLOCK_DELAY_VFD, 0x00002222 },
- { REG_A6XX_RBBM_CLOCK_MODE_HLSQ, 0x00002222 },
- { REG_A6XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000 },
- { REG_A6XX_RBBM_CLOCK_HYST_HLSQ, 0x00000000 },
- { REG_A6XX_RBBM_CLOCK_DELAY_HLSQ_2, 0x00000002 },
- { REG_A7XX_RBBM_CLOCK_MODE_BV_LRZ, 0x55555552 },
- { REG_A7XX_RBBM_CLOCK_MODE_CP, 0x00000223 },
- { REG_A6XX_RBBM_CLOCK_CNTL, 0x8aa8aa82 },
- { REG_A6XX_RBBM_ISDB_CNT, 0x00000182 },
- { REG_A6XX_RBBM_RAC_THRESHOLD_CNT, 0x00000000 },
- { REG_A6XX_RBBM_SP_HYST_CNT, 0x00000000 },
- { REG_A6XX_RBBM_CLOCK_CNTL_GMU_GX, 0x00000222 },
- { REG_A6XX_RBBM_CLOCK_DELAY_GMU_GX, 0x00000111 },
- { REG_A6XX_RBBM_CLOCK_HYST_GMU_GX, 0x00000555 },
- {},
-};
-
-const struct adreno_reglist a740_hwcg[] = {
- { REG_A6XX_RBBM_CLOCK_CNTL_SP0, 0x02222222 },
- { REG_A6XX_RBBM_CLOCK_CNTL2_SP0, 0x22022222 },
- { REG_A6XX_RBBM_CLOCK_HYST_SP0, 0x003cf3cf },
- { REG_A6XX_RBBM_CLOCK_DELAY_SP0, 0x00000080 },
- { REG_A6XX_RBBM_CLOCK_CNTL_TP0, 0x22222220 },
- { REG_A6XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222 },
- { REG_A6XX_RBBM_CLOCK_CNTL3_TP0, 0x22222222 },
- { REG_A6XX_RBBM_CLOCK_CNTL4_TP0, 0x00222222 },
- { REG_A6XX_RBBM_CLOCK_HYST_TP0, 0x77777777 },
- { REG_A6XX_RBBM_CLOCK_HYST2_TP0, 0x77777777 },
- { REG_A6XX_RBBM_CLOCK_HYST3_TP0, 0x77777777 },
- { REG_A6XX_RBBM_CLOCK_HYST4_TP0, 0x00077777 },
- { REG_A6XX_RBBM_CLOCK_DELAY_TP0, 0x11111111 },
- { REG_A6XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111 },
- { REG_A6XX_RBBM_CLOCK_DELAY3_TP0, 0x11111111 },
- { REG_A6XX_RBBM_CLOCK_DELAY4_TP0, 0x00011111 },
- { REG_A6XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222 },
- { REG_A6XX_RBBM_CLOCK_CNTL2_UCHE, 0x00222222 },
- { REG_A6XX_RBBM_CLOCK_HYST_UCHE, 0x00000444 },
- { REG_A6XX_RBBM_CLOCK_DELAY_UCHE, 0x00000222 },
- { REG_A6XX_RBBM_CLOCK_CNTL_RB0, 0x22222222 },
- { REG_A6XX_RBBM_CLOCK_CNTL2_RB0, 0x01002222 },
- { REG_A6XX_RBBM_CLOCK_CNTL_CCU0, 0x00002220 },
- { REG_A6XX_RBBM_CLOCK_HYST_RB_CCU0, 0x44000f00 },
- { REG_A6XX_RBBM_CLOCK_CNTL_RAC, 0x25222022 },
- { REG_A6XX_RBBM_CLOCK_CNTL2_RAC, 0x00555555 },
- { REG_A6XX_RBBM_CLOCK_DELAY_RAC, 0x00000011 },
- { REG_A6XX_RBBM_CLOCK_HYST_RAC, 0x00440044 },
- { REG_A6XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222 },
- { REG_A7XX_RBBM_CLOCK_MODE2_GRAS, 0x00000222 },
- { REG_A7XX_RBBM_CLOCK_MODE_BV_GRAS, 0x00222222 },
- { REG_A6XX_RBBM_CLOCK_MODE_GPC, 0x02222223 },
- { REG_A6XX_RBBM_CLOCK_MODE_VFD, 0x00222222 },
- { REG_A7XX_RBBM_CLOCK_MODE_BV_GPC, 0x00222222 },
- { REG_A7XX_RBBM_CLOCK_MODE_BV_VFD, 0x00002222 },
- { REG_A6XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000 },
- { REG_A6XX_RBBM_CLOCK_HYST_GPC, 0x04104004 },
- { REG_A6XX_RBBM_CLOCK_HYST_VFD, 0x00000000 },
- { REG_A6XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00000000 },
- { REG_A6XX_RBBM_CLOCK_DELAY_GPC, 0x00000200 },
- { REG_A6XX_RBBM_CLOCK_DELAY_VFD, 0x00000000 },
- { REG_A6XX_RBBM_CLOCK_MODE_HLSQ, 0x00002222 },
- { REG_A6XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000 },
- { REG_A6XX_RBBM_CLOCK_HYST_HLSQ, 0x00000000 },
- { REG_A7XX_RBBM_CLOCK_MODE_BV_LRZ, 0x55555552 },
- { REG_A7XX_RBBM_CLOCK_HYST2_VFD, 0x00000000 },
- { REG_A7XX_RBBM_CLOCK_MODE_CP, 0x00000222 },
- { REG_A6XX_RBBM_CLOCK_CNTL, 0x8aa8aa82 },
- { REG_A6XX_RBBM_ISDB_CNT, 0x00000182 },
- { REG_A6XX_RBBM_RAC_THRESHOLD_CNT, 0x00000000 },
- { REG_A6XX_RBBM_SP_HYST_CNT, 0x00000000 },
- { REG_A6XX_RBBM_CLOCK_CNTL_GMU_GX, 0x00000222 },
- { REG_A6XX_RBBM_CLOCK_DELAY_GMU_GX, 0x00000111 },
- { REG_A6XX_RBBM_CLOCK_HYST_GMU_GX, 0x00000555 },
- {},
-};
-
static void a6xx_set_hwcg(struct msm_gpu *gpu, bool state)
{
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
@@ -1020,7 +404,7 @@ static void a6xx_set_hwcg(struct msm_gpu *gpu, bool state)
unsigned int i;
u32 val, clock_cntl_on, cgc_mode;
- if (!(adreno_gpu->info->hwcg || adreno_is_a7xx(adreno_gpu)))
+ if (!(adreno_gpu->info->a6xx->hwcg || adreno_is_a7xx(adreno_gpu)))
return;
if (adreno_is_a630(adreno_gpu))
@@ -1043,7 +427,7 @@ static void a6xx_set_hwcg(struct msm_gpu *gpu, bool state)
state ? 0x5555 : 0);
}
- if (!adreno_gpu->info->hwcg) {
+ if (!adreno_gpu->info->a6xx->hwcg) {
gpu_write(gpu, REG_A7XX_RBBM_CLOCK_CNTL_GLOBAL, 1);
gpu_write(gpu, REG_A7XX_RBBM_CGC_GLOBAL_LOAD_CMD, state ? 1 : 0);
@@ -1072,7 +456,7 @@ static void a6xx_set_hwcg(struct msm_gpu *gpu, bool state)
if (!adreno_is_a610_family(adreno_gpu) && !adreno_is_a7xx(adreno_gpu))
gmu_rmw(gmu, REG_A6XX_GPU_GMU_GX_SPTPRAC_CLOCK_CONTROL, 1, 0);
- for (i = 0; (reg = &adreno_gpu->info->hwcg[i], reg->offset); i++)
+ for (i = 0; (reg = &adreno_gpu->info->a6xx->hwcg[i], reg->offset); i++)
gpu_write(gpu, reg->offset, state ? reg->value : 0);
/* Enable SP clock */
@@ -1082,256 +466,11 @@ static void a6xx_set_hwcg(struct msm_gpu *gpu, bool state)
gpu_write(gpu, REG_A6XX_RBBM_CLOCK_CNTL, state ? clock_cntl_on : 0);
}
-/* For a615, a616, a618, a619, a630, a640 and a680 */
-static const u32 a6xx_protect[] = {
- A6XX_PROTECT_RDONLY(0x00000, 0x04ff),
- A6XX_PROTECT_RDONLY(0x00501, 0x0005),
- A6XX_PROTECT_RDONLY(0x0050b, 0x02f4),
- A6XX_PROTECT_NORDWR(0x0050e, 0x0000),
- A6XX_PROTECT_NORDWR(0x00510, 0x0000),
- A6XX_PROTECT_NORDWR(0x00534, 0x0000),
- A6XX_PROTECT_NORDWR(0x00800, 0x0082),
- A6XX_PROTECT_NORDWR(0x008a0, 0x0008),
- A6XX_PROTECT_NORDWR(0x008ab, 0x0024),
- A6XX_PROTECT_RDONLY(0x008de, 0x00ae),
- A6XX_PROTECT_NORDWR(0x00900, 0x004d),
- A6XX_PROTECT_NORDWR(0x0098d, 0x0272),
- A6XX_PROTECT_NORDWR(0x00e00, 0x0001),
- A6XX_PROTECT_NORDWR(0x00e03, 0x000c),
- A6XX_PROTECT_NORDWR(0x03c00, 0x00c3),
- A6XX_PROTECT_RDONLY(0x03cc4, 0x1fff),
- A6XX_PROTECT_NORDWR(0x08630, 0x01cf),
- A6XX_PROTECT_NORDWR(0x08e00, 0x0000),
- A6XX_PROTECT_NORDWR(0x08e08, 0x0000),
- A6XX_PROTECT_NORDWR(0x08e50, 0x001f),
- A6XX_PROTECT_NORDWR(0x09624, 0x01db),
- A6XX_PROTECT_NORDWR(0x09e70, 0x0001),
- A6XX_PROTECT_NORDWR(0x09e78, 0x0187),
- A6XX_PROTECT_NORDWR(0x0a630, 0x01cf),
- A6XX_PROTECT_NORDWR(0x0ae02, 0x0000),
- A6XX_PROTECT_NORDWR(0x0ae50, 0x032f),
- A6XX_PROTECT_NORDWR(0x0b604, 0x0000),
- A6XX_PROTECT_NORDWR(0x0be02, 0x0001),
- A6XX_PROTECT_NORDWR(0x0be20, 0x17df),
- A6XX_PROTECT_NORDWR(0x0f000, 0x0bff),
- A6XX_PROTECT_RDONLY(0x0fc00, 0x1fff),
- A6XX_PROTECT_NORDWR(0x11c00, 0x0000), /* note: infinite range */
-};
-
-/* These are for a620 and a650 */
-static const u32 a650_protect[] = {
- A6XX_PROTECT_RDONLY(0x00000, 0x04ff),
- A6XX_PROTECT_RDONLY(0x00501, 0x0005),
- A6XX_PROTECT_RDONLY(0x0050b, 0x02f4),
- A6XX_PROTECT_NORDWR(0x0050e, 0x0000),
- A6XX_PROTECT_NORDWR(0x00510, 0x0000),
- A6XX_PROTECT_NORDWR(0x00534, 0x0000),
- A6XX_PROTECT_NORDWR(0x00800, 0x0082),
- A6XX_PROTECT_NORDWR(0x008a0, 0x0008),
- A6XX_PROTECT_NORDWR(0x008ab, 0x0024),
- A6XX_PROTECT_RDONLY(0x008de, 0x00ae),
- A6XX_PROTECT_NORDWR(0x00900, 0x004d),
- A6XX_PROTECT_NORDWR(0x0098d, 0x0272),
- A6XX_PROTECT_NORDWR(0x00e00, 0x0001),
- A6XX_PROTECT_NORDWR(0x00e03, 0x000c),
- A6XX_PROTECT_NORDWR(0x03c00, 0x00c3),
- A6XX_PROTECT_RDONLY(0x03cc4, 0x1fff),
- A6XX_PROTECT_NORDWR(0x08630, 0x01cf),
- A6XX_PROTECT_NORDWR(0x08e00, 0x0000),
- A6XX_PROTECT_NORDWR(0x08e08, 0x0000),
- A6XX_PROTECT_NORDWR(0x08e50, 0x001f),
- A6XX_PROTECT_NORDWR(0x08e80, 0x027f),
- A6XX_PROTECT_NORDWR(0x09624, 0x01db),
- A6XX_PROTECT_NORDWR(0x09e60, 0x0011),
- A6XX_PROTECT_NORDWR(0x09e78, 0x0187),
- A6XX_PROTECT_NORDWR(0x0a630, 0x01cf),
- A6XX_PROTECT_NORDWR(0x0ae02, 0x0000),
- A6XX_PROTECT_NORDWR(0x0ae50, 0x032f),
- A6XX_PROTECT_NORDWR(0x0b604, 0x0000),
- A6XX_PROTECT_NORDWR(0x0b608, 0x0007),
- A6XX_PROTECT_NORDWR(0x0be02, 0x0001),
- A6XX_PROTECT_NORDWR(0x0be20, 0x17df),
- A6XX_PROTECT_NORDWR(0x0f000, 0x0bff),
- A6XX_PROTECT_RDONLY(0x0fc00, 0x1fff),
- A6XX_PROTECT_NORDWR(0x18400, 0x1fff),
- A6XX_PROTECT_NORDWR(0x1a800, 0x1fff),
- A6XX_PROTECT_NORDWR(0x1f400, 0x0443),
- A6XX_PROTECT_RDONLY(0x1f844, 0x007b),
- A6XX_PROTECT_NORDWR(0x1f887, 0x001b),
- A6XX_PROTECT_NORDWR(0x1f8c0, 0x0000), /* note: infinite range */
-};
-
-/* These are for a635 and a660 */
-static const u32 a660_protect[] = {
- A6XX_PROTECT_RDONLY(0x00000, 0x04ff),
- A6XX_PROTECT_RDONLY(0x00501, 0x0005),
- A6XX_PROTECT_RDONLY(0x0050b, 0x02f4),
- A6XX_PROTECT_NORDWR(0x0050e, 0x0000),
- A6XX_PROTECT_NORDWR(0x00510, 0x0000),
- A6XX_PROTECT_NORDWR(0x00534, 0x0000),
- A6XX_PROTECT_NORDWR(0x00800, 0x0082),
- A6XX_PROTECT_NORDWR(0x008a0, 0x0008),
- A6XX_PROTECT_NORDWR(0x008ab, 0x0024),
- A6XX_PROTECT_RDONLY(0x008de, 0x00ae),
- A6XX_PROTECT_NORDWR(0x00900, 0x004d),
- A6XX_PROTECT_NORDWR(0x0098d, 0x0272),
- A6XX_PROTECT_NORDWR(0x00e00, 0x0001),
- A6XX_PROTECT_NORDWR(0x00e03, 0x000c),
- A6XX_PROTECT_NORDWR(0x03c00, 0x00c3),
- A6XX_PROTECT_RDONLY(0x03cc4, 0x1fff),
- A6XX_PROTECT_NORDWR(0x08630, 0x01cf),
- A6XX_PROTECT_NORDWR(0x08e00, 0x0000),
- A6XX_PROTECT_NORDWR(0x08e08, 0x0000),
- A6XX_PROTECT_NORDWR(0x08e50, 0x001f),
- A6XX_PROTECT_NORDWR(0x08e80, 0x027f),
- A6XX_PROTECT_NORDWR(0x09624, 0x01db),
- A6XX_PROTECT_NORDWR(0x09e60, 0x0011),
- A6XX_PROTECT_NORDWR(0x09e78, 0x0187),
- A6XX_PROTECT_NORDWR(0x0a630, 0x01cf),
- A6XX_PROTECT_NORDWR(0x0ae02, 0x0000),
- A6XX_PROTECT_NORDWR(0x0ae50, 0x012f),
- A6XX_PROTECT_NORDWR(0x0b604, 0x0000),
- A6XX_PROTECT_NORDWR(0x0b608, 0x0006),
- A6XX_PROTECT_NORDWR(0x0be02, 0x0001),
- A6XX_PROTECT_NORDWR(0x0be20, 0x015f),
- A6XX_PROTECT_NORDWR(0x0d000, 0x05ff),
- A6XX_PROTECT_NORDWR(0x0f000, 0x0bff),
- A6XX_PROTECT_RDONLY(0x0fc00, 0x1fff),
- A6XX_PROTECT_NORDWR(0x18400, 0x1fff),
- A6XX_PROTECT_NORDWR(0x1a400, 0x1fff),
- A6XX_PROTECT_NORDWR(0x1f400, 0x0443),
- A6XX_PROTECT_RDONLY(0x1f844, 0x007b),
- A6XX_PROTECT_NORDWR(0x1f860, 0x0000),
- A6XX_PROTECT_NORDWR(0x1f887, 0x001b),
- A6XX_PROTECT_NORDWR(0x1f8c0, 0x0000), /* note: infinite range */
-};
-
-/* These are for a690 */
-static const u32 a690_protect[] = {
- A6XX_PROTECT_RDONLY(0x00000, 0x004ff),
- A6XX_PROTECT_RDONLY(0x00501, 0x00001),
- A6XX_PROTECT_RDONLY(0x0050b, 0x002f4),
- A6XX_PROTECT_NORDWR(0x0050e, 0x00000),
- A6XX_PROTECT_NORDWR(0x00510, 0x00000),
- A6XX_PROTECT_NORDWR(0x00534, 0x00000),
- A6XX_PROTECT_NORDWR(0x00800, 0x00082),
- A6XX_PROTECT_NORDWR(0x008a0, 0x00008),
- A6XX_PROTECT_NORDWR(0x008ab, 0x00024),
- A6XX_PROTECT_RDONLY(0x008de, 0x000ae),
- A6XX_PROTECT_NORDWR(0x00900, 0x0004d),
- A6XX_PROTECT_NORDWR(0x0098d, 0x00272),
- A6XX_PROTECT_NORDWR(0x00e00, 0x00001),
- A6XX_PROTECT_NORDWR(0x00e03, 0x0000c),
- A6XX_PROTECT_NORDWR(0x03c00, 0x000c3),
- A6XX_PROTECT_RDONLY(0x03cc4, 0x01fff),
- A6XX_PROTECT_NORDWR(0x08630, 0x001cf),
- A6XX_PROTECT_NORDWR(0x08e00, 0x00000),
- A6XX_PROTECT_NORDWR(0x08e08, 0x00007),
- A6XX_PROTECT_NORDWR(0x08e50, 0x0001f),
- A6XX_PROTECT_NORDWR(0x08e80, 0x0027f),
- A6XX_PROTECT_NORDWR(0x09624, 0x001db),
- A6XX_PROTECT_NORDWR(0x09e60, 0x00011),
- A6XX_PROTECT_NORDWR(0x09e78, 0x00187),
- A6XX_PROTECT_NORDWR(0x0a630, 0x001cf),
- A6XX_PROTECT_NORDWR(0x0ae02, 0x00000),
- A6XX_PROTECT_NORDWR(0x0ae50, 0x0012f),
- A6XX_PROTECT_NORDWR(0x0b604, 0x00000),
- A6XX_PROTECT_NORDWR(0x0b608, 0x00006),
- A6XX_PROTECT_NORDWR(0x0be02, 0x00001),
- A6XX_PROTECT_NORDWR(0x0be20, 0x0015f),
- A6XX_PROTECT_NORDWR(0x0d000, 0x005ff),
- A6XX_PROTECT_NORDWR(0x0f000, 0x00bff),
- A6XX_PROTECT_RDONLY(0x0fc00, 0x01fff),
- A6XX_PROTECT_NORDWR(0x11c00, 0x00000), /*note: infiite range */
-};
-
-static const u32 a730_protect[] = {
- A6XX_PROTECT_RDONLY(0x00000, 0x04ff),
- A6XX_PROTECT_RDONLY(0x0050b, 0x0058),
- A6XX_PROTECT_NORDWR(0x0050e, 0x0000),
- A6XX_PROTECT_NORDWR(0x00510, 0x0000),
- A6XX_PROTECT_NORDWR(0x00534, 0x0000),
- A6XX_PROTECT_RDONLY(0x005fb, 0x009d),
- A6XX_PROTECT_NORDWR(0x00699, 0x01e9),
- A6XX_PROTECT_NORDWR(0x008a0, 0x0008),
- A6XX_PROTECT_NORDWR(0x008ab, 0x0024),
- /* 0x008d0-0x008dd and 0x008e0-0x008e6 are unprotected on purpose for tools like perfetto */
- A6XX_PROTECT_NORDWR(0x008de, 0x0001),
- A6XX_PROTECT_RDONLY(0x008e7, 0x014b),
- A6XX_PROTECT_NORDWR(0x00900, 0x004d),
- A6XX_PROTECT_NORDWR(0x0098d, 0x00b2),
- A6XX_PROTECT_NORDWR(0x00a41, 0x01be),
- A6XX_PROTECT_NORDWR(0x00df0, 0x0001),
- A6XX_PROTECT_NORDWR(0x00e01, 0x0000),
- A6XX_PROTECT_NORDWR(0x00e07, 0x0008),
- A6XX_PROTECT_NORDWR(0x03c00, 0x00c3),
- A6XX_PROTECT_RDONLY(0x03cc4, 0x1fff),
- A6XX_PROTECT_NORDWR(0x08630, 0x01cf),
- A6XX_PROTECT_NORDWR(0x08e00, 0x0000),
- A6XX_PROTECT_NORDWR(0x08e08, 0x0000),
- A6XX_PROTECT_NORDWR(0x08e50, 0x001f),
- A6XX_PROTECT_NORDWR(0x08e80, 0x0280),
- A6XX_PROTECT_NORDWR(0x09624, 0x01db),
- A6XX_PROTECT_NORDWR(0x09e40, 0x0000),
- A6XX_PROTECT_NORDWR(0x09e64, 0x000d),
- A6XX_PROTECT_NORDWR(0x09e78, 0x0187),
- A6XX_PROTECT_NORDWR(0x0a630, 0x01cf),
- A6XX_PROTECT_NORDWR(0x0ae02, 0x0000),
- A6XX_PROTECT_NORDWR(0x0ae50, 0x000f),
- A6XX_PROTECT_NORDWR(0x0ae66, 0x0003),
- A6XX_PROTECT_NORDWR(0x0ae6f, 0x0003),
- A6XX_PROTECT_NORDWR(0x0b604, 0x0003),
- A6XX_PROTECT_NORDWR(0x0ec00, 0x0fff),
- A6XX_PROTECT_RDONLY(0x0fc00, 0x1fff),
- A6XX_PROTECT_NORDWR(0x18400, 0x0053),
- A6XX_PROTECT_RDONLY(0x18454, 0x0004),
- A6XX_PROTECT_NORDWR(0x18459, 0x1fff),
- A6XX_PROTECT_NORDWR(0x1a459, 0x1fff),
- A6XX_PROTECT_NORDWR(0x1c459, 0x1fff),
- A6XX_PROTECT_NORDWR(0x1f400, 0x0443),
- A6XX_PROTECT_RDONLY(0x1f844, 0x007b),
- A6XX_PROTECT_NORDWR(0x1f860, 0x0000),
- A6XX_PROTECT_NORDWR(0x1f878, 0x002a),
- /* CP_PROTECT_REG[45, 46] are left untouched! */
- 0,
- 0,
- A6XX_PROTECT_NORDWR(0x1f8c0, 0x00000),
-};
-
static void a6xx_set_cp_protect(struct msm_gpu *gpu)
{
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
- const u32 *regs = a6xx_protect;
- unsigned i, count, count_max;
-
- if (adreno_is_a650(adreno_gpu) || adreno_is_a702(adreno_gpu)) {
- regs = a650_protect;
- count = ARRAY_SIZE(a650_protect);
- count_max = 48;
- BUILD_BUG_ON(ARRAY_SIZE(a650_protect) > 48);
- } else if (adreno_is_a690(adreno_gpu)) {
- regs = a690_protect;
- count = ARRAY_SIZE(a690_protect);
- count_max = 48;
- BUILD_BUG_ON(ARRAY_SIZE(a690_protect) > 48);
- } else if (adreno_is_a660_family(adreno_gpu)) {
- regs = a660_protect;
- count = ARRAY_SIZE(a660_protect);
- count_max = 48;
- BUILD_BUG_ON(ARRAY_SIZE(a660_protect) > 48);
- } else if (adreno_is_a730(adreno_gpu) ||
- adreno_is_a740(adreno_gpu) ||
- adreno_is_a750(adreno_gpu)) {
- regs = a730_protect;
- count = ARRAY_SIZE(a730_protect);
- count_max = 48;
- BUILD_BUG_ON(ARRAY_SIZE(a730_protect) > 48);
- } else {
- regs = a6xx_protect;
- count = ARRAY_SIZE(a6xx_protect);
- count_max = 32;
- BUILD_BUG_ON(ARRAY_SIZE(a6xx_protect) > 32);
- }
+ const struct adreno_protect *protect = adreno_gpu->info->a6xx->protect;
+ unsigned i;
/*
* Enable access protection to privileged registers, fault on an access
@@ -1343,13 +482,13 @@ static void a6xx_set_cp_protect(struct msm_gpu *gpu)
A6XX_CP_PROTECT_CNTL_ACCESS_FAULT_ON_VIOL_EN |
A6XX_CP_PROTECT_CNTL_LAST_SPAN_INF_RANGE);
- for (i = 0; i < count - 1; i++) {
+ for (i = 0; i < protect->count - 1; i++) {
/* Intentionally skip writing to some registers */
- if (regs[i])
- gpu_write(gpu, REG_A6XX_CP_PROTECT(i), regs[i]);
+ if (protect->regs[i])
+ gpu_write(gpu, REG_A6XX_CP_PROTECT(i), protect->regs[i]);
}
/* last CP_PROTECT to have "infinite" length on the last entry */
- gpu_write(gpu, REG_A6XX_CP_PROTECT(count_max - 1), regs[i]);
+ gpu_write(gpu, REG_A6XX_CP_PROTECT(protect->count_max - 1), protect->regs[i]);
}
static void a6xx_calc_ubwc_config(struct adreno_gpu *gpu)
@@ -1409,7 +548,7 @@ static void a6xx_calc_ubwc_config(struct adreno_gpu *gpu)
if (adreno_is_a702(gpu)) {
gpu->ubwc_config.highest_bank_bit = 14;
gpu->ubwc_config.min_acc_len = 1;
- gpu->ubwc_config.ubwc_mode = 2;
+ gpu->ubwc_config.ubwc_mode = 0;
}
}
@@ -1686,7 +825,8 @@ static int a6xx_zap_shader_init(struct msm_gpu *gpu)
A6XX_RBBM_INT_0_MASK_RBBM_HANG_DETECT | \
A6XX_RBBM_INT_0_MASK_UCHE_OOB_ACCESS | \
A6XX_RBBM_INT_0_MASK_UCHE_TRAP_INTR | \
- A6XX_RBBM_INT_0_MASK_TSBWRITEERROR)
+ A6XX_RBBM_INT_0_MASK_TSBWRITEERROR | \
+ A6XX_RBBM_INT_0_MASK_SWFUSEVIOLATION)
#define A7XX_APRIV_MASK (A6XX_CP_APRIV_CNTL_ICACHE | \
A6XX_CP_APRIV_CNTL_RBFETCH | \
@@ -1715,20 +855,18 @@ static int hw_init(struct msm_gpu *gpu)
/* Clear GBIF halt in case GX domain was not collapsed */
if (adreno_is_a619_holi(adreno_gpu)) {
gpu_write(gpu, REG_A6XX_GBIF_HALT, 0);
+ gpu_read(gpu, REG_A6XX_GBIF_HALT);
+
gpu_write(gpu, REG_A6XX_RBBM_GPR0_CNTL, 0);
- /* Let's make extra sure that the GPU can access the memory.. */
- mb();
+ gpu_read(gpu, REG_A6XX_RBBM_GPR0_CNTL);
} else if (a6xx_has_gbif(adreno_gpu)) {
gpu_write(gpu, REG_A6XX_GBIF_HALT, 0);
+ gpu_read(gpu, REG_A6XX_GBIF_HALT);
+
gpu_write(gpu, REG_A6XX_RBBM_GBIF_HALT, 0);
- /* Let's make extra sure that the GPU can access the memory.. */
- mb();
+ gpu_read(gpu, REG_A6XX_RBBM_GBIF_HALT);
}
- /* Some GPUs are stubborn and take their sweet time to unhalt GBIF! */
- if (adreno_is_a7xx(adreno_gpu) && a6xx_has_gbif(adreno_gpu))
- spin_until(!gpu_read(gpu, REG_A6XX_GBIF_HALT_ACK));
-
gpu_write(gpu, REG_A6XX_RBBM_SECVID_TSB_CNTL, 0);
if (adreno_is_a619_holi(adreno_gpu))
@@ -1891,7 +1029,7 @@ static int hw_init(struct msm_gpu *gpu)
gpu_write(gpu, REG_A6XX_UCHE_CLIENT_PF, BIT(7) | 0x1);
/* Set weights for bicubic filtering */
- if (adreno_is_a650_family(adreno_gpu)) {
+ if (adreno_is_a650_family(adreno_gpu) || adreno_is_x185(adreno_gpu)) {
gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_0, 0);
gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_1,
0x3fe05ff4);
@@ -1951,6 +1089,17 @@ static int hw_init(struct msm_gpu *gpu)
BIT(6) | BIT(5) | BIT(3) | BIT(2) | BIT(1));
}
+ if (adreno_is_a750(adreno_gpu)) {
+ /* Disable ubwc merged UFC request feature */
+ gpu_rmw(gpu, REG_A6XX_RB_CMP_DBG_ECO_CNTL, BIT(19), BIT(19));
+
+ /* Enable TP flaghint and other performance settings */
+ gpu_write(gpu, REG_A6XX_TPL1_DBG_ECO_CNTL1, 0xc0700);
+ } else if (adreno_is_a7xx(adreno_gpu)) {
+ /* Disable non-ubwc read reqs from passing write reqs */
+ gpu_rmw(gpu, REG_A6XX_RB_CMP_DBG_ECO_CNTL, BIT(11), BIT(11));
+ }
+
/* Enable interrupts */
gpu_write(gpu, REG_A6XX_RBBM_INT_0_MASK,
adreno_is_a7xx(adreno_gpu) ? A7XX_INT_MASK : A6XX_INT_MASK);
@@ -2356,6 +1505,27 @@ static void a6xx_fault_detect_irq(struct msm_gpu *gpu)
kthread_queue_work(gpu->worker, &gpu->recover_work);
}
+static void a7xx_sw_fuse_violation_irq(struct msm_gpu *gpu)
+{
+ u32 status;
+
+ status = gpu_read(gpu, REG_A7XX_RBBM_SW_FUSE_INT_STATUS);
+ gpu_write(gpu, REG_A7XX_RBBM_SW_FUSE_INT_MASK, 0);
+
+ dev_err_ratelimited(&gpu->pdev->dev, "SW fuse violation status=%8.8x\n", status);
+
+ /*
+ * Ignore FASTBLEND violations, because the HW will silently fall back
+ * to legacy blending.
+ */
+ if (status & (A7XX_CX_MISC_SW_FUSE_VALUE_RAYTRACING |
+ A7XX_CX_MISC_SW_FUSE_VALUE_LPAC)) {
+ del_timer(&gpu->hangcheck_timer);
+
+ kthread_queue_work(gpu->worker, &gpu->recover_work);
+ }
+}
+
static irqreturn_t a6xx_irq(struct msm_gpu *gpu)
{
struct msm_drm_private *priv = gpu->dev->dev_private;
@@ -2384,6 +1554,9 @@ static irqreturn_t a6xx_irq(struct msm_gpu *gpu)
if (status & A6XX_RBBM_INT_0_MASK_UCHE_OOB_ACCESS)
dev_err_ratelimited(&gpu->pdev->dev, "UCHE | Out of bounds access\n");
+ if (status & A6XX_RBBM_INT_0_MASK_SWFUSEVIOLATION)
+ a7xx_sw_fuse_violation_irq(gpu);
+
if (status & A6XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS)
msm_gpu_retire(gpu);
@@ -2525,6 +1698,56 @@ 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)) {
+ /*
+ * 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 a750 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)
@@ -3095,6 +2318,14 @@ struct msm_gpu *a6xx_gpu_init(struct drm_device *dev)
return ERR_PTR(ret);
}
+ if (adreno_is_a7xx(adreno_gpu)) {
+ ret = a7xx_cx_mem_init(a6xx_gpu);
+ if (ret) {
+ a6xx_destroy(&(a6xx_gpu->base.base));
+ return ERR_PTR(ret);
+ }
+ }
+
if (gpu->aspace)
msm_mmu_set_fault_handler(gpu->aspace->mmu, gpu,
a6xx_fault_handler);
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
index 8917032b7515..e3e5c53ae8af 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
@@ -12,6 +12,18 @@
extern bool hang_debug;
+/**
+ * struct a6xx_info - a6xx specific information from device table
+ *
+ * @hwcg: hw clock gating register sequence
+ * @protect: CP_PROTECT settings
+ */
+struct a6xx_info {
+ const struct adreno_reglist *hwcg;
+ const struct adreno_protect *protect;
+ u32 gmu_chipid;
+};
+
struct a6xx_gpu {
struct adreno_gpu base;
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c
index 0a7717a4fc2f..789a11416f7a 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c
@@ -8,19 +8,16 @@
#include "a6xx_gpu_state.h"
#include "a6xx_gmu.xml.h"
-/* Ignore diagnostics about register tables that we aren't using yet. We don't
- * want to modify these headers too much from their original source.
- */
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-variable"
-#pragma GCC diagnostic ignored "-Wunused-const-variable"
+static const unsigned int *gen7_0_0_external_core_regs[] __always_unused;
+static const unsigned int *gen7_2_0_external_core_regs[] __always_unused;
+static const unsigned int *gen7_9_0_external_core_regs[] __always_unused;
+static struct gen7_sptp_cluster_registers gen7_9_0_sptp_clusters[] __always_unused;
+static const u32 gen7_9_0_cx_debugbus_blocks[] __always_unused;
#include "adreno_gen7_0_0_snapshot.h"
#include "adreno_gen7_2_0_snapshot.h"
#include "adreno_gen7_9_0_snapshot.h"
-#pragma GCC diagnostic pop
-
struct a6xx_gpu_state_obj {
const void *handle;
u32 *data;
diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c
index c3703a51287b..cfc74a9e2646 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_device.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
@@ -20,610 +20,36 @@ bool allow_vram_carveout = false;
MODULE_PARM_DESC(allow_vram_carveout, "Allow using VRAM Carveout, in place of IOMMU");
module_param_named(allow_vram_carveout, allow_vram_carveout, bool, 0600);
-static const struct adreno_info gpulist[] = {
- {
- .chip_ids = ADRENO_CHIP_IDS(0x02000000),
- .family = ADRENO_2XX_GEN1,
- .revn = 200,
- .fw = {
- [ADRENO_FW_PM4] = "yamato_pm4.fw",
- [ADRENO_FW_PFP] = "yamato_pfp.fw",
- },
- .gmem = SZ_256K,
- .inactive_period = DRM_MSM_INACTIVE_PERIOD,
- .init = a2xx_gpu_init,
- }, { /* a200 on i.mx51 has only 128kib gmem */
- .chip_ids = ADRENO_CHIP_IDS(0x02000001),
- .family = ADRENO_2XX_GEN1,
- .revn = 201,
- .fw = {
- [ADRENO_FW_PM4] = "yamato_pm4.fw",
- [ADRENO_FW_PFP] = "yamato_pfp.fw",
- },
- .gmem = SZ_128K,
- .inactive_period = DRM_MSM_INACTIVE_PERIOD,
- .init = a2xx_gpu_init,
- }, {
- .chip_ids = ADRENO_CHIP_IDS(0x02020000),
- .family = ADRENO_2XX_GEN2,
- .revn = 220,
- .fw = {
- [ADRENO_FW_PM4] = "leia_pm4_470.fw",
- [ADRENO_FW_PFP] = "leia_pfp_470.fw",
- },
- .gmem = SZ_512K,
- .inactive_period = DRM_MSM_INACTIVE_PERIOD,
- .init = a2xx_gpu_init,
- }, {
- .chip_ids = ADRENO_CHIP_IDS(0x03000512),
- .family = ADRENO_3XX,
- .fw = {
- [ADRENO_FW_PM4] = "a330_pm4.fw",
- [ADRENO_FW_PFP] = "a330_pfp.fw",
- },
- .gmem = SZ_128K,
- .inactive_period = DRM_MSM_INACTIVE_PERIOD,
- .init = a3xx_gpu_init,
- }, {
- .chip_ids = ADRENO_CHIP_IDS(0x03000520),
- .family = ADRENO_3XX,
- .revn = 305,
- .fw = {
- [ADRENO_FW_PM4] = "a300_pm4.fw",
- [ADRENO_FW_PFP] = "a300_pfp.fw",
- },
- .gmem = SZ_256K,
- .inactive_period = DRM_MSM_INACTIVE_PERIOD,
- .init = a3xx_gpu_init,
- }, {
- .chip_ids = ADRENO_CHIP_IDS(0x03000600),
- .family = ADRENO_3XX,
- .revn = 307, /* because a305c is revn==306 */
- .fw = {
- [ADRENO_FW_PM4] = "a300_pm4.fw",
- [ADRENO_FW_PFP] = "a300_pfp.fw",
- },
- .gmem = SZ_128K,
- .inactive_period = DRM_MSM_INACTIVE_PERIOD,
- .init = a3xx_gpu_init,
- }, {
- .chip_ids = ADRENO_CHIP_IDS(
- 0x03020000,
- 0x03020001,
- 0x03020002
- ),
- .family = ADRENO_3XX,
- .revn = 320,
- .fw = {
- [ADRENO_FW_PM4] = "a300_pm4.fw",
- [ADRENO_FW_PFP] = "a300_pfp.fw",
- },
- .gmem = SZ_512K,
- .inactive_period = DRM_MSM_INACTIVE_PERIOD,
- .init = a3xx_gpu_init,
- }, {
- .chip_ids = ADRENO_CHIP_IDS(
- 0x03030000,
- 0x03030001,
- 0x03030002
- ),
- .family = ADRENO_3XX,
- .revn = 330,
- .fw = {
- [ADRENO_FW_PM4] = "a330_pm4.fw",
- [ADRENO_FW_PFP] = "a330_pfp.fw",
- },
- .gmem = SZ_1M,
- .inactive_period = DRM_MSM_INACTIVE_PERIOD,
- .init = a3xx_gpu_init,
- }, {
- .chip_ids = ADRENO_CHIP_IDS(0x04000500),
- .family = ADRENO_4XX,
- .revn = 405,
- .fw = {
- [ADRENO_FW_PM4] = "a420_pm4.fw",
- [ADRENO_FW_PFP] = "a420_pfp.fw",
- },
- .gmem = SZ_256K,
- .inactive_period = DRM_MSM_INACTIVE_PERIOD,
- .init = a4xx_gpu_init,
- }, {
- .chip_ids = ADRENO_CHIP_IDS(0x04020000),
- .family = ADRENO_4XX,
- .revn = 420,
- .fw = {
- [ADRENO_FW_PM4] = "a420_pm4.fw",
- [ADRENO_FW_PFP] = "a420_pfp.fw",
- },
- .gmem = (SZ_1M + SZ_512K),
- .inactive_period = DRM_MSM_INACTIVE_PERIOD,
- .init = a4xx_gpu_init,
- }, {
- .chip_ids = ADRENO_CHIP_IDS(0x04030002),
- .family = ADRENO_4XX,
- .revn = 430,
- .fw = {
- [ADRENO_FW_PM4] = "a420_pm4.fw",
- [ADRENO_FW_PFP] = "a420_pfp.fw",
- },
- .gmem = (SZ_1M + SZ_512K),
- .inactive_period = DRM_MSM_INACTIVE_PERIOD,
- .init = a4xx_gpu_init,
- }, {
- .chip_ids = ADRENO_CHIP_IDS(0x05000600),
- .family = ADRENO_5XX,
- .revn = 506,
- .fw = {
- [ADRENO_FW_PM4] = "a530_pm4.fw",
- [ADRENO_FW_PFP] = "a530_pfp.fw",
- },
- .gmem = (SZ_128K + SZ_8K),
- /*
- * Increase inactive period to 250 to avoid bouncing
- * the GDSC which appears to make it grumpy
- */
- .inactive_period = 250,
- .quirks = ADRENO_QUIRK_TWO_PASS_USE_WFI |
- ADRENO_QUIRK_LMLOADKILL_DISABLE,
- .init = a5xx_gpu_init,
- .zapfw = "a506_zap.mdt",
- }, {
- .chip_ids = ADRENO_CHIP_IDS(0x05000800),
- .family = ADRENO_5XX,
- .revn = 508,
- .fw = {
- [ADRENO_FW_PM4] = "a530_pm4.fw",
- [ADRENO_FW_PFP] = "a530_pfp.fw",
- },
- .gmem = (SZ_128K + SZ_8K),
- /*
- * Increase inactive period to 250 to avoid bouncing
- * the GDSC which appears to make it grumpy
- */
- .inactive_period = 250,
- .quirks = ADRENO_QUIRK_LMLOADKILL_DISABLE,
- .init = a5xx_gpu_init,
- .zapfw = "a508_zap.mdt",
- }, {
- .chip_ids = ADRENO_CHIP_IDS(0x05000900),
- .family = ADRENO_5XX,
- .revn = 509,
- .fw = {
- [ADRENO_FW_PM4] = "a530_pm4.fw",
- [ADRENO_FW_PFP] = "a530_pfp.fw",
- },
- .gmem = (SZ_256K + SZ_16K),
- /*
- * Increase inactive period to 250 to avoid bouncing
- * the GDSC which appears to make it grumpy
- */
- .inactive_period = 250,
- .quirks = ADRENO_QUIRK_LMLOADKILL_DISABLE,
- .init = a5xx_gpu_init,
- /* Adreno 509 uses the same ZAP as 512 */
- .zapfw = "a512_zap.mdt",
- }, {
- .chip_ids = ADRENO_CHIP_IDS(0x05010000),
- .family = ADRENO_5XX,
- .revn = 510,
- .fw = {
- [ADRENO_FW_PM4] = "a530_pm4.fw",
- [ADRENO_FW_PFP] = "a530_pfp.fw",
- },
- .gmem = SZ_256K,
- /*
- * Increase inactive period to 250 to avoid bouncing
- * the GDSC which appears to make it grumpy
- */
- .inactive_period = 250,
- .init = a5xx_gpu_init,
- }, {
- .chip_ids = ADRENO_CHIP_IDS(0x05010200),
- .family = ADRENO_5XX,
- .revn = 512,
- .fw = {
- [ADRENO_FW_PM4] = "a530_pm4.fw",
- [ADRENO_FW_PFP] = "a530_pfp.fw",
- },
- .gmem = (SZ_256K + SZ_16K),
- /*
- * Increase inactive period to 250 to avoid bouncing
- * the GDSC which appears to make it grumpy
- */
- .inactive_period = 250,
- .quirks = ADRENO_QUIRK_LMLOADKILL_DISABLE,
- .init = a5xx_gpu_init,
- .zapfw = "a512_zap.mdt",
- }, {
- .chip_ids = ADRENO_CHIP_IDS(
- 0x05030002,
- 0x05030004
- ),
- .family = ADRENO_5XX,
- .revn = 530,
- .fw = {
- [ADRENO_FW_PM4] = "a530_pm4.fw",
- [ADRENO_FW_PFP] = "a530_pfp.fw",
- [ADRENO_FW_GPMU] = "a530v3_gpmu.fw2",
- },
- .gmem = SZ_1M,
- /*
- * Increase inactive period to 250 to avoid bouncing
- * the GDSC which appears to make it grumpy
- */
- .inactive_period = 250,
- .quirks = ADRENO_QUIRK_TWO_PASS_USE_WFI |
- ADRENO_QUIRK_FAULT_DETECT_MASK,
- .init = a5xx_gpu_init,
- .zapfw = "a530_zap.mdt",
- }, {
- .chip_ids = ADRENO_CHIP_IDS(0x05040001),
- .family = ADRENO_5XX,
- .revn = 540,
- .fw = {
- [ADRENO_FW_PM4] = "a530_pm4.fw",
- [ADRENO_FW_PFP] = "a530_pfp.fw",
- [ADRENO_FW_GPMU] = "a540_gpmu.fw2",
- },
- .gmem = SZ_1M,
- /*
- * Increase inactive period to 250 to avoid bouncing
- * the GDSC which appears to make it grumpy
- */
- .inactive_period = 250,
- .quirks = ADRENO_QUIRK_LMLOADKILL_DISABLE,
- .init = a5xx_gpu_init,
- .zapfw = "a540_zap.mdt",
- }, {
- .chip_ids = ADRENO_CHIP_IDS(0x06010000),
- .family = ADRENO_6XX_GEN1,
- .revn = 610,
- .fw = {
- [ADRENO_FW_SQE] = "a630_sqe.fw",
- },
- .gmem = (SZ_128K + SZ_4K),
- .inactive_period = DRM_MSM_INACTIVE_PERIOD,
- .init = a6xx_gpu_init,
- .zapfw = "a610_zap.mdt",
- .hwcg = a612_hwcg,
- /*
- * There are (at least) three SoCs implementing A610: SM6125
- * (trinket), SM6115 (bengal) and SM6225 (khaje). Trinket does
- * not have speedbinning, as only a single SKU exists and we
- * don't support khaje upstream yet. Hence, this matching
- * table is only valid for bengal.
- */
- .speedbins = ADRENO_SPEEDBINS(
- { 0, 0 },
- { 206, 1 },
- { 200, 2 },
- { 157, 3 },
- { 127, 4 },
- ),
- }, {
- .machine = "qcom,sm7150",
- .chip_ids = ADRENO_CHIP_IDS(0x06010800),
- .family = ADRENO_6XX_GEN1,
- .fw = {
- [ADRENO_FW_SQE] = "a630_sqe.fw",
- [ADRENO_FW_GMU] = "a630_gmu.bin",
- },
- .gmem = SZ_512K,
- .inactive_period = DRM_MSM_INACTIVE_PERIOD,
- .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT,
- .init = a6xx_gpu_init,
- .zapfw = "a615_zap.mbn",
- .hwcg = a615_hwcg,
- .speedbins = ADRENO_SPEEDBINS(
- { 0, 0 },
- { 128, 1 },
- { 146, 2 },
- { 167, 3 },
- { 172, 4 },
- ),
- }, {
- .chip_ids = ADRENO_CHIP_IDS(0x06010800),
- .family = ADRENO_6XX_GEN1,
- .revn = 618,
- .fw = {
- [ADRENO_FW_SQE] = "a630_sqe.fw",
- [ADRENO_FW_GMU] = "a630_gmu.bin",
- },
- .gmem = SZ_512K,
- .inactive_period = DRM_MSM_INACTIVE_PERIOD,
- .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT,
- .init = a6xx_gpu_init,
- .speedbins = ADRENO_SPEEDBINS(
- { 0, 0 },
- { 169, 1 },
- { 174, 2 },
- ),
- }, {
- .machine = "qcom,sm4350",
- .chip_ids = ADRENO_CHIP_IDS(0x06010900),
- .family = ADRENO_6XX_GEN1,
- .revn = 619,
- .fw = {
- [ADRENO_FW_SQE] = "a630_sqe.fw",
- [ADRENO_FW_GMU] = "a619_gmu.bin",
- },
- .gmem = SZ_512K,
- .inactive_period = DRM_MSM_INACTIVE_PERIOD,
- .init = a6xx_gpu_init,
- .zapfw = "a615_zap.mdt",
- .hwcg = a615_hwcg,
- .speedbins = ADRENO_SPEEDBINS(
- { 0, 0 },
- { 138, 1 },
- { 92, 2 },
- ),
- }, {
- .machine = "qcom,sm6375",
- .chip_ids = ADRENO_CHIP_IDS(0x06010901),
- .family = ADRENO_6XX_GEN1,
- .revn = 619,
- .fw = {
- [ADRENO_FW_SQE] = "a630_sqe.fw",
- [ADRENO_FW_GMU] = "a619_gmu.bin",
- },
- .gmem = SZ_512K,
- .inactive_period = DRM_MSM_INACTIVE_PERIOD,
- .init = a6xx_gpu_init,
- .zapfw = "a615_zap.mdt",
- .hwcg = a615_hwcg,
- .speedbins = ADRENO_SPEEDBINS(
- { 0, 0 },
- { 190, 1 },
- { 177, 2 },
- ),
- }, {
- .chip_ids = ADRENO_CHIP_IDS(0x06010900),
- .family = ADRENO_6XX_GEN1,
- .revn = 619,
- .fw = {
- [ADRENO_FW_SQE] = "a630_sqe.fw",
- [ADRENO_FW_GMU] = "a619_gmu.bin",
- },
- .gmem = SZ_512K,
- .inactive_period = DRM_MSM_INACTIVE_PERIOD,
- .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT,
- .init = a6xx_gpu_init,
- .zapfw = "a615_zap.mdt",
- .hwcg = a615_hwcg,
- .speedbins = ADRENO_SPEEDBINS(
- { 0, 0 },
- { 120, 4 },
- { 138, 3 },
- { 169, 2 },
- { 180, 1 },
- ),
- }, {
- .chip_ids = ADRENO_CHIP_IDS(
- 0x06030001,
- 0x06030002
- ),
- .family = ADRENO_6XX_GEN1,
- .revn = 630,
- .fw = {
- [ADRENO_FW_SQE] = "a630_sqe.fw",
- [ADRENO_FW_GMU] = "a630_gmu.bin",
- },
- .gmem = SZ_1M,
- .inactive_period = DRM_MSM_INACTIVE_PERIOD,
- .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT,
- .init = a6xx_gpu_init,
- .zapfw = "a630_zap.mdt",
- .hwcg = a630_hwcg,
- }, {
- .chip_ids = ADRENO_CHIP_IDS(0x06040001),
- .family = ADRENO_6XX_GEN2,
- .revn = 640,
- .fw = {
- [ADRENO_FW_SQE] = "a630_sqe.fw",
- [ADRENO_FW_GMU] = "a640_gmu.bin",
- },
- .gmem = SZ_1M,
- .inactive_period = DRM_MSM_INACTIVE_PERIOD,
- .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT,
- .init = a6xx_gpu_init,
- .zapfw = "a640_zap.mdt",
- .hwcg = a640_hwcg,
- .speedbins = ADRENO_SPEEDBINS(
- { 0, 0 },
- { 1, 1 },
- ),
- }, {
- .chip_ids = ADRENO_CHIP_IDS(0x06050002),
- .family = ADRENO_6XX_GEN3,
- .revn = 650,
- .fw = {
- [ADRENO_FW_SQE] = "a650_sqe.fw",
- [ADRENO_FW_GMU] = "a650_gmu.bin",
- },
- .gmem = SZ_1M + SZ_128K,
- .inactive_period = DRM_MSM_INACTIVE_PERIOD,
- .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT |
- ADRENO_QUIRK_HAS_HW_APRIV,
- .init = a6xx_gpu_init,
- .zapfw = "a650_zap.mdt",
- .hwcg = a650_hwcg,
- .address_space_size = SZ_16G,
- .speedbins = ADRENO_SPEEDBINS(
- { 0, 0 },
- { 1, 1 },
- { 2, 3 }, /* Yep, 2 and 3 are swapped! :/ */
- { 3, 2 },
- ),
- }, {
- .chip_ids = ADRENO_CHIP_IDS(0x06060001),
- .family = ADRENO_6XX_GEN4,
- .revn = 660,
- .fw = {
- [ADRENO_FW_SQE] = "a660_sqe.fw",
- [ADRENO_FW_GMU] = "a660_gmu.bin",
- },
- .gmem = SZ_1M + SZ_512K,
- .inactive_period = DRM_MSM_INACTIVE_PERIOD,
- .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT |
- ADRENO_QUIRK_HAS_HW_APRIV,
- .init = a6xx_gpu_init,
- .zapfw = "a660_zap.mdt",
- .hwcg = a660_hwcg,
- .address_space_size = SZ_16G,
- }, {
- .chip_ids = ADRENO_CHIP_IDS(0x06030500),
- .family = ADRENO_6XX_GEN4,
- .fw = {
- [ADRENO_FW_SQE] = "a660_sqe.fw",
- [ADRENO_FW_GMU] = "a660_gmu.bin",
- },
- .gmem = SZ_512K,
- .inactive_period = DRM_MSM_INACTIVE_PERIOD,
- .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT |
- ADRENO_QUIRK_HAS_HW_APRIV,
- .init = a6xx_gpu_init,
- .zapfw = "a660_zap.mbn",
- .hwcg = a660_hwcg,
- .address_space_size = SZ_16G,
- .speedbins = ADRENO_SPEEDBINS(
- { 0, 0 },
- { 117, 0 },
- { 172, 2 }, /* Called speedbin 1 downstream, but let's not break things! */
- { 190, 1 },
- ),
- }, {
- .chip_ids = ADRENO_CHIP_IDS(0x06080001),
- .family = ADRENO_6XX_GEN2,
- .revn = 680,
- .fw = {
- [ADRENO_FW_SQE] = "a630_sqe.fw",
- [ADRENO_FW_GMU] = "a640_gmu.bin",
- },
- .gmem = SZ_2M,
- .inactive_period = DRM_MSM_INACTIVE_PERIOD,
- .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT,
- .init = a6xx_gpu_init,
- .zapfw = "a640_zap.mdt",
- .hwcg = a640_hwcg,
- }, {
- .chip_ids = ADRENO_CHIP_IDS(0x06090000),
- .family = ADRENO_6XX_GEN4,
- .fw = {
- [ADRENO_FW_SQE] = "a660_sqe.fw",
- [ADRENO_FW_GMU] = "a660_gmu.bin",
- },
- .gmem = SZ_4M,
- .inactive_period = DRM_MSM_INACTIVE_PERIOD,
- .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT |
- ADRENO_QUIRK_HAS_HW_APRIV,
- .init = a6xx_gpu_init,
- .zapfw = "a690_zap.mdt",
- .hwcg = a690_hwcg,
- .address_space_size = SZ_16G,
- }, {
- .chip_ids = ADRENO_CHIP_IDS(0x07000200),
- .family = ADRENO_6XX_GEN1, /* NOT a mistake! */
- .fw = {
- [ADRENO_FW_SQE] = "a702_sqe.fw",
- },
- .gmem = SZ_128K,
- .inactive_period = DRM_MSM_INACTIVE_PERIOD,
- .quirks = ADRENO_QUIRK_HAS_HW_APRIV,
- .init = a6xx_gpu_init,
- .zapfw = "a702_zap.mbn",
- .hwcg = a702_hwcg,
- .speedbins = ADRENO_SPEEDBINS(
- { 0, 0 },
- { 236, 1 },
- { 178, 2 },
- { 142, 3 },
- ),
- }, {
- .chip_ids = ADRENO_CHIP_IDS(0x07030001),
- .family = ADRENO_7XX_GEN1,
- .fw = {
- [ADRENO_FW_SQE] = "a730_sqe.fw",
- [ADRENO_FW_GMU] = "gmu_gen70000.bin",
- },
- .gmem = SZ_2M,
- .inactive_period = DRM_MSM_INACTIVE_PERIOD,
- .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT |
- ADRENO_QUIRK_HAS_HW_APRIV,
- .init = a6xx_gpu_init,
- .zapfw = "a730_zap.mdt",
- .hwcg = a730_hwcg,
- .address_space_size = SZ_16G,
- }, {
- .chip_ids = ADRENO_CHIP_IDS(0x43050a01), /* "C510v2" */
- .family = ADRENO_7XX_GEN2,
- .fw = {
- [ADRENO_FW_SQE] = "a740_sqe.fw",
- [ADRENO_FW_GMU] = "gmu_gen70200.bin",
- },
- .gmem = 3 * SZ_1M,
- .inactive_period = DRM_MSM_INACTIVE_PERIOD,
- .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT |
- ADRENO_QUIRK_HAS_HW_APRIV,
- .init = a6xx_gpu_init,
- .zapfw = "a740_zap.mdt",
- .hwcg = a740_hwcg,
- .address_space_size = SZ_16G,
- }, {
- .chip_ids = ADRENO_CHIP_IDS(0x43051401), /* "C520v2" */
- .family = ADRENO_7XX_GEN3,
- .fw = {
- [ADRENO_FW_SQE] = "gen70900_sqe.fw",
- [ADRENO_FW_GMU] = "gmu_gen70900.bin",
- },
- .gmem = 3 * SZ_1M,
- .inactive_period = DRM_MSM_INACTIVE_PERIOD,
- .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT |
- ADRENO_QUIRK_HAS_HW_APRIV,
- .init = a6xx_gpu_init,
- .zapfw = "gen70900_zap.mbn",
- .address_space_size = SZ_16G,
- },
+extern const struct adreno_gpulist a2xx_gpulist;
+extern const struct adreno_gpulist a3xx_gpulist;
+extern const struct adreno_gpulist a4xx_gpulist;
+extern const struct adreno_gpulist a5xx_gpulist;
+extern const struct adreno_gpulist a6xx_gpulist;
+extern const struct adreno_gpulist a7xx_gpulist;
+
+static const struct adreno_gpulist *gpulists[] = {
+ &a2xx_gpulist,
+ &a3xx_gpulist,
+ &a4xx_gpulist,
+ &a5xx_gpulist,
+ &a6xx_gpulist,
+ &a7xx_gpulist,
};
-MODULE_FIRMWARE("qcom/a300_pm4.fw");
-MODULE_FIRMWARE("qcom/a300_pfp.fw");
-MODULE_FIRMWARE("qcom/a330_pm4.fw");
-MODULE_FIRMWARE("qcom/a330_pfp.fw");
-MODULE_FIRMWARE("qcom/a420_pm4.fw");
-MODULE_FIRMWARE("qcom/a420_pfp.fw");
-MODULE_FIRMWARE("qcom/a530_pm4.fw");
-MODULE_FIRMWARE("qcom/a530_pfp.fw");
-MODULE_FIRMWARE("qcom/a530v3_gpmu.fw2");
-MODULE_FIRMWARE("qcom/a530_zap.mdt");
-MODULE_FIRMWARE("qcom/a530_zap.b00");
-MODULE_FIRMWARE("qcom/a530_zap.b01");
-MODULE_FIRMWARE("qcom/a530_zap.b02");
-MODULE_FIRMWARE("qcom/a540_gpmu.fw2");
-MODULE_FIRMWARE("qcom/a615_zap.mbn");
-MODULE_FIRMWARE("qcom/a619_gmu.bin");
-MODULE_FIRMWARE("qcom/a630_sqe.fw");
-MODULE_FIRMWARE("qcom/a630_gmu.bin");
-MODULE_FIRMWARE("qcom/a630_zap.mbn");
-MODULE_FIRMWARE("qcom/a640_gmu.bin");
-MODULE_FIRMWARE("qcom/a650_gmu.bin");
-MODULE_FIRMWARE("qcom/a650_sqe.fw");
-MODULE_FIRMWARE("qcom/a660_gmu.bin");
-MODULE_FIRMWARE("qcom/a660_sqe.fw");
-MODULE_FIRMWARE("qcom/leia_pfp_470.fw");
-MODULE_FIRMWARE("qcom/leia_pm4_470.fw");
-MODULE_FIRMWARE("qcom/yamato_pfp.fw");
-MODULE_FIRMWARE("qcom/yamato_pm4.fw");
-
static const struct adreno_info *adreno_info(uint32_t chip_id)
{
/* identify gpu: */
- for (int i = 0; i < ARRAY_SIZE(gpulist); i++) {
- const struct adreno_info *info = &gpulist[i];
- if (info->machine && !of_machine_is_compatible(info->machine))
- continue;
- for (int j = 0; info->chip_ids[j]; j++)
- if (info->chip_ids[j] == chip_id)
- return info;
+ for (int i = 0; i < ARRAY_SIZE(gpulists); i++) {
+ for (int j = 0; j < gpulists[i]->gpus_count; j++) {
+ const struct adreno_info *info = &gpulists[i]->gpus[j];
+
+ if (info->machine && !of_machine_is_compatible(info->machine))
+ continue;
+
+ for (int k = 0; info->chip_ids[k]; k++)
+ if (info->chip_ids[k] == chip_id)
+ return info;
+ }
}
return NULL;
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index 074fb498706f..1c6626747b98 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -46,7 +46,7 @@ static int zap_shader_load_mdt(struct msm_gpu *gpu, const char *fwname,
}
np = of_get_child_by_name(dev->of_node, "zap-shader");
- if (!np) {
+ if (!of_device_is_available(np)) {
zap_available = false;
return -ENODEV;
}
@@ -376,6 +376,9 @@ int adreno_get_param(struct msm_gpu *gpu, struct msm_file_private *ctx,
case MSM_PARAM_HIGHEST_BANK_BIT:
*value = adreno_gpu->ubwc_config.highest_bank_bit;
return 0;
+ case MSM_PARAM_RAYTRACING:
+ *value = adreno_gpu->has_ray_tracing;
+ return 0;
default:
DBG("%s: invalid param: %u", gpu->name, param);
return -EINVAL;
@@ -887,6 +890,7 @@ void adreno_show(struct msm_gpu *gpu, struct msm_gpu_state *state,
drm_printf(p, " - iova: 0x%016llx\n",
state->bos[i].iova);
drm_printf(p, " size: %zd\n", state->bos[i].size);
+ drm_printf(p, " flags: 0x%x\n", state->bos[i].flags);
drm_printf(p, " name: %-32s\n", state->bos[i].name);
adreno_show_object(p, &state->bos[i].data,
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
index 77526892eb8c..1ab523a163a0 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
@@ -77,14 +77,13 @@ struct adreno_reglist {
u32 value;
};
-extern const struct adreno_reglist a612_hwcg[], a615_hwcg[], a630_hwcg[], a640_hwcg[], a650_hwcg[];
-extern const struct adreno_reglist a660_hwcg[], a690_hwcg[], a702_hwcg[], a730_hwcg[], a740_hwcg[];
-
struct adreno_speedbin {
uint16_t fuse;
uint16_t speedbin;
};
+struct a6xx_info;
+
struct adreno_info {
const char *machine;
/**
@@ -101,7 +100,9 @@ struct adreno_info {
struct msm_gpu *(*init)(struct drm_device *dev);
const char *zapfw;
u32 inactive_period;
- const struct adreno_reglist *hwcg;
+ union {
+ const struct a6xx_info *a6xx;
+ };
u64 address_space_size;
/**
* @speedbins: Optional table of fuse to speedbin mappings
@@ -114,6 +115,16 @@ struct adreno_info {
#define ADRENO_CHIP_IDS(tbl...) (uint32_t[]) { tbl, 0 }
+struct adreno_gpulist {
+ const struct adreno_info *gpus;
+ unsigned gpus_count;
+};
+
+#define DECLARE_ADRENO_GPULIST(name) \
+const struct adreno_gpulist name ## _gpulist = { \
+ name ## _gpus, ARRAY_SIZE(name ## _gpus) \
+}
+
/*
* Helper to build a speedbin table, ie. the table:
* fuse | speedbin
@@ -132,6 +143,19 @@ struct adreno_info {
*/
#define ADRENO_SPEEDBINS(tbl...) (struct adreno_speedbin[]) { tbl {SHRT_MAX, 0} }
+struct adreno_protect {
+ const uint32_t *regs;
+ uint32_t count;
+ uint32_t count_max;
+};
+
+#define DECLARE_ADRENO_PROTECT(name, __count_max) \
+static const struct adreno_protect name = { \
+ .regs = name ## _regs, \
+ .count = ARRAY_SIZE(name ## _regs), \
+ .count_max = __count_max, \
+};
+
struct adreno_gpu {
struct msm_gpu base;
const struct adreno_info *info;
@@ -182,6 +206,8 @@ struct adreno_gpu {
*/
const unsigned int *reg_offsets;
bool gmu_is_wrapper;
+
+ bool has_ray_tracing;
};
#define to_adreno_gpu(x) container_of(x, struct adreno_gpu, base)
@@ -298,6 +324,11 @@ static inline int adreno_is_a430(const struct adreno_gpu *gpu)
return adreno_is_revn(gpu, 430);
}
+static inline int adreno_is_a505(const struct adreno_gpu *gpu)
+{
+ return adreno_is_revn(gpu, 505);
+}
+
static inline int adreno_is_a506(const struct adreno_gpu *gpu)
{
return adreno_is_revn(gpu, 506);
@@ -448,6 +479,11 @@ static inline int adreno_is_a750(struct adreno_gpu *gpu)
return gpu->info->chip_ids[0] == 0x43051401;
}
+static inline int adreno_is_x185(struct adreno_gpu *gpu)
+{
+ return gpu->info->chip_ids[0] == 0x43050c01;
+}
+
static inline int adreno_is_a740_family(struct adreno_gpu *gpu)
{
if (WARN_ON_ONCE(!gpu->info))
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
new file mode 100644
index 000000000000..2fe674d1e059
--- /dev/null
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_2_sm7150.h
@@ -0,0 +1,335 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2024, Danila Tikhonov <danila@jiaxyga.com>
+ */
+
+#ifndef _DPU_5_2_SM7150_H
+#define _DPU_5_2_SM7150_H
+
+static const struct dpu_caps sm7150_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 = 2880,
+ .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
+ .max_hdeci_exp = MAX_HORZ_DECIMATION,
+ .max_vdeci_exp = MAX_VERT_DECIMATION,
+};
+
+static const struct dpu_mdp_cfg sm7150_mdp = {
+ .name = "top_0",
+ .base = 0x0, .len = 0x45c,
+ .features = BIT(DPU_MDP_AUDIO_SELECT),
+ .clk_ctrls = {
+ [DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 },
+ [DPU_CLK_CTRL_VIG1] = { .reg_off = 0x2b4, .bit_off = 0 },
+ [DPU_CLK_CTRL_DMA0] = { .reg_off = 0x2ac, .bit_off = 8 },
+ [DPU_CLK_CTRL_DMA1] = { .reg_off = 0x2b4, .bit_off = 8 },
+ [DPU_CLK_CTRL_DMA2] = { .reg_off = 0x2bc, .bit_off = 8 },
+ [DPU_CLK_CTRL_WB2] = { .reg_off = 0x2bc, .bit_off = 16 },
+ },
+};
+
+static const struct dpu_ctl_cfg sm7150_ctl[] = {
+ {
+ .name = "ctl_0", .id = CTL_0,
+ .base = 0x1000, .len = 0x1e0,
+ .features = BIT(DPU_CTL_ACTIVE_CFG) | BIT(DPU_CTL_SPLIT_DISPLAY),
+ .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9),
+ }, {
+ .name = "ctl_1", .id = CTL_1,
+ .base = 0x1200, .len = 0x1e0,
+ .features = BIT(DPU_CTL_ACTIVE_CFG) | BIT(DPU_CTL_SPLIT_DISPLAY),
+ .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10),
+ }, {
+ .name = "ctl_2", .id = CTL_2,
+ .base = 0x1400, .len = 0x1e0,
+ .features = BIT(DPU_CTL_ACTIVE_CFG),
+ .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11),
+ }, {
+ .name = "ctl_3", .id = CTL_3,
+ .base = 0x1600, .len = 0x1e0,
+ .features = BIT(DPU_CTL_ACTIVE_CFG),
+ .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12),
+ }, {
+ .name = "ctl_4", .id = CTL_4,
+ .base = 0x1800, .len = 0x1e0,
+ .features = BIT(DPU_CTL_ACTIVE_CFG),
+ .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 13),
+ }, {
+ .name = "ctl_5", .id = CTL_5,
+ .base = 0x1a00, .len = 0x1e0,
+ .features = BIT(DPU_CTL_ACTIVE_CFG),
+ .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 23),
+ },
+};
+
+static const struct dpu_sspp_cfg sm7150_sspp[] = {
+ {
+ .name = "sspp_0", .id = SSPP_VIG0,
+ .base = 0x4000, .len = 0x1f0,
+ .features = VIG_SDM845_MASK,
+ .sblk = &dpu_vig_sblk_qseed3_2_4,
+ .xin_id = 0,
+ .type = SSPP_TYPE_VIG,
+ .clk_ctrl = DPU_CLK_CTRL_VIG0,
+ }, {
+ .name = "sspp_1", .id = SSPP_VIG1,
+ .base = 0x6000, .len = 0x1f0,
+ .features = VIG_SDM845_MASK,
+ .sblk = &dpu_vig_sblk_qseed3_2_4,
+ .xin_id = 4,
+ .type = SSPP_TYPE_VIG,
+ .clk_ctrl = DPU_CLK_CTRL_VIG1,
+ }, {
+ .name = "sspp_2", .id = SSPP_DMA0,
+ .base = 0x24000, .len = 0x1f0,
+ .features = DMA_SDM845_MASK,
+ .sblk = &dpu_dma_sblk,
+ .xin_id = 1,
+ .type = SSPP_TYPE_DMA,
+ .clk_ctrl = DPU_CLK_CTRL_DMA0,
+ }, {
+ .name = "sspp_9", .id = SSPP_DMA1,
+ .base = 0x26000, .len = 0x1f0,
+ .features = DMA_SDM845_MASK,
+ .sblk = &dpu_dma_sblk,
+ .xin_id = 5,
+ .type = SSPP_TYPE_DMA,
+ .clk_ctrl = DPU_CLK_CTRL_DMA1,
+ }, {
+ .name = "sspp_10", .id = SSPP_DMA2,
+ .base = 0x28000, .len = 0x1f0,
+ .features = DMA_CURSOR_SDM845_MASK,
+ .sblk = &dpu_dma_sblk,
+ .xin_id = 9,
+ .type = SSPP_TYPE_DMA,
+ .clk_ctrl = DPU_CLK_CTRL_DMA2,
+ },
+};
+
+static const struct dpu_lm_cfg sm7150_lm[] = {
+ {
+ .name = "lm_0", .id = LM_0,
+ .base = 0x44000, .len = 0x320,
+ .features = MIXER_SDM845_MASK,
+ .sblk = &sdm845_lm_sblk,
+ .lm_pair = LM_1,
+ .pingpong = PINGPONG_0,
+ .dspp = DSPP_0,
+ }, {
+ .name = "lm_1", .id = LM_1,
+ .base = 0x45000, .len = 0x320,
+ .features = MIXER_SDM845_MASK,
+ .sblk = &sdm845_lm_sblk,
+ .lm_pair = LM_0,
+ .pingpong = PINGPONG_1,
+ .dspp = DSPP_1,
+ }, {
+ .name = "lm_2", .id = LM_2,
+ .base = 0x46000, .len = 0x320,
+ .features = MIXER_SDM845_MASK,
+ .sblk = &sdm845_lm_sblk,
+ .lm_pair = LM_3,
+ .pingpong = PINGPONG_2,
+ }, {
+ .name = "lm_3", .id = LM_3,
+ .base = 0x47000, .len = 0x320,
+ .features = MIXER_SDM845_MASK,
+ .sblk = &sdm845_lm_sblk,
+ .lm_pair = LM_2,
+ .pingpong = PINGPONG_3,
+ },
+};
+
+static const struct dpu_dspp_cfg sm7150_dspp[] = {
+ {
+ .name = "dspp_0", .id = DSPP_0,
+ .base = 0x54000, .len = 0x1800,
+ .features = DSPP_SC7180_MASK,
+ .sblk = &sdm845_dspp_sblk,
+ }, {
+ .name = "dspp_1", .id = DSPP_1,
+ .base = 0x56000, .len = 0x1800,
+ .features = DSPP_SC7180_MASK,
+ .sblk = &sdm845_dspp_sblk,
+ },
+};
+
+static const struct dpu_pingpong_cfg sm7150_pp[] = {
+ {
+ .name = "pingpong_0", .id = PINGPONG_0,
+ .base = 0x70000, .len = 0xd4,
+ .features = PINGPONG_SM8150_MASK,
+ .sblk = &sdm845_pp_sblk,
+ .merge_3d = MERGE_3D_0,
+ .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8),
+ }, {
+ .name = "pingpong_1", .id = PINGPONG_1,
+ .base = 0x70800, .len = 0xd4,
+ .features = PINGPONG_SM8150_MASK,
+ .sblk = &sdm845_pp_sblk,
+ .merge_3d = MERGE_3D_0,
+ .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9),
+ }, {
+ .name = "pingpong_2", .id = PINGPONG_2,
+ .base = 0x71000, .len = 0xd4,
+ .features = PINGPONG_SM8150_MASK,
+ .sblk = &sdm845_pp_sblk,
+ .merge_3d = MERGE_3D_1,
+ .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10),
+ }, {
+ .name = "pingpong_3", .id = PINGPONG_3,
+ .base = 0x71800, .len = 0xd4,
+ .features = PINGPONG_SM8150_MASK,
+ .sblk = &sdm845_pp_sblk,
+ .merge_3d = MERGE_3D_1,
+ .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11),
+ },
+};
+
+static const struct dpu_merge_3d_cfg sm7150_merge_3d[] = {
+ {
+ .name = "merge_3d_0", .id = MERGE_3D_0,
+ .base = 0x83000, .len = 0x8,
+ }, {
+ .name = "merge_3d_1", .id = MERGE_3D_1,
+ .base = 0x83100, .len = 0x8,
+ },
+};
+
+static const struct dpu_dsc_cfg sm7150_dsc[] = {
+ {
+ .name = "dsc_0", .id = DSC_0,
+ .base = 0x80000, .len = 0x140,
+ .features = BIT(DPU_DSC_OUTPUT_CTRL),
+ }, {
+ .name = "dsc_1", .id = DSC_1,
+ .base = 0x80400, .len = 0x140,
+ .features = BIT(DPU_DSC_OUTPUT_CTRL),
+ },
+};
+
+static const struct dpu_intf_cfg sm7150_intf[] = {
+ {
+ .name = "intf_0", .id = INTF_0,
+ .base = 0x6a000, .len = 0x280,
+ .features = INTF_SC7180_MASK,
+ .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 = 0x6a800, .len = 0x2bc,
+ .features = INTF_SC7180_MASK,
+ .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 = 0x6b000, .len = 0x2bc,
+ .features = INTF_SC7180_MASK,
+ .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 = 0x6b800, .len = 0x280,
+ .features = INTF_SC7180_MASK,
+ .type = INTF_DP,
+ .controller_id = MSM_DP_CONTROLLER_1,
+ .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_wb_cfg sm7150_wb[] = {
+ {
+ .name = "wb_2", .id = WB_2,
+ .base = 0x65000, .len = 0x2c8,
+ .features = WB_SM8250_MASK,
+ .format_list = wb2_formats_rgb,
+ .num_formats = ARRAY_SIZE(wb2_formats_rgb),
+ .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),
+ },
+};
+
+static const struct dpu_perf_cfg sm7150_perf_data = {
+ .max_bw_low = 7100000,
+ .max_bw_high = 7100000,
+ .min_core_ib = 2400000,
+ .min_llcc_ib = 800000,
+ .min_dram_ib = 800000,
+ .min_prefill_lines = 24,
+ .danger_lut_tbl = {0xf, 0xffff, 0x0},
+ .safe_lut_tbl = {0xfff8, 0xf000, 0xffff},
+ .qos_lut_tbl = {
+ {
+ .nentry = ARRAY_SIZE(sm8150_qos_linear),
+ .entries = sm8150_qos_linear
+ }, {
+ .nentry = ARRAY_SIZE(sc7180_qos_macrotile),
+ .entries = sc7180_qos_macrotile
+ }, {
+ .nentry = ARRAY_SIZE(sc7180_qos_nrt),
+ .entries = sc7180_qos_nrt
+ },
+ },
+ .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 sm7150_mdss_ver = {
+ .core_major_ver = 5,
+ .core_minor_ver = 2,
+};
+
+const struct dpu_mdss_cfg dpu_sm7150_cfg = {
+ .mdss_ver = &sm7150_mdss_ver,
+ .caps = &sm7150_dpu_caps,
+ .mdp = &sm7150_mdp,
+ .ctl_count = ARRAY_SIZE(sm7150_ctl),
+ .ctl = sm7150_ctl,
+ .sspp_count = ARRAY_SIZE(sm7150_sspp),
+ .sspp = sm7150_sspp,
+ .mixer_count = ARRAY_SIZE(sm7150_lm),
+ .mixer = sm7150_lm,
+ .dspp_count = ARRAY_SIZE(sm7150_dspp),
+ .dspp = sm7150_dspp,
+ .pingpong_count = ARRAY_SIZE(sm7150_pp),
+ .pingpong = sm7150_pp,
+ .merge_3d_count = ARRAY_SIZE(sm7150_merge_3d),
+ .merge_3d = sm7150_merge_3d,
+ .dsc_count = ARRAY_SIZE(sm7150_dsc),
+ .dsc = sm7150_dsc,
+ .intf_count = ARRAY_SIZE(sm7150_intf),
+ .intf = sm7150_intf,
+ .wb_count = ARRAY_SIZE(sm7150_wb),
+ .wb = sm7150_wb,
+ .vbif_count = ARRAY_SIZE(sdm845_vbif),
+ .vbif = sdm845_vbif,
+ .perf = &sm7150_perf_data,
+};
+
+#endif
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 9f2164782844..4c1be2f0555f 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -658,18 +658,18 @@ static void dpu_crtc_frame_event_work(struct kthread_work *work)
DPU_ATRACE_END("crtc_frame_event");
}
-/*
- * dpu_crtc_frame_event_cb - crtc frame event callback API. CRTC module
- * registers this API to encoder for all frame event callbacks like
- * frame_error, frame_done, idle_timeout, etc. Encoder may call different events
- * from different context - IRQ, user thread, commit_thread, etc. Each event
- * should be carefully reviewed and should be processed in proper task context
- * to avoid schedulin delay or properly manage the irq context's bottom half
- * processing.
+/**
+ * dpu_crtc_frame_event_cb - crtc frame event callback API
+ * @crtc: Pointer to crtc
+ * @event: Event to process
+ *
+ * Encoder may call this for different events from different context - IRQ,
+ * user thread, commit_thread, etc. Each event should be carefully reviewed and
+ * should be processed in proper task context to avoid schedulin delay or
+ * properly manage the irq context's bottom half processing.
*/
-static void dpu_crtc_frame_event_cb(void *data, u32 event)
+void dpu_crtc_frame_event_cb(struct drm_crtc *crtc, u32 event)
{
- struct drm_crtc *crtc = (struct drm_crtc *)data;
struct dpu_crtc *dpu_crtc;
struct msm_drm_private *priv;
struct dpu_crtc_frame_event *fevent;
@@ -1091,9 +1091,6 @@ static void dpu_crtc_disable(struct drm_crtc *crtc,
dpu_core_perf_crtc_update(crtc, 0);
- drm_for_each_encoder_mask(encoder, crtc->dev, crtc->state->encoder_mask)
- dpu_encoder_register_frame_event_callback(encoder, NULL, NULL);
-
memset(cstate->mixers, 0, sizeof(cstate->mixers));
cstate->num_mixers = 0;
@@ -1132,8 +1129,6 @@ static void dpu_crtc_enable(struct drm_crtc *crtc,
*/
if (dpu_encoder_get_intf_mode(encoder) == INTF_MODE_VIDEO)
request_bandwidth = true;
- dpu_encoder_register_frame_event_callback(encoder,
- dpu_crtc_frame_event_cb, (void *)crtc);
}
if (request_bandwidth)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
index 539b68b1626a..b26d5fe40c72 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
@@ -300,4 +300,6 @@ static inline enum dpu_crtc_client_type dpu_crtc_get_client_type(
return crtc && crtc->state ? RT_CLIENT : NRT_CLIENT;
}
+void dpu_crtc_frame_event_cb(struct drm_crtc *crtc, u32 event);
+
#endif /* _DPU_CRTC_H_ */
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 119f3ea50a7c..34c56e855af7 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -151,8 +151,6 @@ enum dpu_enc_rc_states {
* @frame_busy_mask: Bitmask tracking which phys_enc we are still
* busy processing current command.
* Bit0 = phys_encs[0] etc.
- * @crtc_frame_event_cb: callback handler for frame event
- * @crtc_frame_event_cb_data: callback handler private data
* @frame_done_timeout_ms: frame done timeout in ms
* @frame_done_timeout_cnt: atomic counter tracking the number of frame
* done timeouts
@@ -192,8 +190,6 @@ struct dpu_encoder_virt {
struct mutex enc_lock;
DECLARE_BITMAP(frame_busy_mask, MAX_PHYS_ENCODERS_PER_VIRTUAL);
- void (*crtc_frame_event_cb)(void *, u32 event);
- void *crtc_frame_event_cb_data;
atomic_t frame_done_timeout_ms;
atomic_t frame_done_timeout_cnt;
@@ -428,7 +424,7 @@ int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc,
return -EWOULDBLOCK;
}
- if (irq_idx < 0) {
+ if (irq_idx == 0) {
DRM_DEBUG_KMS("skip irq wait id=%u, callback=%ps\n",
DRMID(phys_enc->parent), func);
return 0;
@@ -564,7 +560,7 @@ bool dpu_encoder_use_dsc_merge(struct drm_encoder *drm_enc)
return (num_dsc > 0) && (num_dsc > intf_count);
}
-static struct drm_dsc_config *dpu_encoder_get_dsc_config(struct drm_encoder *drm_enc)
+struct drm_dsc_config *dpu_encoder_get_dsc_config(struct drm_encoder *drm_enc)
{
struct msm_drm_private *priv = drm_enc->dev->dev_private;
struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
@@ -736,18 +732,14 @@ static void _dpu_encoder_update_vsync_source(struct dpu_encoder_virt *dpu_enc,
return;
}
- if (hw_mdptop->ops.setup_vsync_source &&
- disp_info->is_cmd_mode) {
+ if (hw_mdptop->ops.setup_vsync_source) {
for (i = 0; i < dpu_enc->num_phys_encs; i++)
vsync_cfg.ppnumber[i] = dpu_enc->hw_pp[i]->idx;
vsync_cfg.pp_count = dpu_enc->num_phys_encs;
vsync_cfg.frame_rate = drm_mode_vrefresh(&dpu_enc->base.crtc->state->adjusted_mode);
- if (disp_info->is_te_using_watchdog_timer)
- vsync_cfg.vsync_source = DPU_VSYNC_SOURCE_WD_TIMER_0;
- else
- vsync_cfg.vsync_source = DPU_VSYNC0_SOURCE_GPIO;
+ vsync_cfg.vsync_source = disp_info->vsync_source;
hw_mdptop->ops.setup_vsync_source(hw_mdptop, &vsync_cfg);
@@ -1200,6 +1192,8 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
phys->hw_ctl = to_dpu_hw_ctl(hw_ctl[i]);
phys->cached_mode = crtc_state->adjusted_mode;
+ if (phys->ops.atomic_mode_set)
+ phys->ops.atomic_mode_set(phys, crtc_state, conn_state);
}
}
@@ -1226,7 +1220,8 @@ static void _dpu_encoder_virt_enable_helper(struct drm_encoder *drm_enc)
dpu_enc->cur_master->hw_mdptop->ops.intf_audio_select(
dpu_enc->cur_master->hw_mdptop);
- _dpu_encoder_update_vsync_source(dpu_enc, &dpu_enc->disp_info);
+ if (dpu_enc->disp_info.is_cmd_mode)
+ _dpu_encoder_update_vsync_source(dpu_enc, &dpu_enc->disp_info);
if (dpu_enc->disp_info.intf_type == INTF_DSI &&
!WARN_ON(dpu_enc->num_phys_encs == 0)) {
@@ -1454,28 +1449,6 @@ void dpu_encoder_toggle_vblank_for_crtc(struct drm_encoder *drm_enc,
}
}
-void dpu_encoder_register_frame_event_callback(struct drm_encoder *drm_enc,
- void (*frame_event_cb)(void *, u32 event),
- void *frame_event_cb_data)
-{
- struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
- unsigned long lock_flags;
- bool enable;
-
- enable = frame_event_cb ? true : false;
-
- if (!drm_enc) {
- DPU_ERROR("invalid encoder\n");
- return;
- }
- trace_dpu_enc_frame_event_cb(DRMID(drm_enc), enable);
-
- spin_lock_irqsave(&dpu_enc->enc_spinlock, lock_flags);
- dpu_enc->crtc_frame_event_cb = frame_event_cb;
- dpu_enc->crtc_frame_event_cb_data = frame_event_cb_data;
- spin_unlock_irqrestore(&dpu_enc->enc_spinlock, lock_flags);
-}
-
void dpu_encoder_frame_done_callback(
struct drm_encoder *drm_enc,
struct dpu_encoder_phys *ready_phys, u32 event)
@@ -1515,15 +1488,12 @@ void dpu_encoder_frame_done_callback(
dpu_encoder_resource_control(drm_enc,
DPU_ENC_RC_EVENT_FRAME_DONE);
- if (dpu_enc->crtc_frame_event_cb)
- dpu_enc->crtc_frame_event_cb(
- dpu_enc->crtc_frame_event_cb_data,
- event);
+ if (dpu_enc->crtc)
+ dpu_crtc_frame_event_cb(dpu_enc->crtc, event);
}
} else {
- if (dpu_enc->crtc_frame_event_cb)
- dpu_enc->crtc_frame_event_cb(
- dpu_enc->crtc_frame_event_cb_data, event);
+ if (dpu_enc->crtc)
+ dpu_crtc_frame_event_cb(dpu_enc->crtc, event);
}
}
@@ -1741,8 +1711,7 @@ void dpu_encoder_trigger_kickoff_pending(struct drm_encoder *drm_enc)
phys = dpu_enc->phys_encs[i];
ctl = phys->hw_ctl;
- if (ctl->ops.clear_pending_flush)
- ctl->ops.clear_pending_flush(ctl);
+ ctl->ops.clear_pending_flush(ctl);
/* update only for command mode primary ctl */
if ((phys == dpu_enc->cur_master) &&
@@ -2457,7 +2426,7 @@ static void dpu_encoder_frame_done_timeout(struct timer_list *t)
return;
}
- if (!dpu_enc->frame_busy_mask[0] || !dpu_enc->crtc_frame_event_cb) {
+ if (!dpu_enc->frame_busy_mask[0] || !dpu_enc->crtc) {
DRM_DEBUG_KMS("id:%u invalid timeout frame_busy_mask=%lu\n",
DRMID(drm_enc), dpu_enc->frame_busy_mask[0]);
return;
@@ -2473,7 +2442,7 @@ static void dpu_encoder_frame_done_timeout(struct timer_list *t)
event = DPU_ENCODER_FRAME_EVENT_ERROR;
trace_dpu_enc_frame_done_timeout(DRMID(drm_enc), event);
- dpu_enc->crtc_frame_event_cb(dpu_enc->crtc_frame_event_cb_data, event);
+ dpu_crtc_frame_event_cb(dpu_enc->crtc, event);
}
static const struct drm_encoder_helper_funcs dpu_encoder_helper_funcs = {
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
index 76be77e30954..f7465a1774aa 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
@@ -26,15 +26,14 @@
* @h_tile_instance: Controller instance used per tile. Number of elements is
* based on num_of_h_tiles
* @is_cmd_mode Boolean to indicate if the CMD mode is requested
- * @is_te_using_watchdog_timer: Boolean to indicate watchdog TE is
- * used instead of panel TE in cmd mode panels
+ * @vsync_source: Source of the TE signal for DSI CMD devices
*/
struct msm_display_info {
enum dpu_intf_type intf_type;
uint32_t num_of_h_tiles;
uint32_t h_tile_instance[MAX_H_TILES_PER_DISPLAY];
bool is_cmd_mode;
- bool is_te_using_watchdog_timer;
+ enum dpu_vsync_source vsync_source;
};
/**
@@ -56,16 +55,6 @@ void dpu_encoder_toggle_vblank_for_crtc(struct drm_encoder *encoder,
struct drm_crtc *crtc, bool enable);
/**
- * dpu_encoder_register_frame_event_callback - provide callback to encoder that
- * will be called after the request is complete, or other events.
- * @encoder: encoder pointer
- * @cb: callback pointer, provide NULL to deregister
- * @data: user data provided to callback
- */
-void dpu_encoder_register_frame_event_callback(struct drm_encoder *encoder,
- void (*cb)(void *, u32), void *data);
-
-/**
* dpu_encoder_prepare_for_kickoff - schedule double buffer flip of the ctl
* path (i.e. ctl flush and start) at next appropriate time.
* Immediately: if no previous commit is outstanding.
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
index 002e89cc1705..e77ebe3a68da 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -69,6 +69,8 @@ struct dpu_encoder_phys;
* @is_master: Whether this phys_enc is the current master
* encoder. Can be switched at enable time. Based
* on split_role and current mode (CMD/VID).
+ * @atomic_mode_set: DRM Call. Set a DRM mode.
+ * This likely caches the mode, for use at enable.
* @enable: DRM Call. Enable a DRM mode.
* @disable: DRM Call. Disable mode.
* @control_vblank_irq Register/Deregister for VBLANK IRQ
@@ -93,6 +95,9 @@ struct dpu_encoder_phys;
struct dpu_encoder_phys_ops {
void (*prepare_commit)(struct dpu_encoder_phys *encoder);
bool (*is_master)(struct dpu_encoder_phys *encoder);
+ void (*atomic_mode_set)(struct dpu_encoder_phys *encoder,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state);
void (*enable)(struct dpu_encoder_phys *encoder);
void (*disable)(struct dpu_encoder_phys *encoder);
int (*control_vblank_irq)(struct dpu_encoder_phys *enc, bool enable);
@@ -335,6 +340,14 @@ static inline enum dpu_3d_blend_mode dpu_encoder_helper_get_3d_blend_mode(
unsigned int dpu_encoder_helper_get_dsc(struct dpu_encoder_phys *phys_enc);
/**
+ * dpu_encoder_get_dsc_config - get DSC config for the DPU encoder
+ * This helper function is used by physical encoder to get DSC config
+ * used for this encoder.
+ * @drm_enc: Pointer to encoder structure
+ */
+struct drm_dsc_config *dpu_encoder_get_dsc_config(struct drm_encoder *drm_enc);
+
+/**
* dpu_encoder_get_drm_fmt - return DRM fourcc format
* @phys_enc: Pointer to physical encoder structure
*/
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 489be1c0c704..6fc31d47cd1d 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
@@ -142,6 +142,23 @@ static void dpu_encoder_phys_cmd_underrun_irq(void *arg)
dpu_encoder_underrun_callback(phys_enc->parent, phys_enc);
}
+static void dpu_encoder_phys_cmd_atomic_mode_set(
+ struct dpu_encoder_phys *phys_enc,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state)
+{
+ phys_enc->irq[INTR_IDX_CTL_START] = phys_enc->hw_ctl->caps->intr_start;
+
+ phys_enc->irq[INTR_IDX_PINGPONG] = phys_enc->hw_pp->caps->intr_done;
+
+ if (phys_enc->has_intf_te)
+ phys_enc->irq[INTR_IDX_RDPTR] = phys_enc->hw_intf->cap->intr_tear_rd_ptr;
+ else
+ phys_enc->irq[INTR_IDX_RDPTR] = phys_enc->hw_pp->caps->intr_rdptr;
+
+ phys_enc->irq[INTR_IDX_UNDERRUN] = phys_enc->hw_intf->cap->intr_underrun;
+}
+
static int _dpu_encoder_phys_cmd_handle_ppdone_timeout(
struct dpu_encoder_phys *phys_enc)
{
@@ -280,14 +297,6 @@ static void dpu_encoder_phys_cmd_irq_enable(struct dpu_encoder_phys *phys_enc)
phys_enc->hw_pp->idx - PINGPONG_0,
phys_enc->vblank_refcount);
- phys_enc->irq[INTR_IDX_CTL_START] = phys_enc->hw_ctl->caps->intr_start;
- phys_enc->irq[INTR_IDX_PINGPONG] = phys_enc->hw_pp->caps->intr_done;
-
- if (phys_enc->has_intf_te)
- phys_enc->irq[INTR_IDX_RDPTR] = phys_enc->hw_intf->cap->intr_tear_rd_ptr;
- else
- phys_enc->irq[INTR_IDX_RDPTR] = phys_enc->hw_pp->caps->intr_rdptr;
-
dpu_core_irq_register_callback(phys_enc->dpu_kms,
phys_enc->irq[INTR_IDX_PINGPONG],
dpu_encoder_phys_cmd_pp_tx_done_irq,
@@ -298,7 +307,7 @@ static void dpu_encoder_phys_cmd_irq_enable(struct dpu_encoder_phys *phys_enc)
phys_enc);
dpu_encoder_phys_cmd_control_vblank_irq(phys_enc, true);
- if (dpu_encoder_phys_cmd_is_master(phys_enc))
+ if (dpu_encoder_phys_cmd_is_master(phys_enc) && phys_enc->irq[INTR_IDX_CTL_START])
dpu_core_irq_register_callback(phys_enc->dpu_kms,
phys_enc->irq[INTR_IDX_CTL_START],
dpu_encoder_phys_cmd_ctl_start_irq,
@@ -311,17 +320,13 @@ static void dpu_encoder_phys_cmd_irq_disable(struct dpu_encoder_phys *phys_enc)
phys_enc->hw_pp->idx - PINGPONG_0,
phys_enc->vblank_refcount);
- if (dpu_encoder_phys_cmd_is_master(phys_enc))
+ if (dpu_encoder_phys_cmd_is_master(phys_enc) && phys_enc->irq[INTR_IDX_CTL_START])
dpu_core_irq_unregister_callback(phys_enc->dpu_kms,
phys_enc->irq[INTR_IDX_CTL_START]);
dpu_core_irq_unregister_callback(phys_enc->dpu_kms, phys_enc->irq[INTR_IDX_UNDERRUN]);
dpu_encoder_phys_cmd_control_vblank_irq(phys_enc, false);
dpu_core_irq_unregister_callback(phys_enc->dpu_kms, phys_enc->irq[INTR_IDX_PINGPONG]);
-
- phys_enc->irq[INTR_IDX_CTL_START] = 0;
- phys_enc->irq[INTR_IDX_PINGPONG] = 0;
- phys_enc->irq[INTR_IDX_RDPTR] = 0;
}
static void dpu_encoder_phys_cmd_tearcheck_config(
@@ -698,6 +703,7 @@ static void dpu_encoder_phys_cmd_init_ops(
struct dpu_encoder_phys_ops *ops)
{
ops->is_master = dpu_encoder_phys_cmd_is_master;
+ ops->atomic_mode_set = dpu_encoder_phys_cmd_atomic_mode_set;
ops->enable = dpu_encoder_phys_cmd_enable;
ops->disable = dpu_encoder_phys_cmd_disable;
ops->control_vblank_irq = dpu_encoder_phys_cmd_control_vblank_irq;
@@ -736,8 +742,6 @@ struct dpu_encoder_phys *dpu_encoder_phys_cmd_init(struct drm_device *dev,
dpu_encoder_phys_cmd_init_ops(&phys_enc->ops);
phys_enc->intf_mode = INTF_MODE_CMD;
- phys_enc->irq[INTR_IDX_UNDERRUN] = phys_enc->hw_intf->cap->intr_underrun;
-
cmd_enc->stream_sel = 0;
if (!phys_enc->hw_intf) {
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 ef69c2f408c3..ba8878d21cf0 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
@@ -11,6 +11,7 @@
#include "dpu_trace.h"
#include "disp/msm_disp_snapshot.h"
+#include <drm/display/drm_dsc_helper.h>
#include <drm/drm_managed.h>
#define DPU_DEBUG_VIDENC(e, fmt, ...) DPU_DEBUG("enc%d intf%d " fmt, \
@@ -115,6 +116,23 @@ static void drm_mode_to_intf_timing_params(
timing->h_front_porch = timing->h_front_porch >> 1;
timing->hsync_pulse_width = timing->hsync_pulse_width >> 1;
}
+
+ /*
+ * for DSI, if compression is enabled, then divide the horizonal active
+ * timing parameters by compression ratio. bits of 3 components(R/G/B)
+ * is compressed into bits of 1 pixel.
+ */
+ if (phys_enc->hw_intf->cap->type != INTF_DP && timing->compression_en) {
+ struct drm_dsc_config *dsc =
+ dpu_encoder_get_dsc_config(phys_enc->parent);
+ /*
+ * TODO: replace drm_dsc_get_bpp_int with logic to handle
+ * fractional part if there is fraction
+ */
+ timing->width = timing->width * drm_dsc_get_bpp_int(dsc) /
+ (dsc->bits_per_component * 3);
+ timing->xres = timing->width;
+ }
}
static u32 get_horizontal_total(const struct dpu_hw_intf_timing_params *timing)
@@ -289,7 +307,8 @@ static void dpu_encoder_phys_vid_setup_timing_engine(
spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags);
phys_enc->hw_intf->ops.setup_timing_gen(phys_enc->hw_intf,
- &timing_params, fmt);
+ &timing_params, fmt,
+ phys_enc->dpu_kms->catalog->mdss_ver);
phys_enc->hw_ctl->ops.setup_intf_cfg(phys_enc->hw_ctl, &intf_cfg);
/* setup which pp blk will connect to this intf */
@@ -356,6 +375,16 @@ static bool dpu_encoder_phys_vid_needs_single_flush(
return phys_enc->split_role != ENC_ROLE_SOLO;
}
+static void dpu_encoder_phys_vid_atomic_mode_set(
+ struct dpu_encoder_phys *phys_enc,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state)
+{
+ phys_enc->irq[INTR_IDX_VSYNC] = phys_enc->hw_intf->cap->intr_vsync;
+
+ phys_enc->irq[INTR_IDX_UNDERRUN] = phys_enc->hw_intf->cap->intr_underrun;
+}
+
static int dpu_encoder_phys_vid_control_vblank_irq(
struct dpu_encoder_phys *phys_enc,
bool enable)
@@ -699,6 +728,7 @@ static int dpu_encoder_phys_vid_get_frame_count(
static void dpu_encoder_phys_vid_init_ops(struct dpu_encoder_phys_ops *ops)
{
ops->is_master = dpu_encoder_phys_vid_is_master;
+ ops->atomic_mode_set = dpu_encoder_phys_vid_atomic_mode_set;
ops->enable = dpu_encoder_phys_vid_enable;
ops->disable = dpu_encoder_phys_vid_disable;
ops->control_vblank_irq = dpu_encoder_phys_vid_control_vblank_irq;
@@ -737,8 +767,6 @@ struct dpu_encoder_phys *dpu_encoder_phys_vid_init(struct drm_device *dev,
dpu_encoder_phys_vid_init_ops(&phys_enc->ops);
phys_enc->intf_mode = INTF_MODE_VIDEO;
- phys_enc->irq[INTR_IDX_VSYNC] = phys_enc->hw_intf->cap->intr_vsync;
- phys_enc->irq[INTR_IDX_UNDERRUN] = phys_enc->hw_intf->cap->intr_underrun;
DPU_DEBUG_VIDENC(phys_enc, "created intf idx:%d\n", p->hw_intf->idx);
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 d3ea91c1d7d2..882c717859ce 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
@@ -404,6 +404,15 @@ static void dpu_encoder_phys_wb_irq_disable(struct dpu_encoder_phys *phys)
dpu_core_irq_unregister_callback(phys->dpu_kms, phys->irq[INTR_IDX_WB_DONE]);
}
+static void dpu_encoder_phys_wb_atomic_mode_set(
+ struct dpu_encoder_phys *phys_enc,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state)
+{
+
+ phys_enc->irq[INTR_IDX_WB_DONE] = phys_enc->hw_wb->caps->intr_wb_done;
+}
+
static void _dpu_encoder_phys_wb_handle_wbdone_timeout(
struct dpu_encoder_phys *phys_enc)
{
@@ -529,8 +538,7 @@ static void dpu_encoder_phys_wb_disable(struct dpu_encoder_phys *phys_enc)
}
/* reset h/w before final flush */
- if (phys_enc->hw_ctl->ops.clear_pending_flush)
- phys_enc->hw_ctl->ops.clear_pending_flush(phys_enc->hw_ctl);
+ phys_enc->hw_ctl->ops.clear_pending_flush(phys_enc->hw_ctl);
/*
* New CTL reset sequence from 5.0 MDP onwards.
@@ -640,6 +648,7 @@ static bool dpu_encoder_phys_wb_is_valid_for_commit(struct dpu_encoder_phys *phy
static void dpu_encoder_phys_wb_init_ops(struct dpu_encoder_phys_ops *ops)
{
ops->is_master = dpu_encoder_phys_wb_is_master;
+ ops->atomic_mode_set = dpu_encoder_phys_wb_atomic_mode_set;
ops->enable = dpu_encoder_phys_wb_enable;
ops->disable = dpu_encoder_phys_wb_disable;
ops->wait_for_commit_done = dpu_encoder_phys_wb_wait_for_commit_done;
@@ -685,7 +694,6 @@ struct dpu_encoder_phys *dpu_encoder_phys_wb_init(struct drm_device *dev,
dpu_encoder_phys_wb_init_ops(&phys_enc->ops);
phys_enc->intf_mode = INTF_MODE_WB_LINE;
- phys_enc->irq[INTR_IDX_WB_DONE] = phys_enc->hw_wb->caps->intr_wb_done;
atomic_set(&wb_enc->wbirq_refcount, 0);
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 f2b6eac7601d..fc178ec73907 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
@@ -220,12 +220,9 @@ static const u32 wb2_formats_rgb[] = {
DRM_FORMAT_RGBA4444,
DRM_FORMAT_RGBX4444,
DRM_FORMAT_XRGB4444,
- DRM_FORMAT_BGR565,
DRM_FORMAT_BGR888,
- DRM_FORMAT_ABGR8888,
DRM_FORMAT_BGRA8888,
DRM_FORMAT_BGRX8888,
- DRM_FORMAT_XBGR8888,
DRM_FORMAT_ABGR1555,
DRM_FORMAT_BGRA5551,
DRM_FORMAT_XBGR1555,
@@ -254,12 +251,9 @@ static const u32 wb2_formats_rgb_yuv[] = {
DRM_FORMAT_RGBA4444,
DRM_FORMAT_RGBX4444,
DRM_FORMAT_XRGB4444,
- DRM_FORMAT_BGR565,
DRM_FORMAT_BGR888,
- DRM_FORMAT_ABGR8888,
DRM_FORMAT_BGRA8888,
DRM_FORMAT_BGRX8888,
- DRM_FORMAT_XBGR8888,
DRM_FORMAT_ABGR1555,
DRM_FORMAT_BGRA5551,
DRM_FORMAT_XBGR1555,
@@ -688,6 +682,7 @@ static const struct dpu_qos_lut_entry sc7180_qos_nrt[] = {
#include "catalog/dpu_5_0_sm8150.h"
#include "catalog/dpu_5_1_sc8180x.h"
+#include "catalog/dpu_5_2_sm7150.h"
#include "catalog/dpu_5_4_sm6125.h"
#include "catalog/dpu_6_0_sm8250.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 d1aef778340b..37e18e820a20 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
@@ -838,6 +838,7 @@ extern const struct dpu_mdss_cfg dpu_sdm845_cfg;
extern const struct dpu_mdss_cfg dpu_sdm670_cfg;
extern const struct dpu_mdss_cfg dpu_sm8150_cfg;
extern const struct dpu_mdss_cfg dpu_sc8180x_cfg;
+extern const struct dpu_mdss_cfg dpu_sm7150_cfg;
extern const struct dpu_mdss_cfg dpu_sm8250_cfg;
extern const struct dpu_mdss_cfg dpu_sc7180_cfg;
extern const struct dpu_mdss_cfg dpu_sm6115_cfg;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
index ef56280bea93..4401fdc0f3e4 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
@@ -83,7 +83,8 @@ struct dpu_hw_ctl_ops {
/**
* Clear the value of the cached pending_flush_mask
- * No effect on hardware
+ * No effect on hardware.
+ * Required to be implemented.
* @ctx : ctl path ctx pointer
*/
void (*clear_pending_flush)(struct dpu_hw_ctl *ctx);
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 225c1c7768ff..29cb854f831a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
@@ -98,7 +98,8 @@
static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *intf,
const struct dpu_hw_intf_timing_params *p,
- const struct msm_format *fmt)
+ const struct msm_format *fmt,
+ const struct dpu_mdss_version *mdss_ver)
{
struct dpu_hw_blk_reg_map *c = &intf->hw;
u32 hsync_period, vsync_period;
@@ -168,6 +169,20 @@ 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 (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 &&
+ mdss_ver->core_major_ver >= 7)
+ intf_cfg2 |= INTF_CFG2_DCE_DATA_COMPRESS;
+
hsync_data_start_x = hsync_start_x;
hsync_data_end_x = hsync_start_x + data_width - 1;
@@ -462,7 +477,7 @@ static int dpu_hw_intf_get_vsync_info(struct dpu_hw_intf *intf,
}
static void dpu_hw_intf_vsync_sel(struct dpu_hw_intf *intf,
- u32 vsync_source)
+ enum dpu_vsync_source vsync_source)
{
struct dpu_hw_blk_reg_map *c;
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 f9015c67a574..fc23650dfbf0 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h
@@ -81,7 +81,8 @@ struct dpu_hw_intf_cmd_mode_cfg {
struct dpu_hw_intf_ops {
void (*setup_timing_gen)(struct dpu_hw_intf *intf,
const struct dpu_hw_intf_timing_params *p,
- const struct msm_format *fmt);
+ const struct msm_format *fmt,
+ const struct dpu_mdss_version *mdss_ver);
void (*setup_prg_fetch)(struct dpu_hw_intf *intf,
const struct dpu_hw_intf_prog_fetch *fetch);
@@ -107,7 +108,7 @@ struct dpu_hw_intf_ops {
int (*connect_external_te)(struct dpu_hw_intf *intf, bool enable_external_te);
- void (*vsync_sel)(struct dpu_hw_intf *intf, u32 vsync_source);
+ void (*vsync_sel)(struct dpu_hw_intf *intf, enum dpu_vsync_source vsync_source);
/**
* Disable autorefresh if enabled
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 66759623fc42..a2eff36a2224 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
@@ -54,18 +54,20 @@
#define DPU_BLEND_BG_INV_MOD_ALPHA (1 << 12)
#define DPU_BLEND_BG_TRANSP_EN (1 << 13)
-#define DPU_VSYNC0_SOURCE_GPIO 0
-#define DPU_VSYNC1_SOURCE_GPIO 1
-#define DPU_VSYNC2_SOURCE_GPIO 2
-#define DPU_VSYNC_SOURCE_INTF_0 3
-#define DPU_VSYNC_SOURCE_INTF_1 4
-#define DPU_VSYNC_SOURCE_INTF_2 5
-#define DPU_VSYNC_SOURCE_INTF_3 6
-#define DPU_VSYNC_SOURCE_WD_TIMER_4 11
-#define DPU_VSYNC_SOURCE_WD_TIMER_3 12
-#define DPU_VSYNC_SOURCE_WD_TIMER_2 13
-#define DPU_VSYNC_SOURCE_WD_TIMER_1 14
-#define DPU_VSYNC_SOURCE_WD_TIMER_0 15
+enum dpu_vsync_source {
+ DPU_VSYNC_SOURCE_GPIO_0,
+ DPU_VSYNC_SOURCE_GPIO_1,
+ DPU_VSYNC_SOURCE_GPIO_2,
+ DPU_VSYNC_SOURCE_INTF_0 = 3,
+ DPU_VSYNC_SOURCE_INTF_1,
+ DPU_VSYNC_SOURCE_INTF_2,
+ DPU_VSYNC_SOURCE_INTF_3,
+ DPU_VSYNC_SOURCE_WD_TIMER_4 = 11,
+ DPU_VSYNC_SOURCE_WD_TIMER_3,
+ DPU_VSYNC_SOURCE_WD_TIMER_2,
+ DPU_VSYNC_SOURCE_WD_TIMER_1,
+ DPU_VSYNC_SOURCE_WD_TIMER_0,
+};
enum dpu_hw_blk_type {
DPU_HW_BLK_TOP = 0,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c
index 05e48cf4ec1d..6e2ac50b94a4 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c
@@ -107,8 +107,8 @@ static void dpu_hw_get_danger_status(struct dpu_hw_mdp *mdp,
status->sspp[SSPP_CURSOR1] = (value >> 26) & 0x3;
}
-static void dpu_hw_setup_vsync_source(struct dpu_hw_mdp *mdp,
- struct dpu_vsync_source_cfg *cfg)
+static void dpu_hw_setup_wd_timer(struct dpu_hw_mdp *mdp,
+ struct dpu_vsync_source_cfg *cfg)
{
struct dpu_hw_blk_reg_map *c;
u32 reg, wd_load_value, wd_ctl, wd_ctl2;
@@ -163,8 +163,8 @@ static void dpu_hw_setup_vsync_source(struct dpu_hw_mdp *mdp,
}
}
-static void dpu_hw_setup_vsync_source_and_vsync_sel(struct dpu_hw_mdp *mdp,
- struct dpu_vsync_source_cfg *cfg)
+static void dpu_hw_setup_vsync_sel(struct dpu_hw_mdp *mdp,
+ struct dpu_vsync_source_cfg *cfg)
{
struct dpu_hw_blk_reg_map *c;
u32 reg, i;
@@ -187,7 +187,7 @@ static void dpu_hw_setup_vsync_source_and_vsync_sel(struct dpu_hw_mdp *mdp,
}
DPU_REG_WRITE(c, MDP_VSYNC_SEL, reg);
- dpu_hw_setup_vsync_source(mdp, cfg);
+ dpu_hw_setup_wd_timer(mdp, cfg);
}
static void dpu_hw_get_safe_status(struct dpu_hw_mdp *mdp,
@@ -239,9 +239,9 @@ static void _setup_mdp_ops(struct dpu_hw_mdp_ops *ops,
ops->get_danger_status = dpu_hw_get_danger_status;
if (cap & BIT(DPU_MDP_VSYNC_SEL))
- ops->setup_vsync_source = dpu_hw_setup_vsync_source_and_vsync_sel;
+ ops->setup_vsync_source = dpu_hw_setup_vsync_sel;
else
- ops->setup_vsync_source = dpu_hw_setup_vsync_source;
+ ops->setup_vsync_source = dpu_hw_setup_wd_timer;
ops->get_safe_status = dpu_hw_get_safe_status;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h
index 6f3dc98087df..5c9a7ede991e 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h
@@ -64,7 +64,7 @@ struct dpu_vsync_source_cfg {
u32 pp_count;
u32 frame_rate;
u32 ppnumber[PINGPONG_MAX];
- u32 vsync_source;
+ enum dpu_vsync_source vsync_source;
};
/**
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 1955848b1b78..d1e2143110f2 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -505,6 +505,44 @@ static void dpu_kms_wait_flush(struct msm_kms *kms, unsigned crtc_mask)
dpu_kms_wait_for_commit_done(kms, crtc);
}
+static const char *dpu_vsync_sources[] = {
+ [DPU_VSYNC_SOURCE_GPIO_0] = "mdp_vsync_p",
+ [DPU_VSYNC_SOURCE_GPIO_1] = "mdp_vsync_s",
+ [DPU_VSYNC_SOURCE_GPIO_2] = "mdp_vsync_e",
+ [DPU_VSYNC_SOURCE_INTF_0] = "mdp_intf0",
+ [DPU_VSYNC_SOURCE_INTF_1] = "mdp_intf1",
+ [DPU_VSYNC_SOURCE_INTF_2] = "mdp_intf2",
+ [DPU_VSYNC_SOURCE_INTF_3] = "mdp_intf3",
+ [DPU_VSYNC_SOURCE_WD_TIMER_0] = "timer0",
+ [DPU_VSYNC_SOURCE_WD_TIMER_1] = "timer1",
+ [DPU_VSYNC_SOURCE_WD_TIMER_2] = "timer2",
+ [DPU_VSYNC_SOURCE_WD_TIMER_3] = "timer3",
+ [DPU_VSYNC_SOURCE_WD_TIMER_4] = "timer4",
+};
+
+static int dpu_kms_dsi_set_te_source(struct msm_display_info *info,
+ struct msm_dsi *dsi)
+{
+ const char *te_source = msm_dsi_get_te_source(dsi);
+ int i;
+
+ if (!te_source) {
+ info->vsync_source = DPU_VSYNC_SOURCE_GPIO_0;
+ return 0;
+ }
+
+ /* we can not use match_string since dpu_vsync_sources is a sparse array */
+ for (i = 0; i < ARRAY_SIZE(dpu_vsync_sources); i++) {
+ if (dpu_vsync_sources[i] &&
+ !strcmp(dpu_vsync_sources[i], te_source)) {
+ info->vsync_source = i;
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
static int _dpu_kms_initialize_dsi(struct drm_device *dev,
struct msm_drm_private *priv,
struct dpu_kms *dpu_kms)
@@ -543,6 +581,12 @@ static int _dpu_kms_initialize_dsi(struct drm_device *dev,
info.is_cmd_mode = msm_dsi_is_cmd_mode(priv->dsi[i]);
+ rc = dpu_kms_dsi_set_te_source(&info, priv->dsi[i]);
+ if (rc) {
+ DPU_ERROR("failed to identify TE source for dsi display\n");
+ return rc;
+ }
+
encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_DSI, &info);
if (IS_ERR(encoder)) {
DPU_ERROR("encoder init failed for dsi display\n");
@@ -1405,6 +1449,7 @@ static const struct of_device_id dpu_dt_match[] = {
{ .compatible = "qcom,sm6125-dpu", .data = &dpu_sm6125_cfg, },
{ .compatible = "qcom,sm6350-dpu", .data = &dpu_sm6350_cfg, },
{ .compatible = "qcom,sm6375-dpu", .data = &dpu_sm6375_cfg, },
+ { .compatible = "qcom,sm7150-dpu", .data = &dpu_sm7150_cfg, },
{ .compatible = "qcom,sm8150-dpu", .data = &dpu_sm8150_cfg, },
{ .compatible = "qcom,sm8250-dpu", .data = &dpu_sm8250_cfg, },
{ .compatible = "qcom,sm8350-dpu", .data = &dpu_sm8350_cfg, },
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index 1c3a2657450c..40c4dd2c3139 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -18,6 +18,7 @@
#include <drm/drm_gem_atomic_helper.h>
#include "msm_drv.h"
+#include "msm_mdss.h"
#include "dpu_kms.h"
#include "dpu_formats.h"
#include "dpu_hw_sspp.h"
@@ -1342,10 +1343,14 @@ void dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable)
static bool dpu_plane_format_mod_supported(struct drm_plane *plane,
uint32_t format, uint64_t modifier)
{
+ struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane);
+ bool has_no_ubwc = (dpu_kms->mdss->ubwc_enc_version == 0) &&
+ (dpu_kms->mdss->ubwc_dec_version == 0);
+
if (modifier == DRM_FORMAT_MOD_LINEAR)
return true;
- if (modifier == DRM_FORMAT_MOD_QCOM_COMPRESSED)
+ if (modifier == DRM_FORMAT_MOD_QCOM_COMPRESSED && !has_no_ubwc)
return dpu_find_format(format, qcom_compressed_supported_formats,
ARRAY_SIZE(qcom_compressed_supported_formats));
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h
index 0fdd41162e4b..5307cbc2007c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h
@@ -354,10 +354,6 @@ DEFINE_EVENT(dpu_enc_id_enable_template, dpu_enc_vblank_cb,
TP_PROTO(uint32_t drm_id, bool enable),
TP_ARGS(drm_id, enable)
);
-DEFINE_EVENT(dpu_enc_id_enable_template, dpu_enc_frame_event_cb,
- TP_PROTO(uint32_t drm_id, bool enable),
- TP_ARGS(drm_id, enable)
-);
DEFINE_EVENT(dpu_enc_id_enable_template, dpu_enc_phys_cmd_connect_te,
TP_PROTO(uint32_t drm_id, bool enable),
TP_ARGS(drm_id, enable)
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c
index c5179e4c393c..df464f7c05bf 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c
@@ -837,8 +837,7 @@ static const struct mdp5_cfg_hw msm8x53_config = {
.name = "msm8x53",
.mdp = {
.count = 1,
- .caps = MDP_CAP_CDM |
- MDP_CAP_SRC_SPLIT,
+ .caps = MDP_CAP_CDM,
},
.ctl = {
.count = 3,
@@ -1011,6 +1010,93 @@ static const struct mdp5_cfg_hw msm8917_config = {
.max_clk = 320000000,
};
+static const struct mdp5_cfg_hw msm8937_config = {
+ .name = "msm8937",
+ .mdp = {
+ .count = 1,
+ .caps = MDP_CAP_CDM,
+ },
+ .ctl = {
+ .count = 3,
+ .base = { 0x01000, 0x01200, 0x01400 },
+ .flush_hw_mask = 0xffffffff,
+ },
+ .pipe_vig = {
+ .count = 1,
+ .base = { 0x04000 },
+ .caps = MDP_PIPE_CAP_HFLIP |
+ MDP_PIPE_CAP_VFLIP |
+ MDP_PIPE_CAP_SCALE |
+ MDP_PIPE_CAP_CSC |
+ MDP_PIPE_CAP_DECIMATION |
+ MDP_PIPE_CAP_SW_PIX_EXT |
+ 0,
+ },
+ .pipe_rgb = {
+ .count = 2,
+ .base = { 0x14000, 0x16000 },
+ .caps = MDP_PIPE_CAP_HFLIP |
+ MDP_PIPE_CAP_VFLIP |
+ MDP_PIPE_CAP_DECIMATION |
+ MDP_PIPE_CAP_SW_PIX_EXT |
+ 0,
+ },
+ .pipe_dma = {
+ .count = 1,
+ .base = { 0x24000 },
+ .caps = MDP_PIPE_CAP_HFLIP |
+ MDP_PIPE_CAP_VFLIP |
+ MDP_PIPE_CAP_SW_PIX_EXT |
+ 0,
+ },
+ .pipe_cursor = {
+ .count = 1,
+ .base = { 0x34000 },
+ .caps = MDP_PIPE_CAP_HFLIP |
+ MDP_PIPE_CAP_VFLIP |
+ MDP_PIPE_CAP_SW_PIX_EXT |
+ MDP_PIPE_CAP_CURSOR |
+ 0,
+ },
+
+ .lm = {
+ .count = 2,
+ .base = { 0x44000, 0x45000 },
+ .instances = {
+ { .id = 0, .pp = 0, .dspp = 0,
+ .caps = MDP_LM_CAP_DISPLAY |
+ MDP_LM_CAP_PAIR },
+ { .id = 1, .pp = 1, .dspp = -1,
+ .caps = MDP_LM_CAP_DISPLAY },
+ },
+ .nb_stages = 5,
+ .max_width = 2048,
+ .max_height = 0xFFFF,
+ },
+ .dspp = {
+ .count = 1,
+ .base = { 0x54000 },
+
+ },
+ .pp = {
+ .count = 2,
+ .base = { 0x70000, 0x70800 },
+ },
+ .cdm = {
+ .count = 1,
+ .base = { 0x79200 },
+ },
+ .intf = {
+ .base = { 0x00000, 0x6a800, 0x6b000 },
+ .connect = {
+ [0] = INTF_DISABLED,
+ [1] = INTF_DSI,
+ [2] = INTF_DSI,
+ },
+ },
+ .max_clk = 320000000,
+};
+
static const struct mdp5_cfg_hw msm8998_config = {
.name = "msm8998",
.mdp = {
@@ -1325,6 +1411,7 @@ static const struct mdp5_cfg_handler cfg_handlers_v1[] = {
{ .revision = 9, .config = { .hw = &msm8x94_config } },
{ .revision = 7, .config = { .hw = &msm8x96_config } },
{ .revision = 11, .config = { .hw = &msm8x76_config } },
+ { .revision = 14, .config = { .hw = &msm8937_config } },
{ .revision = 15, .config = { .hw = &msm8917_config } },
{ .revision = 16, .config = { .hw = &msm8x53_config } },
};
diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c
index da46a433bf74..00dfafbebe0e 100644
--- a/drivers/gpu/drm/msm/dp/dp_aux.c
+++ b/drivers/gpu/drm/msm/dp/dp_aux.c
@@ -513,7 +513,10 @@ static int dp_wait_hpd_asserted(struct drm_dp_aux *dp_aux,
aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
- pm_runtime_get_sync(aux->dev);
+ ret = pm_runtime_resume_and_get(aux->dev);
+ if (ret)
+ return ret;
+
ret = dp_catalog_aux_wait_for_hpd_connect_state(aux->catalog, wait_us);
pm_runtime_put_sync(aux->dev);
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index 672a7ba52eda..9622e58dce3e 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -360,26 +360,25 @@ static int dp_display_send_hpd_notification(struct dp_display_private *dp,
static int dp_display_process_hpd_high(struct dp_display_private *dp)
{
+ struct drm_connector *connector = dp->dp_display.connector;
+ const struct drm_display_info *info = &connector->display_info;
int rc = 0;
- struct edid *edid;
- rc = dp_panel_read_sink_caps(dp->panel, dp->dp_display.connector);
+ rc = dp_panel_read_sink_caps(dp->panel, connector);
if (rc)
goto end;
dp_link_process_request(dp->link);
if (!dp->dp_display.is_edp)
- drm_dp_set_subconnector_property(dp->dp_display.connector,
+ drm_dp_set_subconnector_property(connector,
connector_status_connected,
dp->panel->dpcd,
dp->panel->downstream_ports);
- edid = dp->panel->edid;
-
dp->dp_display.psr_supported = dp->panel->psr_cap.version && psr_enabled;
- dp->audio_supported = drm_detect_monitor_audio(edid);
+ dp->audio_supported = info->has_audio;
dp_panel_handle_sink_request(dp->panel);
/*
diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c
index 07db8f37cd06..a916b5f3b317 100644
--- a/drivers/gpu/drm/msm/dp/dp_panel.c
+++ b/drivers/gpu/drm/msm/dp/dp_panel.c
@@ -108,28 +108,6 @@ static u32 dp_panel_get_supported_bpp(struct dp_panel *dp_panel,
return bpp;
}
-static int dp_panel_update_modes(struct drm_connector *connector,
- struct edid *edid)
-{
- int rc = 0;
-
- if (edid) {
- rc = drm_connector_update_edid_property(connector, edid);
- if (rc) {
- DRM_ERROR("failed to update edid property %d\n", rc);
- return rc;
- }
- rc = drm_add_edid_modes(connector, edid);
- return rc;
- }
-
- rc = drm_connector_update_edid_property(connector, NULL);
- if (rc)
- DRM_ERROR("failed to update edid property %d\n", rc);
-
- return rc;
-}
-
int dp_panel_read_sink_caps(struct dp_panel *dp_panel,
struct drm_connector *connector)
{
@@ -175,12 +153,13 @@ int dp_panel_read_sink_caps(struct dp_panel *dp_panel,
if (rc)
return rc;
- kfree(dp_panel->edid);
- dp_panel->edid = NULL;
+ drm_edid_free(dp_panel->drm_edid);
+
+ dp_panel->drm_edid = drm_edid_read_ddc(connector, &panel->aux->ddc);
+
+ drm_edid_connector_update(connector, dp_panel->drm_edid);
- dp_panel->edid = drm_get_edid(connector,
- &panel->aux->ddc);
- if (!dp_panel->edid) {
+ if (!dp_panel->drm_edid) {
DRM_ERROR("panel edid read failed\n");
/* check edid read fail is due to unplug */
if (!dp_catalog_link_is_connected(panel->catalog)) {
@@ -224,13 +203,13 @@ int dp_panel_get_modes(struct dp_panel *dp_panel,
return -EINVAL;
}
- if (dp_panel->edid)
- return dp_panel_update_modes(connector, dp_panel->edid);
+ if (dp_panel->drm_edid)
+ return drm_edid_connector_add_modes(connector);
return 0;
}
-static u8 dp_panel_get_edid_checksum(struct edid *edid)
+static u8 dp_panel_get_edid_checksum(const struct edid *edid)
{
edid += edid->extensions;
@@ -249,10 +228,12 @@ void dp_panel_handle_sink_request(struct dp_panel *dp_panel)
panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
if (panel->link->sink_request & DP_TEST_LINK_EDID_READ) {
+ /* FIXME: get rid of drm_edid_raw() */
+ const struct edid *edid = drm_edid_raw(dp_panel->drm_edid);
u8 checksum;
- if (dp_panel->edid)
- checksum = dp_panel_get_edid_checksum(dp_panel->edid);
+ if (edid)
+ checksum = dp_panel_get_edid_checksum(edid);
else
checksum = dp_panel->connector->real_edid_checksum;
@@ -539,5 +520,5 @@ void dp_panel_put(struct dp_panel *dp_panel)
if (!dp_panel)
return;
- kfree(dp_panel->edid);
+ drm_edid_free(dp_panel->drm_edid);
}
diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h b/drivers/gpu/drm/msm/dp/dp_panel.h
index 4ea42fa936ae..6722e3923fa5 100644
--- a/drivers/gpu/drm/msm/dp/dp_panel.h
+++ b/drivers/gpu/drm/msm/dp/dp_panel.h
@@ -39,7 +39,7 @@ struct dp_panel {
u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS];
struct dp_link_info link_info;
- struct edid *edid;
+ const struct drm_edid *drm_edid;
struct drm_connector *connector;
struct dp_display_mode dp_mode;
struct dp_panel_psr psr_cap;
diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h
index afc290408ba4..87496db203d6 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.h
@@ -37,6 +37,7 @@ struct msm_dsi {
struct mipi_dsi_host *host;
struct msm_dsi_phy *phy;
+ const char *te_source;
struct drm_bridge *next_bridge;
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
index a50f4dda5941..185d7de0bf37 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -7,7 +7,6 @@
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/err.h>
-#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/mfd/syscon.h>
#include <linux/of.h>
@@ -130,9 +129,6 @@ struct msm_dsi_host {
unsigned long src_clk_rate;
- struct gpio_desc *disp_en_gpio;
- struct gpio_desc *te_gpio;
-
const struct msm_dsi_cfg_handler *cfg_hnd;
struct completion dma_comp;
@@ -754,6 +750,8 @@ static void dsi_ctrl_enable(struct msm_dsi_host *msm_host,
data |= DSI_VID_CFG0_TRAFFIC_MODE(dsi_get_traffic_mode(flags));
data |= DSI_VID_CFG0_DST_FORMAT(dsi_get_vid_fmt(mipi_fmt));
data |= DSI_VID_CFG0_VIRT_CHANNEL(msm_host->channel);
+ if (msm_dsi_host_is_wide_bus_enabled(&msm_host->base))
+ data |= DSI_VID_CFG0_DATABUS_WIDEN;
dsi_write(msm_host, REG_DSI_VID_CFG0, data);
/* Do not swap RGB colors */
@@ -778,7 +776,6 @@ static void dsi_ctrl_enable(struct msm_dsi_host *msm_host,
if (cfg_hnd->minor >= MSM_DSI_6G_VER_MINOR_V1_3)
data |= DSI_CMD_MODE_MDP_CTRL2_BURST_MODE;
- /* TODO: Allow for video-mode support once tested/fixed */
if (msm_dsi_host_is_wide_bus_enabled(&msm_host->base))
data |= DSI_CMD_MODE_MDP_CTRL2_DATABUS_WIDEN;
@@ -856,6 +853,7 @@ static void dsi_update_dsc_timing(struct msm_dsi_host *msm_host, bool is_cmd_mod
u32 slice_per_intf, total_bytes_per_intf;
u32 pkt_per_line;
u32 eol_byte_num;
+ u32 bytes_per_pkt;
/* first calculate dsc parameters and then program
* compress mode registers
@@ -863,6 +861,7 @@ static void dsi_update_dsc_timing(struct msm_dsi_host *msm_host, bool is_cmd_mod
slice_per_intf = msm_dsc_get_slices_per_intf(dsc, hdisplay);
total_bytes_per_intf = dsc->slice_chunk_size * slice_per_intf;
+ bytes_per_pkt = dsc->slice_chunk_size; /* * slice_per_pkt; */
eol_byte_num = total_bytes_per_intf % 3;
@@ -882,7 +881,11 @@ static void dsi_update_dsc_timing(struct msm_dsi_host *msm_host, bool is_cmd_mod
/* DSI_VIDEO_COMPRESSION_MODE & DSI_COMMAND_COMPRESSION_MODE
* registers have similar offsets, so for below common code use
* DSI_VIDEO_COMPRESSION_MODE_XXXX for setting bits
+ *
+ * pkt_per_line is log2 encoded, >>1 works for supported values (1,2,4)
*/
+ if (pkt_per_line > 4)
+ drm_warn_once(msm_host->dev, "pkt_per_line too big");
reg |= DSI_VIDEO_COMPRESSION_MODE_CTRL_PKT_PER_LINE(pkt_per_line >> 1);
reg |= DSI_VIDEO_COMPRESSION_MODE_CTRL_EOL_BYTE_NUM(eol_byte_num);
reg |= DSI_VIDEO_COMPRESSION_MODE_CTRL_EN;
@@ -900,6 +903,7 @@ static void dsi_update_dsc_timing(struct msm_dsi_host *msm_host, bool is_cmd_mod
dsi_write(msm_host, REG_DSI_COMMAND_COMPRESSION_MODE_CTRL, reg_ctrl);
dsi_write(msm_host, REG_DSI_COMMAND_COMPRESSION_MODE_CTRL2, reg_ctrl2);
} else {
+ reg |= DSI_VIDEO_COMPRESSION_MODE_CTRL_WC(bytes_per_pkt);
dsi_write(msm_host, REG_DSI_VIDEO_COMPRESSION_MODE_CTRL, reg);
}
}
@@ -1613,28 +1617,6 @@ static irqreturn_t dsi_host_irq(int irq, void *ptr)
return IRQ_HANDLED;
}
-static int dsi_host_init_panel_gpios(struct msm_dsi_host *msm_host,
- struct device *panel_device)
-{
- msm_host->disp_en_gpio = devm_gpiod_get_optional(panel_device,
- "disp-enable",
- GPIOD_OUT_LOW);
- if (IS_ERR(msm_host->disp_en_gpio)) {
- DBG("cannot get disp-enable-gpios %ld",
- PTR_ERR(msm_host->disp_en_gpio));
- return PTR_ERR(msm_host->disp_en_gpio);
- }
-
- msm_host->te_gpio = devm_gpiod_get_optional(panel_device, "disp-te",
- GPIOD_IN);
- if (IS_ERR(msm_host->te_gpio)) {
- DBG("cannot get disp-te-gpios %ld", PTR_ERR(msm_host->te_gpio));
- return PTR_ERR(msm_host->te_gpio);
- }
-
- return 0;
-}
-
static int dsi_host_attach(struct mipi_dsi_host *host,
struct mipi_dsi_device *dsi)
{
@@ -1651,11 +1633,6 @@ static int dsi_host_attach(struct mipi_dsi_host *host,
if (dsi->dsc)
msm_host->dsc = dsi->dsc;
- /* Some gpios defined in panel DT need to be controlled by host */
- ret = dsi_host_init_panel_gpios(msm_host, &dsi->dev);
- if (ret)
- return ret;
-
ret = dsi_dev_attach(msm_host->pdev);
if (ret)
return ret;
@@ -1817,9 +1794,11 @@ static int dsi_populate_dsc_params(struct msm_dsi_host *msm_host, struct drm_dsc
static int dsi_host_parse_dt(struct msm_dsi_host *msm_host)
{
+ struct msm_dsi *msm_dsi = platform_get_drvdata(msm_host->pdev);
struct device *dev = &msm_host->pdev->dev;
struct device_node *np = dev->of_node;
struct device_node *endpoint;
+ const char *te_source;
int ret = 0;
/*
@@ -1842,6 +1821,16 @@ static int dsi_host_parse_dt(struct msm_dsi_host *msm_host)
goto err;
}
+ ret = of_property_read_string(endpoint, "qcom,te-source", &te_source);
+ if (ret && ret != -EINVAL) {
+ DRM_DEV_ERROR(dev, "%s: invalid TE source configuration %d\n",
+ __func__, ret);
+ goto err;
+ }
+ if (!ret)
+ msm_dsi->te_source = devm_kstrdup(dev, te_source, GFP_KERNEL);
+ ret = 0;
+
if (of_property_read_bool(np, "syscon-sfpb")) {
msm_host->sfpb = syscon_regmap_lookup_by_phandle(np,
"syscon-sfpb");
@@ -2422,9 +2411,6 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host,
dsi_sw_reset(msm_host);
dsi_ctrl_enable(msm_host, phy_shared_timings, phy);
- if (msm_host->disp_en_gpio)
- gpiod_set_value(msm_host->disp_en_gpio, 1);
-
msm_host->power_on = true;
mutex_unlock(&msm_host->dev_mutex);
@@ -2454,9 +2440,6 @@ int msm_dsi_host_power_off(struct mipi_dsi_host *host)
dsi_ctrl_disable(msm_host);
- if (msm_host->disp_en_gpio)
- gpiod_set_value(msm_host->disp_en_gpio, 0);
-
pinctrl_pm_select_sleep_state(&msm_host->pdev->dev);
cfg_hnd->ops->link_clk_disable(msm_host);
diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
index 5b3f3068fd92..a210b7c9e5ca 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
@@ -603,3 +603,8 @@ bool msm_dsi_is_master_dsi(struct msm_dsi *msm_dsi)
{
return IS_MASTER_DSI_LINK(msm_dsi->id);
}
+
+const char *msm_dsi_get_te_source(struct msm_dsi *msm_dsi)
+{
+ return msm_dsi->te_source;
+}
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
index 24a347fe2998..dd58bc0a49eb 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
@@ -545,6 +545,8 @@ static const struct of_device_id dsi_phy_dt_match[] = {
.data = &dsi_phy_28nm_lp_cfgs },
{ .compatible = "qcom,dsi-phy-28nm-8226",
.data = &dsi_phy_28nm_8226_cfgs },
+ { .compatible = "qcom,dsi-phy-28nm-8937",
+ .data = &dsi_phy_28nm_8937_cfgs },
#endif
#ifdef CONFIG_DRM_MSM_DSI_20NM_PHY
{ .compatible = "qcom,dsi-phy-20nm",
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
index 5a5dc3faa971..4953459edd63 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
@@ -12,11 +12,6 @@
#include "dsi.h"
-#define dsi_phy_read(offset) readl((offset))
-#define dsi_phy_write(offset, data) writel((data), (offset))
-#define dsi_phy_write_udelay(offset, data, delay_us) { writel((data), (offset)); udelay(delay_us); }
-#define dsi_phy_write_ndelay(offset, data, delay_ns) { writel((data), (offset)); ndelay(delay_ns); }
-
struct msm_dsi_phy_ops {
int (*pll_init)(struct msm_dsi_phy *phy);
int (*enable)(struct msm_dsi_phy *phy,
@@ -47,6 +42,7 @@ extern const struct msm_dsi_phy_cfg dsi_phy_28nm_hpm_cfgs;
extern const struct msm_dsi_phy_cfg dsi_phy_28nm_hpm_famb_cfgs;
extern const struct msm_dsi_phy_cfg dsi_phy_28nm_lp_cfgs;
extern const struct msm_dsi_phy_cfg dsi_phy_28nm_8226_cfgs;
+extern const struct msm_dsi_phy_cfg dsi_phy_28nm_8937_cfgs;
extern const struct msm_dsi_phy_cfg dsi_phy_28nm_8960_cfgs;
extern const struct msm_dsi_phy_cfg dsi_phy_20nm_cfgs;
extern const struct msm_dsi_phy_cfg dsi_phy_14nm_cfgs;
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c
index 27b592c776a3..677c62571811 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c
@@ -187,20 +187,20 @@ static void dsi_pll_ssc_commit(struct dsi_pll_10nm *pll, struct dsi_pll_config *
if (config->enable_ssc) {
pr_debug("SSC is enabled\n");
- dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_SSC_STEPSIZE_LOW_1,
- config->ssc_stepsize & 0xff);
- dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_SSC_STEPSIZE_HIGH_1,
- config->ssc_stepsize >> 8);
- dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_SSC_DIV_PER_LOW_1,
- config->ssc_div_per & 0xff);
- dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_SSC_DIV_PER_HIGH_1,
- config->ssc_div_per >> 8);
- dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_SSC_DIV_ADJPER_LOW_1,
- config->ssc_adj_per & 0xff);
- dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_SSC_DIV_ADJPER_HIGH_1,
- config->ssc_adj_per >> 8);
- dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_SSC_CONTROL,
- SSC_EN | (config->ssc_center ? SSC_CENTER : 0));
+ writel(config->ssc_stepsize & 0xff,
+ base + REG_DSI_10nm_PHY_PLL_SSC_STEPSIZE_LOW_1);
+ writel(config->ssc_stepsize >> 8,
+ base + REG_DSI_10nm_PHY_PLL_SSC_STEPSIZE_HIGH_1);
+ writel(config->ssc_div_per & 0xff,
+ base + REG_DSI_10nm_PHY_PLL_SSC_DIV_PER_LOW_1);
+ writel(config->ssc_div_per >> 8,
+ base + REG_DSI_10nm_PHY_PLL_SSC_DIV_PER_HIGH_1);
+ writel(config->ssc_adj_per & 0xff,
+ base + REG_DSI_10nm_PHY_PLL_SSC_DIV_ADJPER_LOW_1);
+ writel(config->ssc_adj_per >> 8,
+ base + REG_DSI_10nm_PHY_PLL_SSC_DIV_ADJPER_HIGH_1);
+ writel(SSC_EN | (config->ssc_center ? SSC_CENTER : 0),
+ base + REG_DSI_10nm_PHY_PLL_SSC_CONTROL);
}
}
@@ -208,49 +208,43 @@ static void dsi_pll_config_hzindep_reg(struct dsi_pll_10nm *pll)
{
void __iomem *base = pll->phy->pll_base;
- dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_ANALOG_CONTROLS_ONE, 0x80);
- dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_ANALOG_CONTROLS_TWO, 0x03);
- dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_ANALOG_CONTROLS_THREE, 0x00);
- dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_DSM_DIVIDER, 0x00);
- dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_FEEDBACK_DIVIDER, 0x4e);
- dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_CALIBRATION_SETTINGS, 0x40);
- dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_BAND_SEL_CAL_SETTINGS_THREE,
- 0xba);
- dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_FREQ_DETECT_SETTINGS_ONE,
- 0x0c);
- dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_OUTDIV, 0x00);
- dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_CORE_OVERRIDE, 0x00);
- dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_PLL_DIGITAL_TIMERS_TWO,
- 0x08);
- dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_PLL_PROP_GAIN_RATE_1, 0x08);
- dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_PLL_BAND_SET_RATE_1, 0xc0);
- dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_PLL_INT_GAIN_IFILT_BAND_1,
- 0xfa);
- dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_PLL_FL_INT_GAIN_PFILT_BAND_1,
- 0x4c);
- dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_PLL_LOCK_OVERRIDE, 0x80);
- dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_PFILT, 0x29);
- dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_IFILT, 0x3f);
+ writel(0x80, base + REG_DSI_10nm_PHY_PLL_ANALOG_CONTROLS_ONE);
+ writel(0x03, base + REG_DSI_10nm_PHY_PLL_ANALOG_CONTROLS_TWO);
+ writel(0x00, base + REG_DSI_10nm_PHY_PLL_ANALOG_CONTROLS_THREE);
+ writel(0x00, base + REG_DSI_10nm_PHY_PLL_DSM_DIVIDER);
+ writel(0x4e, base + REG_DSI_10nm_PHY_PLL_FEEDBACK_DIVIDER);
+ writel(0x40, base + REG_DSI_10nm_PHY_PLL_CALIBRATION_SETTINGS);
+ writel(0xba, base + REG_DSI_10nm_PHY_PLL_BAND_SEL_CAL_SETTINGS_THREE);
+ writel(0x0c, base + REG_DSI_10nm_PHY_PLL_FREQ_DETECT_SETTINGS_ONE);
+ writel(0x00, base + REG_DSI_10nm_PHY_PLL_OUTDIV);
+ writel(0x00, base + REG_DSI_10nm_PHY_PLL_CORE_OVERRIDE);
+ writel(0x08, base + REG_DSI_10nm_PHY_PLL_PLL_DIGITAL_TIMERS_TWO);
+ writel(0x08, base + REG_DSI_10nm_PHY_PLL_PLL_PROP_GAIN_RATE_1);
+ writel(0xc0, base + REG_DSI_10nm_PHY_PLL_PLL_BAND_SET_RATE_1);
+ writel(0xfa, base + REG_DSI_10nm_PHY_PLL_PLL_INT_GAIN_IFILT_BAND_1);
+ writel(0x4c, base + REG_DSI_10nm_PHY_PLL_PLL_FL_INT_GAIN_PFILT_BAND_1);
+ writel(0x80, base + REG_DSI_10nm_PHY_PLL_PLL_LOCK_OVERRIDE);
+ writel(0x29, base + REG_DSI_10nm_PHY_PLL_PFILT);
+ writel(0x3f, base + REG_DSI_10nm_PHY_PLL_IFILT);
}
static void dsi_pll_commit(struct dsi_pll_10nm *pll, struct dsi_pll_config *config)
{
void __iomem *base = pll->phy->pll_base;
- dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_CORE_INPUT_OVERRIDE, 0x12);
- dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_DECIMAL_DIV_START_1,
- config->decimal_div_start);
- dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_FRAC_DIV_START_LOW_1,
- config->frac_div_start & 0xff);
- dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_FRAC_DIV_START_MID_1,
- (config->frac_div_start & 0xff00) >> 8);
- dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_FRAC_DIV_START_HIGH_1,
- (config->frac_div_start & 0x30000) >> 16);
- dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_PLL_LOCKDET_RATE_1, 64);
- dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_PLL_LOCK_DELAY, 0x06);
- dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_CMODE, 0x10);
- dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_CLOCK_INVERTERS,
- config->pll_clock_inverters);
+ writel(0x12, base + REG_DSI_10nm_PHY_PLL_CORE_INPUT_OVERRIDE);
+ writel(config->decimal_div_start,
+ base + REG_DSI_10nm_PHY_PLL_DECIMAL_DIV_START_1);
+ writel(config->frac_div_start & 0xff,
+ base + REG_DSI_10nm_PHY_PLL_FRAC_DIV_START_LOW_1);
+ writel((config->frac_div_start & 0xff00) >> 8,
+ base + REG_DSI_10nm_PHY_PLL_FRAC_DIV_START_MID_1);
+ writel((config->frac_div_start & 0x30000) >> 16,
+ base + REG_DSI_10nm_PHY_PLL_FRAC_DIV_START_HIGH_1);
+ writel(64, base + REG_DSI_10nm_PHY_PLL_PLL_LOCKDET_RATE_1);
+ writel(0x06, base + REG_DSI_10nm_PHY_PLL_PLL_LOCK_DELAY);
+ writel(0x10, base + REG_DSI_10nm_PHY_PLL_CMODE);
+ writel(config->pll_clock_inverters, base + REG_DSI_10nm_PHY_PLL_CLOCK_INVERTERS);
}
static int dsi_pll_10nm_vco_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -305,21 +299,19 @@ static int dsi_pll_10nm_lock_status(struct dsi_pll_10nm *pll)
static void dsi_pll_disable_pll_bias(struct dsi_pll_10nm *pll)
{
- u32 data = dsi_phy_read(pll->phy->base + REG_DSI_10nm_PHY_CMN_CTRL_0);
+ u32 data = readl(pll->phy->base + REG_DSI_10nm_PHY_CMN_CTRL_0);
- dsi_phy_write(pll->phy->pll_base + REG_DSI_10nm_PHY_PLL_SYSTEM_MUXES, 0);
- dsi_phy_write(pll->phy->base + REG_DSI_10nm_PHY_CMN_CTRL_0,
- data & ~BIT(5));
+ writel(0, pll->phy->pll_base + REG_DSI_10nm_PHY_PLL_SYSTEM_MUXES);
+ writel(data & ~BIT(5), pll->phy->base + REG_DSI_10nm_PHY_CMN_CTRL_0);
ndelay(250);
}
static void dsi_pll_enable_pll_bias(struct dsi_pll_10nm *pll)
{
- u32 data = dsi_phy_read(pll->phy->base + REG_DSI_10nm_PHY_CMN_CTRL_0);
+ u32 data = readl(pll->phy->base + REG_DSI_10nm_PHY_CMN_CTRL_0);
- dsi_phy_write(pll->phy->base + REG_DSI_10nm_PHY_CMN_CTRL_0,
- data | BIT(5));
- dsi_phy_write(pll->phy->pll_base + REG_DSI_10nm_PHY_PLL_SYSTEM_MUXES, 0xc0);
+ writel(data | BIT(5), pll->phy->base + REG_DSI_10nm_PHY_CMN_CTRL_0);
+ writel(0xc0, pll->phy->pll_base + REG_DSI_10nm_PHY_PLL_SYSTEM_MUXES);
ndelay(250);
}
@@ -327,18 +319,16 @@ static void dsi_pll_disable_global_clk(struct dsi_pll_10nm *pll)
{
u32 data;
- data = dsi_phy_read(pll->phy->base + REG_DSI_10nm_PHY_CMN_CLK_CFG1);
- dsi_phy_write(pll->phy->base + REG_DSI_10nm_PHY_CMN_CLK_CFG1,
- data & ~BIT(5));
+ data = readl(pll->phy->base + REG_DSI_10nm_PHY_CMN_CLK_CFG1);
+ writel(data & ~BIT(5), pll->phy->base + REG_DSI_10nm_PHY_CMN_CLK_CFG1);
}
static void dsi_pll_enable_global_clk(struct dsi_pll_10nm *pll)
{
u32 data;
- data = dsi_phy_read(pll->phy->base + REG_DSI_10nm_PHY_CMN_CLK_CFG1);
- dsi_phy_write(pll->phy->base + REG_DSI_10nm_PHY_CMN_CLK_CFG1,
- data | BIT(5));
+ data = readl(pll->phy->base + REG_DSI_10nm_PHY_CMN_CLK_CFG1);
+ writel(data | BIT(5), pll->phy->base + REG_DSI_10nm_PHY_CMN_CLK_CFG1);
}
static int dsi_pll_10nm_vco_prepare(struct clk_hw *hw)
@@ -358,8 +348,7 @@ static int dsi_pll_10nm_vco_prepare(struct clk_hw *hw)
}
/* Start PLL */
- dsi_phy_write(pll_10nm->phy->base + REG_DSI_10nm_PHY_CMN_PLL_CNTRL,
- 0x01);
+ writel(0x01, pll_10nm->phy->base + REG_DSI_10nm_PHY_CMN_PLL_CNTRL);
/*
* ensure all PLL configurations are written prior to checking
@@ -380,11 +369,9 @@ static int dsi_pll_10nm_vco_prepare(struct clk_hw *hw)
if (pll_10nm->slave)
dsi_pll_enable_global_clk(pll_10nm->slave);
- dsi_phy_write(pll_10nm->phy->base + REG_DSI_10nm_PHY_CMN_RBUF_CTRL,
- 0x01);
+ writel(0x01, pll_10nm->phy->base + REG_DSI_10nm_PHY_CMN_RBUF_CTRL);
if (pll_10nm->slave)
- dsi_phy_write(pll_10nm->slave->phy->base +
- REG_DSI_10nm_PHY_CMN_RBUF_CTRL, 0x01);
+ writel(0x01, pll_10nm->slave->phy->base + REG_DSI_10nm_PHY_CMN_RBUF_CTRL);
error:
return rc;
@@ -392,7 +379,7 @@ error:
static void dsi_pll_disable_sub(struct dsi_pll_10nm *pll)
{
- dsi_phy_write(pll->phy->base + REG_DSI_10nm_PHY_CMN_RBUF_CTRL, 0);
+ writel(0, pll->phy->base + REG_DSI_10nm_PHY_CMN_RBUF_CTRL);
dsi_pll_disable_pll_bias(pll);
}
@@ -406,7 +393,7 @@ static void dsi_pll_10nm_vco_unprepare(struct clk_hw *hw)
* powering down the PLL
*/
dsi_pll_disable_global_clk(pll_10nm);
- dsi_phy_write(pll_10nm->phy->base + REG_DSI_10nm_PHY_CMN_PLL_CNTRL, 0);
+ writel(0, pll_10nm->phy->base + REG_DSI_10nm_PHY_CMN_PLL_CNTRL);
dsi_pll_disable_sub(pll_10nm);
if (pll_10nm->slave) {
dsi_pll_disable_global_clk(pll_10nm->slave);
@@ -429,13 +416,13 @@ static unsigned long dsi_pll_10nm_vco_recalc_rate(struct clk_hw *hw,
u32 dec;
u64 pll_freq, tmp64;
- dec = dsi_phy_read(base + REG_DSI_10nm_PHY_PLL_DECIMAL_DIV_START_1);
+ dec = readl(base + REG_DSI_10nm_PHY_PLL_DECIMAL_DIV_START_1);
dec &= 0xff;
- frac = dsi_phy_read(base + REG_DSI_10nm_PHY_PLL_FRAC_DIV_START_LOW_1);
- frac |= ((dsi_phy_read(base + REG_DSI_10nm_PHY_PLL_FRAC_DIV_START_MID_1) &
+ frac = readl(base + REG_DSI_10nm_PHY_PLL_FRAC_DIV_START_LOW_1);
+ frac |= ((readl(base + REG_DSI_10nm_PHY_PLL_FRAC_DIV_START_MID_1) &
0xff) << 8);
- frac |= ((dsi_phy_read(base + REG_DSI_10nm_PHY_PLL_FRAC_DIV_START_HIGH_1) &
+ frac |= ((readl(base + REG_DSI_10nm_PHY_PLL_FRAC_DIV_START_HIGH_1) &
0x3) << 16);
/*
@@ -488,15 +475,15 @@ static void dsi_10nm_pll_save_state(struct msm_dsi_phy *phy)
void __iomem *phy_base = pll_10nm->phy->base;
u32 cmn_clk_cfg0, cmn_clk_cfg1;
- cached->pll_out_div = dsi_phy_read(pll_10nm->phy->pll_base +
+ cached->pll_out_div = readl(pll_10nm->phy->pll_base +
REG_DSI_10nm_PHY_PLL_PLL_OUTDIV_RATE);
cached->pll_out_div &= 0x3;
- cmn_clk_cfg0 = dsi_phy_read(phy_base + REG_DSI_10nm_PHY_CMN_CLK_CFG0);
+ cmn_clk_cfg0 = readl(phy_base + REG_DSI_10nm_PHY_CMN_CLK_CFG0);
cached->bit_clk_div = cmn_clk_cfg0 & 0xf;
cached->pix_clk_div = (cmn_clk_cfg0 & 0xf0) >> 4;
- cmn_clk_cfg1 = dsi_phy_read(phy_base + REG_DSI_10nm_PHY_CMN_CLK_CFG1);
+ cmn_clk_cfg1 = readl(phy_base + REG_DSI_10nm_PHY_CMN_CLK_CFG1);
cached->pll_mux = cmn_clk_cfg1 & 0x3;
DBG("DSI PLL%d outdiv %x bit_clk_div %x pix_clk_div %x pll_mux %x",
@@ -512,18 +499,18 @@ static int dsi_10nm_pll_restore_state(struct msm_dsi_phy *phy)
u32 val;
int ret;
- val = dsi_phy_read(pll_10nm->phy->pll_base + REG_DSI_10nm_PHY_PLL_PLL_OUTDIV_RATE);
+ val = readl(pll_10nm->phy->pll_base + REG_DSI_10nm_PHY_PLL_PLL_OUTDIV_RATE);
val &= ~0x3;
val |= cached->pll_out_div;
- dsi_phy_write(pll_10nm->phy->pll_base + REG_DSI_10nm_PHY_PLL_PLL_OUTDIV_RATE, val);
+ writel(val, pll_10nm->phy->pll_base + REG_DSI_10nm_PHY_PLL_PLL_OUTDIV_RATE);
- dsi_phy_write(phy_base + REG_DSI_10nm_PHY_CMN_CLK_CFG0,
- cached->bit_clk_div | (cached->pix_clk_div << 4));
+ writel(cached->bit_clk_div | (cached->pix_clk_div << 4),
+ phy_base + REG_DSI_10nm_PHY_CMN_CLK_CFG0);
- val = dsi_phy_read(phy_base + REG_DSI_10nm_PHY_CMN_CLK_CFG1);
+ val = readl(phy_base + REG_DSI_10nm_PHY_CMN_CLK_CFG1);
val &= ~0x3;
val |= cached->pll_mux;
- dsi_phy_write(phy_base + REG_DSI_10nm_PHY_CMN_CLK_CFG1, val);
+ writel(val, phy_base + REG_DSI_10nm_PHY_CMN_CLK_CFG1);
ret = dsi_pll_10nm_vco_set_rate(phy->vco_hw,
pll_10nm->vco_current_rate,
@@ -561,7 +548,7 @@ static int dsi_10nm_set_usecase(struct msm_dsi_phy *phy)
}
/* set PLL src */
- dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_CLK_CFG1, (data << 2));
+ writel(data << 2, base + REG_DSI_10nm_PHY_CMN_CLK_CFG1);
return 0;
}
@@ -724,7 +711,7 @@ static int dsi_phy_hw_v3_0_is_pll_on(struct msm_dsi_phy *phy)
void __iomem *base = phy->base;
u32 data = 0;
- data = dsi_phy_read(base + REG_DSI_10nm_PHY_CMN_PLL_CNTRL);
+ data = readl(base + REG_DSI_10nm_PHY_CMN_PLL_CNTRL);
mb(); /* make sure read happened */
return (data & BIT(0));
@@ -740,11 +727,9 @@ static void dsi_phy_hw_v3_0_config_lpcdrx(struct msm_dsi_phy *phy, bool enable)
* corresponding to the logical data lane 0
*/
if (enable)
- dsi_phy_write(lane_base +
- REG_DSI_10nm_PHY_LN_LPRX_CTRL(phy_lane_0), 0x3);
+ writel(0x3, lane_base + REG_DSI_10nm_PHY_LN_LPRX_CTRL(phy_lane_0));
else
- dsi_phy_write(lane_base +
- REG_DSI_10nm_PHY_LN_LPRX_CTRL(phy_lane_0), 0);
+ writel(0, lane_base + REG_DSI_10nm_PHY_LN_LPRX_CTRL(phy_lane_0));
}
static void dsi_phy_hw_v3_0_lane_settings(struct msm_dsi_phy *phy)
@@ -759,43 +744,40 @@ static void dsi_phy_hw_v3_0_lane_settings(struct msm_dsi_phy *phy)
/* Strength ctrl settings */
for (i = 0; i < 5; i++) {
- dsi_phy_write(lane_base + REG_DSI_10nm_PHY_LN_LPTX_STR_CTRL(i),
- 0x55);
+ writel(0x55, lane_base + REG_DSI_10nm_PHY_LN_LPTX_STR_CTRL(i));
/*
* Disable LPRX and CDRX for all lanes. And later on, it will
* be only enabled for the physical data lane corresponding
* to the logical data lane 0
*/
- dsi_phy_write(lane_base + REG_DSI_10nm_PHY_LN_LPRX_CTRL(i), 0);
- dsi_phy_write(lane_base + REG_DSI_10nm_PHY_LN_PIN_SWAP(i), 0x0);
- dsi_phy_write(lane_base + REG_DSI_10nm_PHY_LN_HSTX_STR_CTRL(i),
- 0x88);
+ writel(0, lane_base + REG_DSI_10nm_PHY_LN_LPRX_CTRL(i));
+ writel(0x0, lane_base + REG_DSI_10nm_PHY_LN_PIN_SWAP(i));
+ writel(0x88, lane_base + REG_DSI_10nm_PHY_LN_HSTX_STR_CTRL(i));
}
dsi_phy_hw_v3_0_config_lpcdrx(phy, true);
/* other settings */
for (i = 0; i < 5; i++) {
- dsi_phy_write(lane_base + REG_DSI_10nm_PHY_LN_CFG0(i), 0x0);
- dsi_phy_write(lane_base + REG_DSI_10nm_PHY_LN_CFG1(i), 0x0);
- dsi_phy_write(lane_base + REG_DSI_10nm_PHY_LN_CFG2(i), 0x0);
- dsi_phy_write(lane_base + REG_DSI_10nm_PHY_LN_CFG3(i),
- i == 4 ? 0x80 : 0x0);
+ writel(0, lane_base + REG_DSI_10nm_PHY_LN_CFG0(i));
+ writel(0, lane_base + REG_DSI_10nm_PHY_LN_CFG1(i));
+ writel(0, lane_base + REG_DSI_10nm_PHY_LN_CFG2(i));
+ writel(i == 4 ? 0x80 : 0x0, lane_base + REG_DSI_10nm_PHY_LN_CFG3(i));
/* platform specific dsi phy drive strength adjustment */
- dsi_phy_write(lane_base + REG_DSI_10nm_PHY_LN_OFFSET_TOP_CTRL(i),
- tuning_cfg->rescode_offset_top[i]);
- dsi_phy_write(lane_base + REG_DSI_10nm_PHY_LN_OFFSET_BOT_CTRL(i),
- tuning_cfg->rescode_offset_bot[i]);
+ writel(tuning_cfg->rescode_offset_top[i],
+ lane_base + REG_DSI_10nm_PHY_LN_OFFSET_TOP_CTRL(i));
+ writel(tuning_cfg->rescode_offset_bot[i],
+ lane_base + REG_DSI_10nm_PHY_LN_OFFSET_BOT_CTRL(i));
- dsi_phy_write(lane_base + REG_DSI_10nm_PHY_LN_TX_DCTRL(i),
- tx_dctrl[i]);
+ writel(tx_dctrl[i],
+ lane_base + REG_DSI_10nm_PHY_LN_TX_DCTRL(i));
}
if (!(phy->cfg->quirks & DSI_PHY_10NM_QUIRK_OLD_TIMINGS)) {
/* Toggle BIT 0 to release freeze I/0 */
- dsi_phy_write(lane_base + REG_DSI_10nm_PHY_LN_TX_DCTRL(3), 0x05);
- dsi_phy_write(lane_base + REG_DSI_10nm_PHY_LN_TX_DCTRL(3), 0x04);
+ writel(0x05, lane_base + REG_DSI_10nm_PHY_LN_TX_DCTRL(3));
+ writel(0x04, lane_base + REG_DSI_10nm_PHY_LN_TX_DCTRL(3));
}
}
@@ -833,64 +815,51 @@ static int dsi_10nm_phy_enable(struct msm_dsi_phy *phy,
/* de-assert digital and pll power down */
data = BIT(6) | BIT(5);
- dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_CTRL_0, data);
+ writel(data, base + REG_DSI_10nm_PHY_CMN_CTRL_0);
/* Assert PLL core reset */
- dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_PLL_CNTRL, 0x00);
+ writel(0x00, base + REG_DSI_10nm_PHY_CMN_PLL_CNTRL);
/* turn off resync FIFO */
- dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_RBUF_CTRL, 0x00);
+ writel(0x00, base + REG_DSI_10nm_PHY_CMN_RBUF_CTRL);
/* Select MS1 byte-clk */
- dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_GLBL_CTRL, 0x10);
+ writel(0x10, base + REG_DSI_10nm_PHY_CMN_GLBL_CTRL);
/* Enable LDO with platform specific drive level/amplitude adjustment */
- dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_VREG_CTRL,
- tuning_cfg->vreg_ctrl);
+ writel(tuning_cfg->vreg_ctrl, base + REG_DSI_10nm_PHY_CMN_VREG_CTRL);
/* Configure PHY lane swap (TODO: we need to calculate this) */
- dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_LANE_CFG0, 0x21);
- dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_LANE_CFG1, 0x84);
+ writel(0x21, base + REG_DSI_10nm_PHY_CMN_LANE_CFG0);
+ writel(0x84, base + REG_DSI_10nm_PHY_CMN_LANE_CFG1);
/* DSI PHY timings */
- dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_TIMING_CTRL_0,
- timing->hs_halfbyte_en);
- dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_TIMING_CTRL_1,
- timing->clk_zero);
- dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_TIMING_CTRL_2,
- timing->clk_prepare);
- dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_TIMING_CTRL_3,
- timing->clk_trail);
- dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_TIMING_CTRL_4,
- timing->hs_exit);
- dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_TIMING_CTRL_5,
- timing->hs_zero);
- dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_TIMING_CTRL_6,
- timing->hs_prepare);
- dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_TIMING_CTRL_7,
- timing->hs_trail);
- dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_TIMING_CTRL_8,
- timing->hs_rqst);
- dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_TIMING_CTRL_9,
- timing->ta_go | (timing->ta_sure << 3));
- dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_TIMING_CTRL_10,
- timing->ta_get);
- dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_TIMING_CTRL_11,
- 0x00);
+ writel(timing->hs_halfbyte_en, base + REG_DSI_10nm_PHY_CMN_TIMING_CTRL_0);
+ writel(timing->clk_zero, base + REG_DSI_10nm_PHY_CMN_TIMING_CTRL_1);
+ writel(timing->clk_prepare, base + REG_DSI_10nm_PHY_CMN_TIMING_CTRL_2);
+ writel(timing->clk_trail, base + REG_DSI_10nm_PHY_CMN_TIMING_CTRL_3);
+ writel(timing->hs_exit, base + REG_DSI_10nm_PHY_CMN_TIMING_CTRL_4);
+ writel(timing->hs_zero, base + REG_DSI_10nm_PHY_CMN_TIMING_CTRL_5);
+ writel(timing->hs_prepare, base + REG_DSI_10nm_PHY_CMN_TIMING_CTRL_6);
+ writel(timing->hs_trail, base + REG_DSI_10nm_PHY_CMN_TIMING_CTRL_7);
+ writel(timing->hs_rqst, base + REG_DSI_10nm_PHY_CMN_TIMING_CTRL_8);
+ writel(timing->ta_go | (timing->ta_sure << 3), base + REG_DSI_10nm_PHY_CMN_TIMING_CTRL_9);
+ writel(timing->ta_get, base + REG_DSI_10nm_PHY_CMN_TIMING_CTRL_10);
+ writel(0x00, base + REG_DSI_10nm_PHY_CMN_TIMING_CTRL_11);
/* Remove power down from all blocks */
- dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_CTRL_0, 0x7f);
+ writel(0x7f, base + REG_DSI_10nm_PHY_CMN_CTRL_0);
/* power up lanes */
- data = dsi_phy_read(base + REG_DSI_10nm_PHY_CMN_CTRL_0);
+ data = readl(base + REG_DSI_10nm_PHY_CMN_CTRL_0);
/* TODO: only power up lanes that are used */
data |= 0x1F;
- dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_CTRL_0, data);
- dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_LANE_CTRL0, 0x1F);
+ writel(data, base + REG_DSI_10nm_PHY_CMN_CTRL_0);
+ writel(0x1F, base + REG_DSI_10nm_PHY_CMN_LANE_CTRL0);
/* Select full-rate mode */
- dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_CTRL_2, 0x40);
+ writel(0x40, base + REG_DSI_10nm_PHY_CMN_CTRL_2);
ret = dsi_10nm_set_usecase(phy);
if (ret) {
@@ -918,15 +887,15 @@ static void dsi_10nm_phy_disable(struct msm_dsi_phy *phy)
pr_warn("Turning OFF PHY while PLL is on\n");
dsi_phy_hw_v3_0_config_lpcdrx(phy, false);
- data = dsi_phy_read(base + REG_DSI_10nm_PHY_CMN_CTRL_0);
+ data = readl(base + REG_DSI_10nm_PHY_CMN_CTRL_0);
/* disable all lanes */
data &= ~0x1F;
- dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_CTRL_0, data);
- dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_LANE_CTRL0, 0);
+ writel(data, base + REG_DSI_10nm_PHY_CMN_CTRL_0);
+ writel(0, base + REG_DSI_10nm_PHY_CMN_LANE_CTRL0);
/* Turn off all PHY blocks */
- dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_CTRL_0, 0x00);
+ writel(0x00, base + REG_DSI_10nm_PHY_CMN_CTRL_0);
/* make sure phy is turned off */
wmb();
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c
index 31deda1c664a..1723f0e4faa4 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c
@@ -116,7 +116,7 @@ static bool pll_14nm_poll_for_ready(struct dsi_pll_14nm *pll_14nm,
tries = nb_tries;
while (tries--) {
- val = dsi_phy_read(base + REG_DSI_14nm_PHY_PLL_RESET_SM_READY_STATUS);
+ val = readl(base + REG_DSI_14nm_PHY_PLL_RESET_SM_READY_STATUS);
pll_locked = !!(val & BIT(5));
if (pll_locked)
@@ -130,7 +130,7 @@ static bool pll_14nm_poll_for_ready(struct dsi_pll_14nm *pll_14nm,
tries = nb_tries;
while (tries--) {
- val = dsi_phy_read(base + REG_DSI_14nm_PHY_PLL_RESET_SM_READY_STATUS);
+ val = readl(base + REG_DSI_14nm_PHY_PLL_RESET_SM_READY_STATUS);
pll_ready = !!(val & BIT(0));
if (pll_ready)
@@ -288,29 +288,29 @@ static void pll_db_commit_ssc(struct dsi_pll_14nm *pll, struct dsi_pll_config *p
data = pconf->ssc_adj_period;
data &= 0x0ff;
- dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_SSC_ADJ_PER1, data);
+ writel(data, base + REG_DSI_14nm_PHY_PLL_SSC_ADJ_PER1);
data = (pconf->ssc_adj_period >> 8);
data &= 0x03;
- dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_SSC_ADJ_PER2, data);
+ writel(data, base + REG_DSI_14nm_PHY_PLL_SSC_ADJ_PER2);
data = pconf->ssc_period;
data &= 0x0ff;
- dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_SSC_PER1, data);
+ writel(data, base + REG_DSI_14nm_PHY_PLL_SSC_PER1);
data = (pconf->ssc_period >> 8);
data &= 0x0ff;
- dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_SSC_PER2, data);
+ writel(data, base + REG_DSI_14nm_PHY_PLL_SSC_PER2);
data = pconf->ssc_step_size;
data &= 0x0ff;
- dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_SSC_STEP_SIZE1, data);
+ writel(data, base + REG_DSI_14nm_PHY_PLL_SSC_STEP_SIZE1);
data = (pconf->ssc_step_size >> 8);
data &= 0x0ff;
- dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_SSC_STEP_SIZE2, data);
+ writel(data, base + REG_DSI_14nm_PHY_PLL_SSC_STEP_SIZE2);
data = (pconf->ssc_center & 0x01);
data <<= 1;
data |= 0x01; /* enable */
- dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_SSC_EN_CENTER, data);
+ writel(data, base + REG_DSI_14nm_PHY_PLL_SSC_EN_CENTER);
wmb(); /* make sure register committed */
}
@@ -323,43 +323,45 @@ static void pll_db_commit_common(struct dsi_pll_14nm *pll,
/* confgiure the non frequency dependent pll registers */
data = 0;
- dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_SYSCLK_EN_RESET, data);
+ writel(data, base + REG_DSI_14nm_PHY_PLL_SYSCLK_EN_RESET);
- dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_TXCLK_EN, 1);
+ writel(1, base + REG_DSI_14nm_PHY_PLL_TXCLK_EN);
- dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_RESETSM_CNTRL, 48);
- dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_RESETSM_CNTRL2, 4 << 3); /* bandgap_timer */
- dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_RESETSM_CNTRL5, 5); /* pll_wakeup_timer */
+ writel(48, base + REG_DSI_14nm_PHY_PLL_RESETSM_CNTRL);
+ /* bandgap_timer */
+ writel(4 << 3, base + REG_DSI_14nm_PHY_PLL_RESETSM_CNTRL2);
+ /* pll_wakeup_timer */
+ writel(5, base + REG_DSI_14nm_PHY_PLL_RESETSM_CNTRL5);
data = pconf->pll_vco_div_ref & 0xff;
- dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_VCO_DIV_REF1, data);
+ writel(data, base + REG_DSI_14nm_PHY_PLL_VCO_DIV_REF1);
data = (pconf->pll_vco_div_ref >> 8) & 0x3;
- dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_VCO_DIV_REF2, data);
+ writel(data, base + REG_DSI_14nm_PHY_PLL_VCO_DIV_REF2);
data = pconf->pll_kvco_div_ref & 0xff;
- dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_KVCO_DIV_REF1, data);
+ writel(data, base + REG_DSI_14nm_PHY_PLL_KVCO_DIV_REF1);
data = (pconf->pll_kvco_div_ref >> 8) & 0x3;
- dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_KVCO_DIV_REF2, data);
+ writel(data, base + REG_DSI_14nm_PHY_PLL_KVCO_DIV_REF2);
- dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_PLL_MISC1, 16);
+ writel(16, base + REG_DSI_14nm_PHY_PLL_PLL_MISC1);
- dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_IE_TRIM, 4);
+ writel(4, base + REG_DSI_14nm_PHY_PLL_IE_TRIM);
- dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_IP_TRIM, 4);
+ writel(4, base + REG_DSI_14nm_PHY_PLL_IP_TRIM);
- dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_CP_SET_CUR, 1 << 3 | 1);
+ writel(1 << 3 | 1, base + REG_DSI_14nm_PHY_PLL_CP_SET_CUR);
- dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_PLL_ICPCSET, 0 << 3 | 0);
+ writel(0 << 3 | 0, base + REG_DSI_14nm_PHY_PLL_PLL_ICPCSET);
- dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_PLL_ICPMSET, 0 << 3 | 0);
+ writel(0 << 3 | 0, base + REG_DSI_14nm_PHY_PLL_PLL_ICPMSET);
- dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_PLL_ICP_SET, 4 << 3 | 4);
+ writel(4 << 3 | 4, base + REG_DSI_14nm_PHY_PLL_PLL_ICP_SET);
- dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_PLL_LPF1, 1 << 4 | 11);
+ writel(1 << 4 | 11, base + REG_DSI_14nm_PHY_PLL_PLL_LPF1);
- dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_IPTAT_TRIM, 7);
+ writel(7, base + REG_DSI_14nm_PHY_PLL_IPTAT_TRIM);
- dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_PLL_CRCTRL, 1 << 4 | 2);
+ writel(1 << 4 | 2, base + REG_DSI_14nm_PHY_PLL_PLL_CRCTRL);
}
static void pll_14nm_software_reset(struct dsi_pll_14nm *pll_14nm)
@@ -369,13 +371,14 @@ static void pll_14nm_software_reset(struct dsi_pll_14nm *pll_14nm)
/* de assert pll start and apply pll sw reset */
/* stop pll */
- dsi_phy_write(cmn_base + REG_DSI_14nm_PHY_CMN_PLL_CNTRL, 0);
+ writel(0, cmn_base + REG_DSI_14nm_PHY_CMN_PLL_CNTRL);
/* pll sw reset */
- dsi_phy_write_udelay(cmn_base + REG_DSI_14nm_PHY_CMN_CTRL_1, 0x20, 10);
+ writel(0x20, cmn_base + REG_DSI_14nm_PHY_CMN_CTRL_1);
+ udelay(10);
wmb(); /* make sure register committed */
- dsi_phy_write(cmn_base + REG_DSI_14nm_PHY_CMN_CTRL_1, 0);
+ writel(0, cmn_base + REG_DSI_14nm_PHY_CMN_CTRL_1);
wmb(); /* make sure register committed */
}
@@ -388,50 +391,50 @@ static void pll_db_commit_14nm(struct dsi_pll_14nm *pll,
DBG("DSI%d PLL", pll->phy->id);
- dsi_phy_write(cmn_base + REG_DSI_14nm_PHY_CMN_LDO_CNTRL, 0x3c);
+ writel(0x3c, cmn_base + REG_DSI_14nm_PHY_CMN_LDO_CNTRL);
pll_db_commit_common(pll, pconf);
pll_14nm_software_reset(pll);
/* Use the /2 path in Mux */
- dsi_phy_write(cmn_base + REG_DSI_14nm_PHY_CMN_CLK_CFG1, 1);
+ writel(1, cmn_base + REG_DSI_14nm_PHY_CMN_CLK_CFG1);
data = 0xff; /* data, clk, pll normal operation */
- dsi_phy_write(cmn_base + REG_DSI_14nm_PHY_CMN_CTRL_0, data);
+ writel(data, cmn_base + REG_DSI_14nm_PHY_CMN_CTRL_0);
/* configure the frequency dependent pll registers */
data = pconf->dec_start;
- dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_DEC_START, data);
+ writel(data, base + REG_DSI_14nm_PHY_PLL_DEC_START);
data = pconf->div_frac_start & 0xff;
- dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_DIV_FRAC_START1, data);
+ writel(data, base + REG_DSI_14nm_PHY_PLL_DIV_FRAC_START1);
data = (pconf->div_frac_start >> 8) & 0xff;
- dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_DIV_FRAC_START2, data);
+ writel(data, base + REG_DSI_14nm_PHY_PLL_DIV_FRAC_START2);
data = (pconf->div_frac_start >> 16) & 0xf;
- dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_DIV_FRAC_START3, data);
+ writel(data, base + REG_DSI_14nm_PHY_PLL_DIV_FRAC_START3);
data = pconf->plllock_cmp & 0xff;
- dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_PLLLOCK_CMP1, data);
+ writel(data, base + REG_DSI_14nm_PHY_PLL_PLLLOCK_CMP1);
data = (pconf->plllock_cmp >> 8) & 0xff;
- dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_PLLLOCK_CMP2, data);
+ writel(data, base + REG_DSI_14nm_PHY_PLL_PLLLOCK_CMP2);
data = (pconf->plllock_cmp >> 16) & 0x3;
- dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_PLLLOCK_CMP3, data);
+ writel(data, base + REG_DSI_14nm_PHY_PLL_PLLLOCK_CMP3);
data = pconf->plllock_cnt << 1 | 0 << 3; /* plllock_rng */
- dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_PLLLOCK_CMP_EN, data);
+ writel(data, base + REG_DSI_14nm_PHY_PLL_PLLLOCK_CMP_EN);
data = pconf->pll_vco_count & 0xff;
- dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_VCO_COUNT1, data);
+ writel(data, base + REG_DSI_14nm_PHY_PLL_VCO_COUNT1);
data = (pconf->pll_vco_count >> 8) & 0xff;
- dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_VCO_COUNT2, data);
+ writel(data, base + REG_DSI_14nm_PHY_PLL_VCO_COUNT2);
data = pconf->pll_kvco_count & 0xff;
- dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_KVCO_COUNT1, data);
+ writel(data, base + REG_DSI_14nm_PHY_PLL_KVCO_COUNT1);
data = (pconf->pll_kvco_count >> 8) & 0x3;
- dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_KVCO_COUNT2, data);
+ writel(data, base + REG_DSI_14nm_PHY_PLL_KVCO_COUNT2);
/*
* High nibble configures the post divider internal to the VCO. It's
@@ -442,7 +445,7 @@ static void pll_db_commit_14nm(struct dsi_pll_14nm *pll,
* 2: divided by 4
* 3: divided by 8
*/
- dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_PLL_LPF2_POSTDIV, 0 << 4 | 3);
+ writel(0 << 4 | 3, base + REG_DSI_14nm_PHY_PLL_PLL_LPF2_POSTDIV);
if (pconf->ssc_en)
pll_db_commit_ssc(pll, pconf);
@@ -497,16 +500,16 @@ static unsigned long dsi_pll_14nm_vco_recalc_rate(struct clk_hw *hw,
u32 dec_start;
u64 ref_clk = parent_rate;
- dec_start = dsi_phy_read(base + REG_DSI_14nm_PHY_PLL_DEC_START);
+ dec_start = readl(base + REG_DSI_14nm_PHY_PLL_DEC_START);
dec_start &= 0x0ff;
DBG("dec_start = %x", dec_start);
- div_frac_start = (dsi_phy_read(base + REG_DSI_14nm_PHY_PLL_DIV_FRAC_START3)
+ div_frac_start = (readl(base + REG_DSI_14nm_PHY_PLL_DIV_FRAC_START3)
& 0xf) << 16;
- div_frac_start |= (dsi_phy_read(base + REG_DSI_14nm_PHY_PLL_DIV_FRAC_START2)
+ div_frac_start |= (readl(base + REG_DSI_14nm_PHY_PLL_DIV_FRAC_START2)
& 0xff) << 8;
- div_frac_start |= dsi_phy_read(base + REG_DSI_14nm_PHY_PLL_DIV_FRAC_START1)
+ div_frac_start |= readl(base + REG_DSI_14nm_PHY_PLL_DIV_FRAC_START1)
& 0xff;
DBG("div_frac_start = %x", div_frac_start);
@@ -542,8 +545,8 @@ static int dsi_pll_14nm_vco_prepare(struct clk_hw *hw)
if (dsi_pll_14nm_vco_recalc_rate(hw, VCO_REF_CLK_RATE) == 0)
dsi_pll_14nm_vco_set_rate(hw, pll_14nm->phy->cfg->min_pll_rate, VCO_REF_CLK_RATE);
- dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_VREF_CFG1, 0x10);
- dsi_phy_write(cmn_base + REG_DSI_14nm_PHY_CMN_PLL_CNTRL, 1);
+ writel(0x10, base + REG_DSI_14nm_PHY_PLL_VREF_CFG1);
+ writel(1, cmn_base + REG_DSI_14nm_PHY_CMN_PLL_CNTRL);
locked = pll_14nm_poll_for_ready(pll_14nm, POLL_MAX_READS,
POLL_TIMEOUT_US);
@@ -569,7 +572,7 @@ static void dsi_pll_14nm_vco_unprepare(struct clk_hw *hw)
if (unlikely(!pll_14nm->phy->pll_on))
return;
- dsi_phy_write(cmn_base + REG_DSI_14nm_PHY_CMN_PLL_CNTRL, 0);
+ writel(0, cmn_base + REG_DSI_14nm_PHY_CMN_PLL_CNTRL);
pll_14nm->phy->pll_on = false;
}
@@ -611,7 +614,7 @@ static unsigned long dsi_pll_14nm_postdiv_recalc_rate(struct clk_hw *hw,
DBG("DSI%d PLL parent rate=%lu", pll_14nm->phy->id, parent_rate);
- val = dsi_phy_read(base + REG_DSI_14nm_PHY_CMN_CLK_CFG0) >> shift;
+ val = readl(base + REG_DSI_14nm_PHY_CMN_CLK_CFG0) >> shift;
val &= div_mask(width);
return divider_recalc_rate(hw, parent_rate, val, NULL,
@@ -653,11 +656,11 @@ static int dsi_pll_14nm_postdiv_set_rate(struct clk_hw *hw, unsigned long rate,
spin_lock_irqsave(lock, flags);
- val = dsi_phy_read(base + REG_DSI_14nm_PHY_CMN_CLK_CFG0);
+ val = readl(base + REG_DSI_14nm_PHY_CMN_CLK_CFG0);
val &= ~(div_mask(width) << shift);
val |= value << shift;
- dsi_phy_write(base + REG_DSI_14nm_PHY_CMN_CLK_CFG0, val);
+ writel(val, base + REG_DSI_14nm_PHY_CMN_CLK_CFG0);
/* If we're master in bonded DSI mode, then the slave PLL's post-dividers
* follow the master's post dividers
@@ -666,7 +669,7 @@ static int dsi_pll_14nm_postdiv_set_rate(struct clk_hw *hw, unsigned long rate,
struct dsi_pll_14nm *pll_14nm_slave = pll_14nm->slave;
void __iomem *slave_base = pll_14nm_slave->phy->base;
- dsi_phy_write(slave_base + REG_DSI_14nm_PHY_CMN_CLK_CFG0, val);
+ writel(val, slave_base + REG_DSI_14nm_PHY_CMN_CLK_CFG0);
}
spin_unlock_irqrestore(lock, flags);
@@ -691,7 +694,7 @@ static void dsi_14nm_pll_save_state(struct msm_dsi_phy *phy)
void __iomem *cmn_base = pll_14nm->phy->base;
u32 data;
- data = dsi_phy_read(cmn_base + REG_DSI_14nm_PHY_CMN_CLK_CFG0);
+ data = readl(cmn_base + REG_DSI_14nm_PHY_CMN_CLK_CFG0);
cached_state->n1postdiv = data & 0xf;
cached_state->n2postdiv = (data >> 4) & 0xf;
@@ -723,14 +726,14 @@ static int dsi_14nm_pll_restore_state(struct msm_dsi_phy *phy)
DBG("DSI%d PLL restore state %x %x", pll_14nm->phy->id,
cached_state->n1postdiv, cached_state->n2postdiv);
- dsi_phy_write(cmn_base + REG_DSI_14nm_PHY_CMN_CLK_CFG0, data);
+ writel(data, cmn_base + REG_DSI_14nm_PHY_CMN_CLK_CFG0);
/* also restore post-dividers for slave DSI PLL */
if (phy->usecase == MSM_DSI_PHY_MASTER) {
struct dsi_pll_14nm *pll_14nm_slave = pll_14nm->slave;
void __iomem *slave_base = pll_14nm_slave->phy->base;
- dsi_phy_write(slave_base + REG_DSI_14nm_PHY_CMN_CLK_CFG0, data);
+ writel(data, slave_base + REG_DSI_14nm_PHY_CMN_CLK_CFG0);
}
return 0;
@@ -758,9 +761,9 @@ static int dsi_14nm_set_usecase(struct msm_dsi_phy *phy)
return -EINVAL;
}
- dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_CLKBUFLR_EN, clkbuflr_en);
+ writel(clkbuflr_en, base + REG_DSI_14nm_PHY_PLL_CLKBUFLR_EN);
if (bandgap)
- dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_PLL_BANDGAP, bandgap);
+ writel(bandgap, base + REG_DSI_14nm_PHY_PLL_PLL_BANDGAP);
return 0;
}
@@ -917,27 +920,27 @@ static void dsi_14nm_dphy_set_timing(struct msm_dsi_phy *phy,
u32 halfbyte_en = clk_ln ? timing->hs_halfbyte_en_ckln :
timing->hs_halfbyte_en;
- dsi_phy_write(base + REG_DSI_14nm_PHY_LN_TIMING_CTRL_4(lane_idx),
- DSI_14nm_PHY_LN_TIMING_CTRL_4_HS_EXIT(timing->hs_exit));
- dsi_phy_write(base + REG_DSI_14nm_PHY_LN_TIMING_CTRL_5(lane_idx),
- DSI_14nm_PHY_LN_TIMING_CTRL_5_HS_ZERO(zero));
- dsi_phy_write(base + REG_DSI_14nm_PHY_LN_TIMING_CTRL_6(lane_idx),
- DSI_14nm_PHY_LN_TIMING_CTRL_6_HS_PREPARE(prepare));
- dsi_phy_write(base + REG_DSI_14nm_PHY_LN_TIMING_CTRL_7(lane_idx),
- DSI_14nm_PHY_LN_TIMING_CTRL_7_HS_TRAIL(trail));
- dsi_phy_write(base + REG_DSI_14nm_PHY_LN_TIMING_CTRL_8(lane_idx),
- DSI_14nm_PHY_LN_TIMING_CTRL_8_HS_RQST(rqst));
- dsi_phy_write(base + REG_DSI_14nm_PHY_LN_CFG0(lane_idx),
- DSI_14nm_PHY_LN_CFG0_PREPARE_DLY(prep_dly));
- dsi_phy_write(base + REG_DSI_14nm_PHY_LN_CFG1(lane_idx),
- halfbyte_en ? DSI_14nm_PHY_LN_CFG1_HALFBYTECLK_EN : 0);
- dsi_phy_write(base + REG_DSI_14nm_PHY_LN_TIMING_CTRL_9(lane_idx),
- DSI_14nm_PHY_LN_TIMING_CTRL_9_TA_GO(timing->ta_go) |
- DSI_14nm_PHY_LN_TIMING_CTRL_9_TA_SURE(timing->ta_sure));
- dsi_phy_write(base + REG_DSI_14nm_PHY_LN_TIMING_CTRL_10(lane_idx),
- DSI_14nm_PHY_LN_TIMING_CTRL_10_TA_GET(timing->ta_get));
- dsi_phy_write(base + REG_DSI_14nm_PHY_LN_TIMING_CTRL_11(lane_idx),
- DSI_14nm_PHY_LN_TIMING_CTRL_11_TRIG3_CMD(0xa0));
+ writel(DSI_14nm_PHY_LN_TIMING_CTRL_4_HS_EXIT(timing->hs_exit),
+ base + REG_DSI_14nm_PHY_LN_TIMING_CTRL_4(lane_idx));
+ writel(DSI_14nm_PHY_LN_TIMING_CTRL_5_HS_ZERO(zero),
+ base + REG_DSI_14nm_PHY_LN_TIMING_CTRL_5(lane_idx));
+ writel(DSI_14nm_PHY_LN_TIMING_CTRL_6_HS_PREPARE(prepare),
+ base + REG_DSI_14nm_PHY_LN_TIMING_CTRL_6(lane_idx));
+ writel(DSI_14nm_PHY_LN_TIMING_CTRL_7_HS_TRAIL(trail),
+ base + REG_DSI_14nm_PHY_LN_TIMING_CTRL_7(lane_idx));
+ writel(DSI_14nm_PHY_LN_TIMING_CTRL_8_HS_RQST(rqst),
+ base + REG_DSI_14nm_PHY_LN_TIMING_CTRL_8(lane_idx));
+ writel(DSI_14nm_PHY_LN_CFG0_PREPARE_DLY(prep_dly),
+ base + REG_DSI_14nm_PHY_LN_CFG0(lane_idx));
+ writel(halfbyte_en ? DSI_14nm_PHY_LN_CFG1_HALFBYTECLK_EN : 0,
+ base + REG_DSI_14nm_PHY_LN_CFG1(lane_idx));
+ writel(DSI_14nm_PHY_LN_TIMING_CTRL_9_TA_GO(timing->ta_go) |
+ DSI_14nm_PHY_LN_TIMING_CTRL_9_TA_SURE(timing->ta_sure),
+ base + REG_DSI_14nm_PHY_LN_TIMING_CTRL_9(lane_idx));
+ writel(DSI_14nm_PHY_LN_TIMING_CTRL_10_TA_GET(timing->ta_get),
+ base + REG_DSI_14nm_PHY_LN_TIMING_CTRL_10(lane_idx));
+ writel(DSI_14nm_PHY_LN_TIMING_CTRL_11_TRIG3_CMD(0xa0),
+ base + REG_DSI_14nm_PHY_LN_TIMING_CTRL_11(lane_idx));
}
static int dsi_14nm_phy_enable(struct msm_dsi_phy *phy,
@@ -961,49 +964,44 @@ static int dsi_14nm_phy_enable(struct msm_dsi_phy *phy,
data = 0x1c;
if (phy->usecase != MSM_DSI_PHY_STANDALONE)
data |= DSI_14nm_PHY_CMN_LDO_CNTRL_VREG_CTRL(32);
- dsi_phy_write(base + REG_DSI_14nm_PHY_CMN_LDO_CNTRL, data);
+ writel(data, base + REG_DSI_14nm_PHY_CMN_LDO_CNTRL);
- dsi_phy_write(base + REG_DSI_14nm_PHY_CMN_GLBL_TEST_CTRL, 0x1);
+ writel(0x1, base + REG_DSI_14nm_PHY_CMN_GLBL_TEST_CTRL);
/* 4 data lanes + 1 clk lane configuration */
for (i = 0; i < 5; i++) {
- dsi_phy_write(lane_base + REG_DSI_14nm_PHY_LN_VREG_CNTRL(i),
- 0x1d);
-
- dsi_phy_write(lane_base +
- REG_DSI_14nm_PHY_LN_STRENGTH_CTRL_0(i), 0xff);
- dsi_phy_write(lane_base +
- REG_DSI_14nm_PHY_LN_STRENGTH_CTRL_1(i),
- (i == PHY_14NM_CKLN_IDX) ? 0x00 : 0x06);
-
- dsi_phy_write(lane_base + REG_DSI_14nm_PHY_LN_CFG3(i),
- (i == PHY_14NM_CKLN_IDX) ? 0x8f : 0x0f);
- dsi_phy_write(lane_base + REG_DSI_14nm_PHY_LN_CFG2(i), 0x10);
- dsi_phy_write(lane_base + REG_DSI_14nm_PHY_LN_TEST_DATAPATH(i),
- 0);
- dsi_phy_write(lane_base + REG_DSI_14nm_PHY_LN_TEST_STR(i),
- 0x88);
+ writel(0x1d, lane_base + REG_DSI_14nm_PHY_LN_VREG_CNTRL(i));
+
+ writel(0xff, lane_base + REG_DSI_14nm_PHY_LN_STRENGTH_CTRL_0(i));
+ writel(i == PHY_14NM_CKLN_IDX ? 0x00 : 0x06,
+ lane_base + REG_DSI_14nm_PHY_LN_STRENGTH_CTRL_1(i));
+
+ writel(i == PHY_14NM_CKLN_IDX ? 0x8f : 0x0f,
+ lane_base + REG_DSI_14nm_PHY_LN_CFG3(i));
+ writel(0x10, lane_base + REG_DSI_14nm_PHY_LN_CFG2(i));
+ writel(0, lane_base + REG_DSI_14nm_PHY_LN_TEST_DATAPATH(i));
+ writel(0x88, lane_base + REG_DSI_14nm_PHY_LN_TEST_STR(i));
dsi_14nm_dphy_set_timing(phy, timing, i);
}
/* Make sure PLL is not start */
- dsi_phy_write(base + REG_DSI_14nm_PHY_CMN_PLL_CNTRL, 0x00);
+ writel(0x00, base + REG_DSI_14nm_PHY_CMN_PLL_CNTRL);
wmb(); /* make sure everything is written before reset and enable */
/* reset digital block */
- dsi_phy_write(base + REG_DSI_14nm_PHY_CMN_CTRL_1, 0x80);
+ writel(0x80, base + REG_DSI_14nm_PHY_CMN_CTRL_1);
wmb(); /* ensure reset is asserted */
udelay(100);
- dsi_phy_write(base + REG_DSI_14nm_PHY_CMN_CTRL_1, 0x00);
+ writel(0x00, base + REG_DSI_14nm_PHY_CMN_CTRL_1);
- glbl_test_ctrl = dsi_phy_read(base + REG_DSI_14nm_PHY_CMN_GLBL_TEST_CTRL);
+ glbl_test_ctrl = readl(base + REG_DSI_14nm_PHY_CMN_GLBL_TEST_CTRL);
if (phy->id == DSI_1 && phy->usecase == MSM_DSI_PHY_SLAVE)
glbl_test_ctrl |= DSI_14nm_PHY_CMN_GLBL_TEST_CTRL_BITCLK_HS_SEL;
else
glbl_test_ctrl &= ~DSI_14nm_PHY_CMN_GLBL_TEST_CTRL_BITCLK_HS_SEL;
- dsi_phy_write(base + REG_DSI_14nm_PHY_CMN_GLBL_TEST_CTRL, glbl_test_ctrl);
+ writel(glbl_test_ctrl, base + REG_DSI_14nm_PHY_CMN_GLBL_TEST_CTRL);
ret = dsi_14nm_set_usecase(phy);
if (ret) {
DRM_DEV_ERROR(&phy->pdev->dev, "%s: set pll usecase failed, %d\n",
@@ -1012,15 +1010,15 @@ static int dsi_14nm_phy_enable(struct msm_dsi_phy *phy,
}
/* Remove power down from PLL and all lanes */
- dsi_phy_write(base + REG_DSI_14nm_PHY_CMN_CTRL_0, 0xff);
+ writel(0xff, base + REG_DSI_14nm_PHY_CMN_CTRL_0);
return 0;
}
static void dsi_14nm_phy_disable(struct msm_dsi_phy *phy)
{
- dsi_phy_write(phy->base + REG_DSI_14nm_PHY_CMN_GLBL_TEST_CTRL, 0);
- dsi_phy_write(phy->base + REG_DSI_14nm_PHY_CMN_CTRL_0, 0);
+ writel(0, phy->base + REG_DSI_14nm_PHY_CMN_GLBL_TEST_CTRL);
+ writel(0, phy->base + REG_DSI_14nm_PHY_CMN_CTRL_0);
/* ensure that the phy is completely disabled */
wmb();
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c
index c9752b991744..cee34b76c3d2 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c
@@ -12,32 +12,32 @@ static void dsi_20nm_dphy_set_timing(struct msm_dsi_phy *phy,
{
void __iomem *base = phy->base;
- dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_0,
- DSI_20nm_PHY_TIMING_CTRL_0_CLK_ZERO(timing->clk_zero));
- dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_1,
- DSI_20nm_PHY_TIMING_CTRL_1_CLK_TRAIL(timing->clk_trail));
- dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_2,
- DSI_20nm_PHY_TIMING_CTRL_2_CLK_PREPARE(timing->clk_prepare));
+ writel(DSI_20nm_PHY_TIMING_CTRL_0_CLK_ZERO(timing->clk_zero),
+ base + REG_DSI_20nm_PHY_TIMING_CTRL_0);
+ writel(DSI_20nm_PHY_TIMING_CTRL_1_CLK_TRAIL(timing->clk_trail),
+ base + REG_DSI_20nm_PHY_TIMING_CTRL_1);
+ writel(DSI_20nm_PHY_TIMING_CTRL_2_CLK_PREPARE(timing->clk_prepare),
+ base + REG_DSI_20nm_PHY_TIMING_CTRL_2);
if (timing->clk_zero & BIT(8))
- dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_3,
- DSI_20nm_PHY_TIMING_CTRL_3_CLK_ZERO_8);
- dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_4,
- DSI_20nm_PHY_TIMING_CTRL_4_HS_EXIT(timing->hs_exit));
- dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_5,
- DSI_20nm_PHY_TIMING_CTRL_5_HS_ZERO(timing->hs_zero));
- dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_6,
- DSI_20nm_PHY_TIMING_CTRL_6_HS_PREPARE(timing->hs_prepare));
- dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_7,
- DSI_20nm_PHY_TIMING_CTRL_7_HS_TRAIL(timing->hs_trail));
- dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_8,
- DSI_20nm_PHY_TIMING_CTRL_8_HS_RQST(timing->hs_rqst));
- dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_9,
- DSI_20nm_PHY_TIMING_CTRL_9_TA_GO(timing->ta_go) |
- DSI_20nm_PHY_TIMING_CTRL_9_TA_SURE(timing->ta_sure));
- dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_10,
- DSI_20nm_PHY_TIMING_CTRL_10_TA_GET(timing->ta_get));
- dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_11,
- DSI_20nm_PHY_TIMING_CTRL_11_TRIG3_CMD(0));
+ writel(DSI_20nm_PHY_TIMING_CTRL_3_CLK_ZERO_8,
+ base + REG_DSI_20nm_PHY_TIMING_CTRL_3);
+ writel(DSI_20nm_PHY_TIMING_CTRL_4_HS_EXIT(timing->hs_exit),
+ base + REG_DSI_20nm_PHY_TIMING_CTRL_4);
+ writel(DSI_20nm_PHY_TIMING_CTRL_5_HS_ZERO(timing->hs_zero),
+ base + REG_DSI_20nm_PHY_TIMING_CTRL_5);
+ writel(DSI_20nm_PHY_TIMING_CTRL_6_HS_PREPARE(timing->hs_prepare),
+ base + REG_DSI_20nm_PHY_TIMING_CTRL_6);
+ writel(DSI_20nm_PHY_TIMING_CTRL_7_HS_TRAIL(timing->hs_trail),
+ base + REG_DSI_20nm_PHY_TIMING_CTRL_7);
+ writel(DSI_20nm_PHY_TIMING_CTRL_8_HS_RQST(timing->hs_rqst),
+ base + REG_DSI_20nm_PHY_TIMING_CTRL_8);
+ writel(DSI_20nm_PHY_TIMING_CTRL_9_TA_GO(timing->ta_go) |
+ DSI_20nm_PHY_TIMING_CTRL_9_TA_SURE(timing->ta_sure),
+ base + REG_DSI_20nm_PHY_TIMING_CTRL_9);
+ writel(DSI_20nm_PHY_TIMING_CTRL_10_TA_GET(timing->ta_get),
+ base + REG_DSI_20nm_PHY_TIMING_CTRL_10);
+ writel(DSI_20nm_PHY_TIMING_CTRL_11_TRIG3_CMD(0),
+ base + REG_DSI_20nm_PHY_TIMING_CTRL_11);
}
static void dsi_20nm_phy_regulator_ctrl(struct msm_dsi_phy *phy, bool enable)
@@ -45,23 +45,23 @@ static void dsi_20nm_phy_regulator_ctrl(struct msm_dsi_phy *phy, bool enable)
void __iomem *base = phy->reg_base;
if (!enable) {
- dsi_phy_write(base + REG_DSI_20nm_PHY_REGULATOR_CAL_PWR_CFG, 0);
+ writel(0, base + REG_DSI_20nm_PHY_REGULATOR_CAL_PWR_CFG);
return;
}
if (phy->regulator_ldo_mode) {
- dsi_phy_write(phy->base + REG_DSI_20nm_PHY_LDO_CNTRL, 0x1d);
+ writel(0x1d, phy->base + REG_DSI_20nm_PHY_LDO_CNTRL);
return;
}
/* non LDO mode */
- dsi_phy_write(base + REG_DSI_20nm_PHY_REGULATOR_CTRL_1, 0x03);
- dsi_phy_write(base + REG_DSI_20nm_PHY_REGULATOR_CTRL_2, 0x03);
- dsi_phy_write(base + REG_DSI_20nm_PHY_REGULATOR_CTRL_3, 0x00);
- dsi_phy_write(base + REG_DSI_20nm_PHY_REGULATOR_CTRL_4, 0x20);
- dsi_phy_write(base + REG_DSI_20nm_PHY_REGULATOR_CAL_PWR_CFG, 0x01);
- dsi_phy_write(phy->base + REG_DSI_20nm_PHY_LDO_CNTRL, 0x00);
- dsi_phy_write(base + REG_DSI_20nm_PHY_REGULATOR_CTRL_0, 0x03);
+ writel(0x03, base + REG_DSI_20nm_PHY_REGULATOR_CTRL_1);
+ writel(0x03, base + REG_DSI_20nm_PHY_REGULATOR_CTRL_2);
+ writel(0x00, base + REG_DSI_20nm_PHY_REGULATOR_CTRL_3);
+ writel(0x20, base + REG_DSI_20nm_PHY_REGULATOR_CTRL_4);
+ writel(0x01, base + REG_DSI_20nm_PHY_REGULATOR_CAL_PWR_CFG);
+ writel(0x00, phy->base + REG_DSI_20nm_PHY_LDO_CNTRL);
+ writel(0x03, base + REG_DSI_20nm_PHY_REGULATOR_CTRL_0);
}
static int dsi_20nm_phy_enable(struct msm_dsi_phy *phy,
@@ -83,49 +83,48 @@ static int dsi_20nm_phy_enable(struct msm_dsi_phy *phy,
dsi_20nm_phy_regulator_ctrl(phy, true);
- dsi_phy_write(base + REG_DSI_20nm_PHY_STRENGTH_0, 0xff);
+ writel(0xff, base + REG_DSI_20nm_PHY_STRENGTH_0);
- val = dsi_phy_read(base + REG_DSI_20nm_PHY_GLBL_TEST_CTRL);
+ val = readl(base + REG_DSI_20nm_PHY_GLBL_TEST_CTRL);
if (phy->id == DSI_1 && phy->usecase == MSM_DSI_PHY_STANDALONE)
val |= DSI_20nm_PHY_GLBL_TEST_CTRL_BITCLK_HS_SEL;
else
val &= ~DSI_20nm_PHY_GLBL_TEST_CTRL_BITCLK_HS_SEL;
- dsi_phy_write(base + REG_DSI_20nm_PHY_GLBL_TEST_CTRL, val);
+ writel(val, base + REG_DSI_20nm_PHY_GLBL_TEST_CTRL);
for (i = 0; i < 4; i++) {
- dsi_phy_write(base + REG_DSI_20nm_PHY_LN_CFG_3(i),
- (i >> 1) * 0x40);
- dsi_phy_write(base + REG_DSI_20nm_PHY_LN_TEST_STR_0(i), 0x01);
- dsi_phy_write(base + REG_DSI_20nm_PHY_LN_TEST_STR_1(i), 0x46);
- dsi_phy_write(base + REG_DSI_20nm_PHY_LN_CFG_0(i), 0x02);
- dsi_phy_write(base + REG_DSI_20nm_PHY_LN_CFG_1(i), 0xa0);
- dsi_phy_write(base + REG_DSI_20nm_PHY_LN_CFG_4(i), cfg_4[i]);
+ writel((i >> 1) * 0x40, base + REG_DSI_20nm_PHY_LN_CFG_3(i));
+ writel(0x01, base + REG_DSI_20nm_PHY_LN_TEST_STR_0(i));
+ writel(0x46, base + REG_DSI_20nm_PHY_LN_TEST_STR_1(i));
+ writel(0x02, base + REG_DSI_20nm_PHY_LN_CFG_0(i));
+ writel(0xa0, base + REG_DSI_20nm_PHY_LN_CFG_1(i));
+ writel(cfg_4[i], base + REG_DSI_20nm_PHY_LN_CFG_4(i));
}
- dsi_phy_write(base + REG_DSI_20nm_PHY_LNCK_CFG_3, 0x80);
- dsi_phy_write(base + REG_DSI_20nm_PHY_LNCK_TEST_STR0, 0x01);
- dsi_phy_write(base + REG_DSI_20nm_PHY_LNCK_TEST_STR1, 0x46);
- dsi_phy_write(base + REG_DSI_20nm_PHY_LNCK_CFG_0, 0x00);
- dsi_phy_write(base + REG_DSI_20nm_PHY_LNCK_CFG_1, 0xa0);
- dsi_phy_write(base + REG_DSI_20nm_PHY_LNCK_CFG_2, 0x00);
- dsi_phy_write(base + REG_DSI_20nm_PHY_LNCK_CFG_4, 0x00);
+ writel(0x80, base + REG_DSI_20nm_PHY_LNCK_CFG_3);
+ writel(0x01, base + REG_DSI_20nm_PHY_LNCK_TEST_STR0);
+ writel(0x46, base + REG_DSI_20nm_PHY_LNCK_TEST_STR1);
+ writel(0x00, base + REG_DSI_20nm_PHY_LNCK_CFG_0);
+ writel(0xa0, base + REG_DSI_20nm_PHY_LNCK_CFG_1);
+ writel(0x00, base + REG_DSI_20nm_PHY_LNCK_CFG_2);
+ writel(0x00, base + REG_DSI_20nm_PHY_LNCK_CFG_4);
dsi_20nm_dphy_set_timing(phy, timing);
- dsi_phy_write(base + REG_DSI_20nm_PHY_CTRL_1, 0x00);
+ writel(0x00, base + REG_DSI_20nm_PHY_CTRL_1);
- dsi_phy_write(base + REG_DSI_20nm_PHY_STRENGTH_1, 0x06);
+ writel(0x06, base + REG_DSI_20nm_PHY_STRENGTH_1);
/* make sure everything is written before enable */
wmb();
- dsi_phy_write(base + REG_DSI_20nm_PHY_CTRL_0, 0x7f);
+ writel(0x7f, base + REG_DSI_20nm_PHY_CTRL_0);
return 0;
}
static void dsi_20nm_phy_disable(struct msm_dsi_phy *phy)
{
- dsi_phy_write(phy->base + REG_DSI_20nm_PHY_CTRL_0, 0);
+ writel(0, phy->base + REG_DSI_20nm_PHY_CTRL_0);
dsi_20nm_phy_regulator_ctrl(phy, false);
}
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c
index ceec7bb87bf1..1383e3a4e050 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c
@@ -83,7 +83,7 @@ static bool pll_28nm_poll_for_ready(struct dsi_pll_28nm *pll_28nm,
u32 val;
while (nb_tries--) {
- val = dsi_phy_read(pll_28nm->phy->pll_base + REG_DSI_28nm_PHY_PLL_STATUS);
+ val = readl(pll_28nm->phy->pll_base + REG_DSI_28nm_PHY_PLL_STATUS);
pll_locked = !!(val & DSI_28nm_PHY_PLL_STATUS_PLL_RDY);
if (pll_locked)
@@ -104,9 +104,10 @@ static void pll_28nm_software_reset(struct dsi_pll_28nm *pll_28nm)
* Add HW recommended delays after toggling the software
* reset bit off and back on.
*/
- dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_TEST_CFG,
- DSI_28nm_PHY_PLL_TEST_CFG_PLL_SW_RESET, 1);
- dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_TEST_CFG, 0x00, 1);
+ writel(DSI_28nm_PHY_PLL_TEST_CFG_PLL_SW_RESET, base + REG_DSI_28nm_PHY_PLL_TEST_CFG);
+ udelay(1);
+ writel(0, base + REG_DSI_28nm_PHY_PLL_TEST_CFG);
+ udelay(1);
}
/*
@@ -128,7 +129,7 @@ static int dsi_pll_28nm_clk_set_rate(struct clk_hw *hw, unsigned long rate,
VERB("rate=%lu, parent's=%lu", rate, parent_rate);
/* Force postdiv2 to be div-4 */
- dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_POSTDIV2_CFG, 3);
+ writel(3, base + REG_DSI_28nm_PHY_PLL_POSTDIV2_CFG);
/* Configure the Loop filter resistance */
for (i = 0; i < LPFR_LUT_SIZE; i++)
@@ -139,11 +140,11 @@ static int dsi_pll_28nm_clk_set_rate(struct clk_hw *hw, unsigned long rate,
rate);
return -EINVAL;
}
- dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_LPFR_CFG, lpfr_lut[i].resistance);
+ writel(lpfr_lut[i].resistance, base + REG_DSI_28nm_PHY_PLL_LPFR_CFG);
/* Loop filter capacitance values : c1 and c2 */
- dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_LPFC1_CFG, 0x70);
- dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_LPFC2_CFG, 0x15);
+ writel(0x70, base + REG_DSI_28nm_PHY_PLL_LPFC1_CFG);
+ writel(0x15, base + REG_DSI_28nm_PHY_PLL_LPFC2_CFG);
rem = rate % VCO_REF_CLK_RATE;
if (rem) {
@@ -168,7 +169,7 @@ static int dsi_pll_28nm_clk_set_rate(struct clk_hw *hw, unsigned long rate,
DBG("Generated VCO Clock: %lu", gen_vco_clk);
rem = 0;
- sdm_cfg1 = dsi_phy_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG1);
+ sdm_cfg1 = readl(base + REG_DSI_28nm_PHY_PLL_SDM_CFG1);
sdm_cfg1 &= ~DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET__MASK;
if (frac_n_mode) {
sdm_cfg0 = 0x0;
@@ -195,17 +196,17 @@ static int dsi_pll_28nm_clk_set_rate(struct clk_hw *hw, unsigned long rate,
cal_cfg10 = (u32)((gen_vco_clk % (256 * 1000000)) / 1000000);
DBG("cal_cfg10=%d, cal_cfg11=%d", cal_cfg10, cal_cfg11);
- dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_CHGPUMP_CFG, 0x02);
- dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG3, 0x2b);
- dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG4, 0x06);
- dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2, 0x0d);
+ writel(0x02, base + REG_DSI_28nm_PHY_PLL_CHGPUMP_CFG);
+ writel(0x2b, base + REG_DSI_28nm_PHY_PLL_CAL_CFG3);
+ writel(0x06, base + REG_DSI_28nm_PHY_PLL_CAL_CFG4);
+ writel(0x0d, base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2);
- dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG1, sdm_cfg1);
- dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG2,
- DSI_28nm_PHY_PLL_SDM_CFG2_FREQ_SEED_7_0(sdm_cfg2));
- dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG3,
- DSI_28nm_PHY_PLL_SDM_CFG3_FREQ_SEED_15_8(sdm_cfg3));
- dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG4, 0x00);
+ writel(sdm_cfg1, base + REG_DSI_28nm_PHY_PLL_SDM_CFG1);
+ writel(DSI_28nm_PHY_PLL_SDM_CFG2_FREQ_SEED_7_0(sdm_cfg2),
+ base + REG_DSI_28nm_PHY_PLL_SDM_CFG2);
+ writel(DSI_28nm_PHY_PLL_SDM_CFG3_FREQ_SEED_15_8(sdm_cfg3),
+ base + REG_DSI_28nm_PHY_PLL_SDM_CFG3);
+ writel(0, base + REG_DSI_28nm_PHY_PLL_SDM_CFG4);
/* Add hardware recommended delay for correct PLL configuration */
if (pll_28nm->phy->cfg->quirks & DSI_PHY_28NM_QUIRK_PHY_LP)
@@ -213,18 +214,18 @@ static int dsi_pll_28nm_clk_set_rate(struct clk_hw *hw, unsigned long rate,
else
udelay(1);
- dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_REFCLK_CFG, refclk_cfg);
- dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_PWRGEN_CFG, 0x00);
- dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_VCOLPF_CFG, 0x31);
- dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG0, sdm_cfg0);
- dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG0, 0x12);
- dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG6, 0x30);
- dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG7, 0x00);
- dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG8, 0x60);
- dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG9, 0x00);
- dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG10, cal_cfg10 & 0xff);
- dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG11, cal_cfg11 & 0xff);
- dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_EFUSE_CFG, 0x20);
+ writel(refclk_cfg, base + REG_DSI_28nm_PHY_PLL_REFCLK_CFG);
+ writel(0x00, base + REG_DSI_28nm_PHY_PLL_PWRGEN_CFG);
+ writel(0x31, base + REG_DSI_28nm_PHY_PLL_VCOLPF_CFG);
+ writel(sdm_cfg0, base + REG_DSI_28nm_PHY_PLL_SDM_CFG0);
+ writel(0x12, base + REG_DSI_28nm_PHY_PLL_CAL_CFG0);
+ writel(0x30, base + REG_DSI_28nm_PHY_PLL_CAL_CFG6);
+ writel(0x00, base + REG_DSI_28nm_PHY_PLL_CAL_CFG7);
+ writel(0x60, base + REG_DSI_28nm_PHY_PLL_CAL_CFG8);
+ writel(0x00, base + REG_DSI_28nm_PHY_PLL_CAL_CFG9);
+ writel(cal_cfg10 & 0xff, base + REG_DSI_28nm_PHY_PLL_CAL_CFG10);
+ writel(cal_cfg11 & 0xff, base + REG_DSI_28nm_PHY_PLL_CAL_CFG11);
+ writel(0x20, base + REG_DSI_28nm_PHY_PLL_EFUSE_CFG);
return 0;
}
@@ -250,27 +251,27 @@ static unsigned long dsi_pll_28nm_clk_recalc_rate(struct clk_hw *hw,
VERB("parent_rate=%lu", parent_rate);
/* Check to see if the ref clk doubler is enabled */
- doubler = dsi_phy_read(base + REG_DSI_28nm_PHY_PLL_REFCLK_CFG) &
+ doubler = readl(base + REG_DSI_28nm_PHY_PLL_REFCLK_CFG) &
DSI_28nm_PHY_PLL_REFCLK_CFG_DBLR;
ref_clk += (doubler * VCO_REF_CLK_RATE);
/* see if it is integer mode or sdm mode */
- sdm0 = dsi_phy_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG0);
+ sdm0 = readl(base + REG_DSI_28nm_PHY_PLL_SDM_CFG0);
if (sdm0 & DSI_28nm_PHY_PLL_SDM_CFG0_BYP) {
/* integer mode */
sdm_byp_div = FIELD(
- dsi_phy_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG0),
+ readl(base + REG_DSI_28nm_PHY_PLL_SDM_CFG0),
DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV) + 1;
vco_rate = ref_clk * sdm_byp_div;
} else {
/* sdm mode */
sdm_dc_off = FIELD(
- dsi_phy_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG1),
+ readl(base + REG_DSI_28nm_PHY_PLL_SDM_CFG1),
DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET);
DBG("sdm_dc_off = %d", sdm_dc_off);
- sdm2 = FIELD(dsi_phy_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG2),
+ sdm2 = FIELD(readl(base + REG_DSI_28nm_PHY_PLL_SDM_CFG2),
DSI_28nm_PHY_PLL_SDM_CFG2_FREQ_SEED_7_0);
- sdm3 = FIELD(dsi_phy_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG3),
+ sdm3 = FIELD(readl(base + REG_DSI_28nm_PHY_PLL_SDM_CFG3),
DSI_28nm_PHY_PLL_SDM_CFG3_FREQ_SEED_15_8);
sdm_freq_seed = (sdm3 << 8) | sdm2;
DBG("sdm_freq_seed = %d", sdm_freq_seed);
@@ -303,22 +304,26 @@ static int _dsi_pll_28nm_vco_prepare_hpm(struct dsi_pll_28nm *pll_28nm)
* Add necessary delays recommended by hardware.
*/
val = DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B;
- dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 1);
+ writel(val, base + REG_DSI_28nm_PHY_PLL_GLB_CFG);
+ udelay(1);
val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B;
- dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 200);
+ writel(val, base + REG_DSI_28nm_PHY_PLL_GLB_CFG);
+ udelay(200);
val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B;
- dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 500);
+ writel(val, base + REG_DSI_28nm_PHY_PLL_GLB_CFG);
+ udelay(500);
val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE;
- dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 600);
+ writel(val, base + REG_DSI_28nm_PHY_PLL_GLB_CFG);
+ udelay(600);
for (i = 0; i < 2; i++) {
/* DSI Uniphy lock detect setting */
- dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2,
- 0x0c, 100);
- dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2, 0x0d);
+ writel(0x0c, base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2);
+ udelay(100);
+ writel(0x0d, base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2);
/* poll for PLL ready status */
locked = pll_28nm_poll_for_ready(pll_28nm, max_reads,
@@ -333,22 +338,28 @@ static int _dsi_pll_28nm_vco_prepare_hpm(struct dsi_pll_28nm *pll_28nm)
* Add necessary delays recommended by hardware.
*/
val = DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B;
- dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 1);
+ writel(val, base + REG_DSI_28nm_PHY_PLL_GLB_CFG);
+ udelay(1);
val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B;
- dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 200);
+ writel(val, base + REG_DSI_28nm_PHY_PLL_GLB_CFG);
+ udelay(200);
val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B;
- dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 250);
+ writel(val, base + REG_DSI_28nm_PHY_PLL_GLB_CFG);
+ udelay(250);
val &= ~DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B;
- dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 200);
+ writel(val, base + REG_DSI_28nm_PHY_PLL_GLB_CFG);
+ udelay(200);
val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B;
- dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 500);
+ writel(val, base + REG_DSI_28nm_PHY_PLL_GLB_CFG);
+ udelay(500);
val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE;
- dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 600);
+ writel(val, base + REG_DSI_28nm_PHY_PLL_GLB_CFG);
+ udelay(600);
}
if (unlikely(!locked))
@@ -396,24 +407,27 @@ static int dsi_pll_28nm_vco_prepare_8226(struct clk_hw *hw)
* PLL power up sequence.
* Add necessary delays recommended by hardware.
*/
- dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG1, 0x34);
+ writel(0x34, base + REG_DSI_28nm_PHY_PLL_CAL_CFG1);
val = DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B;
- dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 200);
+ writel(val, base + REG_DSI_28nm_PHY_PLL_GLB_CFG);
+ udelay(200);
val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B;
- dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 200);
+ writel(val, base + REG_DSI_28nm_PHY_PLL_GLB_CFG);
+ udelay(200);
val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B;
val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE;
- dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 600);
+ writel(val, base + REG_DSI_28nm_PHY_PLL_GLB_CFG);
+ udelay(600);
for (i = 0; i < 7; i++) {
/* DSI Uniphy lock detect setting */
- dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2, 0x0d);
- dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2,
- 0x0c, 100);
- dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2, 0x0d);
+ writel(0x0d, base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2);
+ writel(0x0c, base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2);
+ udelay(100);
+ writel(0x0d, base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2);
/* poll for PLL ready status */
locked = pll_28nm_poll_for_ready(pll_28nm,
@@ -427,15 +441,18 @@ static int dsi_pll_28nm_vco_prepare_8226(struct clk_hw *hw)
* PLL power up sequence.
* Add necessary delays recommended by hardware.
*/
- dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_PWRGEN_CFG, 0x00, 50);
+ writel(0x00, base + REG_DSI_28nm_PHY_PLL_PWRGEN_CFG);
+ udelay(50);
val = DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B;
val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B;
- dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 100);
+ writel(val, base + REG_DSI_28nm_PHY_PLL_GLB_CFG);
+ udelay(100);
val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B;
val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE;
- dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 600);
+ writel(val, base + REG_DSI_28nm_PHY_PLL_GLB_CFG);
+ udelay(600);
}
if (unlikely(!locked))
@@ -466,21 +483,27 @@ static int dsi_pll_28nm_vco_prepare_lp(struct clk_hw *hw)
* PLL power up sequence.
* Add necessary delays recommended by hardware.
*/
- dsi_phy_write_ndelay(base + REG_DSI_28nm_PHY_PLL_CAL_CFG1, 0x34, 500);
+ writel(0x34, base + REG_DSI_28nm_PHY_PLL_CAL_CFG1);
+ ndelay(500);
val = DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B;
- dsi_phy_write_ndelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 500);
+ writel(val, base + REG_DSI_28nm_PHY_PLL_GLB_CFG);
+ ndelay(500);
val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B;
- dsi_phy_write_ndelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 500);
+ writel(val, base + REG_DSI_28nm_PHY_PLL_GLB_CFG);
+ ndelay(500);
val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B |
DSI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE;
- dsi_phy_write_ndelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 500);
+ writel(val, base + REG_DSI_28nm_PHY_PLL_GLB_CFG);
+ ndelay(500);
/* DSI PLL toggle lock detect setting */
- dsi_phy_write_ndelay(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2, 0x04, 500);
- dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2, 0x05, 512);
+ writel(0x04, base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2);
+ ndelay(500);
+ writel(0x05, base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2);
+ udelay(512);
locked = pll_28nm_poll_for_ready(pll_28nm, max_reads, timeout_us);
@@ -504,7 +527,7 @@ static void dsi_pll_28nm_vco_unprepare(struct clk_hw *hw)
if (unlikely(!pll_28nm->phy->pll_on))
return;
- dsi_phy_write(pll_28nm->phy->pll_base + REG_DSI_28nm_PHY_PLL_GLB_CFG, 0x00);
+ writel(0, pll_28nm->phy->pll_base + REG_DSI_28nm_PHY_PLL_GLB_CFG);
pll_28nm->phy->pll_on = false;
}
@@ -560,10 +583,10 @@ static void dsi_28nm_pll_save_state(struct msm_dsi_phy *phy)
void __iomem *base = pll_28nm->phy->pll_base;
cached_state->postdiv3 =
- dsi_phy_read(base + REG_DSI_28nm_PHY_PLL_POSTDIV3_CFG);
+ readl(base + REG_DSI_28nm_PHY_PLL_POSTDIV3_CFG);
cached_state->postdiv1 =
- dsi_phy_read(base + REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG);
- cached_state->byte_mux = dsi_phy_read(base + REG_DSI_28nm_PHY_PLL_VREG_CFG);
+ readl(base + REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG);
+ cached_state->byte_mux = readl(base + REG_DSI_28nm_PHY_PLL_VREG_CFG);
if (dsi_pll_28nm_clk_is_enabled(phy->vco_hw))
cached_state->vco_rate = clk_hw_get_rate(phy->vco_hw);
else
@@ -585,12 +608,9 @@ static int dsi_28nm_pll_restore_state(struct msm_dsi_phy *phy)
return ret;
}
- dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_POSTDIV3_CFG,
- cached_state->postdiv3);
- dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG,
- cached_state->postdiv1);
- dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_VREG_CFG,
- cached_state->byte_mux);
+ writel(cached_state->postdiv3, base + REG_DSI_28nm_PHY_PLL_POSTDIV3_CFG);
+ writel(cached_state->postdiv1, base + REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG);
+ writel(cached_state->byte_mux, base + REG_DSI_28nm_PHY_PLL_VREG_CFG);
return 0;
}
@@ -700,72 +720,71 @@ static void dsi_28nm_dphy_set_timing(struct msm_dsi_phy *phy,
{
void __iomem *base = phy->base;
- dsi_phy_write(base + REG_DSI_28nm_PHY_TIMING_CTRL_0,
- DSI_28nm_PHY_TIMING_CTRL_0_CLK_ZERO(timing->clk_zero));
- dsi_phy_write(base + REG_DSI_28nm_PHY_TIMING_CTRL_1,
- DSI_28nm_PHY_TIMING_CTRL_1_CLK_TRAIL(timing->clk_trail));
- dsi_phy_write(base + REG_DSI_28nm_PHY_TIMING_CTRL_2,
- DSI_28nm_PHY_TIMING_CTRL_2_CLK_PREPARE(timing->clk_prepare));
+ writel(DSI_28nm_PHY_TIMING_CTRL_0_CLK_ZERO(timing->clk_zero),
+ base + REG_DSI_28nm_PHY_TIMING_CTRL_0);
+ writel(DSI_28nm_PHY_TIMING_CTRL_1_CLK_TRAIL(timing->clk_trail),
+ base + REG_DSI_28nm_PHY_TIMING_CTRL_1);
+ writel(DSI_28nm_PHY_TIMING_CTRL_2_CLK_PREPARE(timing->clk_prepare),
+ base + REG_DSI_28nm_PHY_TIMING_CTRL_2);
if (timing->clk_zero & BIT(8))
- dsi_phy_write(base + REG_DSI_28nm_PHY_TIMING_CTRL_3,
- DSI_28nm_PHY_TIMING_CTRL_3_CLK_ZERO_8);
- dsi_phy_write(base + REG_DSI_28nm_PHY_TIMING_CTRL_4,
- DSI_28nm_PHY_TIMING_CTRL_4_HS_EXIT(timing->hs_exit));
- dsi_phy_write(base + REG_DSI_28nm_PHY_TIMING_CTRL_5,
- DSI_28nm_PHY_TIMING_CTRL_5_HS_ZERO(timing->hs_zero));
- dsi_phy_write(base + REG_DSI_28nm_PHY_TIMING_CTRL_6,
- DSI_28nm_PHY_TIMING_CTRL_6_HS_PREPARE(timing->hs_prepare));
- dsi_phy_write(base + REG_DSI_28nm_PHY_TIMING_CTRL_7,
- DSI_28nm_PHY_TIMING_CTRL_7_HS_TRAIL(timing->hs_trail));
- dsi_phy_write(base + REG_DSI_28nm_PHY_TIMING_CTRL_8,
- DSI_28nm_PHY_TIMING_CTRL_8_HS_RQST(timing->hs_rqst));
- dsi_phy_write(base + REG_DSI_28nm_PHY_TIMING_CTRL_9,
- DSI_28nm_PHY_TIMING_CTRL_9_TA_GO(timing->ta_go) |
- DSI_28nm_PHY_TIMING_CTRL_9_TA_SURE(timing->ta_sure));
- dsi_phy_write(base + REG_DSI_28nm_PHY_TIMING_CTRL_10,
- DSI_28nm_PHY_TIMING_CTRL_10_TA_GET(timing->ta_get));
- dsi_phy_write(base + REG_DSI_28nm_PHY_TIMING_CTRL_11,
- DSI_28nm_PHY_TIMING_CTRL_11_TRIG3_CMD(0));
+ writel(DSI_28nm_PHY_TIMING_CTRL_3_CLK_ZERO_8,
+ base + REG_DSI_28nm_PHY_TIMING_CTRL_3);
+ writel(DSI_28nm_PHY_TIMING_CTRL_4_HS_EXIT(timing->hs_exit),
+ base + REG_DSI_28nm_PHY_TIMING_CTRL_4);
+ writel(DSI_28nm_PHY_TIMING_CTRL_5_HS_ZERO(timing->hs_zero),
+ base + REG_DSI_28nm_PHY_TIMING_CTRL_5);
+ writel(DSI_28nm_PHY_TIMING_CTRL_6_HS_PREPARE(timing->hs_prepare),
+ base + REG_DSI_28nm_PHY_TIMING_CTRL_6);
+ writel(DSI_28nm_PHY_TIMING_CTRL_7_HS_TRAIL(timing->hs_trail),
+ base + REG_DSI_28nm_PHY_TIMING_CTRL_7);
+ writel(DSI_28nm_PHY_TIMING_CTRL_8_HS_RQST(timing->hs_rqst),
+ base + REG_DSI_28nm_PHY_TIMING_CTRL_8);
+ writel(DSI_28nm_PHY_TIMING_CTRL_9_TA_GO(timing->ta_go) |
+ DSI_28nm_PHY_TIMING_CTRL_9_TA_SURE(timing->ta_sure),
+ base + REG_DSI_28nm_PHY_TIMING_CTRL_9);
+ writel(DSI_28nm_PHY_TIMING_CTRL_10_TA_GET(timing->ta_get),
+ base + REG_DSI_28nm_PHY_TIMING_CTRL_10);
+ writel(DSI_28nm_PHY_TIMING_CTRL_11_TRIG3_CMD(0),
+ base + REG_DSI_28nm_PHY_TIMING_CTRL_11);
}
static void dsi_28nm_phy_regulator_enable_dcdc(struct msm_dsi_phy *phy)
{
void __iomem *base = phy->reg_base;
- dsi_phy_write(base + REG_DSI_28nm_PHY_REGULATOR_CTRL_0, 0x0);
- dsi_phy_write(base + REG_DSI_28nm_PHY_REGULATOR_CAL_PWR_CFG, 1);
- dsi_phy_write(base + REG_DSI_28nm_PHY_REGULATOR_CTRL_5, 0);
- dsi_phy_write(base + REG_DSI_28nm_PHY_REGULATOR_CTRL_3, 0);
- dsi_phy_write(base + REG_DSI_28nm_PHY_REGULATOR_CTRL_2, 0x3);
- dsi_phy_write(base + REG_DSI_28nm_PHY_REGULATOR_CTRL_1, 0x9);
- dsi_phy_write(base + REG_DSI_28nm_PHY_REGULATOR_CTRL_0, 0x7);
- dsi_phy_write(base + REG_DSI_28nm_PHY_REGULATOR_CTRL_4, 0x20);
- dsi_phy_write(phy->base + REG_DSI_28nm_PHY_LDO_CNTRL, 0x00);
+ writel(0x0, base + REG_DSI_28nm_PHY_REGULATOR_CTRL_0);
+ writel(1, base + REG_DSI_28nm_PHY_REGULATOR_CAL_PWR_CFG);
+ writel(0, base + REG_DSI_28nm_PHY_REGULATOR_CTRL_5);
+ writel(0, base + REG_DSI_28nm_PHY_REGULATOR_CTRL_3);
+ writel(0x3, base + REG_DSI_28nm_PHY_REGULATOR_CTRL_2);
+ writel(0x9, base + REG_DSI_28nm_PHY_REGULATOR_CTRL_1);
+ writel(0x7, base + REG_DSI_28nm_PHY_REGULATOR_CTRL_0);
+ writel(0x20, base + REG_DSI_28nm_PHY_REGULATOR_CTRL_4);
+ writel(0x00, phy->base + REG_DSI_28nm_PHY_LDO_CNTRL);
}
static void dsi_28nm_phy_regulator_enable_ldo(struct msm_dsi_phy *phy)
{
void __iomem *base = phy->reg_base;
- dsi_phy_write(base + REG_DSI_28nm_PHY_REGULATOR_CTRL_0, 0x0);
- dsi_phy_write(base + REG_DSI_28nm_PHY_REGULATOR_CAL_PWR_CFG, 0);
- dsi_phy_write(base + REG_DSI_28nm_PHY_REGULATOR_CTRL_5, 0x7);
- dsi_phy_write(base + REG_DSI_28nm_PHY_REGULATOR_CTRL_3, 0);
- dsi_phy_write(base + REG_DSI_28nm_PHY_REGULATOR_CTRL_2, 0x1);
- dsi_phy_write(base + REG_DSI_28nm_PHY_REGULATOR_CTRL_1, 0x1);
- dsi_phy_write(base + REG_DSI_28nm_PHY_REGULATOR_CTRL_4, 0x20);
+ writel(0x0, base + REG_DSI_28nm_PHY_REGULATOR_CTRL_0);
+ writel(0, base + REG_DSI_28nm_PHY_REGULATOR_CAL_PWR_CFG);
+ writel(0x7, base + REG_DSI_28nm_PHY_REGULATOR_CTRL_5);
+ writel(0, base + REG_DSI_28nm_PHY_REGULATOR_CTRL_3);
+ writel(0x1, base + REG_DSI_28nm_PHY_REGULATOR_CTRL_2);
+ writel(0x1, base + REG_DSI_28nm_PHY_REGULATOR_CTRL_1);
+ writel(0x20, base + REG_DSI_28nm_PHY_REGULATOR_CTRL_4);
if (phy->cfg->quirks & DSI_PHY_28NM_QUIRK_PHY_LP)
- dsi_phy_write(phy->base + REG_DSI_28nm_PHY_LDO_CNTRL, 0x05);
+ writel(0x05, phy->base + REG_DSI_28nm_PHY_LDO_CNTRL);
else
- dsi_phy_write(phy->base + REG_DSI_28nm_PHY_LDO_CNTRL, 0x0d);
+ writel(0x0d, phy->base + REG_DSI_28nm_PHY_LDO_CNTRL);
}
static void dsi_28nm_phy_regulator_ctrl(struct msm_dsi_phy *phy, bool enable)
{
if (!enable) {
- dsi_phy_write(phy->reg_base +
- REG_DSI_28nm_PHY_REGULATOR_CAL_PWR_CFG, 0);
+ writel(0, phy->reg_base + REG_DSI_28nm_PHY_REGULATOR_CAL_PWR_CFG);
return;
}
@@ -792,49 +811,49 @@ static int dsi_28nm_phy_enable(struct msm_dsi_phy *phy,
return -EINVAL;
}
- dsi_phy_write(base + REG_DSI_28nm_PHY_STRENGTH_0, 0xff);
+ writel(0xff, base + REG_DSI_28nm_PHY_STRENGTH_0);
dsi_28nm_phy_regulator_ctrl(phy, true);
dsi_28nm_dphy_set_timing(phy, timing);
- dsi_phy_write(base + REG_DSI_28nm_PHY_CTRL_1, 0x00);
- dsi_phy_write(base + REG_DSI_28nm_PHY_CTRL_0, 0x5f);
+ writel(0x00, base + REG_DSI_28nm_PHY_CTRL_1);
+ writel(0x5f, base + REG_DSI_28nm_PHY_CTRL_0);
- dsi_phy_write(base + REG_DSI_28nm_PHY_STRENGTH_1, 0x6);
+ writel(0x6, base + REG_DSI_28nm_PHY_STRENGTH_1);
for (i = 0; i < 4; i++) {
- dsi_phy_write(base + REG_DSI_28nm_PHY_LN_CFG_0(i), 0);
- dsi_phy_write(base + REG_DSI_28nm_PHY_LN_CFG_1(i), 0);
- dsi_phy_write(base + REG_DSI_28nm_PHY_LN_CFG_2(i), 0);
- dsi_phy_write(base + REG_DSI_28nm_PHY_LN_CFG_3(i), 0);
- dsi_phy_write(base + REG_DSI_28nm_PHY_LN_CFG_4(i), 0);
- dsi_phy_write(base + REG_DSI_28nm_PHY_LN_TEST_DATAPATH(i), 0);
- dsi_phy_write(base + REG_DSI_28nm_PHY_LN_DEBUG_SEL(i), 0);
- dsi_phy_write(base + REG_DSI_28nm_PHY_LN_TEST_STR_0(i), 0x1);
- dsi_phy_write(base + REG_DSI_28nm_PHY_LN_TEST_STR_1(i), 0x97);
+ writel(0, base + REG_DSI_28nm_PHY_LN_CFG_0(i));
+ writel(0, base + REG_DSI_28nm_PHY_LN_CFG_1(i));
+ writel(0, base + REG_DSI_28nm_PHY_LN_CFG_2(i));
+ writel(0, base + REG_DSI_28nm_PHY_LN_CFG_3(i));
+ writel(0, base + REG_DSI_28nm_PHY_LN_CFG_4(i));
+ writel(0, base + REG_DSI_28nm_PHY_LN_TEST_DATAPATH(i));
+ writel(0, base + REG_DSI_28nm_PHY_LN_DEBUG_SEL(i));
+ writel(0x1, base + REG_DSI_28nm_PHY_LN_TEST_STR_0(i));
+ writel(0x97, base + REG_DSI_28nm_PHY_LN_TEST_STR_1(i));
}
- dsi_phy_write(base + REG_DSI_28nm_PHY_LNCK_CFG_4, 0);
- dsi_phy_write(base + REG_DSI_28nm_PHY_LNCK_CFG_1, 0xc0);
- dsi_phy_write(base + REG_DSI_28nm_PHY_LNCK_TEST_STR0, 0x1);
- dsi_phy_write(base + REG_DSI_28nm_PHY_LNCK_TEST_STR1, 0xbb);
+ writel(0, base + REG_DSI_28nm_PHY_LNCK_CFG_4);
+ writel(0xc0, base + REG_DSI_28nm_PHY_LNCK_CFG_1);
+ writel(0x1, base + REG_DSI_28nm_PHY_LNCK_TEST_STR0);
+ writel(0xbb, base + REG_DSI_28nm_PHY_LNCK_TEST_STR1);
- dsi_phy_write(base + REG_DSI_28nm_PHY_CTRL_0, 0x5f);
+ writel(0x5f, base + REG_DSI_28nm_PHY_CTRL_0);
- val = dsi_phy_read(base + REG_DSI_28nm_PHY_GLBL_TEST_CTRL);
+ val = readl(base + REG_DSI_28nm_PHY_GLBL_TEST_CTRL);
if (phy->id == DSI_1 && phy->usecase == MSM_DSI_PHY_SLAVE)
val &= ~DSI_28nm_PHY_GLBL_TEST_CTRL_BITCLK_HS_SEL;
else
val |= DSI_28nm_PHY_GLBL_TEST_CTRL_BITCLK_HS_SEL;
- dsi_phy_write(base + REG_DSI_28nm_PHY_GLBL_TEST_CTRL, val);
+ writel(val, base + REG_DSI_28nm_PHY_GLBL_TEST_CTRL);
return 0;
}
static void dsi_28nm_phy_disable(struct msm_dsi_phy *phy)
{
- dsi_phy_write(phy->base + REG_DSI_28nm_PHY_CTRL_0, 0);
+ writel(0, phy->base + REG_DSI_28nm_PHY_CTRL_0);
dsi_28nm_phy_regulator_ctrl(phy, false);
/*
@@ -917,3 +936,21 @@ const struct msm_dsi_phy_cfg dsi_phy_28nm_8226_cfgs = {
.num_dsi_phy = 1,
.quirks = DSI_PHY_28NM_QUIRK_PHY_8226,
};
+
+const struct msm_dsi_phy_cfg dsi_phy_28nm_8937_cfgs = {
+ .has_phy_regulator = true,
+ .regulator_data = dsi_phy_28nm_regulators,
+ .num_regulators = ARRAY_SIZE(dsi_phy_28nm_regulators),
+ .ops = {
+ .enable = dsi_28nm_phy_enable,
+ .disable = dsi_28nm_phy_disable,
+ .pll_init = dsi_pll_28nm_init,
+ .save_pll_state = dsi_28nm_pll_save_state,
+ .restore_pll_state = dsi_28nm_pll_restore_state,
+ },
+ .min_pll_rate = VCO_MIN_RATE,
+ .max_pll_rate = VCO_MAX_RATE,
+ .io_start = { 0x1a94400, 0x1a96400 },
+ .num_dsi_phy = 2,
+ .quirks = DSI_PHY_28NM_QUIRK_PHY_LP,
+};
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c
index 26c08047e20c..5311ab7f3c70 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c
@@ -74,7 +74,7 @@ static bool pll_28nm_poll_for_ready(struct dsi_pll_28nm *pll_28nm,
u32 val;
while (nb_tries--) {
- val = dsi_phy_read(pll_28nm->phy->pll_base + REG_DSI_28nm_8960_PHY_PLL_RDY);
+ val = readl(pll_28nm->phy->pll_base + REG_DSI_28nm_8960_PHY_PLL_RDY);
pll_locked = !!(val & DSI_28nm_8960_PHY_PLL_RDY_PLL_RDY);
if (pll_locked)
@@ -103,30 +103,25 @@ static int dsi_pll_28nm_clk_set_rate(struct clk_hw *hw, unsigned long rate,
val = VCO_REF_CLK_RATE / 10;
fb_divider = (temp * VCO_PREF_DIV_RATIO) / val;
fb_divider = fb_divider / 2 - 1;
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_1,
- fb_divider & 0xff);
+ writel(fb_divider & 0xff, base + REG_DSI_28nm_8960_PHY_PLL_CTRL_1);
- val = dsi_phy_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_2);
+ val = readl(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_2);
val |= (fb_divider >> 8) & 0x07;
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_2,
- val);
+ writel(val, base + REG_DSI_28nm_8960_PHY_PLL_CTRL_2);
- val = dsi_phy_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_3);
+ val = readl(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_3);
val |= (VCO_PREF_DIV_RATIO - 1) & 0x3f;
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_3,
- val);
+ writel(val, base + REG_DSI_28nm_8960_PHY_PLL_CTRL_3);
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_6,
- 0xf);
+ writel(0xf, base + REG_DSI_28nm_8960_PHY_PLL_CTRL_6);
- val = dsi_phy_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8);
+ val = readl(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8);
val |= 0x7 << 4;
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8,
- val);
+ writel(val, base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8);
return 0;
}
@@ -149,16 +144,16 @@ static unsigned long dsi_pll_28nm_clk_recalc_rate(struct clk_hw *hw,
VERB("parent_rate=%lu", parent_rate);
- status = dsi_phy_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_0);
+ status = readl(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_0);
if (status & DSI_28nm_8960_PHY_PLL_CTRL_0_ENABLE) {
- fb_divider = dsi_phy_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_1);
+ fb_divider = readl(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_1);
fb_divider &= 0xff;
- temp = dsi_phy_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_2) & 0x07;
+ temp = readl(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_2) & 0x07;
fb_divider = (temp << 8) | fb_divider;
fb_divider += 1;
- ref_divider = dsi_phy_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_3);
+ ref_divider = readl(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_3);
ref_divider &= 0x3f;
ref_divider += 1;
@@ -195,18 +190,18 @@ static int dsi_pll_28nm_vco_prepare(struct clk_hw *hw)
* 2: divide by 8 to get bit clock divider
* 3: write it to POSTDIV1
*/
- val = dsi_phy_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_9);
+ val = readl(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_9);
byte_div = val + 1;
bit_div = byte_div / 8;
- val = dsi_phy_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8);
+ val = readl(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8);
val &= ~0xf;
val |= (bit_div - 1);
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8, val);
+ writel(val, base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8);
/* enable the PLL */
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_0,
- DSI_28nm_8960_PHY_PLL_CTRL_0_ENABLE);
+ writel(DSI_28nm_8960_PHY_PLL_CTRL_0_ENABLE,
+ base + REG_DSI_28nm_8960_PHY_PLL_CTRL_0);
locked = pll_28nm_poll_for_ready(pll_28nm, max_reads, timeout_us);
@@ -230,7 +225,7 @@ static void dsi_pll_28nm_vco_unprepare(struct clk_hw *hw)
if (unlikely(!pll_28nm->phy->pll_on))
return;
- dsi_phy_write(pll_28nm->phy->pll_base + REG_DSI_28nm_8960_PHY_PLL_CTRL_0, 0x00);
+ writel(0x00, pll_28nm->phy->pll_base + REG_DSI_28nm_8960_PHY_PLL_CTRL_0);
pll_28nm->phy->pll_on = false;
}
@@ -277,7 +272,7 @@ static unsigned long clk_bytediv_recalc_rate(struct clk_hw *hw,
struct clk_bytediv *bytediv = to_clk_bytediv(hw);
unsigned int div;
- div = dsi_phy_read(bytediv->reg) & 0xff;
+ div = readl(bytediv->reg) & 0xff;
return parent_rate / (div + 1);
}
@@ -323,9 +318,9 @@ static int clk_bytediv_set_rate(struct clk_hw *hw, unsigned long rate,
factor = get_vco_mul_factor(rate);
- val = dsi_phy_read(bytediv->reg);
+ val = readl(bytediv->reg);
val |= (factor - 1) & 0xff;
- dsi_phy_write(bytediv->reg, val);
+ writel(val, bytediv->reg);
return 0;
}
@@ -347,11 +342,11 @@ static void dsi_28nm_pll_save_state(struct msm_dsi_phy *phy)
void __iomem *base = pll_28nm->phy->pll_base;
cached_state->postdiv3 =
- dsi_phy_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_10);
+ readl(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_10);
cached_state->postdiv2 =
- dsi_phy_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_9);
+ readl(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_9);
cached_state->postdiv1 =
- dsi_phy_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8);
+ readl(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8);
cached_state->vco_rate = clk_hw_get_rate(phy->vco_hw);
}
@@ -371,12 +366,9 @@ static int dsi_28nm_pll_restore_state(struct msm_dsi_phy *phy)
return ret;
}
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_10,
- cached_state->postdiv3);
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_9,
- cached_state->postdiv2);
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8,
- cached_state->postdiv1);
+ writel(cached_state->postdiv3, base + REG_DSI_28nm_8960_PHY_PLL_CTRL_10);
+ writel(cached_state->postdiv2, base + REG_DSI_28nm_8960_PHY_PLL_CTRL_9);
+ writel(cached_state->postdiv1, base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8);
return 0;
}
@@ -477,53 +469,52 @@ static void dsi_28nm_dphy_set_timing(struct msm_dsi_phy *phy,
{
void __iomem *base = phy->base;
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_0,
- DSI_28nm_8960_PHY_TIMING_CTRL_0_CLK_ZERO(timing->clk_zero));
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_1,
- DSI_28nm_8960_PHY_TIMING_CTRL_1_CLK_TRAIL(timing->clk_trail));
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_2,
- DSI_28nm_8960_PHY_TIMING_CTRL_2_CLK_PREPARE(timing->clk_prepare));
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_3, 0x0);
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_4,
- DSI_28nm_8960_PHY_TIMING_CTRL_4_HS_EXIT(timing->hs_exit));
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_5,
- DSI_28nm_8960_PHY_TIMING_CTRL_5_HS_ZERO(timing->hs_zero));
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_6,
- DSI_28nm_8960_PHY_TIMING_CTRL_6_HS_PREPARE(timing->hs_prepare));
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_7,
- DSI_28nm_8960_PHY_TIMING_CTRL_7_HS_TRAIL(timing->hs_trail));
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_8,
- DSI_28nm_8960_PHY_TIMING_CTRL_8_HS_RQST(timing->hs_rqst));
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_9,
- DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_GO(timing->ta_go) |
- DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_SURE(timing->ta_sure));
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_10,
- DSI_28nm_8960_PHY_TIMING_CTRL_10_TA_GET(timing->ta_get));
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_11,
- DSI_28nm_8960_PHY_TIMING_CTRL_11_TRIG3_CMD(0));
+ writel(DSI_28nm_8960_PHY_TIMING_CTRL_0_CLK_ZERO(timing->clk_zero),
+ base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_0);
+ writel(DSI_28nm_8960_PHY_TIMING_CTRL_1_CLK_TRAIL(timing->clk_trail),
+ base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_1);
+ writel(DSI_28nm_8960_PHY_TIMING_CTRL_2_CLK_PREPARE(timing->clk_prepare),
+ base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_2);
+ writel(0, base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_3);
+ writel(DSI_28nm_8960_PHY_TIMING_CTRL_4_HS_EXIT(timing->hs_exit),
+ base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_4);
+ writel(DSI_28nm_8960_PHY_TIMING_CTRL_5_HS_ZERO(timing->hs_zero),
+ base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_5);
+ writel(DSI_28nm_8960_PHY_TIMING_CTRL_6_HS_PREPARE(timing->hs_prepare),
+ base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_6);
+ writel(DSI_28nm_8960_PHY_TIMING_CTRL_7_HS_TRAIL(timing->hs_trail),
+ base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_7);
+ writel(DSI_28nm_8960_PHY_TIMING_CTRL_8_HS_RQST(timing->hs_rqst),
+ base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_8);
+ writel(DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_GO(timing->ta_go) |
+ DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_SURE(timing->ta_sure),
+ base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_9);
+ writel(DSI_28nm_8960_PHY_TIMING_CTRL_10_TA_GET(timing->ta_get),
+ base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_10);
+ writel(DSI_28nm_8960_PHY_TIMING_CTRL_11_TRIG3_CMD(0),
+ base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_11);
}
static void dsi_28nm_phy_regulator_init(struct msm_dsi_phy *phy)
{
void __iomem *base = phy->reg_base;
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_0, 0x3);
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_1, 1);
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_2, 1);
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_3, 0);
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_4,
- 0x100);
+ writel(0x3, base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_0);
+ writel(1, base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_1);
+ writel(1, base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_2);
+ writel(0, base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_3);
+ writel(0x100, base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_4);
}
static void dsi_28nm_phy_regulator_ctrl(struct msm_dsi_phy *phy)
{
void __iomem *base = phy->reg_base;
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_0, 0x3);
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_1, 0xa);
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_2, 0x4);
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_3, 0x0);
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_4, 0x20);
+ writel(0x3, base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_0);
+ writel(0xa, base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_1);
+ writel(0x4, base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_2);
+ writel(0x0, base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_3);
+ writel(0x20, base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_4);
}
static void dsi_28nm_phy_calibration(struct msm_dsi_phy *phy)
@@ -532,21 +523,20 @@ static void dsi_28nm_phy_calibration(struct msm_dsi_phy *phy)
u32 status;
int i = 5000;
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CAL_PWR_CFG,
- 0x3);
+ writel(0x3, base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CAL_PWR_CFG);
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_CAL_SW_CFG_2, 0x0);
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_CAL_HW_CFG_1, 0x5a);
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_CAL_HW_CFG_3, 0x10);
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_CAL_HW_CFG_4, 0x1);
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_CAL_HW_CFG_0, 0x1);
+ writel(0x0, base + REG_DSI_28nm_8960_PHY_MISC_CAL_SW_CFG_2);
+ writel(0x5a, base + REG_DSI_28nm_8960_PHY_MISC_CAL_HW_CFG_1);
+ writel(0x10, base + REG_DSI_28nm_8960_PHY_MISC_CAL_HW_CFG_3);
+ writel(0x1, base + REG_DSI_28nm_8960_PHY_MISC_CAL_HW_CFG_4);
+ writel(0x1, base + REG_DSI_28nm_8960_PHY_MISC_CAL_HW_CFG_0);
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_CAL_HW_TRIGGER, 0x1);
+ writel(0x1, base + REG_DSI_28nm_8960_PHY_MISC_CAL_HW_TRIGGER);
usleep_range(5000, 6000);
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_CAL_HW_TRIGGER, 0x0);
+ writel(0x0, base + REG_DSI_28nm_8960_PHY_MISC_CAL_HW_TRIGGER);
do {
- status = dsi_phy_read(base +
+ status = readl(base +
REG_DSI_28nm_8960_PHY_MISC_CAL_STATUS);
if (!(status & DSI_28nm_8960_PHY_MISC_CAL_STATUS_CAL_BUSY))
@@ -562,23 +552,20 @@ static void dsi_28nm_phy_lane_config(struct msm_dsi_phy *phy)
int i;
for (i = 0; i < 4; i++) {
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LN_CFG_0(i), 0x80);
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LN_CFG_1(i), 0x45);
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LN_CFG_2(i), 0x00);
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LN_TEST_DATAPATH(i),
- 0x00);
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LN_TEST_STR_0(i),
- 0x01);
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LN_TEST_STR_1(i),
- 0x66);
+ writel(0x80, base + REG_DSI_28nm_8960_PHY_LN_CFG_0(i));
+ writel(0x45, base + REG_DSI_28nm_8960_PHY_LN_CFG_1(i));
+ writel(0x00, base + REG_DSI_28nm_8960_PHY_LN_CFG_2(i));
+ writel(0x00, base + REG_DSI_28nm_8960_PHY_LN_TEST_DATAPATH(i));
+ writel(0x01, base + REG_DSI_28nm_8960_PHY_LN_TEST_STR_0(i));
+ writel(0x66, base + REG_DSI_28nm_8960_PHY_LN_TEST_STR_1(i));
}
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LNCK_CFG_0, 0x40);
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LNCK_CFG_1, 0x67);
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LNCK_CFG_2, 0x0);
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LNCK_TEST_DATAPATH, 0x0);
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LNCK_TEST_STR0, 0x1);
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LNCK_TEST_STR1, 0x88);
+ writel(0x40, base + REG_DSI_28nm_8960_PHY_LNCK_CFG_0);
+ writel(0x67, base + REG_DSI_28nm_8960_PHY_LNCK_CFG_1);
+ writel(0x0, base + REG_DSI_28nm_8960_PHY_LNCK_CFG_2);
+ writel(0x0, base + REG_DSI_28nm_8960_PHY_LNCK_TEST_DATAPATH);
+ writel(0x1, base + REG_DSI_28nm_8960_PHY_LNCK_TEST_STR0);
+ writel(0x88, base + REG_DSI_28nm_8960_PHY_LNCK_TEST_STR1);
}
static int dsi_28nm_phy_enable(struct msm_dsi_phy *phy,
@@ -598,18 +585,18 @@ static int dsi_28nm_phy_enable(struct msm_dsi_phy *phy,
dsi_28nm_phy_regulator_init(phy);
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LDO_CTRL, 0x04);
+ writel(0x04, base + REG_DSI_28nm_8960_PHY_LDO_CTRL);
/* strength control */
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_STRENGTH_0, 0xff);
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_STRENGTH_1, 0x00);
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_STRENGTH_2, 0x06);
+ writel(0xff, base + REG_DSI_28nm_8960_PHY_STRENGTH_0);
+ writel(0x00, base + REG_DSI_28nm_8960_PHY_STRENGTH_1);
+ writel(0x06, base + REG_DSI_28nm_8960_PHY_STRENGTH_2);
/* phy ctrl */
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_CTRL_0, 0x5f);
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_CTRL_1, 0x00);
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_CTRL_2, 0x00);
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_CTRL_3, 0x10);
+ writel(0x5f, base + REG_DSI_28nm_8960_PHY_CTRL_0);
+ writel(0x00, base + REG_DSI_28nm_8960_PHY_CTRL_1);
+ writel(0x00, base + REG_DSI_28nm_8960_PHY_CTRL_2);
+ writel(0x10, base + REG_DSI_28nm_8960_PHY_CTRL_3);
dsi_28nm_phy_regulator_ctrl(phy);
@@ -617,10 +604,10 @@ static int dsi_28nm_phy_enable(struct msm_dsi_phy *phy,
dsi_28nm_phy_lane_config(phy);
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_BIST_CTRL_4, 0x0f);
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_BIST_CTRL_1, 0x03);
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_BIST_CTRL_0, 0x03);
- dsi_phy_write(base + REG_DSI_28nm_8960_PHY_BIST_CTRL_4, 0x0);
+ writel(0x0f, base + REG_DSI_28nm_8960_PHY_BIST_CTRL_4);
+ writel(0x03, base + REG_DSI_28nm_8960_PHY_BIST_CTRL_1);
+ writel(0x03, base + REG_DSI_28nm_8960_PHY_BIST_CTRL_0);
+ writel(0x0, base + REG_DSI_28nm_8960_PHY_BIST_CTRL_4);
dsi_28nm_dphy_set_timing(phy, timing);
@@ -629,7 +616,7 @@ static int dsi_28nm_phy_enable(struct msm_dsi_phy *phy,
static void dsi_28nm_phy_disable(struct msm_dsi_phy *phy)
{
- dsi_phy_write(phy->base + REG_DSI_28nm_8960_PHY_CTRL_0, 0x0);
+ writel(0x0, phy->base + REG_DSI_28nm_8960_PHY_CTRL_0);
/*
* Wait for the registers writes to complete in order to
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 82d015aa2d63..3b59137ca674 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
@@ -194,20 +194,20 @@ static void dsi_pll_ssc_commit(struct dsi_pll_7nm *pll, struct dsi_pll_config *c
if (config->enable_ssc) {
pr_debug("SSC is enabled\n");
- dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_SSC_STEPSIZE_LOW_1,
- config->ssc_stepsize & 0xff);
- dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_SSC_STEPSIZE_HIGH_1,
- config->ssc_stepsize >> 8);
- dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_SSC_DIV_PER_LOW_1,
- config->ssc_div_per & 0xff);
- dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_SSC_DIV_PER_HIGH_1,
- config->ssc_div_per >> 8);
- dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_SSC_ADJPER_LOW_1,
- config->ssc_adj_per & 0xff);
- dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_SSC_ADJPER_HIGH_1,
- config->ssc_adj_per >> 8);
- dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_SSC_CONTROL,
- SSC_EN | (config->ssc_center ? SSC_CENTER : 0));
+ writel(config->ssc_stepsize & 0xff,
+ base + REG_DSI_7nm_PHY_PLL_SSC_STEPSIZE_LOW_1);
+ writel(config->ssc_stepsize >> 8,
+ base + REG_DSI_7nm_PHY_PLL_SSC_STEPSIZE_HIGH_1);
+ writel(config->ssc_div_per & 0xff,
+ base + REG_DSI_7nm_PHY_PLL_SSC_DIV_PER_LOW_1);
+ writel(config->ssc_div_per >> 8,
+ base + REG_DSI_7nm_PHY_PLL_SSC_DIV_PER_HIGH_1);
+ writel(config->ssc_adj_per & 0xff,
+ base + REG_DSI_7nm_PHY_PLL_SSC_ADJPER_LOW_1);
+ writel(config->ssc_adj_per >> 8,
+ base + REG_DSI_7nm_PHY_PLL_SSC_ADJPER_HIGH_1);
+ writel(SSC_EN | (config->ssc_center ? SSC_CENTER : 0),
+ base + REG_DSI_7nm_PHY_PLL_SSC_CONTROL);
}
}
@@ -242,36 +242,35 @@ static void dsi_pll_config_hzindep_reg(struct dsi_pll_7nm *pll)
vco_config_1 = 0x01;
}
- dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_FIVE_1,
- analog_controls_five_1);
- dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_VCO_CONFIG_1, vco_config_1);
- dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_FIVE, 0x01);
- dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_TWO, 0x03);
- dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_THREE, 0x00);
- dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_DSM_DIVIDER, 0x00);
- dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_FEEDBACK_DIVIDER, 0x4e);
- dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_CALIBRATION_SETTINGS, 0x40);
- dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_BAND_SEL_CAL_SETTINGS_THREE, 0xba);
- dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_FREQ_DETECT_SETTINGS_ONE, 0x0c);
- dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_OUTDIV, 0x00);
- dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_CORE_OVERRIDE, 0x00);
- dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_PLL_DIGITAL_TIMERS_TWO, 0x08);
- dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_PLL_PROP_GAIN_RATE_1, 0x0a);
- dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_PLL_BAND_SEL_RATE_1, 0xc0);
- dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_PLL_INT_GAIN_IFILT_BAND_1, 0x84);
- dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_PLL_INT_GAIN_IFILT_BAND_1, 0x82);
- dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_PLL_FL_INT_GAIN_PFILT_BAND_1, 0x4c);
- dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_PLL_LOCK_OVERRIDE, 0x80);
- dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_PFILT, 0x29);
- dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_PFILT, 0x2f);
- dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_IFILT, 0x2a);
- dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_IFILT,
- !(pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_PRE_V4_1) ? 0x3f : 0x22);
+ writel(analog_controls_five_1, base + REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_FIVE_1);
+ writel(vco_config_1, base + REG_DSI_7nm_PHY_PLL_VCO_CONFIG_1);
+ writel(0x01, base + REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_FIVE);
+ writel(0x03, base + REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_TWO);
+ writel(0x00, base + REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_THREE);
+ writel(0x00, base + REG_DSI_7nm_PHY_PLL_DSM_DIVIDER);
+ writel(0x4e, base + REG_DSI_7nm_PHY_PLL_FEEDBACK_DIVIDER);
+ writel(0x40, base + REG_DSI_7nm_PHY_PLL_CALIBRATION_SETTINGS);
+ writel(0xba, base + REG_DSI_7nm_PHY_PLL_BAND_SEL_CAL_SETTINGS_THREE);
+ writel(0x0c, base + REG_DSI_7nm_PHY_PLL_FREQ_DETECT_SETTINGS_ONE);
+ writel(0x00, base + REG_DSI_7nm_PHY_PLL_OUTDIV);
+ writel(0x00, base + REG_DSI_7nm_PHY_PLL_CORE_OVERRIDE);
+ writel(0x08, base + REG_DSI_7nm_PHY_PLL_PLL_DIGITAL_TIMERS_TWO);
+ writel(0x0a, base + REG_DSI_7nm_PHY_PLL_PLL_PROP_GAIN_RATE_1);
+ writel(0xc0, base + REG_DSI_7nm_PHY_PLL_PLL_BAND_SEL_RATE_1);
+ writel(0x84, base + REG_DSI_7nm_PHY_PLL_PLL_INT_GAIN_IFILT_BAND_1);
+ writel(0x82, base + REG_DSI_7nm_PHY_PLL_PLL_INT_GAIN_IFILT_BAND_1);
+ writel(0x4c, base + REG_DSI_7nm_PHY_PLL_PLL_FL_INT_GAIN_PFILT_BAND_1);
+ writel(0x80, base + REG_DSI_7nm_PHY_PLL_PLL_LOCK_OVERRIDE);
+ 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,
+ base + REG_DSI_7nm_PHY_PLL_IFILT);
if (!(pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_PRE_V4_1)) {
- dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_PERF_OPTIMIZE, 0x22);
+ writel(0x22, base + REG_DSI_7nm_PHY_PLL_PERF_OPTIMIZE);
if (pll->slave)
- dsi_phy_write(pll->slave->phy->pll_base + REG_DSI_7nm_PHY_PLL_PERF_OPTIMIZE, 0x22);
+ writel(0x22, pll->slave->phy->pll_base + REG_DSI_7nm_PHY_PLL_PERF_OPTIMIZE);
}
}
@@ -279,21 +278,21 @@ static void dsi_pll_commit(struct dsi_pll_7nm *pll, struct dsi_pll_config *confi
{
void __iomem *base = pll->phy->pll_base;
- dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_CORE_INPUT_OVERRIDE, 0x12);
- dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_DECIMAL_DIV_START_1,
- config->decimal_div_start);
- dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_LOW_1,
- config->frac_div_start & 0xff);
- dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_MID_1,
- (config->frac_div_start & 0xff00) >> 8);
- dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_HIGH_1,
- (config->frac_div_start & 0x30000) >> 16);
- dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_PLL_LOCKDET_RATE_1, 0x40);
- dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_PLL_LOCK_DELAY, 0x06);
- dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_CMODE_1,
- pll->phy->cphy_mode ? 0x00 : 0x10);
- dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_CLOCK_INVERTERS,
- config->pll_clock_inverters);
+ writel(0x12, base + REG_DSI_7nm_PHY_PLL_CORE_INPUT_OVERRIDE);
+ writel(config->decimal_div_start,
+ base + REG_DSI_7nm_PHY_PLL_DECIMAL_DIV_START_1);
+ writel(config->frac_div_start & 0xff,
+ base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_LOW_1);
+ writel((config->frac_div_start & 0xff00) >> 8,
+ base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_MID_1);
+ writel((config->frac_div_start & 0x30000) >> 16,
+ base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_HIGH_1);
+ writel(0x40, base + REG_DSI_7nm_PHY_PLL_PLL_LOCKDET_RATE_1);
+ writel(0x06, base + REG_DSI_7nm_PHY_PLL_PLL_LOCK_DELAY);
+ writel(pll->phy->cphy_mode ? 0x00 : 0x10,
+ base + REG_DSI_7nm_PHY_PLL_CMODE_1);
+ writel(config->pll_clock_inverters,
+ base + REG_DSI_7nm_PHY_PLL_CLOCK_INVERTERS);
}
static int dsi_pll_7nm_vco_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -347,19 +346,19 @@ static int dsi_pll_7nm_lock_status(struct dsi_pll_7nm *pll)
static void dsi_pll_disable_pll_bias(struct dsi_pll_7nm *pll)
{
- u32 data = dsi_phy_read(pll->phy->base + REG_DSI_7nm_PHY_CMN_CTRL_0);
+ u32 data = readl(pll->phy->base + REG_DSI_7nm_PHY_CMN_CTRL_0);
- dsi_phy_write(pll->phy->pll_base + REG_DSI_7nm_PHY_PLL_SYSTEM_MUXES, 0);
- dsi_phy_write(pll->phy->base + REG_DSI_7nm_PHY_CMN_CTRL_0, data & ~BIT(5));
+ writel(0, pll->phy->pll_base + REG_DSI_7nm_PHY_PLL_SYSTEM_MUXES);
+ writel(data & ~BIT(5), pll->phy->base + REG_DSI_7nm_PHY_CMN_CTRL_0);
ndelay(250);
}
static void dsi_pll_enable_pll_bias(struct dsi_pll_7nm *pll)
{
- u32 data = dsi_phy_read(pll->phy->base + REG_DSI_7nm_PHY_CMN_CTRL_0);
+ u32 data = readl(pll->phy->base + REG_DSI_7nm_PHY_CMN_CTRL_0);
- dsi_phy_write(pll->phy->base + REG_DSI_7nm_PHY_CMN_CTRL_0, data | BIT(5));
- dsi_phy_write(pll->phy->pll_base + REG_DSI_7nm_PHY_PLL_SYSTEM_MUXES, 0xc0);
+ writel(data | BIT(5), pll->phy->base + REG_DSI_7nm_PHY_CMN_CTRL_0);
+ writel(0xc0, pll->phy->pll_base + REG_DSI_7nm_PHY_PLL_SYSTEM_MUXES);
ndelay(250);
}
@@ -367,19 +366,18 @@ static void dsi_pll_disable_global_clk(struct dsi_pll_7nm *pll)
{
u32 data;
- data = dsi_phy_read(pll->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
- dsi_phy_write(pll->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1, data & ~BIT(5));
+ data = readl(pll->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
+ writel(data & ~BIT(5), pll->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
}
static void dsi_pll_enable_global_clk(struct dsi_pll_7nm *pll)
{
u32 data;
- dsi_phy_write(pll->phy->base + REG_DSI_7nm_PHY_CMN_CTRL_3, 0x04);
+ writel(0x04, pll->phy->base + REG_DSI_7nm_PHY_CMN_CTRL_3);
- data = dsi_phy_read(pll->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
- dsi_phy_write(pll->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1,
- data | BIT(5) | BIT(4));
+ data = readl(pll->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
+ writel(data | BIT(5) | BIT(4), pll->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
}
static void dsi_pll_phy_dig_reset(struct dsi_pll_7nm *pll)
@@ -389,9 +387,9 @@ static void dsi_pll_phy_dig_reset(struct dsi_pll_7nm *pll)
* coming out of a CX or analog rail power collapse while
* ensuring that the pads maintain LP00 or LP11 state
*/
- dsi_phy_write(pll->phy->base + REG_DSI_7nm_PHY_CMN_GLBL_DIGTOP_SPARE4, BIT(0));
+ writel(BIT(0), pll->phy->base + REG_DSI_7nm_PHY_CMN_GLBL_DIGTOP_SPARE4);
wmb(); /* Ensure that the reset is deasserted */
- dsi_phy_write(pll->phy->base + REG_DSI_7nm_PHY_CMN_GLBL_DIGTOP_SPARE4, 0x0);
+ writel(0, pll->phy->base + REG_DSI_7nm_PHY_CMN_GLBL_DIGTOP_SPARE4);
wmb(); /* Ensure that the reset is deasserted */
}
@@ -405,7 +403,7 @@ static int dsi_pll_7nm_vco_prepare(struct clk_hw *hw)
dsi_pll_enable_pll_bias(pll_7nm->slave);
/* Start PLL */
- dsi_phy_write(pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_PLL_CNTRL, 0x01);
+ writel(BIT(0), pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_PLL_CNTRL);
/*
* ensure all PLL configurations are written prior to checking
@@ -441,7 +439,7 @@ error:
static void dsi_pll_disable_sub(struct dsi_pll_7nm *pll)
{
- dsi_phy_write(pll->phy->base + REG_DSI_7nm_PHY_CMN_RBUF_CTRL, 0);
+ writel(0, pll->phy->base + REG_DSI_7nm_PHY_CMN_RBUF_CTRL);
dsi_pll_disable_pll_bias(pll);
}
@@ -455,7 +453,7 @@ static void dsi_pll_7nm_vco_unprepare(struct clk_hw *hw)
* powering down the PLL
*/
dsi_pll_disable_global_clk(pll_7nm);
- dsi_phy_write(pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_PLL_CNTRL, 0);
+ writel(0, pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_PLL_CNTRL);
dsi_pll_disable_sub(pll_7nm);
if (pll_7nm->slave) {
dsi_pll_disable_global_clk(pll_7nm->slave);
@@ -478,13 +476,13 @@ static unsigned long dsi_pll_7nm_vco_recalc_rate(struct clk_hw *hw,
u32 dec;
u64 pll_freq, tmp64;
- dec = dsi_phy_read(base + REG_DSI_7nm_PHY_PLL_DECIMAL_DIV_START_1);
+ dec = readl(base + REG_DSI_7nm_PHY_PLL_DECIMAL_DIV_START_1);
dec &= 0xff;
- frac = dsi_phy_read(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_LOW_1);
- frac |= ((dsi_phy_read(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_MID_1) &
+ frac = readl(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_LOW_1);
+ frac |= ((readl(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_MID_1) &
0xff) << 8);
- frac |= ((dsi_phy_read(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_HIGH_1) &
+ frac |= ((readl(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_HIGH_1) &
0x3) << 16);
/*
@@ -537,15 +535,15 @@ static void dsi_7nm_pll_save_state(struct msm_dsi_phy *phy)
void __iomem *phy_base = pll_7nm->phy->base;
u32 cmn_clk_cfg0, cmn_clk_cfg1;
- cached->pll_out_div = dsi_phy_read(pll_7nm->phy->pll_base +
+ cached->pll_out_div = readl(pll_7nm->phy->pll_base +
REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE);
cached->pll_out_div &= 0x3;
- cmn_clk_cfg0 = dsi_phy_read(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG0);
+ cmn_clk_cfg0 = readl(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG0);
cached->bit_clk_div = cmn_clk_cfg0 & 0xf;
cached->pix_clk_div = (cmn_clk_cfg0 & 0xf0) >> 4;
- cmn_clk_cfg1 = dsi_phy_read(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
+ cmn_clk_cfg1 = readl(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
cached->pll_mux = cmn_clk_cfg1 & 0x3;
DBG("DSI PLL%d outdiv %x bit_clk_div %x pix_clk_div %x pll_mux %x",
@@ -561,18 +559,18 @@ static int dsi_7nm_pll_restore_state(struct msm_dsi_phy *phy)
u32 val;
int ret;
- val = dsi_phy_read(pll_7nm->phy->pll_base + REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE);
+ val = readl(pll_7nm->phy->pll_base + REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE);
val &= ~0x3;
val |= cached->pll_out_div;
- dsi_phy_write(pll_7nm->phy->pll_base + REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE, val);
+ writel(val, pll_7nm->phy->pll_base + REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE);
- dsi_phy_write(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG0,
- cached->bit_clk_div | (cached->pix_clk_div << 4));
+ writel(cached->bit_clk_div | (cached->pix_clk_div << 4),
+ phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG0);
- val = dsi_phy_read(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
+ val = readl(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
val &= ~0x3;
val |= cached->pll_mux;
- dsi_phy_write(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG1, val);
+ writel(val, phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
ret = dsi_pll_7nm_vco_set_rate(phy->vco_hw,
pll_7nm->vco_current_rate,
@@ -610,7 +608,7 @@ static int dsi_7nm_set_usecase(struct msm_dsi_phy *phy)
}
/* set PLL src */
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_CLK_CFG1, (data << 2));
+ writel(data << 2, base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
return 0;
}
@@ -712,8 +710,8 @@ static int pll_7nm_register(struct dsi_pll_7nm *pll_7nm, struct clk_hw **provide
if (pll_7nm->phy->cphy_mode) {
u32 data;
- data = dsi_phy_read(pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
- dsi_phy_write(pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1, data | 3);
+ data = readl(pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
+ writel(data | 3, pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
phy_pll_out_dsi_parent = pll_post_out_div;
} else {
@@ -792,7 +790,7 @@ static int dsi_phy_hw_v4_0_is_pll_on(struct msm_dsi_phy *phy)
void __iomem *base = phy->base;
u32 data = 0;
- data = dsi_phy_read(base + REG_DSI_7nm_PHY_CMN_PLL_CNTRL);
+ data = readl(base + REG_DSI_7nm_PHY_CMN_PLL_CNTRL);
mb(); /* make sure read happened */
return (data & BIT(0));
@@ -808,11 +806,9 @@ static void dsi_phy_hw_v4_0_config_lpcdrx(struct msm_dsi_phy *phy, bool enable)
* corresponding to the logical data lane 0
*/
if (enable)
- dsi_phy_write(lane_base +
- REG_DSI_7nm_PHY_LN_LPRX_CTRL(phy_lane_0), 0x3);
+ writel(0x3, lane_base + REG_DSI_7nm_PHY_LN_LPRX_CTRL(phy_lane_0));
else
- dsi_phy_write(lane_base +
- REG_DSI_7nm_PHY_LN_LPRX_CTRL(phy_lane_0), 0);
+ writel(0, lane_base + REG_DSI_7nm_PHY_LN_LPRX_CTRL(phy_lane_0));
}
static void dsi_phy_hw_v4_0_lane_settings(struct msm_dsi_phy *phy)
@@ -833,18 +829,18 @@ static void dsi_phy_hw_v4_0_lane_settings(struct msm_dsi_phy *phy)
* be only enabled for the physical data lane corresponding
* to the logical data lane 0
*/
- dsi_phy_write(lane_base + REG_DSI_7nm_PHY_LN_LPRX_CTRL(i), 0);
- dsi_phy_write(lane_base + REG_DSI_7nm_PHY_LN_PIN_SWAP(i), 0x0);
+ writel(0, lane_base + REG_DSI_7nm_PHY_LN_LPRX_CTRL(i));
+ writel(0x0, lane_base + REG_DSI_7nm_PHY_LN_PIN_SWAP(i));
}
dsi_phy_hw_v4_0_config_lpcdrx(phy, true);
/* other settings */
for (i = 0; i < 5; i++) {
- dsi_phy_write(lane_base + REG_DSI_7nm_PHY_LN_CFG0(i), 0x0);
- dsi_phy_write(lane_base + REG_DSI_7nm_PHY_LN_CFG1(i), 0x0);
- dsi_phy_write(lane_base + REG_DSI_7nm_PHY_LN_CFG2(i), i == 4 ? 0x8a : 0xa);
- dsi_phy_write(lane_base + REG_DSI_7nm_PHY_LN_TX_DCTRL(i), tx_dctrl[i]);
+ writel(0x0, lane_base + REG_DSI_7nm_PHY_LN_CFG0(i));
+ writel(0x0, lane_base + REG_DSI_7nm_PHY_LN_CFG1(i));
+ writel(i == 4 ? 0x8a : 0xa, lane_base + REG_DSI_7nm_PHY_LN_CFG2(i));
+ writel(tx_dctrl[i], lane_base + REG_DSI_7nm_PHY_LN_TX_DCTRL(i));
}
}
@@ -882,7 +878,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)) {
- dsi_phy_write(phy->base + REG_DSI_7nm_PHY_CMN_GLBL_DIGTOP_SPARE10, 0x1);
+ writel(0x1, phy->base + REG_DSI_7nm_PHY_CMN_GLBL_DIGTOP_SPARE10);
udelay(500);
}
@@ -967,53 +963,53 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy,
/* de-assert digital and pll power down */
data = BIT(6) | BIT(5);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_CTRL_0, data);
+ writel(data, base + REG_DSI_7nm_PHY_CMN_CTRL_0);
/* Assert PLL core reset */
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_PLL_CNTRL, 0x00);
+ writel(0x00, base + REG_DSI_7nm_PHY_CMN_PLL_CNTRL);
/* turn off resync FIFO */
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_RBUF_CTRL, 0x00);
+ writel(0x00, base + REG_DSI_7nm_PHY_CMN_RBUF_CTRL);
/* program CMN_CTRL_4 for minor_ver 2 chipsets*/
if ((phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2) ||
- (dsi_phy_read(base + REG_DSI_7nm_PHY_CMN_REVISION_ID0) & (0xf0)) == 0x20)
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_CTRL_4, 0x04);
+ (readl(base + REG_DSI_7nm_PHY_CMN_REVISION_ID0) & (0xf0)) == 0x20)
+ writel(0x04, base + REG_DSI_7nm_PHY_CMN_CTRL_4);
/* Configure PHY lane swap (TODO: we need to calculate this) */
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_LANE_CFG0, 0x21);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_LANE_CFG1, 0x84);
+ writel(0x21, base + REG_DSI_7nm_PHY_CMN_LANE_CFG0);
+ writel(0x84, base + REG_DSI_7nm_PHY_CMN_LANE_CFG1);
if (phy->cphy_mode)
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_GLBL_CTRL, BIT(6));
+ writel(BIT(6), base + REG_DSI_7nm_PHY_CMN_GLBL_CTRL);
/* Enable LDO */
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_VREG_CTRL_0, vreg_ctrl_0);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_VREG_CTRL_1, vreg_ctrl_1);
-
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_CTRL_3, 0x00);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_GLBL_STR_SWI_CAL_SEL_CTRL,
- glbl_str_swi_cal_sel_ctrl);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_GLBL_HSTX_STR_CTRL_0,
- glbl_hstx_str_ctrl_0);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_GLBL_PEMPH_CTRL_0,
- glbl_pemph_ctrl_0);
+ writel(vreg_ctrl_0, base + REG_DSI_7nm_PHY_CMN_VREG_CTRL_0);
+ writel(vreg_ctrl_1, base + REG_DSI_7nm_PHY_CMN_VREG_CTRL_1);
+
+ writel(0x00, base + REG_DSI_7nm_PHY_CMN_CTRL_3);
+ writel(glbl_str_swi_cal_sel_ctrl,
+ base + REG_DSI_7nm_PHY_CMN_GLBL_STR_SWI_CAL_SEL_CTRL);
+ writel(glbl_hstx_str_ctrl_0,
+ base + REG_DSI_7nm_PHY_CMN_GLBL_HSTX_STR_CTRL_0);
+ writel(glbl_pemph_ctrl_0,
+ base + REG_DSI_7nm_PHY_CMN_GLBL_PEMPH_CTRL_0);
if (phy->cphy_mode)
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_GLBL_PEMPH_CTRL_1, 0x01);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_GLBL_RESCODE_OFFSET_TOP_CTRL,
- glbl_rescode_top_ctrl);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_GLBL_RESCODE_OFFSET_BOT_CTRL,
- glbl_rescode_bot_ctrl);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_GLBL_LPTX_STR_CTRL, 0x55);
+ writel(0x01, base + REG_DSI_7nm_PHY_CMN_GLBL_PEMPH_CTRL_1);
+ writel(glbl_rescode_top_ctrl,
+ base + REG_DSI_7nm_PHY_CMN_GLBL_RESCODE_OFFSET_TOP_CTRL);
+ writel(glbl_rescode_bot_ctrl,
+ base + REG_DSI_7nm_PHY_CMN_GLBL_RESCODE_OFFSET_BOT_CTRL);
+ writel(0x55, base + REG_DSI_7nm_PHY_CMN_GLBL_LPTX_STR_CTRL);
/* Remove power down from all blocks */
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_CTRL_0, 0x7f);
+ writel(0x7f, base + REG_DSI_7nm_PHY_CMN_CTRL_0);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_LANE_CTRL0, lane_ctrl0);
+ writel(lane_ctrl0, base + REG_DSI_7nm_PHY_CMN_LANE_CTRL0);
/* Select full-rate mode */
if (!phy->cphy_mode)
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_CTRL_2, 0x40);
+ writel(0x40, base + REG_DSI_7nm_PHY_CMN_CTRL_2);
ret = dsi_7nm_set_usecase(phy);
if (ret) {
@@ -1024,34 +1020,34 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy,
/* DSI PHY timings */
if (phy->cphy_mode) {
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_0, 0x00);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_4, timing->hs_exit);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_5,
- timing->shared_timings.clk_pre);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_6, timing->clk_prepare);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_7,
- timing->shared_timings.clk_post);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_8, timing->hs_rqst);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_9, 0x02);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_10, 0x04);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_11, 0x00);
+ writel(0x00, base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_0);
+ writel(timing->hs_exit, base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_4);
+ writel(timing->shared_timings.clk_pre,
+ base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_5);
+ writel(timing->clk_prepare, base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_6);
+ writel(timing->shared_timings.clk_post,
+ base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_7);
+ writel(timing->hs_rqst, base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_8);
+ writel(0x02, base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_9);
+ writel(0x04, base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_10);
+ writel(0x00, base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_11);
} else {
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_0, 0x00);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_1, timing->clk_zero);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_2, timing->clk_prepare);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_3, timing->clk_trail);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_4, timing->hs_exit);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_5, timing->hs_zero);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_6, timing->hs_prepare);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_7, timing->hs_trail);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_8, timing->hs_rqst);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_9, 0x02);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_10, 0x04);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_11, 0x00);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_12,
- timing->shared_timings.clk_pre);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_13,
- timing->shared_timings.clk_post);
+ writel(0x00, base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_0);
+ writel(timing->clk_zero, base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_1);
+ writel(timing->clk_prepare, base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_2);
+ writel(timing->clk_trail, base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_3);
+ writel(timing->hs_exit, base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_4);
+ writel(timing->hs_zero, base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_5);
+ writel(timing->hs_prepare, base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_6);
+ writel(timing->hs_trail, base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_7);
+ writel(timing->hs_rqst, base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_8);
+ writel(0x02, base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_9);
+ writel(0x04, base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_10);
+ writel(0x00, base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_11);
+ writel(timing->shared_timings.clk_pre,
+ base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_12);
+ writel(timing->shared_timings.clk_post,
+ base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_13);
}
/* DSI lane settings */
@@ -1067,12 +1063,12 @@ static bool dsi_7nm_set_continuous_clock(struct msm_dsi_phy *phy, bool enable)
void __iomem *base = phy->base;
u32 data;
- data = dsi_phy_read(base + REG_DSI_7nm_PHY_CMN_LANE_CTRL1);
+ data = readl(base + REG_DSI_7nm_PHY_CMN_LANE_CTRL1);
if (enable)
data |= BIT(5) | BIT(6);
else
data &= ~(BIT(5) | BIT(6));
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_LANE_CTRL1, data);
+ writel(data, base + REG_DSI_7nm_PHY_CMN_LANE_CTRL1);
return enable;
}
@@ -1092,21 +1088,21 @@ 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)) {
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_GLBL_DIGTOP_SPARE10, 0x0);
+ writel(0x0, base + REG_DSI_7nm_PHY_CMN_GLBL_DIGTOP_SPARE10);
wmb();
/* Delay to ensure HW removes vote before PHY shut down */
udelay(2);
}
- data = dsi_phy_read(base + REG_DSI_7nm_PHY_CMN_CTRL_0);
+ data = readl(base + REG_DSI_7nm_PHY_CMN_CTRL_0);
/* disable all lanes */
data &= ~0x1F;
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_CTRL_0, data);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_LANE_CTRL0, 0);
+ writel(data, base + REG_DSI_7nm_PHY_CMN_CTRL_0);
+ writel(0, base + REG_DSI_7nm_PHY_CMN_LANE_CTRL0);
/* Turn off all PHY blocks */
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_CTRL_0, 0x00);
+ writel(0x00, base + REG_DSI_7nm_PHY_CMN_CTRL_0);
/* make sure phy is turned off */
wmb();
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 912ebaa5df84..be016d7b4ef1 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -128,6 +128,11 @@ struct msm_drm_private {
struct msm_perf_state *perf;
/**
+ * total_mem: Total/global amount of memory backing GEM objects.
+ */
+ atomic64_t total_mem;
+
+ /**
* List of all GEM objects (mainly for debugfs, protected by obj_lock
* (acquire before per GEM object lock)
*/
@@ -330,6 +335,7 @@ bool msm_dsi_is_bonded_dsi(struct msm_dsi *msm_dsi);
bool msm_dsi_is_master_dsi(struct msm_dsi *msm_dsi);
bool msm_dsi_wide_bus_enabled(struct msm_dsi *msm_dsi);
struct drm_dsc_config *msm_dsi_get_dsc_config(struct msm_dsi *msm_dsi);
+const char *msm_dsi_get_te_source(struct msm_dsi *msm_dsi);
#else
static inline void __init msm_dsi_register(void)
{
@@ -367,6 +373,11 @@ static inline struct drm_dsc_config *msm_dsi_get_dsc_config(struct msm_dsi *msm_
{
return NULL;
}
+
+static inline const char *msm_dsi_get_te_source(struct msm_dsi *msm_dsi)
+{
+ return NULL;
+}
#endif
#ifdef CONFIG_DRM_MSM_DP
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
index a5c6498a43f0..ebc9ba66efb8 100644
--- a/drivers/gpu/drm/msm/msm_gem.c
+++ b/drivers/gpu/drm/msm/msm_gem.c
@@ -12,6 +12,9 @@
#include <linux/pfn_t.h>
#include <drm/drm_prime.h>
+#include <drm/drm_file.h>
+
+#include <trace/events/gpu_mem.h>
#include "msm_drv.h"
#include "msm_fence.h"
@@ -33,6 +36,34 @@ static bool use_pages(struct drm_gem_object *obj)
return !msm_obj->vram_node;
}
+static void update_device_mem(struct msm_drm_private *priv, ssize_t size)
+{
+ uint64_t total_mem = atomic64_add_return(size, &priv->total_mem);
+ trace_gpu_mem_total(0, 0, total_mem);
+}
+
+static void update_ctx_mem(struct drm_file *file, ssize_t size)
+{
+ struct msm_file_private *ctx = file->driver_priv;
+ uint64_t ctx_mem = atomic64_add_return(size, &ctx->ctx_mem);
+
+ rcu_read_lock(); /* Locks file->pid! */
+ trace_gpu_mem_total(0, pid_nr(rcu_dereference(file->pid)), ctx_mem);
+ rcu_read_unlock();
+
+}
+
+static int msm_gem_open(struct drm_gem_object *obj, struct drm_file *file)
+{
+ update_ctx_mem(file, obj->size);
+ return 0;
+}
+
+static void msm_gem_close(struct drm_gem_object *obj, struct drm_file *file)
+{
+ update_ctx_mem(file, -obj->size);
+}
+
/*
* Cache sync.. this is a bit over-complicated, to fit dma-mapping
* API. Really GPU cache is out of scope here (handled on cmdstream)
@@ -156,6 +187,8 @@ static struct page **get_pages(struct drm_gem_object *obj)
return p;
}
+ update_device_mem(dev->dev_private, obj->size);
+
msm_obj->pages = p;
msm_obj->sgt = drm_prime_pages_to_sg(obj->dev, p, npages);
@@ -209,6 +242,8 @@ static void put_pages(struct drm_gem_object *obj)
msm_obj->sgt = NULL;
}
+ update_device_mem(obj->dev->dev_private, -obj->size);
+
if (use_pages(obj))
drm_gem_put_pages(obj, msm_obj->pages, true, false);
else
@@ -1118,6 +1153,8 @@ static const struct vm_operations_struct vm_ops = {
static const struct drm_gem_object_funcs msm_gem_object_funcs = {
.free = msm_gem_free_object,
+ .open = msm_gem_open,
+ .close = msm_gem_close,
.pin = msm_gem_prime_pin,
.unpin = msm_gem_prime_unpin,
.get_sg_table = msm_gem_prime_get_sg_table,
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index cd185b9636d2..3666b42b4ecd 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -222,14 +222,16 @@ static void msm_gpu_crashstate_get_bo(struct msm_gpu_state *state,
struct drm_gem_object *obj, u64 iova, bool full)
{
struct msm_gpu_state_bo *state_bo = &state->bos[state->nr_bos];
+ struct msm_gem_object *msm_obj = to_msm_bo(obj);
/* Don't record write only objects */
state_bo->size = obj->size;
+ state_bo->flags = msm_obj->flags;
state_bo->iova = iova;
- BUILD_BUG_ON(sizeof(state_bo->name) != sizeof(to_msm_bo(obj)->name));
+ BUILD_BUG_ON(sizeof(state_bo->name) != sizeof(msm_obj->name));
- memcpy(state_bo->name, to_msm_bo(obj)->name, sizeof(state_bo->name));
+ memcpy(state_bo->name, msm_obj->name, sizeof(state_bo->name));
if (full) {
void *ptr;
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
index a0c1bd6d1d5b..1f02bb9956be 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -428,6 +428,14 @@ struct msm_file_private {
* level.
*/
struct drm_sched_entity *entities[NR_SCHED_PRIORITIES * MSM_GPU_MAX_RINGS];
+
+ /**
+ * ctx_mem:
+ *
+ * Total amount of memory of GEM buffers with handles attached for
+ * this context.
+ */
+ atomic64_t ctx_mem;
};
/**
@@ -519,6 +527,7 @@ struct msm_gpu_submitqueue {
struct msm_gpu_state_bo {
u64 iova;
size_t size;
+ u32 flags;
void *data;
bool encoded;
char name[32];
diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c
index d5512037c38b..2a94e82316f9 100644
--- a/drivers/gpu/drm/msm/msm_iommu.c
+++ b/drivers/gpu/drm/msm/msm_iommu.c
@@ -407,10 +407,13 @@ struct msm_mmu *msm_iommu_new(struct device *dev, unsigned long quirks)
struct msm_iommu *iommu;
int ret;
- domain = iommu_domain_alloc(dev->bus);
- if (!domain)
+ if (!device_iommu_mapped(dev))
return NULL;
+ domain = iommu_paging_domain_alloc(dev);
+ if (IS_ERR(domain))
+ return ERR_CAST(domain);
+
iommu_set_pgtable_quirks(domain, quirks);
iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
diff --git a/drivers/gpu/drm/msm/msm_mdss.c b/drivers/gpu/drm/msm/msm_mdss.c
index fab6ad4e5107..d90b9471ba6f 100644
--- a/drivers/gpu/drm/msm/msm_mdss.c
+++ b/drivers/gpu/drm/msm/msm_mdss.c
@@ -632,6 +632,13 @@ static const struct msm_mdss_data sm6350_data = {
.reg_bus_bw = 76800,
};
+static const struct msm_mdss_data sm7150_data = {
+ .ubwc_enc_version = UBWC_2_0,
+ .ubwc_dec_version = UBWC_2_0,
+ .highest_bank_bit = 1,
+ .reg_bus_bw = 76800,
+};
+
static const struct msm_mdss_data sm8150_data = {
.ubwc_enc_version = UBWC_3_0,
.ubwc_dec_version = UBWC_3_0,
@@ -713,6 +720,7 @@ static const struct of_device_id mdss_dt_match[] = {
{ .compatible = "qcom,sm6125-mdss", .data = &sm6125_data },
{ .compatible = "qcom,sm6350-mdss", .data = &sm6350_data },
{ .compatible = "qcom,sm6375-mdss", .data = &sm6350_data },
+ { .compatible = "qcom,sm7150-mdss", .data = &sm7150_data },
{ .compatible = "qcom,sm8150-mdss", .data = &sm8150_data },
{ .compatible = "qcom,sm8250-mdss", .data = &sm8250_data },
{ .compatible = "qcom,sm8350-mdss", .data = &sm8350_data },
diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.c b/drivers/gpu/drm/nouveau/dispnv04/disp.c
index 13705c5f1497..4b7497a8755c 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/disp.c
@@ -68,7 +68,7 @@ nv04_display_fini(struct drm_device *dev, bool runtime, bool suspend)
if (nv_two_heads(dev))
NVWriteCRTC(dev, 1, NV_PCRTC_INTR_EN_0, 0);
- if (!runtime)
+ if (!runtime && !drm->headless)
cancel_work_sync(&drm->hpd_work);
if (!suspend)
diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
index 670c9739e5e1..2033214c4b78 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
@@ -209,6 +209,8 @@ static int nv17_tv_get_ld_modes(struct drm_encoder *encoder,
struct drm_display_mode *mode;
mode = drm_mode_duplicate(encoder->dev, tv_mode);
+ if (!mode)
+ continue;
mode->clock = tv_norm->tv_enc_mode.vrefresh *
mode->htotal / 1000 *
@@ -258,6 +260,8 @@ static int nv17_tv_get_hd_modes(struct drm_encoder *encoder,
if (modes[i].hdisplay == output_mode->hdisplay &&
modes[i].vdisplay == output_mode->vdisplay) {
mode = drm_mode_duplicate(encoder->dev, output_mode);
+ if (!mode)
+ continue;
mode->type |= DRM_MODE_TYPE_PREFERRED;
} else {
@@ -265,6 +269,8 @@ static int nv17_tv_get_hd_modes(struct drm_encoder *encoder,
modes[i].vdisplay, 60, false,
(output_mode->flags &
DRM_MODE_FLAG_INTERLACE), false);
+ if (!mode)
+ continue;
}
/* CVT modes are sometimes unsuitable... */
diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index 88728a0b2c25..0efd6b4906cf 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -751,7 +751,7 @@ nv50_audio_enable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc,
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
struct nvif_outp *outp = &nv_encoder->outp;
- if (!nv50_audio_supported(encoder) || !drm_detect_monitor_audio(nv_connector->edid))
+ if (!nv50_audio_supported(encoder) || !nv_connector->base.display_info.has_audio)
return;
mutex_lock(&drm->audio.lock);
@@ -1765,7 +1765,7 @@ nv50_sor_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *sta
if ((disp->disp->object.oclass == GT214_DISP ||
disp->disp->object.oclass >= GF110_DISP) &&
nv_encoder->dcb->type != DCB_OUTPUT_LVDS &&
- drm_detect_monitor_audio(nv_connector->edid))
+ nv_connector->base.display_info.has_audio)
hda = true;
if (!nvif_outp_acquired(outp))
@@ -1774,7 +1774,7 @@ nv50_sor_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *sta
switch (nv_encoder->dcb->type) {
case DCB_OUTPUT_TMDS:
if (disp->disp->object.oclass != NV50_DISP &&
- drm_detect_hdmi_monitor(nv_connector->edid))
+ nv_connector->base.display_info.is_hdmi)
nv50_hdmi_enable(encoder, nv_crtc, nv_connector, state, mode, hda);
if (nv_encoder->outp.or.link & 1) {
@@ -1787,7 +1787,7 @@ nv50_sor_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *sta
*/
if (mode->clock >= 165000 &&
nv_encoder->dcb->duallink_possible &&
- !drm_detect_hdmi_monitor(nv_connector->edid))
+ !nv_connector->base.display_info.is_hdmi)
proto = NV507D_SOR_SET_CONTROL_PROTOCOL_DUAL_TMDS;
} else {
proto = NV507D_SOR_SET_CONTROL_PROTOCOL_SINGLE_TMDS_B;
@@ -2680,7 +2680,7 @@ nv50_display_fini(struct drm_device *dev, bool runtime, bool suspend)
nv50_mstm_fini(nouveau_encoder(encoder));
}
- if (!runtime)
+ if (!runtime && !drm->headless)
cancel_work_sync(&drm->hpd_work);
}
diff --git a/drivers/gpu/drm/nouveau/dispnv50/head.c b/drivers/gpu/drm/nouveau/dispnv50/head.c
index 83355dbc15ee..d7c74cc43ba5 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/head.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/head.c
@@ -127,14 +127,8 @@ nv50_head_atomic_check_view(struct nv50_head_atom *armh,
struct drm_display_mode *omode = &asyh->state.adjusted_mode;
struct drm_display_mode *umode = &asyh->state.mode;
int mode = asyc->scaler.mode;
- struct edid *edid;
int umode_vdisplay, omode_hdisplay, omode_vdisplay;
- if (connector->edid_blob_ptr)
- edid = (struct edid *)connector->edid_blob_ptr->data;
- else
- edid = NULL;
-
if (!asyc->scaler.full) {
if (mode == DRM_MODE_SCALE_NONE)
omode = umode;
@@ -162,7 +156,7 @@ nv50_head_atomic_check_view(struct nv50_head_atom *armh,
*/
if ((asyc->scaler.underscan.mode == UNDERSCAN_ON ||
(asyc->scaler.underscan.mode == UNDERSCAN_AUTO &&
- drm_detect_hdmi_monitor(edid)))) {
+ connector->display_info.is_hdmi))) {
u32 bX = asyc->scaler.underscan.hborder;
u32 bY = asyc->scaler.underscan.vborder;
u32 r = (asyh->view.oH << 19) / asyh->view.oW;
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h
index a11d16a16c3b..9e6f39912368 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h
@@ -213,6 +213,12 @@ struct nvkm_gsp {
struct mutex mutex;;
struct idr idr;
} client_id;
+
+ /* A linked list of registry items. The registry RPC will be built from it. */
+ struct list_head registry_list;
+
+ /* The size of the registry RPC */
+ size_t registry_rpc_size;
};
static inline bool
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c
index 79cfab53f80e..8c3c1f1e01c5 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.c
@@ -43,11 +43,6 @@
#define BIOSLOG(sip, fmt, arg...) NV_DEBUG(sip->dev, fmt, ##arg)
#define LOG_OLD_VALUE(x)
-struct init_exec {
- bool execute;
- bool repeat;
-};
-
static bool nv_cksum(const uint8_t *data, unsigned int length)
{
/*
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
index 70fb003a6666..0712d0b15170 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -898,7 +898,7 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict,
* Without this the operation can timeout and we'll fallback to a
* software copy, which might take several minutes to finish.
*/
- nouveau_fence_wait(fence, false, false);
+ nouveau_fence_wait(fence, false);
ret = ttm_bo_move_accel_cleanup(bo, &fence->base, evict, false,
new_reg);
nouveau_fence_unref(&fence);
diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c
index 7c97b2886807..66fca95c10c7 100644
--- a/drivers/gpu/drm/nouveau/nouveau_chan.c
+++ b/drivers/gpu/drm/nouveau/nouveau_chan.c
@@ -72,7 +72,7 @@ nouveau_channel_idle(struct nouveau_channel *chan)
ret = nouveau_fence_new(&fence, chan);
if (!ret) {
- ret = nouveau_fence_wait(fence, false, false);
+ ret = nouveau_fence_wait(fence, false);
nouveau_fence_unref(&fence);
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 856b3ef5edb8..b06aa473102b 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -1001,6 +1001,9 @@ nouveau_connector_get_modes(struct drm_connector *connector)
struct drm_display_mode *mode;
mode = drm_mode_duplicate(dev, nv_connector->native_mode);
+ if (!mode)
+ return 0;
+
drm_mode_probed_add(connector, mode);
ret = 1;
}
@@ -1034,7 +1037,7 @@ get_tmds_link_bandwidth(struct drm_connector *connector)
unsigned duallink_scale =
nouveau_duallink && nv_encoder->dcb->duallink_possible ? 2 : 1;
- if (drm_detect_hdmi_monitor(nv_connector->edid)) {
+ if (nv_connector->base.display_info.is_hdmi) {
info = &nv_connector->base.display_info;
duallink_scale = 1;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index aed5d5b51b43..d4725a968827 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -450,6 +450,9 @@ nouveau_display_hpd_resume(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_drm(dev);
+ if (drm->headless)
+ return;
+
spin_lock_irq(&drm->hpd_lock);
drm->hpd_pending = ~0;
spin_unlock_irq(&drm->hpd_lock);
@@ -635,7 +638,7 @@ nouveau_display_fini(struct drm_device *dev, bool suspend, bool runtime)
}
drm_connector_list_iter_end(&conn_iter);
- if (!runtime)
+ if (!runtime && !drm->headless)
cancel_work_sync(&drm->hpd_work);
drm_kms_helper_poll_disable(dev);
@@ -729,6 +732,7 @@ nouveau_display_create(struct drm_device *dev)
/* no display hw */
if (ret == -ENODEV) {
ret = 0;
+ drm->headless = true;
goto disp_create_err;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_dmem.c b/drivers/gpu/drm/nouveau/nouveau_dmem.c
index 6fb65b01d778..6719353e2e13 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dmem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dmem.c
@@ -128,7 +128,7 @@ static void nouveau_dmem_page_free(struct page *page)
static void nouveau_dmem_fence_done(struct nouveau_fence **fence)
{
if (fence) {
- nouveau_fence_wait(*fence, true, false);
+ nouveau_fence_wait(*fence, false);
nouveau_fence_unref(fence);
} else {
/*
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index a947e1d5f309..a58c31089613 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -32,7 +32,7 @@
#include <drm/drm_aperture.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_ttm.h>
#include <drm/drm_gem_ttm_helper.h>
#include <drm/drm_ioctl.h>
#include <drm/drm_vblank.h>
@@ -846,9 +846,9 @@ static int nouveau_drm_probe(struct pci_dev *pdev,
goto fail_drm_dev_init;
if (nouveau_drm(drm_dev)->client.device.info.ram_size <= 32 * 1024 * 1024)
- drm_fbdev_generic_setup(drm_dev, 8);
+ drm_fbdev_ttm_setup(drm_dev, 8);
else
- drm_fbdev_generic_setup(drm_dev, 32);
+ drm_fbdev_ttm_setup(drm_dev, 32);
quirk_broken_nv_runpm(pdev);
return 0;
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index e239c6bf4afa..25fca98a20bc 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -276,6 +276,7 @@ struct nouveau_drm {
/* modesetting */
struct nvbios vbios;
struct nouveau_display *display;
+ bool headless;
struct work_struct hpd_work;
spinlock_t hpd_lock;
u32 hpd_pending;
diff --git a/drivers/gpu/drm/nouveau/nouveau_exec.c b/drivers/gpu/drm/nouveau/nouveau_exec.c
index e65c0ef23bc7..a0b5f1b16e8b 100644
--- a/drivers/gpu/drm/nouveau/nouveau_exec.c
+++ b/drivers/gpu/drm/nouveau/nouveau_exec.c
@@ -188,7 +188,7 @@ nouveau_exec_job_timeout(struct nouveau_job *job)
return DRM_GPU_SCHED_STAT_NOMINAL;
}
-static struct nouveau_job_ops nouveau_exec_job_ops = {
+static const struct nouveau_job_ops nouveau_exec_job_ops = {
.submit = nouveau_exec_job_submit,
.armed_submit = nouveau_exec_job_armed_submit,
.run = nouveau_exec_job_run,
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c
index 93f08f9479d8..ba469767a20f 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fence.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fence.c
@@ -311,39 +311,11 @@ nouveau_fence_wait_legacy(struct dma_fence *f, bool intr, long wait)
return timeout - t;
}
-static int
-nouveau_fence_wait_busy(struct nouveau_fence *fence, bool intr)
-{
- int ret = 0;
-
- while (!nouveau_fence_done(fence)) {
- if (time_after_eq(jiffies, fence->timeout)) {
- ret = -EBUSY;
- break;
- }
-
- __set_current_state(intr ?
- TASK_INTERRUPTIBLE :
- TASK_UNINTERRUPTIBLE);
-
- if (intr && signal_pending(current)) {
- ret = -ERESTARTSYS;
- break;
- }
- }
-
- __set_current_state(TASK_RUNNING);
- return ret;
-}
-
int
-nouveau_fence_wait(struct nouveau_fence *fence, bool lazy, bool intr)
+nouveau_fence_wait(struct nouveau_fence *fence, bool intr)
{
long ret;
- if (!lazy)
- return nouveau_fence_wait_busy(fence, intr);
-
ret = dma_fence_wait_timeout(&fence->base, intr, 15 * HZ);
if (ret < 0)
return ret;
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.h b/drivers/gpu/drm/nouveau/nouveau_fence.h
index 8bc065acfe35..1b63197b744a 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fence.h
+++ b/drivers/gpu/drm/nouveau/nouveau_fence.h
@@ -23,7 +23,7 @@ void nouveau_fence_unref(struct nouveau_fence **);
int nouveau_fence_emit(struct nouveau_fence *);
bool nouveau_fence_done(struct nouveau_fence *);
-int nouveau_fence_wait(struct nouveau_fence *, bool lazy, bool intr);
+int nouveau_fence_wait(struct nouveau_fence *, bool intr);
int nouveau_fence_sync(struct nouveau_bo *, struct nouveau_channel *, bool exclusive, bool intr);
struct nouveau_fence_chan {
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
index 5a887d67dc0e..2e535caa7d6e 100644
--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
@@ -928,7 +928,7 @@ revalidate:
}
if (sync) {
- if (!(ret = nouveau_fence_wait(fence, false, false))) {
+ if (!(ret = nouveau_fence_wait(fence, false))) {
if ((ret = dma_fence_get_status(&fence->base)) == 1)
ret = 0;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_sched.h b/drivers/gpu/drm/nouveau/nouveau_sched.h
index e1f01a23e6f6..20cd1da8db73 100644
--- a/drivers/gpu/drm/nouveau/nouveau_sched.h
+++ b/drivers/gpu/drm/nouveau/nouveau_sched.h
@@ -42,7 +42,7 @@ struct nouveau_job_args {
u32 count;
} out_sync;
- struct nouveau_job_ops *ops;
+ const struct nouveau_job_ops *ops;
};
struct nouveau_job {
@@ -73,7 +73,7 @@ struct nouveau_job {
u32 count;
} out_sync;
- struct nouveau_job_ops {
+ const struct nouveau_job_ops {
/* If .submit() returns without any error, it is guaranteed that
* armed_submit() is called.
*/
diff --git a/drivers/gpu/drm/nouveau/nouveau_uvmm.c b/drivers/gpu/drm/nouveau/nouveau_uvmm.c
index ee02cd833c5e..9402fa320a7e 100644
--- a/drivers/gpu/drm/nouveau/nouveau_uvmm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_uvmm.c
@@ -1534,7 +1534,7 @@ nouveau_uvmm_bind_job_cleanup(struct nouveau_job *job)
nouveau_uvmm_bind_job_put(bind_job);
}
-static struct nouveau_job_ops nouveau_bind_job_ops = {
+static const struct nouveau_job_ops nouveau_bind_job_ops = {
.submit = nouveau_uvmm_bind_job_submit,
.armed_submit = nouveau_uvmm_bind_job_armed_submit,
.run = nouveau_uvmm_bind_job_run,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c
index abe41f7a3404..cf58f9da9139 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c
@@ -54,6 +54,8 @@
#include <nvrm/535.113.01/nvidia/kernel/inc/vgpu/rpc_global_enums.h>
#include <linux/acpi.h>
+#include <linux/ctype.h>
+#include <linux/parser.h>
#define GSP_MSG_MIN_SIZE GSP_PAGE_SIZE
#define GSP_MSG_MAX_SIZE GSP_PAGE_MIN_SIZE * 16
@@ -1080,53 +1082,365 @@ r535_gsp_rpc_unloading_guest_driver(struct nvkm_gsp *gsp, bool suspend)
return nvkm_gsp_rpc_wr(gsp, rpc, true);
}
+enum registry_type {
+ REGISTRY_TABLE_ENTRY_TYPE_DWORD = 1, /* 32-bit unsigned integer */
+ REGISTRY_TABLE_ENTRY_TYPE_BINARY = 2, /* Binary blob */
+ REGISTRY_TABLE_ENTRY_TYPE_STRING = 3, /* Null-terminated string */
+};
+
+/* An arbitrary limit to the length of a registry key */
+#define REGISTRY_MAX_KEY_LENGTH 64
+
+/**
+ * registry_list_entry - linked list member for a registry key/value
+ * @head: list_head struct
+ * @type: dword, binary, or string
+ * @klen: the length of name of the key
+ * @vlen: the length of the value
+ * @key: the key name
+ * @dword: the data, if REGISTRY_TABLE_ENTRY_TYPE_DWORD
+ * @binary: the data, if TYPE_BINARY or TYPE_STRING
+ *
+ * Every registry key/value is represented internally by this struct.
+ *
+ * Type DWORD is a simple 32-bit unsigned integer, and its value is stored in
+ * @dword.
+ *
+ * Types BINARY and STRING are variable-length binary blobs. The only real
+ * difference between BINARY and STRING is that STRING is null-terminated and
+ * is expected to contain only printable characters.
+ *
+ * Note: it is technically possible to have multiple keys with the same name
+ * but different types, but this is not useful since GSP-RM expects keys to
+ * have only one specific type.
+ */
+struct registry_list_entry {
+ struct list_head head;
+ enum registry_type type;
+ size_t klen;
+ char key[REGISTRY_MAX_KEY_LENGTH];
+ size_t vlen;
+ u32 dword; /* TYPE_DWORD */
+ u8 binary[] __counted_by(vlen); /* TYPE_BINARY or TYPE_STRING */
+};
+
+/**
+ * add_registry -- adds a registry entry
+ * @gsp: gsp pointer
+ * @key: name of the registry key
+ * @type: type of data
+ * @data: pointer to value
+ * @length: size of data, in bytes
+ *
+ * Adds a registry key/value pair to the registry database.
+ *
+ * This function collects the registry information in a linked list. After
+ * all registry keys have been added, build_registry() is used to create the
+ * RPC data structure.
+ *
+ * registry_rpc_size is a running total of the size of all registry keys.
+ * It's used to avoid an O(n) calculation of the size when the RPC is built.
+ *
+ * Returns 0 on success, or negative error code on error.
+ */
+static int add_registry(struct nvkm_gsp *gsp, const char *key,
+ enum registry_type type, const void *data, size_t length)
+{
+ struct registry_list_entry *reg;
+ const size_t nlen = strnlen(key, REGISTRY_MAX_KEY_LENGTH) + 1;
+ size_t alloc_size; /* extra bytes to alloc for binary or string value */
+
+ if (nlen > REGISTRY_MAX_KEY_LENGTH)
+ return -EINVAL;
+
+ alloc_size = (type == REGISTRY_TABLE_ENTRY_TYPE_DWORD) ? 0 : length;
+
+ reg = kmalloc(sizeof(*reg) + alloc_size, GFP_KERNEL);
+ if (!reg)
+ return -ENOMEM;
+
+ switch (type) {
+ case REGISTRY_TABLE_ENTRY_TYPE_DWORD:
+ reg->dword = *(const u32 *)(data);
+ break;
+ case REGISTRY_TABLE_ENTRY_TYPE_BINARY:
+ case REGISTRY_TABLE_ENTRY_TYPE_STRING:
+ memcpy(reg->binary, data, alloc_size);
+ break;
+ default:
+ nvkm_error(&gsp->subdev, "unrecognized registry type %u for '%s'\n",
+ type, key);
+ kfree(reg);
+ return -EINVAL;
+ }
+
+ memcpy(reg->key, key, nlen);
+ reg->klen = nlen;
+ reg->vlen = length;
+ reg->type = type;
+
+ list_add_tail(&reg->head, &gsp->registry_list);
+ gsp->registry_rpc_size += sizeof(PACKED_REGISTRY_ENTRY) + nlen + alloc_size;
+
+ return 0;
+}
+
+static int add_registry_num(struct nvkm_gsp *gsp, const char *key, u32 value)
+{
+ return add_registry(gsp, key, REGISTRY_TABLE_ENTRY_TYPE_DWORD,
+ &value, sizeof(u32));
+}
+
+static int add_registry_string(struct nvkm_gsp *gsp, const char *key, const char *value)
+{
+ return add_registry(gsp, key, REGISTRY_TABLE_ENTRY_TYPE_STRING,
+ value, strlen(value) + 1);
+}
+
+/**
+ * build_registry -- create the registry RPC data
+ * @gsp: gsp pointer
+ * @registry: pointer to the RPC payload to fill
+ *
+ * After all registry key/value pairs have been added, call this function to
+ * build the RPC.
+ *
+ * The registry RPC looks like this:
+ *
+ * +-----------------+
+ * |NvU32 size; |
+ * |NvU32 numEntries;|
+ * +-----------------+
+ * +----------------------------------------+
+ * |PACKED_REGISTRY_ENTRY |
+ * +----------------------------------------+
+ * |Null-terminated key (string) for entry 0|
+ * +----------------------------------------+
+ * |Binary/string data value for entry 0 | (only if necessary)
+ * +----------------------------------------+
+ *
+ * +----------------------------------------+
+ * |PACKED_REGISTRY_ENTRY |
+ * +----------------------------------------+
+ * |Null-terminated key (string) for entry 1|
+ * +----------------------------------------+
+ * |Binary/string data value for entry 1 | (only if necessary)
+ * +----------------------------------------+
+ * ... (and so on, one copy for each entry)
+ *
+ *
+ * The 'data' field of an entry is either a 32-bit integer (for type DWORD)
+ * or an offset into the PACKED_REGISTRY_TABLE (for types BINARY and STRING).
+ *
+ * All memory allocated by add_registry() is released.
+ */
+static void build_registry(struct nvkm_gsp *gsp, PACKED_REGISTRY_TABLE *registry)
+{
+ struct registry_list_entry *reg, *n;
+ size_t str_offset;
+ unsigned int i = 0;
+
+ registry->numEntries = list_count_nodes(&gsp->registry_list);
+ str_offset = struct_size(registry, entries, registry->numEntries);
+
+ list_for_each_entry_safe(reg, n, &gsp->registry_list, head) {
+ registry->entries[i].type = reg->type;
+ registry->entries[i].length = reg->vlen;
+
+ /* Append the key name to the table */
+ registry->entries[i].nameOffset = str_offset;
+ memcpy((void *)registry + str_offset, reg->key, reg->klen);
+ str_offset += reg->klen;
+
+ switch (reg->type) {
+ case REGISTRY_TABLE_ENTRY_TYPE_DWORD:
+ registry->entries[i].data = reg->dword;
+ break;
+ case REGISTRY_TABLE_ENTRY_TYPE_BINARY:
+ case REGISTRY_TABLE_ENTRY_TYPE_STRING:
+ /* If the type is binary or string, also append the value */
+ memcpy((void *)registry + str_offset, reg->binary, reg->vlen);
+ registry->entries[i].data = str_offset;
+ str_offset += reg->vlen;
+ break;
+ default:
+ break;
+ }
+
+ i++;
+ list_del(&reg->head);
+ kfree(reg);
+ }
+
+ /* Double-check that we calculated the sizes correctly */
+ WARN_ON(gsp->registry_rpc_size != str_offset);
+
+ registry->size = gsp->registry_rpc_size;
+}
+
+/**
+ * clean_registry -- clean up registry memory in case of error
+ * @gsp: gsp pointer
+ *
+ * Call this function to clean up all memory allocated by add_registry()
+ * in case of error and build_registry() is not called.
+ */
+static void clean_registry(struct nvkm_gsp *gsp)
+{
+ struct registry_list_entry *reg, *n;
+
+ list_for_each_entry_safe(reg, n, &gsp->registry_list, head) {
+ list_del(&reg->head);
+ kfree(reg);
+ }
+
+ gsp->registry_rpc_size = sizeof(PACKED_REGISTRY_TABLE);
+}
+
+MODULE_PARM_DESC(NVreg_RegistryDwords,
+ "A semicolon-separated list of key=integer pairs of GSP-RM registry keys");
+static char *NVreg_RegistryDwords;
+module_param(NVreg_RegistryDwords, charp, 0400);
+
/* dword only */
struct nv_gsp_registry_entries {
const char *name;
u32 value;
};
+/**
+ * r535_registry_entries - required registry entries for GSP-RM
+ *
+ * This array lists registry entries that are required for GSP-RM to
+ * function correctly.
+ *
+ * RMSecBusResetEnable - enables PCI secondary bus reset
+ * RMForcePcieConfigSave - forces GSP-RM to preserve PCI configuration
+ * registers on any PCI reset.
+ */
static const struct nv_gsp_registry_entries r535_registry_entries[] = {
{ "RMSecBusResetEnable", 1 },
{ "RMForcePcieConfigSave", 1 },
};
#define NV_GSP_REG_NUM_ENTRIES ARRAY_SIZE(r535_registry_entries)
+/**
+ * strip - strips all characters in 'reject' from 's'
+ * @s: string to strip
+ * @reject: string of characters to remove
+ *
+ * 's' is modified.
+ *
+ * Returns the length of the new string.
+ */
+static size_t strip(char *s, const char *reject)
+{
+ char *p = s, *p2 = s;
+ size_t length = 0;
+ char c;
+
+ do {
+ while ((c = *p2) && strchr(reject, c))
+ p2++;
+
+ *p++ = c = *p2++;
+ length++;
+ } while (c);
+
+ return length;
+}
+
+/**
+ * r535_gsp_rpc_set_registry - build registry RPC and call GSP-RM
+ * @gsp: gsp pointer
+ *
+ * The GSP-RM registry is a set of key/value pairs that configure some aspects
+ * of GSP-RM. The keys are strings, and the values are 32-bit integers.
+ *
+ * The registry is built from a combination of a static hard-coded list (see
+ * above) and entries passed on the driver's command line.
+ */
static int
r535_gsp_rpc_set_registry(struct nvkm_gsp *gsp)
{
PACKED_REGISTRY_TABLE *rpc;
- char *strings;
- int str_offset;
- int i;
- size_t rpc_size = struct_size(rpc, entries, NV_GSP_REG_NUM_ENTRIES);
+ unsigned int i;
+ int ret;
- /* add strings + null terminator */
- for (i = 0; i < NV_GSP_REG_NUM_ENTRIES; i++)
- rpc_size += strlen(r535_registry_entries[i].name) + 1;
+ INIT_LIST_HEAD(&gsp->registry_list);
+ gsp->registry_rpc_size = sizeof(PACKED_REGISTRY_TABLE);
- rpc = nvkm_gsp_rpc_get(gsp, NV_VGPU_MSG_FUNCTION_SET_REGISTRY, rpc_size);
- if (IS_ERR(rpc))
- return PTR_ERR(rpc);
+ for (i = 0; i < NV_GSP_REG_NUM_ENTRIES; i++) {
+ ret = add_registry_num(gsp, r535_registry_entries[i].name,
+ r535_registry_entries[i].value);
+ if (ret)
+ goto fail;
+ }
- rpc->numEntries = NV_GSP_REG_NUM_ENTRIES;
+ /*
+ * The NVreg_RegistryDwords parameter is a string of key=value
+ * pairs separated by semicolons. We need to extract and trim each
+ * substring, and then parse the substring to extract the key and
+ * value.
+ */
+ if (NVreg_RegistryDwords) {
+ char *p = kstrdup(NVreg_RegistryDwords, GFP_KERNEL);
+ char *start, *next = p, *equal;
+
+ if (!p) {
+ ret = -ENOMEM;
+ goto fail;
+ }
- str_offset = offsetof(typeof(*rpc), entries[NV_GSP_REG_NUM_ENTRIES]);
- strings = (char *)rpc + str_offset;
- for (i = 0; i < NV_GSP_REG_NUM_ENTRIES; i++) {
- int name_len = strlen(r535_registry_entries[i].name) + 1;
-
- rpc->entries[i].nameOffset = str_offset;
- rpc->entries[i].type = 1;
- rpc->entries[i].data = r535_registry_entries[i].value;
- rpc->entries[i].length = 4;
- memcpy(strings, r535_registry_entries[i].name, name_len);
- strings += name_len;
- str_offset += name_len;
+ /* Remove any whitespace from the parameter string */
+ strip(p, " \t\n");
+
+ while ((start = strsep(&next, ";"))) {
+ long value;
+
+ equal = strchr(start, '=');
+ if (!equal || equal == start || equal[1] == 0) {
+ nvkm_error(&gsp->subdev,
+ "ignoring invalid registry string '%s'\n",
+ start);
+ continue;
+ }
+
+ /* Truncate the key=value string to just key */
+ *equal = 0;
+
+ ret = kstrtol(equal + 1, 0, &value);
+ if (!ret) {
+ ret = add_registry_num(gsp, start, value);
+ } else {
+ /* Not a number, so treat it as a string */
+ ret = add_registry_string(gsp, start, equal + 1);
+ }
+
+ if (ret) {
+ nvkm_error(&gsp->subdev,
+ "ignoring invalid registry key/value '%s=%s'\n",
+ start, equal + 1);
+ continue;
+ }
+ }
+
+ kfree(p);
+ }
+
+ rpc = nvkm_gsp_rpc_get(gsp, NV_VGPU_MSG_FUNCTION_SET_REGISTRY, gsp->registry_rpc_size);
+ if (IS_ERR(rpc)) {
+ ret = PTR_ERR(rpc);
+ goto fail;
}
- rpc->size = str_offset;
+
+ build_registry(gsp, rpc);
return nvkm_gsp_rpc_wr(gsp, rpc, false);
+
+fail:
+ clean_registry(gsp);
+ return ret;
}
#if defined(CONFIG_ACPI) && defined(CONFIG_X86)
diff --git a/drivers/gpu/drm/omapdrm/Kconfig b/drivers/gpu/drm/omapdrm/Kconfig
index 6c49270cb290..3f7139e211d2 100644
--- a/drivers/gpu/drm/omapdrm/Kconfig
+++ b/drivers/gpu/drm/omapdrm/Kconfig
@@ -2,7 +2,7 @@
config DRM_OMAP
tristate "OMAP DRM"
depends on DRM && OF
- depends on ARCH_OMAP2PLUS
+ depends on ARCH_OMAP2PLUS || (COMPILE_TEST && PAGE_SIZE_LESS_THAN_64KB)
select DRM_KMS_HELPER
select FB_DMAMEM_HELPERS_DEFERRED if DRM_FBDEV_EMULATION
select VIDEOMODE_HELPERS
diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c
index 9ea0c64c26b5..fdae677558f3 100644
--- a/drivers/gpu/drm/omapdrm/omap_gem.c
+++ b/drivers/gpu/drm/omapdrm/omap_gem.c
@@ -1023,8 +1023,8 @@ struct sg_table *omap_gem_get_sg(struct drm_gem_object *obj,
if (addr) {
for_each_sg(sgt->sgl, sg, count, i) {
- sg_set_page(sg, phys_to_page(addr), len,
- offset_in_page(addr));
+ sg_set_page(sg, pfn_to_page(__phys_to_pfn(addr)),
+ len, offset_in_page(addr));
sg_dma_address(sg) = addr;
sg_dma_len(sg) = len;
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index 2ae0eb0638f3..9f49b0189d3b 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -145,6 +145,15 @@ config DRM_PANEL_LVDS
handling of power supplies or control signals. It implements automatic
backlight handling if the panel is attached to a backlight controller.
+config DRM_PANEL_HIMAX_HX83102
+ tristate "Himax HX83102-based panels"
+ depends on OF
+ depends on DRM_MIPI_DSI
+ depends on BACKLIGHT_CLASS_DEVICE
+ help
+ Say Y if you want to enable support for panels based on the
+ Himax HX83102 controller.
+
config DRM_PANEL_HIMAX_HX83112A
tristate "Himax HX83112A-based DSI panel"
depends on OF
@@ -196,6 +205,15 @@ 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"
+ depends on OF
+ depends on DRM_MIPI_DSI
+ depends on BACKLIGHT_CLASS_DEVICE
+ help
+ Say Y if you want to enable support for panels based on the
+ Ilitek ILI9806E controller.
+
config DRM_PANEL_ILITEK_ILI9881C
tristate "Ilitek ILI9881C-based panels"
depends on OF
@@ -319,6 +337,17 @@ config DRM_PANEL_LEADTEK_LTK500HD1829
24 bit RGB per pixel. It provides a MIPI DSI interface to
the host and has a built-in LED backlight.
+config DRM_PANEL_LINCOLNTECH_LCD197
+ tristate "Lincoln Technologies lcd197 panel"
+ depends on OF
+ depends on DRM_MIPI_DSI
+ depends on BACKLIGHT_CLASS_DEVICE
+ help
+ Say Y here if you want to enable support for lincolntech lcd197
+ TFT-LCD modules. The panel has a 1080x1920 resolution and uses
+ 24 bit RGB per pixel. It provides a MIPI DSI interface to
+ the host.
+
config DRM_PANEL_LG_LB035Q02
tristate "LG LB035Q024573 RGB panel"
depends on GPIOLIB && OF && SPI
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index f0203f6e02f4..5581387707c6 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -15,11 +15,13 @@ obj-$(CONFIG_DRM_PANEL_EBBG_FT8719) += panel-ebbg-ft8719.o
obj-$(CONFIG_DRM_PANEL_ELIDA_KD35T133) += panel-elida-kd35t133.o
obj-$(CONFIG_DRM_PANEL_FEIXIN_K101_IM2BA02) += panel-feixin-k101-im2ba02.o
obj-$(CONFIG_DRM_PANEL_FEIYANG_FY07024DI26A30D) += panel-feiyang-fy07024di26a30d.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_HX8394) += panel-himax-hx8394.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_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
@@ -32,6 +34,7 @@ obj-$(CONFIG_DRM_PANEL_KHADAS_TS050) += panel-khadas-ts050.o
obj-$(CONFIG_DRM_PANEL_KINGDISPLAY_KD097D04) += panel-kingdisplay-kd097d04.o
obj-$(CONFIG_DRM_PANEL_LEADTEK_LTK050H3146W) += panel-leadtek-ltk050h3146w.o
obj-$(CONFIG_DRM_PANEL_LEADTEK_LTK500HD1829) += panel-leadtek-ltk500hd1829.o
+obj-$(CONFIG_DRM_PANEL_LINCOLNTECH_LCD197) += panel-lincolntech-lcd197.o
obj-$(CONFIG_DRM_PANEL_LG_LB035Q02) += panel-lg-lb035q02.o
obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o
obj-$(CONFIG_DRM_PANEL_LG_SW43408) += panel-lg-sw43408.o
diff --git a/drivers/gpu/drm/panel/panel-abt-y030xx067a.c b/drivers/gpu/drm/panel/panel-abt-y030xx067a.c
index 662c7bcbe6e5..4692c36fe217 100644
--- a/drivers/gpu/drm/panel/panel-abt-y030xx067a.c
+++ b/drivers/gpu/drm/panel/panel-abt-y030xx067a.c
@@ -381,4 +381,5 @@ module_spi_driver(y030xx067a_driver);
MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
MODULE_AUTHOR("Christophe Branchereau <cbranchereau@gmail.com>");
+MODULE_DESCRIPTION("Asia Better Technology Ltd. Y030XX067A IPS LCD panel driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/panel/panel-asus-z00t-tm5p5-n35596.c b/drivers/gpu/drm/panel/panel-asus-z00t-tm5p5-n35596.c
index bcaa63d1955f..b05a663c134c 100644
--- a/drivers/gpu/drm/panel/panel-asus-z00t-tm5p5-n35596.c
+++ b/drivers/gpu/drm/panel/panel-asus-z00t-tm5p5-n35596.c
@@ -33,119 +33,97 @@ static void tm5p5_nt35596_reset(struct tm5p5_nt35596 *ctx)
usleep_range(15000, 16000);
}
-static int tm5p5_nt35596_on(struct tm5p5_nt35596 *ctx)
+static void tm5p5_nt35596_on(struct mipi_dsi_multi_context *dsi_ctx)
{
- struct mipi_dsi_device *dsi = ctx->dsi;
-
- mipi_dsi_generic_write_seq(dsi, 0xff, 0x05);
- mipi_dsi_generic_write_seq(dsi, 0xfb, 0x01);
- mipi_dsi_generic_write_seq(dsi, 0xc5, 0x31);
- mipi_dsi_generic_write_seq(dsi, 0xff, 0x04);
- mipi_dsi_generic_write_seq(dsi, 0x01, 0x84);
- mipi_dsi_generic_write_seq(dsi, 0x05, 0x25);
- mipi_dsi_generic_write_seq(dsi, 0x06, 0x01);
- mipi_dsi_generic_write_seq(dsi, 0x07, 0x20);
- mipi_dsi_generic_write_seq(dsi, 0x08, 0x06);
- mipi_dsi_generic_write_seq(dsi, 0x09, 0x08);
- mipi_dsi_generic_write_seq(dsi, 0x0a, 0x10);
- mipi_dsi_generic_write_seq(dsi, 0x0b, 0x10);
- mipi_dsi_generic_write_seq(dsi, 0x0c, 0x10);
- mipi_dsi_generic_write_seq(dsi, 0x0d, 0x14);
- mipi_dsi_generic_write_seq(dsi, 0x0e, 0x14);
- mipi_dsi_generic_write_seq(dsi, 0x0f, 0x14);
- mipi_dsi_generic_write_seq(dsi, 0x10, 0x14);
- mipi_dsi_generic_write_seq(dsi, 0x11, 0x14);
- mipi_dsi_generic_write_seq(dsi, 0x12, 0x14);
- mipi_dsi_generic_write_seq(dsi, 0x17, 0xf3);
- mipi_dsi_generic_write_seq(dsi, 0x18, 0xc0);
- mipi_dsi_generic_write_seq(dsi, 0x19, 0xc0);
- mipi_dsi_generic_write_seq(dsi, 0x1a, 0xc0);
- mipi_dsi_generic_write_seq(dsi, 0x1b, 0xb3);
- mipi_dsi_generic_write_seq(dsi, 0x1c, 0xb3);
- mipi_dsi_generic_write_seq(dsi, 0x1d, 0xb3);
- mipi_dsi_generic_write_seq(dsi, 0x1e, 0xb3);
- mipi_dsi_generic_write_seq(dsi, 0x1f, 0xb3);
- mipi_dsi_generic_write_seq(dsi, 0x20, 0xb3);
- mipi_dsi_generic_write_seq(dsi, 0xfb, 0x01);
- mipi_dsi_generic_write_seq(dsi, 0xff, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xfb, 0x01);
- mipi_dsi_generic_write_seq(dsi, 0x35, 0x01);
- mipi_dsi_generic_write_seq(dsi, 0xd3, 0x06);
- mipi_dsi_generic_write_seq(dsi, 0xd4, 0x04);
- mipi_dsi_generic_write_seq(dsi, 0x5e, 0x0d);
- mipi_dsi_generic_write_seq(dsi, 0x11, 0x00);
- msleep(100);
- mipi_dsi_generic_write_seq(dsi, 0x29, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0x53, 0x24);
-
- return 0;
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xff, 0x05);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xfb, 0x01);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xc5, 0x31);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xff, 0x04);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x01, 0x84);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x05, 0x25);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x06, 0x01);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x07, 0x20);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x08, 0x06);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x09, 0x08);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x0a, 0x10);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x0b, 0x10);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x0c, 0x10);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x0d, 0x14);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x0e, 0x14);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x0f, 0x14);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x10, 0x14);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x11, 0x14);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x12, 0x14);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x17, 0xf3);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x18, 0xc0);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x19, 0xc0);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x1a, 0xc0);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x1b, 0xb3);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x1c, 0xb3);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x1d, 0xb3);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x1e, 0xb3);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x1f, 0xb3);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x20, 0xb3);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xfb, 0x01);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xff, 0x00);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xfb, 0x01);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x35, 0x01);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xd3, 0x06);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xd4, 0x04);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x5e, 0x0d);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x11, 0x00);
+
+ mipi_dsi_msleep(dsi_ctx, 100);
+
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x29, 0x00);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x53, 0x24);
}
-static int tm5p5_nt35596_off(struct tm5p5_nt35596 *ctx)
+static void tm5p5_nt35596_off(struct mipi_dsi_multi_context *dsi_ctx)
{
- struct mipi_dsi_device *dsi = ctx->dsi;
- struct device *dev = &dsi->dev;
- int ret;
-
- ret = mipi_dsi_dcs_set_display_off(dsi);
- if (ret < 0) {
- dev_err(dev, "Failed to set display off: %d\n", ret);
- return ret;
- }
- msleep(60);
+ mipi_dsi_dcs_set_display_off_multi(dsi_ctx);
- ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
- if (ret < 0) {
- dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
- return ret;
- }
+ mipi_dsi_msleep(dsi_ctx, 60);
- mipi_dsi_dcs_write_seq(dsi, 0x4f, 0x01);
+ mipi_dsi_dcs_enter_sleep_mode_multi(dsi_ctx);
- return 0;
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0x4f, 0x01);
}
static int tm5p5_nt35596_prepare(struct drm_panel *panel)
{
struct tm5p5_nt35596 *ctx = to_tm5p5_nt35596(panel);
- struct device *dev = &ctx->dsi->dev;
- int ret;
+ struct mipi_dsi_multi_context dsi_ctx = {.dsi = ctx->dsi};
- ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
- if (ret < 0) {
- dev_err(dev, "Failed to enable regulators: %d\n", ret);
- return ret;
- }
+ dsi_ctx.accum_err = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+ if (dsi_ctx.accum_err)
+ return dsi_ctx.accum_err;
tm5p5_nt35596_reset(ctx);
- ret = tm5p5_nt35596_on(ctx);
- if (ret < 0) {
- dev_err(dev, "Failed to initialize panel: %d\n", ret);
+ tm5p5_nt35596_on(&dsi_ctx);
+
+ if (dsi_ctx.accum_err) {
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
regulator_bulk_disable(ARRAY_SIZE(ctx->supplies),
ctx->supplies);
- return ret;
}
- return 0;
+ return dsi_ctx.accum_err;
}
static int tm5p5_nt35596_unprepare(struct drm_panel *panel)
{
struct tm5p5_nt35596 *ctx = to_tm5p5_nt35596(panel);
- struct device *dev = &ctx->dsi->dev;
- int ret;
+ struct mipi_dsi_multi_context dsi_ctx = {.dsi = ctx->dsi};
- ret = tm5p5_nt35596_off(ctx);
- if (ret < 0)
- dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
+ tm5p5_nt35596_off(&dsi_ctx);
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
regulator_bulk_disable(ARRAY_SIZE(ctx->supplies),
ctx->supplies);
- return 0;
+ return dsi_ctx.accum_err;
}
static const struct drm_display_mode tm5p5_nt35596_mode = {
diff --git a/drivers/gpu/drm/panel/panel-auo-a030jtn01.c b/drivers/gpu/drm/panel/panel-auo-a030jtn01.c
index 6c86ebf2cad7..77604d6a4e72 100644
--- a/drivers/gpu/drm/panel/panel-auo-a030jtn01.c
+++ b/drivers/gpu/drm/panel/panel-auo-a030jtn01.c
@@ -305,4 +305,5 @@ module_spi_driver(a030jtn01_driver);
MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
MODULE_AUTHOR("Christophe Branchereau <cbranchereau@gmail.com>");
+MODULE_DESCRIPTION("AU Optronics A030JTN01.0 TFT LCD panel driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/panel/panel-boe-himax8279d.c b/drivers/gpu/drm/panel/panel-boe-himax8279d.c
index e225840b0d67..df746baae301 100644
--- a/drivers/gpu/drm/panel/panel-boe-himax8279d.c
+++ b/drivers/gpu/drm/panel/panel-boe-himax8279d.c
@@ -47,9 +47,6 @@ struct panel_info {
struct gpio_desc *enable_gpio;
struct gpio_desc *pp33_gpio;
struct gpio_desc *pp18_gpio;
-
- bool prepared;
- bool enabled;
};
static inline struct panel_info *to_panel_info(struct drm_panel *panel)
@@ -86,17 +83,12 @@ static int boe_panel_disable(struct drm_panel *panel)
struct panel_info *pinfo = to_panel_info(panel);
int err;
- if (!pinfo->enabled)
- return 0;
-
err = mipi_dsi_dcs_set_display_off(pinfo->link);
if (err < 0) {
dev_err(panel->dev, "failed to set display off: %d\n", err);
return err;
}
- pinfo->enabled = false;
-
return 0;
}
@@ -105,9 +97,6 @@ static int boe_panel_unprepare(struct drm_panel *panel)
struct panel_info *pinfo = to_panel_info(panel);
int err;
- if (!pinfo->prepared)
- return 0;
-
err = mipi_dsi_dcs_set_display_off(pinfo->link);
if (err < 0)
dev_err(panel->dev, "failed to set display off: %d\n", err);
@@ -121,8 +110,6 @@ static int boe_panel_unprepare(struct drm_panel *panel)
disable_gpios(pinfo);
- pinfo->prepared = false;
-
return 0;
}
@@ -131,9 +118,6 @@ static int boe_panel_prepare(struct drm_panel *panel)
struct panel_info *pinfo = to_panel_info(panel);
int err;
- if (pinfo->prepared)
- return 0;
-
gpiod_set_value(pinfo->pp18_gpio, 1);
/* T1: 5ms - 6ms */
usleep_range(5000, 6000);
@@ -180,8 +164,6 @@ static int boe_panel_prepare(struct drm_panel *panel)
/* T7: 20ms - 21ms */
usleep_range(20000, 21000);
- pinfo->prepared = true;
-
return 0;
poweroff:
@@ -194,9 +176,6 @@ static int boe_panel_enable(struct drm_panel *panel)
struct panel_info *pinfo = to_panel_info(panel);
int ret;
- if (pinfo->enabled)
- return 0;
-
usleep_range(120000, 121000);
ret = mipi_dsi_dcs_set_display_on(pinfo->link);
@@ -205,8 +184,6 @@ static int boe_panel_enable(struct drm_panel *panel)
return ret;
}
- pinfo->enabled = true;
-
return 0;
}
@@ -917,14 +894,6 @@ static void panel_remove(struct mipi_dsi_device *dsi)
struct panel_info *pinfo = mipi_dsi_get_drvdata(dsi);
int err;
- err = boe_panel_disable(&pinfo->base);
- if (err < 0)
- dev_err(&dsi->dev, "failed to disable panel: %d\n", err);
-
- err = boe_panel_unprepare(&pinfo->base);
- if (err < 0)
- dev_err(&dsi->dev, "failed to unprepare panel: %d\n", err);
-
err = mipi_dsi_detach(dsi);
if (err < 0)
dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err);
@@ -932,14 +901,6 @@ static void panel_remove(struct mipi_dsi_device *dsi)
drm_panel_remove(&pinfo->base);
}
-static void panel_shutdown(struct mipi_dsi_device *dsi)
-{
- struct panel_info *pinfo = mipi_dsi_get_drvdata(dsi);
-
- boe_panel_disable(&pinfo->base);
- boe_panel_unprepare(&pinfo->base);
-}
-
static struct mipi_dsi_driver panel_driver = {
.driver = {
.name = "panel-boe-himax8279d",
@@ -947,7 +908,6 @@ static struct mipi_dsi_driver panel_driver = {
},
.probe = panel_probe,
.remove = panel_remove,
- .shutdown = panel_shutdown,
};
module_mipi_dsi_driver(panel_driver);
diff --git a/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c b/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c
index 0ffe8f8c01de..ce919a980875 100644
--- a/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c
+++ b/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c
@@ -17,6 +17,8 @@
#include <video/mipi_display.h>
+struct boe_panel;
+
struct panel_desc {
const struct drm_display_mode *modes;
unsigned int bpc;
@@ -32,7 +34,7 @@ struct panel_desc {
unsigned long mode_flags;
enum mipi_dsi_pixel_format format;
- const struct panel_init_cmd *init_cmds;
+ int (*init)(struct boe_panel *boe);
unsigned int lanes;
bool discharge_on_disable;
bool lp11_before_reset;
@@ -50,1409 +52,1351 @@ struct boe_panel {
struct regulator *avee;
struct regulator *avdd;
struct gpio_desc *enable_gpio;
-
- bool prepared;
};
-enum dsi_cmd_type {
- INIT_DCS_CMD,
- DELAY_CMD,
-};
+static int boe_tv110c9m_init(struct boe_panel *boe)
+{
+ struct mipi_dsi_multi_context ctx = { .dsi = boe->dsi };
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x20);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x05, 0xd9);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x78);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x08, 0x5a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0d, 0x63);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0e, 0x91);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0f, 0x73);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x95, 0xe6);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x96, 0xf0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x30, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x6d, 0x66);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x75, 0xa2);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x77, 0x3b);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x00, 0x08, 0x00, 0x23, 0x00, 0x4d, 0x00, 0x6d,
+ 0x00, 0x89, 0x00, 0xa1, 0x00, 0xb6, 0x00, 0xc9);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0x00, 0xda, 0x01, 0x13, 0x01, 0x3c, 0x01, 0x7e,
+ 0x01, 0xab, 0x01, 0xf7, 0x02, 0x2f, 0x02, 0x31);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb2, 0x02, 0x67, 0x02, 0xa6, 0x02, 0xd1, 0x03, 0x08,
+ 0x03, 0x2e, 0x03, 0x5b, 0x03, 0x6b, 0x03, 0x7b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb3, 0x03, 0x8e, 0x03, 0xa2, 0x03, 0xb7, 0x03, 0xe7,
+ 0x03, 0xfd, 0x03, 0xff);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb4, 0x00, 0x08, 0x00, 0x23, 0x00, 0x4d, 0x00, 0x6d,
+ 0x00, 0x89, 0x00, 0xa1, 0x00, 0xb6, 0x00, 0xc9);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb5, 0x00, 0xda, 0x01, 0x13, 0x01, 0x3c, 0x01, 0x7e,
+ 0x01, 0xab, 0x01, 0xf7, 0x02, 0x2f, 0x02, 0x31);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x02, 0x67, 0x02, 0xa6, 0x02, 0xd1, 0x03, 0x08,
+ 0x03, 0x2e, 0x03, 0x5b, 0x03, 0x6b, 0x03, 0x7b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb7, 0x03, 0x8e, 0x03, 0xa2, 0x03, 0xb7, 0x03, 0xe7,
+ 0x03, 0xfd, 0x03, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0x00, 0x08, 0x00, 0x23, 0x00, 0x4d, 0x00, 0x6d,
+ 0x00, 0x89, 0x00, 0xa1, 0x00, 0xb6, 0x00, 0xc9);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0x00, 0xda, 0x01, 0x13, 0x01, 0x3c, 0x01, 0x7e,
+ 0x01, 0xab, 0x01, 0xf7, 0x02, 0x2f, 0x02, 0x31);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x02, 0x67, 0x02, 0xa6, 0x02, 0xd1, 0x03, 0x08,
+ 0x03, 0x2e, 0x03, 0x5b, 0x03, 0x6b, 0x03, 0x7b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbb, 0x03, 0x8e, 0x03, 0xa2, 0x03, 0xb7, 0x03, 0xe7,
+ 0x03, 0xfd, 0x03, 0xff);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x21);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x45, 0x00, 0x65,
+ 0x00, 0x81, 0x00, 0x99, 0x00, 0xae, 0x00, 0xc1);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0x00, 0xd2, 0x01, 0x0b, 0x01, 0x34, 0x01, 0x76,
+ 0x01, 0xa3, 0x01, 0xef, 0x02, 0x27, 0x02, 0x29);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb2, 0x02, 0x5f, 0x02, 0x9e, 0x02, 0xc9, 0x03, 0x00,
+ 0x03, 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb3, 0x03, 0x86, 0x03, 0x9a, 0x03, 0xaf, 0x03, 0xdf,
+ 0x03, 0xf5, 0x03, 0xe0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb4, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x45, 0x00, 0x65,
+ 0x00, 0x81, 0x00, 0x99, 0x00, 0xae, 0x00, 0xc1);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb5, 0x00, 0xd2, 0x01, 0x0b, 0x01, 0x34, 0x01, 0x76,
+ 0x01, 0xa3, 0x01, 0xef, 0x02, 0x27, 0x02, 0x29);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x02, 0x5f, 0x02, 0x9e, 0x02, 0xc9, 0x03, 0x00,
+ 0x03, 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb7, 0x03, 0x86, 0x03, 0x9a, 0x03, 0xaf, 0x03, 0xdf,
+ 0x03, 0xf5, 0x03, 0xe0);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x45, 0x00, 0x65,
+ 0x00, 0x81, 0x00, 0x99, 0x00, 0xae, 0x00, 0xc1);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0x00, 0xd2, 0x01, 0x0b, 0x01, 0x34, 0x01, 0x76,
+ 0x01, 0xa3, 0x01, 0xef, 0x02, 0x27, 0x02, 0x29);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x02, 0x5f, 0x02, 0x9e, 0x02, 0xc9, 0x03, 0x00,
+ 0x03, 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbb, 0x03, 0x86, 0x03, 0x9a, 0x03, 0xaf, 0x03, 0xdf,
+ 0x03, 0xf5, 0x03, 0xe0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x24);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x01, 0x00);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x02, 0x1c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x03, 0x1c);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x04, 0x1d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x05, 0x1d);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x06, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x04);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x08, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x09, 0x0f);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0a, 0x0e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0b, 0x0e);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0c, 0x0d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0d, 0x0d);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0e, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0f, 0x0c);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x10, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x11, 0x08);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x12, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x13, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x14, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x15, 0x00);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x16, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x17, 0x00);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x18, 0x1c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x19, 0x1c);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1a, 0x1d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1b, 0x1d);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1c, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1d, 0x04);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1e, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1f, 0x0f);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x20, 0x0e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x21, 0x0e);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x22, 0x0d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x23, 0x0d);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x24, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x25, 0x0c);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x26, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x27, 0x08);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x28, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x29, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2a, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2b, 0x00);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2d, 0x20);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2f, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x30, 0x44);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x33, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x34, 0x32);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x37, 0x44);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x38, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x39, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3a, 0x5d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3b, 0x60);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3d, 0x42);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3f, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x43, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x47, 0x66);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x4a, 0x5d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x4b, 0x60);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x4c, 0x91);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x4d, 0x21);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x4e, 0x43);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x51, 0x12);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x52, 0x34);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x55, 0x82, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x56, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x58, 0x21);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x59, 0x30);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5a, 0x60);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5b, 0x50);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5e, 0x00, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5f, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x65, 0x82);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x7e, 0x20);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x7f, 0x3c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x82, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x97, 0xc0);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x05, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x05, 0x05, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x91, 0x44);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x92, 0xa9);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x93, 0x1a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x94, 0x96);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd7, 0x55);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xda, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xde, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdb, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdc, 0xa9);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdd, 0x22);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdf, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe0, 0xa9);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe1, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe2, 0xa9);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe3, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe4, 0xa9);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe5, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe6, 0xa9);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5c, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5d, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x8d, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x8e, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb5, 0x90);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x25);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x05, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x19, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1f, 0x60);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x20, 0x50);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x26, 0x60);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x27, 0x50);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x33, 0x60);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x34, 0x50);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3f, 0xe0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x40, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x44, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x45, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x48, 0x60);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x49, 0x50);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5b, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5c, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5d, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5e, 0xd0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x61, 0x60);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x62, 0x50);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xf1, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x2a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x64, 0x16);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x67, 0x16);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x6a, 0x16);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x70, 0x30);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xa2, 0xf3);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xa3, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xa4, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xa5, 0xff);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd6, 0x08);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x26);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x00, 0xa1);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x02, 0x31);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x04, 0x28);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x06, 0x30);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0c, 0x16);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0d, 0x0d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0f, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x11, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x12, 0x50);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x13, 0x56);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x14, 0x57);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x15, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x16, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x17, 0xa0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x18, 0x86);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x19, 0x0d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1a, 0x7f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1b, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1c, 0xbf);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x22, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x23, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2a, 0x0d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2b, 0x7f);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1d, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1e, 0x65);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1f, 0x65);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x24, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x25, 0x65);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2f, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x30, 0x65);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x31, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x32, 0x7d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x39, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3a, 0x65);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x20, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x33, 0x11);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x34, 0x78);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x35, 0x16);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x9e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x4e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x00);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xa9, 0x49);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xaa, 0x4b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xab, 0x48);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xac, 0x43);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xad, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xae, 0x50);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xaf, 0x44);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x54);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0x4e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb2, 0x4d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb3, 0x4c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb4, 0x41);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb5, 0x47);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x53);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb7, 0x3e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0x51);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0x3c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x3b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbb, 0x46);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbc, 0x45);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbd, 0x55);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbe, 0x3d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbf, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x52);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc1, 0x4a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0x39);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0x4f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0x3a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0x42);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x27);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x56, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x58, 0x80);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x59, 0x75);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5a, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5b, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5c, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5d, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5e, 0x20);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5f, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x60, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x61, 0x2e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x62, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x63, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x64, 0x43);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x65, 0x2d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x66, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x67, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x68, 0x44);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x78, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0x00);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x2a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x22, 0x2f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x23, 0x08);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x24, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x25, 0x65);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x26, 0xf8);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x27, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x28, 0x1a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x29, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2a, 0x1a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2b, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2d, 0x1a);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x23);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x00, 0x80);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x00);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0xe0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x14, 0x60);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x16, 0xc0);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0xf0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3a, 0x08);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x20);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x18, 0x40);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x35, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x51, 0x00, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x53, 0x24);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x55, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbb, 0x13);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3b, 0x03, 0x96, 0x1a, 0x04, 0x04);
+
+ mipi_dsi_msleep(&ctx, 100);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x11);
+
+ mipi_dsi_msleep(&ctx, 200);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x29);
+
+ mipi_dsi_msleep(&ctx, 100);
-struct panel_init_cmd {
- enum dsi_cmd_type type;
- size_t len;
- const char *data;
+ return 0;
};
-#define _INIT_DCS_CMD(...) { \
- .type = INIT_DCS_CMD, \
- .len = sizeof((char[]){__VA_ARGS__}), \
- .data = (char[]){__VA_ARGS__} }
-
-#define _INIT_DELAY_CMD(...) { \
- .type = DELAY_CMD,\
- .len = sizeof((char[]){__VA_ARGS__}), \
- .data = (char[]){__VA_ARGS__} }
-
-static const struct panel_init_cmd boe_tv110c9m_init_cmd[] = {
- _INIT_DCS_CMD(0xFF, 0x20),
- _INIT_DCS_CMD(0xFB, 0x01),
- _INIT_DCS_CMD(0x05, 0xD9),
- _INIT_DCS_CMD(0x07, 0x78),
- _INIT_DCS_CMD(0x08, 0x5A),
- _INIT_DCS_CMD(0x0D, 0x63),
- _INIT_DCS_CMD(0x0E, 0x91),
- _INIT_DCS_CMD(0x0F, 0x73),
- _INIT_DCS_CMD(0x95, 0xE6),
- _INIT_DCS_CMD(0x96, 0xF0),
- _INIT_DCS_CMD(0x30, 0x00),
- _INIT_DCS_CMD(0x6D, 0x66),
- _INIT_DCS_CMD(0x75, 0xA2),
- _INIT_DCS_CMD(0x77, 0x3B),
+static int inx_hj110iz_init(struct boe_panel *boe)
+{
+ struct mipi_dsi_multi_context ctx = { .dsi = boe->dsi };
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x20);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x05, 0xd1);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x06, 0xc0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x87);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x08, 0x4b);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0d, 0x63);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0e, 0x91);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0f, 0x69);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x94, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x95, 0xf5);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x96, 0xf5);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x9d, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x9e, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x69, 0x98);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x75, 0xa2);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x77, 0xb3);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x58, 0x43);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x24);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x91, 0x44);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x92, 0x4c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x94, 0x86);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x60, 0x96);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x61, 0xd0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x63, 0x70);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0xca);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x00, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x01, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x02, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x03, 0x29);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x04, 0x22);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x05, 0x22);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x06, 0x0b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x1d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x08, 0x1c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x09, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0a, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0b, 0x09);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0c, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0d, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0e, 0x0d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0f, 0x0e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x10, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x11, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x12, 0x11);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x13, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x14, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x15, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x16, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x17, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x18, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x19, 0x29);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1a, 0x22);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1b, 0x22);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1c, 0x0b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1d, 0x1d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1e, 0x1c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1f, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x20, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x21, 0x09);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x22, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x23, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x24, 0x0d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x25, 0x0e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x26, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x27, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x28, 0x11);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x29, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2a, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2b, 0x03);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2f, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x30, 0x35);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x37, 0xa7);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x39, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3a, 0x46);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3b, 0x32);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3d, 0x12);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3f, 0x33);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x40, 0x31);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x41, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x42, 0x42);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x47, 0x77);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x48, 0x77);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x4a, 0x45);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x4b, 0x45);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x4c, 0x14);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x4d, 0x21);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x4e, 0x43);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x4f, 0x65);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x55, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x56, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x58, 0x21);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x59, 0x70);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5a, 0x46);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5b, 0x32);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5c, 0x88);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5e, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5f, 0x00);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x7a, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x7b, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x7c, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x7d, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x7e, 0x20);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x7f, 0x3c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x80, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x81, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x82, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x97, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0x10);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd7, 0x55);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd8, 0x55);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd9, 0x23);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xda, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdc, 0x65);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdd, 0x55);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xde, 0x27);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdf, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe0, 0x65);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe1, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe2, 0x65);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe3, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe4, 0x65);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe5, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe6, 0x65);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe7, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe8, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe9, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xea, 0x65);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xeb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xee, 0x65);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xef, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xf0, 0x65);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x05, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x05, 0x05, 0x00, 0x00);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x25);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x05, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xf1, 0x10);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1e, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1f, 0x46);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x20, 0x32);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x25, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x26, 0x46);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x27, 0x32);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3f, 0x80);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x40, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x43, 0x00);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x44, 0x46);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x45, 0x46);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x48, 0x46);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x49, 0x32);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5b, 0x80);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5c, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5d, 0x46);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5e, 0x32);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5f, 0x46);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x60, 0x32);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x61, 0x46);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x62, 0x32);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x68, 0x0c);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x6c, 0x0d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x6e, 0x0d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x78, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x79, 0xc5);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x7a, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x7b, 0xb0);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x26);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x00, 0xa1);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x02, 0x31);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0a, 0xf4);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x04, 0x50);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x06, 0x30);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0c, 0x16);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0d, 0x0d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0f, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x11, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x12, 0x50);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x13, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x14, 0x58);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x15, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x16, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x17, 0xa0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x18, 0x86);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x22, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x23, 0x00);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x19, 0x0e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1a, 0x31);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1b, 0x0d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1c, 0x29);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2a, 0x0e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2b, 0x31);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1d, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1e, 0x62);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1f, 0x62);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2f, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x30, 0x62);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x31, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x32, 0x7f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x33, 0x11);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x34, 0x89);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x35, 0x67);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x39, 0x0b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3a, 0x62);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3b, 0x06);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x89);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x4e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xa9, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xaa, 0x3e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xab, 0x3d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xac, 0x3c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xad, 0x3b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xae, 0x3a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xaf, 0x39);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x38);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x27);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd0, 0x11);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd1, 0x54);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xde, 0x43);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdf, 0x02);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x18);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc1, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x56, 0x06);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x58, 0x80);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x59, 0x78);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5a, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5b, 0x18);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5c, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5d, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5e, 0x20);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5f, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x60, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x61, 0x1c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x62, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x63, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x64, 0x44);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x65, 0x1b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x66, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x67, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x68, 0x44);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x98, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb4, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x9b, 0xbe);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xab, 0x14);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbc, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbd, 0x28);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x2a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x22, 0x2f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x23, 0x08);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x24, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x25, 0x62);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x26, 0xf8);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x27, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x28, 0x1a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x29, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2a, 0x1a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2b, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2d, 0x1a);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x64, 0x96);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x65, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x66, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x67, 0x96);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x68, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x69, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x6a, 0x96);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x6b, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x6c, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x70, 0x92);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x71, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x72, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x79, 0x96);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x7a, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x88, 0x96);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x89, 0x10);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xa2, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xa3, 0x30);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xa4, 0xc0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xa5, 0x03);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe8, 0x00);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x97, 0x3c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x98, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x99, 0x95);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x9a, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x9b, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x9c, 0x0b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x9d, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x9e, 0x90);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x25);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x13, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x14, 0xd7);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdb, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdc, 0xd7);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x17, 0xcf);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x19, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1b, 0x5b);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x20);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x24, 0x00, 0x38,
+ 0x00, 0x4c, 0x00, 0x5e, 0x00, 0x6f, 0x00, 0x7e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0x00, 0x8c, 0x00, 0xbe, 0x00, 0xe5, 0x01, 0x27,
+ 0x01, 0x58, 0x01, 0xa8, 0x01, 0xe8, 0x01, 0xea);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb2, 0x02, 0x28, 0x02, 0x71, 0x02, 0x9e, 0x02, 0xda,
+ 0x03, 0x00, 0x03, 0x31, 0x03, 0x40, 0x03, 0x51);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb3, 0x03, 0x62, 0x03, 0x75, 0x03, 0x89, 0x03, 0x9c,
+ 0x03, 0xaa, 0x03, 0xb2);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb4, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x27, 0x00, 0x3d,
+ 0x00, 0x52, 0x00, 0x64, 0x00, 0x75, 0x00, 0x84);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb5, 0x00, 0x93, 0x00, 0xc5, 0x00, 0xec, 0x01, 0x2c,
+ 0x01, 0x5d, 0x01, 0xac, 0x01, 0xec, 0x01, 0xee);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x02, 0x2b, 0x02, 0x73, 0x02, 0xa0, 0x02, 0xdb,
+ 0x03, 0x01, 0x03, 0x31, 0x03, 0x41, 0x03, 0x51);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb7, 0x03, 0x63, 0x03, 0x75, 0x03, 0x89, 0x03, 0x9c,
+ 0x03, 0xaa, 0x03, 0xb2);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x2a, 0x00, 0x40,
+ 0x00, 0x56, 0x00, 0x68, 0x00, 0x7a, 0x00, 0x89);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0x00, 0x98, 0x00, 0xc9, 0x00, 0xf1, 0x01, 0x30,
+ 0x01, 0x61, 0x01, 0xb0, 0x01, 0xef, 0x01, 0xf1);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x02, 0x2e, 0x02, 0x76, 0x02, 0xa3, 0x02, 0xdd,
+ 0x03, 0x02, 0x03, 0x32, 0x03, 0x42, 0x03, 0x53);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbb, 0x03, 0x66, 0x03, 0x75, 0x03, 0x89, 0x03, 0x9c,
+ 0x03, 0xaa, 0x03, 0xb2);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x21);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x24, 0x00, 0x38,
+ 0x00, 0x4c, 0x00, 0x5e, 0x00, 0x6f, 0x00, 0x7e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0x00, 0x8c, 0x00, 0xbe, 0x00, 0xe5, 0x01, 0x27,
+ 0x01, 0x58, 0x01, 0xa8, 0x01, 0xe8, 0x01, 0xea);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb2, 0x02, 0x28, 0x02, 0x71, 0x02, 0x9e, 0x02, 0xda,
+ 0x03, 0x00, 0x03, 0x31, 0x03, 0x40, 0x03, 0x51);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb3, 0x03, 0x62, 0x03, 0x77, 0x03, 0x90, 0x03, 0xac,
+ 0x03, 0xca, 0x03, 0xda);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb4, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x27, 0x00, 0x3d,
+ 0x00, 0x52, 0x00, 0x64, 0x00, 0x75, 0x00, 0x84);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb5, 0x00, 0x93, 0x00, 0xc5, 0x00, 0xec, 0x01, 0x2c,
+ 0x01, 0x5d, 0x01, 0xac, 0x01, 0xec, 0x01, 0xee);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x02, 0x2b, 0x02, 0x73, 0x02, 0xa0, 0x02, 0xdb,
+ 0x03, 0x01, 0x03, 0x31, 0x03, 0x41, 0x03, 0x51);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb7, 0x03, 0x63, 0x03, 0x77, 0x03, 0x90, 0x03, 0xac,
+ 0x03, 0xca, 0x03, 0xda);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x2a, 0x00, 0x40,
+ 0x00, 0x56, 0x00, 0x68, 0x00, 0x7a, 0x00, 0x89);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0x00, 0x98, 0x00, 0xc9, 0x00, 0xf1, 0x01, 0x30,
+ 0x01, 0x61, 0x01, 0xb0, 0x01, 0xef, 0x01, 0xf1);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x02, 0x2e, 0x02, 0x76, 0x02, 0xa3, 0x02, 0xdd,
+ 0x03, 0x02, 0x03, 0x32, 0x03, 0x42, 0x03, 0x53);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbb, 0x03, 0x66, 0x03, 0x77, 0x03, 0x90, 0x03, 0xac,
+ 0x03, 0xca, 0x03, 0xda);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0xf0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3a, 0x08);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0x01);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x20);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x18, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x10);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x10);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x35, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3b, 0x03, 0xae, 0x1a, 0x04, 0x04);
+
+ mipi_dsi_msleep(&ctx, 100);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x11);
+
+ mipi_dsi_msleep(&ctx, 200);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x29);
+
+ mipi_dsi_msleep(&ctx, 100);
- _INIT_DCS_CMD(0xB0, 0x00, 0x08, 0x00, 0x23, 0x00, 0x4D, 0x00, 0x6D, 0x00, 0x89, 0x00, 0xA1, 0x00, 0xB6, 0x00, 0xC9),
- _INIT_DCS_CMD(0xB1, 0x00, 0xDA, 0x01, 0x13, 0x01, 0x3C, 0x01, 0x7E, 0x01, 0xAB, 0x01, 0xF7, 0x02, 0x2F, 0x02, 0x31),
- _INIT_DCS_CMD(0xB2, 0x02, 0x67, 0x02, 0xA6, 0x02, 0xD1, 0x03, 0x08, 0x03, 0x2E, 0x03, 0x5B, 0x03, 0x6B, 0x03, 0x7B),
- _INIT_DCS_CMD(0xB3, 0x03, 0x8E, 0x03, 0xA2, 0x03, 0xB7, 0x03, 0xE7, 0x03, 0xFD, 0x03, 0xFF),
-
- _INIT_DCS_CMD(0xB4, 0x00, 0x08, 0x00, 0x23, 0x00, 0x4D, 0x00, 0x6D, 0x00, 0x89, 0x00, 0xA1, 0x00, 0xB6, 0x00, 0xC9),
- _INIT_DCS_CMD(0xB5, 0x00, 0xDA, 0x01, 0x13, 0x01, 0x3C, 0x01, 0x7E, 0x01, 0xAB, 0x01, 0xF7, 0x02, 0x2F, 0x02, 0x31),
- _INIT_DCS_CMD(0xB6, 0x02, 0x67, 0x02, 0xA6, 0x02, 0xD1, 0x03, 0x08, 0x03, 0x2E, 0x03, 0x5B, 0x03, 0x6B, 0x03, 0x7B),
- _INIT_DCS_CMD(0xB7, 0x03, 0x8E, 0x03, 0xA2, 0x03, 0xB7, 0x03, 0xE7, 0x03, 0xFD, 0x03, 0xFF),
- _INIT_DCS_CMD(0xB8, 0x00, 0x08, 0x00, 0x23, 0x00, 0x4D, 0x00, 0x6D, 0x00, 0x89, 0x00, 0xA1, 0x00, 0xB6, 0x00, 0xC9),
- _INIT_DCS_CMD(0xB9, 0x00, 0xDA, 0x01, 0x13, 0x01, 0x3C, 0x01, 0x7E, 0x01, 0xAB, 0x01, 0xF7, 0x02, 0x2F, 0x02, 0x31),
- _INIT_DCS_CMD(0xBA, 0x02, 0x67, 0x02, 0xA6, 0x02, 0xD1, 0x03, 0x08, 0x03, 0x2E, 0x03, 0x5B, 0x03, 0x6B, 0x03, 0x7B),
- _INIT_DCS_CMD(0xBB, 0x03, 0x8E, 0x03, 0xA2, 0x03, 0xB7, 0x03, 0xE7, 0x03, 0xFD, 0x03, 0xFF),
-
- _INIT_DCS_CMD(0xFF, 0x21),
- _INIT_DCS_CMD(0xFB, 0x01),
-
- _INIT_DCS_CMD(0xB0, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x45, 0x00, 0x65, 0x00, 0x81, 0x00, 0x99, 0x00, 0xAE, 0x00, 0xC1),
- _INIT_DCS_CMD(0xB1, 0x00, 0xD2, 0x01, 0x0B, 0x01, 0x34, 0x01, 0x76, 0x01, 0xA3, 0x01, 0xEF, 0x02, 0x27, 0x02, 0x29),
- _INIT_DCS_CMD(0xB2, 0x02, 0x5F, 0x02, 0x9E, 0x02, 0xC9, 0x03, 0x00, 0x03, 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73),
-
- _INIT_DCS_CMD(0xB3, 0x03, 0x86, 0x03, 0x9A, 0x03, 0xAF, 0x03, 0xDF, 0x03, 0xF5, 0x03, 0xE0),
- _INIT_DCS_CMD(0xB4, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x45, 0x00, 0x65, 0x00, 0x81, 0x00, 0x99, 0x00, 0xAE, 0x00, 0xC1),
- _INIT_DCS_CMD(0xB5, 0x00, 0xD2, 0x01, 0x0B, 0x01, 0x34, 0x01, 0x76, 0x01, 0xA3, 0x01, 0xEF, 0x02, 0x27, 0x02, 0x29),
- _INIT_DCS_CMD(0xB6, 0x02, 0x5F, 0x02, 0x9E, 0x02, 0xC9, 0x03, 0x00, 0x03, 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73),
- _INIT_DCS_CMD(0xB7, 0x03, 0x86, 0x03, 0x9A, 0x03, 0xAF, 0x03, 0xDF, 0x03, 0xF5, 0x03, 0xE0),
-
- _INIT_DCS_CMD(0xB8, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x45, 0x00, 0x65, 0x00, 0x81, 0x00, 0x99, 0x00, 0xAE, 0x00, 0xC1),
- _INIT_DCS_CMD(0xB9, 0x00, 0xD2, 0x01, 0x0B, 0x01, 0x34, 0x01, 0x76, 0x01, 0xA3, 0x01, 0xEF, 0x02, 0x27, 0x02, 0x29),
- _INIT_DCS_CMD(0xBA, 0x02, 0x5F, 0x02, 0x9E, 0x02, 0xC9, 0x03, 0x00, 0x03, 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73),
-
- _INIT_DCS_CMD(0xBB, 0x03, 0x86, 0x03, 0x9A, 0x03, 0xAF, 0x03, 0xDF, 0x03, 0xF5, 0x03, 0xE0),
- _INIT_DCS_CMD(0xFF, 0x24),
- _INIT_DCS_CMD(0xFB, 0x01),
-
- _INIT_DCS_CMD(0x00, 0x00),
- _INIT_DCS_CMD(0x01, 0x00),
-
- _INIT_DCS_CMD(0x02, 0x1C),
- _INIT_DCS_CMD(0x03, 0x1C),
-
- _INIT_DCS_CMD(0x04, 0x1D),
- _INIT_DCS_CMD(0x05, 0x1D),
-
- _INIT_DCS_CMD(0x06, 0x04),
- _INIT_DCS_CMD(0x07, 0x04),
-
- _INIT_DCS_CMD(0x08, 0x0F),
- _INIT_DCS_CMD(0x09, 0x0F),
-
- _INIT_DCS_CMD(0x0A, 0x0E),
- _INIT_DCS_CMD(0x0B, 0x0E),
-
- _INIT_DCS_CMD(0x0C, 0x0D),
- _INIT_DCS_CMD(0x0D, 0x0D),
-
- _INIT_DCS_CMD(0x0E, 0x0C),
- _INIT_DCS_CMD(0x0F, 0x0C),
-
- _INIT_DCS_CMD(0x10, 0x08),
- _INIT_DCS_CMD(0x11, 0x08),
-
- _INIT_DCS_CMD(0x12, 0x00),
- _INIT_DCS_CMD(0x13, 0x00),
- _INIT_DCS_CMD(0x14, 0x00),
- _INIT_DCS_CMD(0x15, 0x00),
-
- _INIT_DCS_CMD(0x16, 0x00),
- _INIT_DCS_CMD(0x17, 0x00),
-
- _INIT_DCS_CMD(0x18, 0x1C),
- _INIT_DCS_CMD(0x19, 0x1C),
-
- _INIT_DCS_CMD(0x1A, 0x1D),
- _INIT_DCS_CMD(0x1B, 0x1D),
-
- _INIT_DCS_CMD(0x1C, 0x04),
- _INIT_DCS_CMD(0x1D, 0x04),
-
- _INIT_DCS_CMD(0x1E, 0x0F),
- _INIT_DCS_CMD(0x1F, 0x0F),
-
- _INIT_DCS_CMD(0x20, 0x0E),
- _INIT_DCS_CMD(0x21, 0x0E),
-
- _INIT_DCS_CMD(0x22, 0x0D),
- _INIT_DCS_CMD(0x23, 0x0D),
-
- _INIT_DCS_CMD(0x24, 0x0C),
- _INIT_DCS_CMD(0x25, 0x0C),
-
- _INIT_DCS_CMD(0x26, 0x08),
- _INIT_DCS_CMD(0x27, 0x08),
-
- _INIT_DCS_CMD(0x28, 0x00),
- _INIT_DCS_CMD(0x29, 0x00),
- _INIT_DCS_CMD(0x2A, 0x00),
- _INIT_DCS_CMD(0x2B, 0x00),
-
- _INIT_DCS_CMD(0x2D, 0x20),
- _INIT_DCS_CMD(0x2F, 0x0A),
- _INIT_DCS_CMD(0x30, 0x44),
- _INIT_DCS_CMD(0x33, 0x0C),
- _INIT_DCS_CMD(0x34, 0x32),
-
- _INIT_DCS_CMD(0x37, 0x44),
- _INIT_DCS_CMD(0x38, 0x40),
- _INIT_DCS_CMD(0x39, 0x00),
- _INIT_DCS_CMD(0x3A, 0x5D),
- _INIT_DCS_CMD(0x3B, 0x60),
- _INIT_DCS_CMD(0x3D, 0x42),
- _INIT_DCS_CMD(0x3F, 0x06),
- _INIT_DCS_CMD(0x43, 0x06),
- _INIT_DCS_CMD(0x47, 0x66),
- _INIT_DCS_CMD(0x4A, 0x5D),
- _INIT_DCS_CMD(0x4B, 0x60),
- _INIT_DCS_CMD(0x4C, 0x91),
- _INIT_DCS_CMD(0x4D, 0x21),
- _INIT_DCS_CMD(0x4E, 0x43),
- _INIT_DCS_CMD(0x51, 0x12),
- _INIT_DCS_CMD(0x52, 0x34),
- _INIT_DCS_CMD(0x55, 0x82, 0x02),
- _INIT_DCS_CMD(0x56, 0x04),
- _INIT_DCS_CMD(0x58, 0x21),
- _INIT_DCS_CMD(0x59, 0x30),
- _INIT_DCS_CMD(0x5A, 0x60),
- _INIT_DCS_CMD(0x5B, 0x50),
- _INIT_DCS_CMD(0x5E, 0x00, 0x06),
- _INIT_DCS_CMD(0x5F, 0x00),
- _INIT_DCS_CMD(0x65, 0x82),
- _INIT_DCS_CMD(0x7E, 0x20),
- _INIT_DCS_CMD(0x7F, 0x3C),
- _INIT_DCS_CMD(0x82, 0x04),
- _INIT_DCS_CMD(0x97, 0xC0),
-
- _INIT_DCS_CMD(0xB6, 0x05, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x05, 0x00, 0x00),
- _INIT_DCS_CMD(0x91, 0x44),
- _INIT_DCS_CMD(0x92, 0xA9),
- _INIT_DCS_CMD(0x93, 0x1A),
- _INIT_DCS_CMD(0x94, 0x96),
- _INIT_DCS_CMD(0xD7, 0x55),
- _INIT_DCS_CMD(0xDA, 0x0A),
- _INIT_DCS_CMD(0xDE, 0x08),
- _INIT_DCS_CMD(0xDB, 0x05),
- _INIT_DCS_CMD(0xDC, 0xA9),
- _INIT_DCS_CMD(0xDD, 0x22),
-
- _INIT_DCS_CMD(0xDF, 0x05),
- _INIT_DCS_CMD(0xE0, 0xA9),
- _INIT_DCS_CMD(0xE1, 0x05),
- _INIT_DCS_CMD(0xE2, 0xA9),
- _INIT_DCS_CMD(0xE3, 0x05),
- _INIT_DCS_CMD(0xE4, 0xA9),
- _INIT_DCS_CMD(0xE5, 0x05),
- _INIT_DCS_CMD(0xE6, 0xA9),
- _INIT_DCS_CMD(0x5C, 0x00),
- _INIT_DCS_CMD(0x5D, 0x00),
- _INIT_DCS_CMD(0x8D, 0x00),
- _INIT_DCS_CMD(0x8E, 0x00),
- _INIT_DCS_CMD(0xB5, 0x90),
- _INIT_DCS_CMD(0xFF, 0x25),
- _INIT_DCS_CMD(0xFB, 0x01),
- _INIT_DCS_CMD(0x05, 0x00),
- _INIT_DCS_CMD(0x19, 0x07),
- _INIT_DCS_CMD(0x1F, 0x60),
- _INIT_DCS_CMD(0x20, 0x50),
- _INIT_DCS_CMD(0x26, 0x60),
- _INIT_DCS_CMD(0x27, 0x50),
- _INIT_DCS_CMD(0x33, 0x60),
- _INIT_DCS_CMD(0x34, 0x50),
- _INIT_DCS_CMD(0x3F, 0xE0),
- _INIT_DCS_CMD(0x40, 0x00),
- _INIT_DCS_CMD(0x44, 0x00),
- _INIT_DCS_CMD(0x45, 0x40),
- _INIT_DCS_CMD(0x48, 0x60),
- _INIT_DCS_CMD(0x49, 0x50),
- _INIT_DCS_CMD(0x5B, 0x00),
- _INIT_DCS_CMD(0x5C, 0x00),
- _INIT_DCS_CMD(0x5D, 0x00),
- _INIT_DCS_CMD(0x5E, 0xD0),
- _INIT_DCS_CMD(0x61, 0x60),
- _INIT_DCS_CMD(0x62, 0x50),
- _INIT_DCS_CMD(0xF1, 0x10),
- _INIT_DCS_CMD(0xFF, 0x2A),
- _INIT_DCS_CMD(0xFB, 0x01),
-
- _INIT_DCS_CMD(0x64, 0x16),
- _INIT_DCS_CMD(0x67, 0x16),
- _INIT_DCS_CMD(0x6A, 0x16),
-
- _INIT_DCS_CMD(0x70, 0x30),
-
- _INIT_DCS_CMD(0xA2, 0xF3),
- _INIT_DCS_CMD(0xA3, 0xFF),
- _INIT_DCS_CMD(0xA4, 0xFF),
- _INIT_DCS_CMD(0xA5, 0xFF),
-
- _INIT_DCS_CMD(0xD6, 0x08),
-
- _INIT_DCS_CMD(0xFF, 0x26),
- _INIT_DCS_CMD(0xFB, 0x01),
- _INIT_DCS_CMD(0x00, 0xA1),
-
- _INIT_DCS_CMD(0x02, 0x31),
- _INIT_DCS_CMD(0x04, 0x28),
- _INIT_DCS_CMD(0x06, 0x30),
- _INIT_DCS_CMD(0x0C, 0x16),
- _INIT_DCS_CMD(0x0D, 0x0D),
- _INIT_DCS_CMD(0x0F, 0x00),
- _INIT_DCS_CMD(0x11, 0x00),
- _INIT_DCS_CMD(0x12, 0x50),
- _INIT_DCS_CMD(0x13, 0x56),
- _INIT_DCS_CMD(0x14, 0x57),
- _INIT_DCS_CMD(0x15, 0x00),
- _INIT_DCS_CMD(0x16, 0x10),
- _INIT_DCS_CMD(0x17, 0xA0),
- _INIT_DCS_CMD(0x18, 0x86),
- _INIT_DCS_CMD(0x19, 0x0D),
- _INIT_DCS_CMD(0x1A, 0x7F),
- _INIT_DCS_CMD(0x1B, 0x0C),
- _INIT_DCS_CMD(0x1C, 0xBF),
- _INIT_DCS_CMD(0x22, 0x00),
- _INIT_DCS_CMD(0x23, 0x00),
- _INIT_DCS_CMD(0x2A, 0x0D),
- _INIT_DCS_CMD(0x2B, 0x7F),
-
- _INIT_DCS_CMD(0x1D, 0x00),
- _INIT_DCS_CMD(0x1E, 0x65),
- _INIT_DCS_CMD(0x1F, 0x65),
- _INIT_DCS_CMD(0x24, 0x00),
- _INIT_DCS_CMD(0x25, 0x65),
- _INIT_DCS_CMD(0x2F, 0x05),
- _INIT_DCS_CMD(0x30, 0x65),
- _INIT_DCS_CMD(0x31, 0x05),
- _INIT_DCS_CMD(0x32, 0x7D),
- _INIT_DCS_CMD(0x39, 0x00),
- _INIT_DCS_CMD(0x3A, 0x65),
- _INIT_DCS_CMD(0x20, 0x01),
- _INIT_DCS_CMD(0x33, 0x11),
- _INIT_DCS_CMD(0x34, 0x78),
- _INIT_DCS_CMD(0x35, 0x16),
- _INIT_DCS_CMD(0xC8, 0x04),
- _INIT_DCS_CMD(0xC9, 0x9E),
- _INIT_DCS_CMD(0xCA, 0x4E),
- _INIT_DCS_CMD(0xCB, 0x00),
-
- _INIT_DCS_CMD(0xA9, 0x49),
- _INIT_DCS_CMD(0xAA, 0x4B),
- _INIT_DCS_CMD(0xAB, 0x48),
- _INIT_DCS_CMD(0xAC, 0x43),
- _INIT_DCS_CMD(0xAD, 0x40),
- _INIT_DCS_CMD(0xAE, 0x50),
- _INIT_DCS_CMD(0xAF, 0x44),
- _INIT_DCS_CMD(0xB0, 0x54),
- _INIT_DCS_CMD(0xB1, 0x4E),
- _INIT_DCS_CMD(0xB2, 0x4D),
- _INIT_DCS_CMD(0xB3, 0x4C),
- _INIT_DCS_CMD(0xB4, 0x41),
- _INIT_DCS_CMD(0xB5, 0x47),
- _INIT_DCS_CMD(0xB6, 0x53),
- _INIT_DCS_CMD(0xB7, 0x3E),
- _INIT_DCS_CMD(0xB8, 0x51),
- _INIT_DCS_CMD(0xB9, 0x3C),
- _INIT_DCS_CMD(0xBA, 0x3B),
- _INIT_DCS_CMD(0xBB, 0x46),
- _INIT_DCS_CMD(0xBC, 0x45),
- _INIT_DCS_CMD(0xBD, 0x55),
- _INIT_DCS_CMD(0xBE, 0x3D),
- _INIT_DCS_CMD(0xBF, 0x3F),
- _INIT_DCS_CMD(0xC0, 0x52),
- _INIT_DCS_CMD(0xC1, 0x4A),
- _INIT_DCS_CMD(0xC2, 0x39),
- _INIT_DCS_CMD(0xC3, 0x4F),
- _INIT_DCS_CMD(0xC4, 0x3A),
- _INIT_DCS_CMD(0xC5, 0x42),
- _INIT_DCS_CMD(0xFF, 0x27),
- _INIT_DCS_CMD(0xFB, 0x01),
-
- _INIT_DCS_CMD(0x56, 0x06),
- _INIT_DCS_CMD(0x58, 0x80),
- _INIT_DCS_CMD(0x59, 0x75),
- _INIT_DCS_CMD(0x5A, 0x00),
- _INIT_DCS_CMD(0x5B, 0x02),
- _INIT_DCS_CMD(0x5C, 0x00),
- _INIT_DCS_CMD(0x5D, 0x00),
- _INIT_DCS_CMD(0x5E, 0x20),
- _INIT_DCS_CMD(0x5F, 0x10),
- _INIT_DCS_CMD(0x60, 0x00),
- _INIT_DCS_CMD(0x61, 0x2E),
- _INIT_DCS_CMD(0x62, 0x00),
- _INIT_DCS_CMD(0x63, 0x01),
- _INIT_DCS_CMD(0x64, 0x43),
- _INIT_DCS_CMD(0x65, 0x2D),
- _INIT_DCS_CMD(0x66, 0x00),
- _INIT_DCS_CMD(0x67, 0x01),
- _INIT_DCS_CMD(0x68, 0x44),
-
- _INIT_DCS_CMD(0x00, 0x00),
- _INIT_DCS_CMD(0x78, 0x00),
- _INIT_DCS_CMD(0xC3, 0x00),
-
- _INIT_DCS_CMD(0xFF, 0x2A),
- _INIT_DCS_CMD(0xFB, 0x01),
-
- _INIT_DCS_CMD(0x22, 0x2F),
- _INIT_DCS_CMD(0x23, 0x08),
-
- _INIT_DCS_CMD(0x24, 0x00),
- _INIT_DCS_CMD(0x25, 0x65),
- _INIT_DCS_CMD(0x26, 0xF8),
- _INIT_DCS_CMD(0x27, 0x00),
- _INIT_DCS_CMD(0x28, 0x1A),
- _INIT_DCS_CMD(0x29, 0x00),
- _INIT_DCS_CMD(0x2A, 0x1A),
- _INIT_DCS_CMD(0x2B, 0x00),
- _INIT_DCS_CMD(0x2D, 0x1A),
-
- _INIT_DCS_CMD(0xFF, 0x23),
- _INIT_DCS_CMD(0xFB, 0x01),
-
- _INIT_DCS_CMD(0x00, 0x80),
- _INIT_DCS_CMD(0x07, 0x00),
-
- _INIT_DCS_CMD(0xFF, 0xE0),
- _INIT_DCS_CMD(0xFB, 0x01),
- _INIT_DCS_CMD(0x14, 0x60),
- _INIT_DCS_CMD(0x16, 0xC0),
-
- _INIT_DCS_CMD(0xFF, 0xF0),
- _INIT_DCS_CMD(0xFB, 0x01),
- _INIT_DCS_CMD(0x3A, 0x08),
-
- _INIT_DCS_CMD(0xFF, 0x10),
- _INIT_DCS_CMD(0xFB, 0x01),
- _INIT_DCS_CMD(0xB9, 0x01),
- _INIT_DCS_CMD(0xFF, 0x20),
- _INIT_DCS_CMD(0xFB, 0x01),
- _INIT_DCS_CMD(0x18, 0x40),
-
- _INIT_DCS_CMD(0xFF, 0x10),
- _INIT_DCS_CMD(0xFB, 0x01),
- _INIT_DCS_CMD(0xB9, 0x02),
- _INIT_DCS_CMD(0x35, 0x00),
- _INIT_DCS_CMD(0x51, 0x00, 0xFF),
- _INIT_DCS_CMD(0x53, 0x24),
- _INIT_DCS_CMD(0x55, 0x00),
- _INIT_DCS_CMD(0xBB, 0x13),
- _INIT_DCS_CMD(0x3B, 0x03, 0x96, 0x1A, 0x04, 0x04),
- _INIT_DELAY_CMD(100),
- _INIT_DCS_CMD(0x11),
- _INIT_DELAY_CMD(200),
- _INIT_DCS_CMD(0x29),
- _INIT_DELAY_CMD(100),
- {},
+ return 0;
};
-static const struct panel_init_cmd inx_hj110iz_init_cmd[] = {
- _INIT_DCS_CMD(0xFF, 0x20),
- _INIT_DCS_CMD(0xFB, 0x01),
- _INIT_DCS_CMD(0x05, 0xD1),
- _INIT_DCS_CMD(0x06, 0xC0),
- _INIT_DCS_CMD(0x07, 0x87),
- _INIT_DCS_CMD(0x08, 0x4B),
-
- _INIT_DCS_CMD(0x0D, 0x63),
- _INIT_DCS_CMD(0x0E, 0x91),
- _INIT_DCS_CMD(0x0F, 0x69),
- _INIT_DCS_CMD(0x94, 0x00),
- _INIT_DCS_CMD(0x95, 0xF5),
- _INIT_DCS_CMD(0x96, 0xF5),
- _INIT_DCS_CMD(0x9D, 0x00),
- _INIT_DCS_CMD(0x9E, 0x00),
- _INIT_DCS_CMD(0x69, 0x98),
- _INIT_DCS_CMD(0x75, 0xA2),
- _INIT_DCS_CMD(0x77, 0xB3),
-
- _INIT_DCS_CMD(0x58, 0x43),
- _INIT_DCS_CMD(0xFF, 0x24),
- _INIT_DCS_CMD(0xFB, 0x01),
- _INIT_DCS_CMD(0x91, 0x44),
- _INIT_DCS_CMD(0x92, 0x4C),
- _INIT_DCS_CMD(0x94, 0x86),
- _INIT_DCS_CMD(0x60, 0x96),
- _INIT_DCS_CMD(0x61, 0xD0),
- _INIT_DCS_CMD(0x63, 0x70),
- _INIT_DCS_CMD(0xC2, 0xCA),
-
- _INIT_DCS_CMD(0x00, 0x03),
- _INIT_DCS_CMD(0x01, 0x03),
- _INIT_DCS_CMD(0x02, 0x03),
- _INIT_DCS_CMD(0x03, 0x29),
- _INIT_DCS_CMD(0x04, 0x22),
- _INIT_DCS_CMD(0x05, 0x22),
- _INIT_DCS_CMD(0x06, 0x0B),
- _INIT_DCS_CMD(0x07, 0x1D),
- _INIT_DCS_CMD(0x08, 0x1C),
- _INIT_DCS_CMD(0x09, 0x05),
- _INIT_DCS_CMD(0x0A, 0x08),
- _INIT_DCS_CMD(0x0B, 0x09),
- _INIT_DCS_CMD(0x0C, 0x0A),
- _INIT_DCS_CMD(0x0D, 0x0C),
- _INIT_DCS_CMD(0x0E, 0x0D),
- _INIT_DCS_CMD(0x0F, 0x0E),
- _INIT_DCS_CMD(0x10, 0x0F),
- _INIT_DCS_CMD(0x11, 0x10),
- _INIT_DCS_CMD(0x12, 0x11),
- _INIT_DCS_CMD(0x13, 0x04),
- _INIT_DCS_CMD(0x14, 0x00),
- _INIT_DCS_CMD(0x15, 0x03),
- _INIT_DCS_CMD(0x16, 0x03),
- _INIT_DCS_CMD(0x17, 0x03),
- _INIT_DCS_CMD(0x18, 0x03),
- _INIT_DCS_CMD(0x19, 0x29),
- _INIT_DCS_CMD(0x1A, 0x22),
- _INIT_DCS_CMD(0x1B, 0x22),
- _INIT_DCS_CMD(0x1C, 0x0B),
- _INIT_DCS_CMD(0x1D, 0x1D),
- _INIT_DCS_CMD(0x1E, 0x1C),
- _INIT_DCS_CMD(0x1F, 0x05),
- _INIT_DCS_CMD(0x20, 0x08),
- _INIT_DCS_CMD(0x21, 0x09),
- _INIT_DCS_CMD(0x22, 0x0A),
- _INIT_DCS_CMD(0x23, 0x0C),
- _INIT_DCS_CMD(0x24, 0x0D),
- _INIT_DCS_CMD(0x25, 0x0E),
- _INIT_DCS_CMD(0x26, 0x0F),
- _INIT_DCS_CMD(0x27, 0x10),
- _INIT_DCS_CMD(0x28, 0x11),
- _INIT_DCS_CMD(0x29, 0x04),
- _INIT_DCS_CMD(0x2A, 0x00),
- _INIT_DCS_CMD(0x2B, 0x03),
-
- _INIT_DCS_CMD(0x2F, 0x0A),
- _INIT_DCS_CMD(0x30, 0x35),
- _INIT_DCS_CMD(0x37, 0xA7),
- _INIT_DCS_CMD(0x39, 0x00),
- _INIT_DCS_CMD(0x3A, 0x46),
- _INIT_DCS_CMD(0x3B, 0x32),
- _INIT_DCS_CMD(0x3D, 0x12),
-
- _INIT_DCS_CMD(0x3F, 0x33),
- _INIT_DCS_CMD(0x40, 0x31),
- _INIT_DCS_CMD(0x41, 0x40),
- _INIT_DCS_CMD(0x42, 0x42),
- _INIT_DCS_CMD(0x47, 0x77),
- _INIT_DCS_CMD(0x48, 0x77),
- _INIT_DCS_CMD(0x4A, 0x45),
- _INIT_DCS_CMD(0x4B, 0x45),
- _INIT_DCS_CMD(0x4C, 0x14),
-
- _INIT_DCS_CMD(0x4D, 0x21),
- _INIT_DCS_CMD(0x4E, 0x43),
- _INIT_DCS_CMD(0x4F, 0x65),
- _INIT_DCS_CMD(0x55, 0x06),
- _INIT_DCS_CMD(0x56, 0x06),
- _INIT_DCS_CMD(0x58, 0x21),
- _INIT_DCS_CMD(0x59, 0x70),
- _INIT_DCS_CMD(0x5A, 0x46),
- _INIT_DCS_CMD(0x5B, 0x32),
- _INIT_DCS_CMD(0x5C, 0x88),
- _INIT_DCS_CMD(0x5E, 0x00, 0x00),
- _INIT_DCS_CMD(0x5F, 0x00),
-
- _INIT_DCS_CMD(0x7A, 0xFF),
- _INIT_DCS_CMD(0x7B, 0xFF),
- _INIT_DCS_CMD(0x7C, 0x00),
- _INIT_DCS_CMD(0x7D, 0x00),
- _INIT_DCS_CMD(0x7E, 0x20),
- _INIT_DCS_CMD(0x7F, 0x3C),
- _INIT_DCS_CMD(0x80, 0x00),
- _INIT_DCS_CMD(0x81, 0x00),
- _INIT_DCS_CMD(0x82, 0x08),
- _INIT_DCS_CMD(0x97, 0x02),
- _INIT_DCS_CMD(0xC5, 0x10),
-
- _INIT_DCS_CMD(0xD7, 0x55),
- _INIT_DCS_CMD(0xD8, 0x55),
- _INIT_DCS_CMD(0xD9, 0x23),
- _INIT_DCS_CMD(0xDA, 0x05),
- _INIT_DCS_CMD(0xDB, 0x01),
- _INIT_DCS_CMD(0xDC, 0x65),
- _INIT_DCS_CMD(0xDD, 0x55),
- _INIT_DCS_CMD(0xDE, 0x27),
- _INIT_DCS_CMD(0xDF, 0x01),
- _INIT_DCS_CMD(0xE0, 0x65),
- _INIT_DCS_CMD(0xE1, 0x01),
- _INIT_DCS_CMD(0xE2, 0x65),
- _INIT_DCS_CMD(0xE3, 0x01),
- _INIT_DCS_CMD(0xE4, 0x65),
- _INIT_DCS_CMD(0xE5, 0x01),
- _INIT_DCS_CMD(0xE6, 0x65),
- _INIT_DCS_CMD(0xE7, 0x00),
- _INIT_DCS_CMD(0xE8, 0x00),
- _INIT_DCS_CMD(0xE9, 0x01),
- _INIT_DCS_CMD(0xEA, 0x65),
- _INIT_DCS_CMD(0xEB, 0x01),
- _INIT_DCS_CMD(0xEE, 0x65),
- _INIT_DCS_CMD(0xEF, 0x01),
- _INIT_DCS_CMD(0xF0, 0x65),
- _INIT_DCS_CMD(0xB6, 0x05, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x05, 0x00, 0x00),
-
- _INIT_DCS_CMD(0xFF, 0x25),
-
- _INIT_DCS_CMD(0xFB, 0x01),
- _INIT_DCS_CMD(0x05, 0x00),
- _INIT_DCS_CMD(0xF1, 0x10),
-
- _INIT_DCS_CMD(0x1E, 0x00),
- _INIT_DCS_CMD(0x1F, 0x46),
- _INIT_DCS_CMD(0x20, 0x32),
-
- _INIT_DCS_CMD(0x25, 0x00),
- _INIT_DCS_CMD(0x26, 0x46),
- _INIT_DCS_CMD(0x27, 0x32),
-
- _INIT_DCS_CMD(0x3F, 0x80),
- _INIT_DCS_CMD(0x40, 0x00),
- _INIT_DCS_CMD(0x43, 0x00),
-
- _INIT_DCS_CMD(0x44, 0x46),
- _INIT_DCS_CMD(0x45, 0x46),
-
- _INIT_DCS_CMD(0x48, 0x46),
- _INIT_DCS_CMD(0x49, 0x32),
-
- _INIT_DCS_CMD(0x5B, 0x80),
-
- _INIT_DCS_CMD(0x5C, 0x00),
- _INIT_DCS_CMD(0x5D, 0x46),
- _INIT_DCS_CMD(0x5E, 0x32),
-
- _INIT_DCS_CMD(0x5F, 0x46),
- _INIT_DCS_CMD(0x60, 0x32),
-
- _INIT_DCS_CMD(0x61, 0x46),
- _INIT_DCS_CMD(0x62, 0x32),
- _INIT_DCS_CMD(0x68, 0x0C),
-
- _INIT_DCS_CMD(0x6C, 0x0D),
- _INIT_DCS_CMD(0x6E, 0x0D),
- _INIT_DCS_CMD(0x78, 0x00),
- _INIT_DCS_CMD(0x79, 0xC5),
- _INIT_DCS_CMD(0x7A, 0x0C),
- _INIT_DCS_CMD(0x7B, 0xB0),
-
- _INIT_DCS_CMD(0xFF, 0x26),
- _INIT_DCS_CMD(0xFB, 0x01),
-
- _INIT_DCS_CMD(0x00, 0xA1),
- _INIT_DCS_CMD(0x02, 0x31),
- _INIT_DCS_CMD(0x0A, 0xF4),
- _INIT_DCS_CMD(0x04, 0x50),
- _INIT_DCS_CMD(0x06, 0x30),
- _INIT_DCS_CMD(0x0C, 0x16),
- _INIT_DCS_CMD(0x0D, 0x0D),
- _INIT_DCS_CMD(0x0F, 0x00),
- _INIT_DCS_CMD(0x11, 0x00),
- _INIT_DCS_CMD(0x12, 0x50),
- _INIT_DCS_CMD(0x13, 0x40),
- _INIT_DCS_CMD(0x14, 0x58),
- _INIT_DCS_CMD(0x15, 0x00),
- _INIT_DCS_CMD(0x16, 0x10),
- _INIT_DCS_CMD(0x17, 0xA0),
- _INIT_DCS_CMD(0x18, 0x86),
- _INIT_DCS_CMD(0x22, 0x00),
- _INIT_DCS_CMD(0x23, 0x00),
-
- _INIT_DCS_CMD(0x19, 0x0E),
- _INIT_DCS_CMD(0x1A, 0x31),
- _INIT_DCS_CMD(0x1B, 0x0D),
- _INIT_DCS_CMD(0x1C, 0x29),
- _INIT_DCS_CMD(0x2A, 0x0E),
- _INIT_DCS_CMD(0x2B, 0x31),
-
- _INIT_DCS_CMD(0x1D, 0x00),
- _INIT_DCS_CMD(0x1E, 0x62),
- _INIT_DCS_CMD(0x1F, 0x62),
-
- _INIT_DCS_CMD(0x2F, 0x06),
- _INIT_DCS_CMD(0x30, 0x62),
- _INIT_DCS_CMD(0x31, 0x06),
- _INIT_DCS_CMD(0x32, 0x7F),
- _INIT_DCS_CMD(0x33, 0x11),
- _INIT_DCS_CMD(0x34, 0x89),
- _INIT_DCS_CMD(0x35, 0x67),
-
- _INIT_DCS_CMD(0x39, 0x0B),
- _INIT_DCS_CMD(0x3A, 0x62),
- _INIT_DCS_CMD(0x3B, 0x06),
-
- _INIT_DCS_CMD(0xC8, 0x04),
- _INIT_DCS_CMD(0xC9, 0x89),
- _INIT_DCS_CMD(0xCA, 0x4E),
- _INIT_DCS_CMD(0xCB, 0x00),
- _INIT_DCS_CMD(0xA9, 0x3F),
- _INIT_DCS_CMD(0xAA, 0x3E),
- _INIT_DCS_CMD(0xAB, 0x3D),
- _INIT_DCS_CMD(0xAC, 0x3C),
- _INIT_DCS_CMD(0xAD, 0x3B),
- _INIT_DCS_CMD(0xAE, 0x3A),
- _INIT_DCS_CMD(0xAF, 0x39),
- _INIT_DCS_CMD(0xB0, 0x38),
-
- _INIT_DCS_CMD(0xFF, 0x27),
- _INIT_DCS_CMD(0xFB, 0x01),
-
- _INIT_DCS_CMD(0xD0, 0x11),
- _INIT_DCS_CMD(0xD1, 0x54),
- _INIT_DCS_CMD(0xDE, 0x43),
- _INIT_DCS_CMD(0xDF, 0x02),
-
- _INIT_DCS_CMD(0xC0, 0x18),
- _INIT_DCS_CMD(0xC1, 0x00),
- _INIT_DCS_CMD(0xC2, 0x00),
- _INIT_DCS_CMD(0x00, 0x00),
- _INIT_DCS_CMD(0xC3, 0x00),
- _INIT_DCS_CMD(0x56, 0x06),
-
- _INIT_DCS_CMD(0x58, 0x80),
- _INIT_DCS_CMD(0x59, 0x78),
- _INIT_DCS_CMD(0x5A, 0x00),
- _INIT_DCS_CMD(0x5B, 0x18),
- _INIT_DCS_CMD(0x5C, 0x00),
- _INIT_DCS_CMD(0x5D, 0x01),
- _INIT_DCS_CMD(0x5E, 0x20),
- _INIT_DCS_CMD(0x5F, 0x10),
- _INIT_DCS_CMD(0x60, 0x00),
- _INIT_DCS_CMD(0x61, 0x1C),
- _INIT_DCS_CMD(0x62, 0x00),
- _INIT_DCS_CMD(0x63, 0x01),
- _INIT_DCS_CMD(0x64, 0x44),
- _INIT_DCS_CMD(0x65, 0x1B),
- _INIT_DCS_CMD(0x66, 0x00),
- _INIT_DCS_CMD(0x67, 0x01),
- _INIT_DCS_CMD(0x68, 0x44),
-
- _INIT_DCS_CMD(0x98, 0x01),
- _INIT_DCS_CMD(0xB4, 0x03),
- _INIT_DCS_CMD(0x9B, 0xBE),
-
- _INIT_DCS_CMD(0xAB, 0x14),
- _INIT_DCS_CMD(0xBC, 0x08),
- _INIT_DCS_CMD(0xBD, 0x28),
-
- _INIT_DCS_CMD(0xFF, 0x2A),
- _INIT_DCS_CMD(0xFB, 0x01),
- _INIT_DCS_CMD(0x22, 0x2F),
- _INIT_DCS_CMD(0x23, 0x08),
-
- _INIT_DCS_CMD(0x24, 0x00),
- _INIT_DCS_CMD(0x25, 0x62),
- _INIT_DCS_CMD(0x26, 0xF8),
- _INIT_DCS_CMD(0x27, 0x00),
- _INIT_DCS_CMD(0x28, 0x1A),
- _INIT_DCS_CMD(0x29, 0x00),
- _INIT_DCS_CMD(0x2A, 0x1A),
- _INIT_DCS_CMD(0x2B, 0x00),
- _INIT_DCS_CMD(0x2D, 0x1A),
-
- _INIT_DCS_CMD(0x64, 0x96),
- _INIT_DCS_CMD(0x65, 0x10),
- _INIT_DCS_CMD(0x66, 0x00),
- _INIT_DCS_CMD(0x67, 0x96),
- _INIT_DCS_CMD(0x68, 0x10),
- _INIT_DCS_CMD(0x69, 0x00),
- _INIT_DCS_CMD(0x6A, 0x96),
- _INIT_DCS_CMD(0x6B, 0x10),
- _INIT_DCS_CMD(0x6C, 0x00),
- _INIT_DCS_CMD(0x70, 0x92),
- _INIT_DCS_CMD(0x71, 0x10),
- _INIT_DCS_CMD(0x72, 0x00),
- _INIT_DCS_CMD(0x79, 0x96),
- _INIT_DCS_CMD(0x7A, 0x10),
- _INIT_DCS_CMD(0x88, 0x96),
- _INIT_DCS_CMD(0x89, 0x10),
-
- _INIT_DCS_CMD(0xA2, 0x3F),
- _INIT_DCS_CMD(0xA3, 0x30),
- _INIT_DCS_CMD(0xA4, 0xC0),
- _INIT_DCS_CMD(0xA5, 0x03),
-
- _INIT_DCS_CMD(0xE8, 0x00),
-
- _INIT_DCS_CMD(0x97, 0x3C),
- _INIT_DCS_CMD(0x98, 0x02),
- _INIT_DCS_CMD(0x99, 0x95),
- _INIT_DCS_CMD(0x9A, 0x06),
- _INIT_DCS_CMD(0x9B, 0x00),
- _INIT_DCS_CMD(0x9C, 0x0B),
- _INIT_DCS_CMD(0x9D, 0x0A),
- _INIT_DCS_CMD(0x9E, 0x90),
-
- _INIT_DCS_CMD(0xFF, 0x25),
- _INIT_DCS_CMD(0x13, 0x02),
- _INIT_DCS_CMD(0x14, 0xD7),
- _INIT_DCS_CMD(0xDB, 0x02),
- _INIT_DCS_CMD(0xDC, 0xD7),
- _INIT_DCS_CMD(0x17, 0xCF),
- _INIT_DCS_CMD(0x19, 0x0F),
- _INIT_DCS_CMD(0x1B, 0x5B),
-
- _INIT_DCS_CMD(0xFF, 0x20),
-
- _INIT_DCS_CMD(0xB0, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x24, 0x00, 0x38, 0x00, 0x4C, 0x00, 0x5E, 0x00, 0x6F, 0x00, 0x7E),
- _INIT_DCS_CMD(0xB1, 0x00, 0x8C, 0x00, 0xBE, 0x00, 0xE5, 0x01, 0x27, 0x01, 0x58, 0x01, 0xA8, 0x01, 0xE8, 0x01, 0xEA),
- _INIT_DCS_CMD(0xB2, 0x02, 0x28, 0x02, 0x71, 0x02, 0x9E, 0x02, 0xDA, 0x03, 0x00, 0x03, 0x31, 0x03, 0x40, 0x03, 0x51),
- _INIT_DCS_CMD(0xB3, 0x03, 0x62, 0x03, 0x75, 0x03, 0x89, 0x03, 0x9C, 0x03, 0xAA, 0x03, 0xB2),
-
- _INIT_DCS_CMD(0xB4, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x27, 0x00, 0x3D, 0x00, 0x52, 0x00, 0x64, 0x00, 0x75, 0x00, 0x84),
- _INIT_DCS_CMD(0xB5, 0x00, 0x93, 0x00, 0xC5, 0x00, 0xEC, 0x01, 0x2C, 0x01, 0x5D, 0x01, 0xAC, 0x01, 0xEC, 0x01, 0xEE),
- _INIT_DCS_CMD(0xB6, 0x02, 0x2B, 0x02, 0x73, 0x02, 0xA0, 0x02, 0xDB, 0x03, 0x01, 0x03, 0x31, 0x03, 0x41, 0x03, 0x51),
- _INIT_DCS_CMD(0xB7, 0x03, 0x63, 0x03, 0x75, 0x03, 0x89, 0x03, 0x9C, 0x03, 0xAA, 0x03, 0xB2),
-
- _INIT_DCS_CMD(0xB8, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x2A, 0x00, 0x40, 0x00, 0x56, 0x00, 0x68, 0x00, 0x7A, 0x00, 0x89),
- _INIT_DCS_CMD(0xB9, 0x00, 0x98, 0x00, 0xC9, 0x00, 0xF1, 0x01, 0x30, 0x01, 0x61, 0x01, 0xB0, 0x01, 0xEF, 0x01, 0xF1),
- _INIT_DCS_CMD(0xBA, 0x02, 0x2E, 0x02, 0x76, 0x02, 0xA3, 0x02, 0xDD, 0x03, 0x02, 0x03, 0x32, 0x03, 0x42, 0x03, 0x53),
- _INIT_DCS_CMD(0xBB, 0x03, 0x66, 0x03, 0x75, 0x03, 0x89, 0x03, 0x9C, 0x03, 0xAA, 0x03, 0xB2),
-
- _INIT_DCS_CMD(0xFF, 0x21),
- _INIT_DCS_CMD(0xB0, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x24, 0x00, 0x38, 0x00, 0x4C, 0x00, 0x5E, 0x00, 0x6F, 0x00, 0x7E),
- _INIT_DCS_CMD(0xB1, 0x00, 0x8C, 0x00, 0xBE, 0x00, 0xE5, 0x01, 0x27, 0x01, 0x58, 0x01, 0xA8, 0x01, 0xE8, 0x01, 0xEA),
- _INIT_DCS_CMD(0xB2, 0x02, 0x28, 0x02, 0x71, 0x02, 0x9E, 0x02, 0xDA, 0x03, 0x00, 0x03, 0x31, 0x03, 0x40, 0x03, 0x51),
- _INIT_DCS_CMD(0xB3, 0x03, 0x62, 0x03, 0x77, 0x03, 0x90, 0x03, 0xAC, 0x03, 0xCA, 0x03, 0xDA),
-
- _INIT_DCS_CMD(0xB4, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x27, 0x00, 0x3D, 0x00, 0x52, 0x00, 0x64, 0x00, 0x75, 0x00, 0x84),
- _INIT_DCS_CMD(0xB5, 0x00, 0x93, 0x00, 0xC5, 0x00, 0xEC, 0x01, 0x2C, 0x01, 0x5D, 0x01, 0xAC, 0x01, 0xEC, 0x01, 0xEE),
- _INIT_DCS_CMD(0xB6, 0x02, 0x2B, 0x02, 0x73, 0x02, 0xA0, 0x02, 0xDB, 0x03, 0x01, 0x03, 0x31, 0x03, 0x41, 0x03, 0x51),
- _INIT_DCS_CMD(0xB7, 0x03, 0x63, 0x03, 0x77, 0x03, 0x90, 0x03, 0xAC, 0x03, 0xCA, 0x03, 0xDA),
-
- _INIT_DCS_CMD(0xB8, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x2A, 0x00, 0x40, 0x00, 0x56, 0x00, 0x68, 0x00, 0x7A, 0x00, 0x89),
- _INIT_DCS_CMD(0xB9, 0x00, 0x98, 0x00, 0xC9, 0x00, 0xF1, 0x01, 0x30, 0x01, 0x61, 0x01, 0xB0, 0x01, 0xEF, 0x01, 0xF1),
- _INIT_DCS_CMD(0xBA, 0x02, 0x2E, 0x02, 0x76, 0x02, 0xA3, 0x02, 0xDD, 0x03, 0x02, 0x03, 0x32, 0x03, 0x42, 0x03, 0x53),
- _INIT_DCS_CMD(0xBB, 0x03, 0x66, 0x03, 0x77, 0x03, 0x90, 0x03, 0xAC, 0x03, 0xCA, 0x03, 0xDA),
-
- _INIT_DCS_CMD(0xFF, 0xF0),
- _INIT_DCS_CMD(0xFB, 0x01),
- _INIT_DCS_CMD(0x3A, 0x08),
-
- _INIT_DCS_CMD(0xFF, 0x10),
- _INIT_DCS_CMD(0xB9, 0x01),
-
- _INIT_DCS_CMD(0xFF, 0x20),
-
- _INIT_DCS_CMD(0x18, 0x40),
- _INIT_DCS_CMD(0xFF, 0x10),
-
- _INIT_DCS_CMD(0xB9, 0x02),
- _INIT_DCS_CMD(0xFF, 0x10),
-
- _INIT_DCS_CMD(0xFB, 0x01),
- _INIT_DCS_CMD(0xB0, 0x01),
- _INIT_DCS_CMD(0x35, 0x00),
- _INIT_DCS_CMD(0x3B, 0x03, 0xAE, 0x1A, 0x04, 0x04),
- _INIT_DELAY_CMD(100),
- _INIT_DCS_CMD(0x11),
- _INIT_DELAY_CMD(200),
- _INIT_DCS_CMD(0x29),
- _INIT_DELAY_CMD(100),
- {},
-};
+static int boe_init(struct boe_panel *boe)
+{
+ struct mipi_dsi_multi_context ctx = { .dsi = boe->dsi };
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0xe5);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb3, 0x52);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb3, 0x88);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x8b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbf, 0x1a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe0, 0x26);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe1, 0x26);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdc, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdd, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcc, 0x26);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcd, 0x26);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd2, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd3, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe6, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe7, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0x09);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0x09);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd8, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd9, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0x0b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0x0b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd6, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd7, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc1, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd4, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd5, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xde, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdf, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc1, 0x0d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0x17);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0x26);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0x31);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0x1c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc6, 0x2c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc7, 0x33);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0x31);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x37);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x37);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x37);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcc, 0x39);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcd, 0x2e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xce, 0x2f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcf, 0x2f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd0, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd2, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd3, 0x0d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd4, 0x17);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd5, 0x26);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd6, 0x31);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd7, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd8, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd9, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xda, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdb, 0x37);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdc, 0x37);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdd, 0x37);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xde, 0x39);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdf, 0x2e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe0, 0x2f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe1, 0x2f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe2, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0x0b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe7, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0x2a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xde, 0x2a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x43);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe4, 0xc0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe5, 0x0d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0xa5);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0xa5);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc7, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd5, 0x32);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbc, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb2, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb3, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb4, 0x25);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb5, 0x39);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x4e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb7, 0x72);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0x97);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0xdc);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x22);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbb, 0xa4);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbc, 0x2b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbd, 0x2f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbe, 0xa9);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbf, 0x25);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x61);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc1, 0x97);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0xb2);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0xcd);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0xd9);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0xe7);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc6, 0xf4);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc7, 0xfa);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0xfc);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x16);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcc, 0xaf);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcd, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xce, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb2, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb3, 0x11);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb4, 0x24);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb5, 0x39);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x4f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb7, 0x72);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0x98);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0xdc);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x23);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbb, 0xa6);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbc, 0x2c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbd, 0x30);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbe, 0xaa);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbf, 0x26);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x62);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc1, 0x9b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0xb5);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0xcf);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0xdb);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0xe8);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc6, 0xf5);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc7, 0xfa);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0xfc);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x16);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcc, 0xaf);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcd, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xce, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x09);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb2, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb3, 0x16);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb4, 0x24);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb5, 0x3b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x4f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb7, 0x73);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0x99);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0xe0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x26);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbb, 0xad);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbc, 0x36);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbd, 0x3a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbe, 0xae);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbf, 0x2a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x66);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc1, 0x9e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0xb8);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0xd1);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0xdd);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0xe9);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc6, 0xf6);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc7, 0xfa);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0xfc);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x16);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcc, 0xaf);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcd, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xce, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb2, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb3, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb4, 0x25);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb5, 0x39);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x4e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb7, 0x72);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0x97);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0xdc);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x22);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbb, 0xa4);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbc, 0x2b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbd, 0x2f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbe, 0xa9);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbf, 0x25);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x61);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc1, 0x97);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0xb2);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0xcd);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0xd9);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0xe7);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc6, 0xf4);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc7, 0xfa);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0xfc);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x16);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcc, 0xaf);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcd, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xce, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x0b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb2, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb3, 0x11);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb4, 0x24);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb5, 0x39);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x4f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb7, 0x72);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0x98);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0xdc);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x23);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbb, 0xa6);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbc, 0x2c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbd, 0x30);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbe, 0xaa);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbf, 0x26);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x62);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc1, 0x9b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0xb5);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0xcf);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0xdb);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0xe8);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc6, 0xf5);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc7, 0xfa);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0xfc);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x16);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcc, 0xaf);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcd, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xce, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb2, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb3, 0x16);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb4, 0x24);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb5, 0x3b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x4f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb7, 0x73);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0x99);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0xe0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x26);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbb, 0xad);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbc, 0x36);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbd, 0x3a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbe, 0xae);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbf, 0x2a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x66);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc1, 0x9e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0xb8);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0xd1);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0xdd);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0xe9);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc6, 0xf6);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc7, 0xfa);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0xfc);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x16);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcc, 0xaf);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcd, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xce, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb3, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0x68);
+
+ mipi_dsi_msleep(&ctx, 150);
-static const struct panel_init_cmd boe_init_cmd[] = {
- _INIT_DCS_CMD(0xB0, 0x05),
- _INIT_DCS_CMD(0xB1, 0xE5),
- _INIT_DCS_CMD(0xB3, 0x52),
- _INIT_DCS_CMD(0xB0, 0x00),
- _INIT_DCS_CMD(0xB3, 0x88),
- _INIT_DCS_CMD(0xB0, 0x04),
- _INIT_DCS_CMD(0xB8, 0x00),
- _INIT_DCS_CMD(0xB0, 0x00),
- _INIT_DCS_CMD(0xB6, 0x03),
- _INIT_DCS_CMD(0xBA, 0x8B),
- _INIT_DCS_CMD(0xBF, 0x1A),
- _INIT_DCS_CMD(0xC0, 0x0F),
- _INIT_DCS_CMD(0xC2, 0x0C),
- _INIT_DCS_CMD(0xC3, 0x02),
- _INIT_DCS_CMD(0xC4, 0x0C),
- _INIT_DCS_CMD(0xC5, 0x02),
- _INIT_DCS_CMD(0xB0, 0x01),
- _INIT_DCS_CMD(0xE0, 0x26),
- _INIT_DCS_CMD(0xE1, 0x26),
- _INIT_DCS_CMD(0xDC, 0x00),
- _INIT_DCS_CMD(0xDD, 0x00),
- _INIT_DCS_CMD(0xCC, 0x26),
- _INIT_DCS_CMD(0xCD, 0x26),
- _INIT_DCS_CMD(0xC8, 0x00),
- _INIT_DCS_CMD(0xC9, 0x00),
- _INIT_DCS_CMD(0xD2, 0x03),
- _INIT_DCS_CMD(0xD3, 0x03),
- _INIT_DCS_CMD(0xE6, 0x04),
- _INIT_DCS_CMD(0xE7, 0x04),
- _INIT_DCS_CMD(0xC4, 0x09),
- _INIT_DCS_CMD(0xC5, 0x09),
- _INIT_DCS_CMD(0xD8, 0x0A),
- _INIT_DCS_CMD(0xD9, 0x0A),
- _INIT_DCS_CMD(0xC2, 0x0B),
- _INIT_DCS_CMD(0xC3, 0x0B),
- _INIT_DCS_CMD(0xD6, 0x0C),
- _INIT_DCS_CMD(0xD7, 0x0C),
- _INIT_DCS_CMD(0xC0, 0x05),
- _INIT_DCS_CMD(0xC1, 0x05),
- _INIT_DCS_CMD(0xD4, 0x06),
- _INIT_DCS_CMD(0xD5, 0x06),
- _INIT_DCS_CMD(0xCA, 0x07),
- _INIT_DCS_CMD(0xCB, 0x07),
- _INIT_DCS_CMD(0xDE, 0x08),
- _INIT_DCS_CMD(0xDF, 0x08),
- _INIT_DCS_CMD(0xB0, 0x02),
- _INIT_DCS_CMD(0xC0, 0x00),
- _INIT_DCS_CMD(0xC1, 0x0D),
- _INIT_DCS_CMD(0xC2, 0x17),
- _INIT_DCS_CMD(0xC3, 0x26),
- _INIT_DCS_CMD(0xC4, 0x31),
- _INIT_DCS_CMD(0xC5, 0x1C),
- _INIT_DCS_CMD(0xC6, 0x2C),
- _INIT_DCS_CMD(0xC7, 0x33),
- _INIT_DCS_CMD(0xC8, 0x31),
- _INIT_DCS_CMD(0xC9, 0x37),
- _INIT_DCS_CMD(0xCA, 0x37),
- _INIT_DCS_CMD(0xCB, 0x37),
- _INIT_DCS_CMD(0xCC, 0x39),
- _INIT_DCS_CMD(0xCD, 0x2E),
- _INIT_DCS_CMD(0xCE, 0x2F),
- _INIT_DCS_CMD(0xCF, 0x2F),
- _INIT_DCS_CMD(0xD0, 0x07),
- _INIT_DCS_CMD(0xD2, 0x00),
- _INIT_DCS_CMD(0xD3, 0x0D),
- _INIT_DCS_CMD(0xD4, 0x17),
- _INIT_DCS_CMD(0xD5, 0x26),
- _INIT_DCS_CMD(0xD6, 0x31),
- _INIT_DCS_CMD(0xD7, 0x3F),
- _INIT_DCS_CMD(0xD8, 0x3F),
- _INIT_DCS_CMD(0xD9, 0x3F),
- _INIT_DCS_CMD(0xDA, 0x3F),
- _INIT_DCS_CMD(0xDB, 0x37),
- _INIT_DCS_CMD(0xDC, 0x37),
- _INIT_DCS_CMD(0xDD, 0x37),
- _INIT_DCS_CMD(0xDE, 0x39),
- _INIT_DCS_CMD(0xDF, 0x2E),
- _INIT_DCS_CMD(0xE0, 0x2F),
- _INIT_DCS_CMD(0xE1, 0x2F),
- _INIT_DCS_CMD(0xE2, 0x07),
- _INIT_DCS_CMD(0xB0, 0x03),
- _INIT_DCS_CMD(0xC8, 0x0B),
- _INIT_DCS_CMD(0xC9, 0x07),
- _INIT_DCS_CMD(0xC3, 0x00),
- _INIT_DCS_CMD(0xE7, 0x00),
- _INIT_DCS_CMD(0xC5, 0x2A),
- _INIT_DCS_CMD(0xDE, 0x2A),
- _INIT_DCS_CMD(0xCA, 0x43),
- _INIT_DCS_CMD(0xC9, 0x07),
- _INIT_DCS_CMD(0xE4, 0xC0),
- _INIT_DCS_CMD(0xE5, 0x0D),
- _INIT_DCS_CMD(0xCB, 0x00),
- _INIT_DCS_CMD(0xB0, 0x06),
- _INIT_DCS_CMD(0xB8, 0xA5),
- _INIT_DCS_CMD(0xC0, 0xA5),
- _INIT_DCS_CMD(0xC7, 0x0F),
- _INIT_DCS_CMD(0xD5, 0x32),
- _INIT_DCS_CMD(0xB8, 0x00),
- _INIT_DCS_CMD(0xC0, 0x00),
- _INIT_DCS_CMD(0xBC, 0x00),
- _INIT_DCS_CMD(0xB0, 0x07),
- _INIT_DCS_CMD(0xB1, 0x00),
- _INIT_DCS_CMD(0xB2, 0x02),
- _INIT_DCS_CMD(0xB3, 0x0F),
- _INIT_DCS_CMD(0xB4, 0x25),
- _INIT_DCS_CMD(0xB5, 0x39),
- _INIT_DCS_CMD(0xB6, 0x4E),
- _INIT_DCS_CMD(0xB7, 0x72),
- _INIT_DCS_CMD(0xB8, 0x97),
- _INIT_DCS_CMD(0xB9, 0xDC),
- _INIT_DCS_CMD(0xBA, 0x22),
- _INIT_DCS_CMD(0xBB, 0xA4),
- _INIT_DCS_CMD(0xBC, 0x2B),
- _INIT_DCS_CMD(0xBD, 0x2F),
- _INIT_DCS_CMD(0xBE, 0xA9),
- _INIT_DCS_CMD(0xBF, 0x25),
- _INIT_DCS_CMD(0xC0, 0x61),
- _INIT_DCS_CMD(0xC1, 0x97),
- _INIT_DCS_CMD(0xC2, 0xB2),
- _INIT_DCS_CMD(0xC3, 0xCD),
- _INIT_DCS_CMD(0xC4, 0xD9),
- _INIT_DCS_CMD(0xC5, 0xE7),
- _INIT_DCS_CMD(0xC6, 0xF4),
- _INIT_DCS_CMD(0xC7, 0xFA),
- _INIT_DCS_CMD(0xC8, 0xFC),
- _INIT_DCS_CMD(0xC9, 0x00),
- _INIT_DCS_CMD(0xCA, 0x00),
- _INIT_DCS_CMD(0xCB, 0x16),
- _INIT_DCS_CMD(0xCC, 0xAF),
- _INIT_DCS_CMD(0xCD, 0xFF),
- _INIT_DCS_CMD(0xCE, 0xFF),
- _INIT_DCS_CMD(0xB0, 0x08),
- _INIT_DCS_CMD(0xB1, 0x04),
- _INIT_DCS_CMD(0xB2, 0x05),
- _INIT_DCS_CMD(0xB3, 0x11),
- _INIT_DCS_CMD(0xB4, 0x24),
- _INIT_DCS_CMD(0xB5, 0x39),
- _INIT_DCS_CMD(0xB6, 0x4F),
- _INIT_DCS_CMD(0xB7, 0x72),
- _INIT_DCS_CMD(0xB8, 0x98),
- _INIT_DCS_CMD(0xB9, 0xDC),
- _INIT_DCS_CMD(0xBA, 0x23),
- _INIT_DCS_CMD(0xBB, 0xA6),
- _INIT_DCS_CMD(0xBC, 0x2C),
- _INIT_DCS_CMD(0xBD, 0x30),
- _INIT_DCS_CMD(0xBE, 0xAA),
- _INIT_DCS_CMD(0xBF, 0x26),
- _INIT_DCS_CMD(0xC0, 0x62),
- _INIT_DCS_CMD(0xC1, 0x9B),
- _INIT_DCS_CMD(0xC2, 0xB5),
- _INIT_DCS_CMD(0xC3, 0xCF),
- _INIT_DCS_CMD(0xC4, 0xDB),
- _INIT_DCS_CMD(0xC5, 0xE8),
- _INIT_DCS_CMD(0xC6, 0xF5),
- _INIT_DCS_CMD(0xC7, 0xFA),
- _INIT_DCS_CMD(0xC8, 0xFC),
- _INIT_DCS_CMD(0xC9, 0x00),
- _INIT_DCS_CMD(0xCA, 0x00),
- _INIT_DCS_CMD(0xCB, 0x16),
- _INIT_DCS_CMD(0xCC, 0xAF),
- _INIT_DCS_CMD(0xCD, 0xFF),
- _INIT_DCS_CMD(0xCE, 0xFF),
- _INIT_DCS_CMD(0xB0, 0x09),
- _INIT_DCS_CMD(0xB1, 0x04),
- _INIT_DCS_CMD(0xB2, 0x02),
- _INIT_DCS_CMD(0xB3, 0x16),
- _INIT_DCS_CMD(0xB4, 0x24),
- _INIT_DCS_CMD(0xB5, 0x3B),
- _INIT_DCS_CMD(0xB6, 0x4F),
- _INIT_DCS_CMD(0xB7, 0x73),
- _INIT_DCS_CMD(0xB8, 0x99),
- _INIT_DCS_CMD(0xB9, 0xE0),
- _INIT_DCS_CMD(0xBA, 0x26),
- _INIT_DCS_CMD(0xBB, 0xAD),
- _INIT_DCS_CMD(0xBC, 0x36),
- _INIT_DCS_CMD(0xBD, 0x3A),
- _INIT_DCS_CMD(0xBE, 0xAE),
- _INIT_DCS_CMD(0xBF, 0x2A),
- _INIT_DCS_CMD(0xC0, 0x66),
- _INIT_DCS_CMD(0xC1, 0x9E),
- _INIT_DCS_CMD(0xC2, 0xB8),
- _INIT_DCS_CMD(0xC3, 0xD1),
- _INIT_DCS_CMD(0xC4, 0xDD),
- _INIT_DCS_CMD(0xC5, 0xE9),
- _INIT_DCS_CMD(0xC6, 0xF6),
- _INIT_DCS_CMD(0xC7, 0xFA),
- _INIT_DCS_CMD(0xC8, 0xFC),
- _INIT_DCS_CMD(0xC9, 0x00),
- _INIT_DCS_CMD(0xCA, 0x00),
- _INIT_DCS_CMD(0xCB, 0x16),
- _INIT_DCS_CMD(0xCC, 0xAF),
- _INIT_DCS_CMD(0xCD, 0xFF),
- _INIT_DCS_CMD(0xCE, 0xFF),
- _INIT_DCS_CMD(0xB0, 0x0A),
- _INIT_DCS_CMD(0xB1, 0x00),
- _INIT_DCS_CMD(0xB2, 0x02),
- _INIT_DCS_CMD(0xB3, 0x0F),
- _INIT_DCS_CMD(0xB4, 0x25),
- _INIT_DCS_CMD(0xB5, 0x39),
- _INIT_DCS_CMD(0xB6, 0x4E),
- _INIT_DCS_CMD(0xB7, 0x72),
- _INIT_DCS_CMD(0xB8, 0x97),
- _INIT_DCS_CMD(0xB9, 0xDC),
- _INIT_DCS_CMD(0xBA, 0x22),
- _INIT_DCS_CMD(0xBB, 0xA4),
- _INIT_DCS_CMD(0xBC, 0x2B),
- _INIT_DCS_CMD(0xBD, 0x2F),
- _INIT_DCS_CMD(0xBE, 0xA9),
- _INIT_DCS_CMD(0xBF, 0x25),
- _INIT_DCS_CMD(0xC0, 0x61),
- _INIT_DCS_CMD(0xC1, 0x97),
- _INIT_DCS_CMD(0xC2, 0xB2),
- _INIT_DCS_CMD(0xC3, 0xCD),
- _INIT_DCS_CMD(0xC4, 0xD9),
- _INIT_DCS_CMD(0xC5, 0xE7),
- _INIT_DCS_CMD(0xC6, 0xF4),
- _INIT_DCS_CMD(0xC7, 0xFA),
- _INIT_DCS_CMD(0xC8, 0xFC),
- _INIT_DCS_CMD(0xC9, 0x00),
- _INIT_DCS_CMD(0xCA, 0x00),
- _INIT_DCS_CMD(0xCB, 0x16),
- _INIT_DCS_CMD(0xCC, 0xAF),
- _INIT_DCS_CMD(0xCD, 0xFF),
- _INIT_DCS_CMD(0xCE, 0xFF),
- _INIT_DCS_CMD(0xB0, 0x0B),
- _INIT_DCS_CMD(0xB1, 0x04),
- _INIT_DCS_CMD(0xB2, 0x05),
- _INIT_DCS_CMD(0xB3, 0x11),
- _INIT_DCS_CMD(0xB4, 0x24),
- _INIT_DCS_CMD(0xB5, 0x39),
- _INIT_DCS_CMD(0xB6, 0x4F),
- _INIT_DCS_CMD(0xB7, 0x72),
- _INIT_DCS_CMD(0xB8, 0x98),
- _INIT_DCS_CMD(0xB9, 0xDC),
- _INIT_DCS_CMD(0xBA, 0x23),
- _INIT_DCS_CMD(0xBB, 0xA6),
- _INIT_DCS_CMD(0xBC, 0x2C),
- _INIT_DCS_CMD(0xBD, 0x30),
- _INIT_DCS_CMD(0xBE, 0xAA),
- _INIT_DCS_CMD(0xBF, 0x26),
- _INIT_DCS_CMD(0xC0, 0x62),
- _INIT_DCS_CMD(0xC1, 0x9B),
- _INIT_DCS_CMD(0xC2, 0xB5),
- _INIT_DCS_CMD(0xC3, 0xCF),
- _INIT_DCS_CMD(0xC4, 0xDB),
- _INIT_DCS_CMD(0xC5, 0xE8),
- _INIT_DCS_CMD(0xC6, 0xF5),
- _INIT_DCS_CMD(0xC7, 0xFA),
- _INIT_DCS_CMD(0xC8, 0xFC),
- _INIT_DCS_CMD(0xC9, 0x00),
- _INIT_DCS_CMD(0xCA, 0x00),
- _INIT_DCS_CMD(0xCB, 0x16),
- _INIT_DCS_CMD(0xCC, 0xAF),
- _INIT_DCS_CMD(0xCD, 0xFF),
- _INIT_DCS_CMD(0xCE, 0xFF),
- _INIT_DCS_CMD(0xB0, 0x0C),
- _INIT_DCS_CMD(0xB1, 0x04),
- _INIT_DCS_CMD(0xB2, 0x02),
- _INIT_DCS_CMD(0xB3, 0x16),
- _INIT_DCS_CMD(0xB4, 0x24),
- _INIT_DCS_CMD(0xB5, 0x3B),
- _INIT_DCS_CMD(0xB6, 0x4F),
- _INIT_DCS_CMD(0xB7, 0x73),
- _INIT_DCS_CMD(0xB8, 0x99),
- _INIT_DCS_CMD(0xB9, 0xE0),
- _INIT_DCS_CMD(0xBA, 0x26),
- _INIT_DCS_CMD(0xBB, 0xAD),
- _INIT_DCS_CMD(0xBC, 0x36),
- _INIT_DCS_CMD(0xBD, 0x3A),
- _INIT_DCS_CMD(0xBE, 0xAE),
- _INIT_DCS_CMD(0xBF, 0x2A),
- _INIT_DCS_CMD(0xC0, 0x66),
- _INIT_DCS_CMD(0xC1, 0x9E),
- _INIT_DCS_CMD(0xC2, 0xB8),
- _INIT_DCS_CMD(0xC3, 0xD1),
- _INIT_DCS_CMD(0xC4, 0xDD),
- _INIT_DCS_CMD(0xC5, 0xE9),
- _INIT_DCS_CMD(0xC6, 0xF6),
- _INIT_DCS_CMD(0xC7, 0xFA),
- _INIT_DCS_CMD(0xC8, 0xFC),
- _INIT_DCS_CMD(0xC9, 0x00),
- _INIT_DCS_CMD(0xCA, 0x00),
- _INIT_DCS_CMD(0xCB, 0x16),
- _INIT_DCS_CMD(0xCC, 0xAF),
- _INIT_DCS_CMD(0xCD, 0xFF),
- _INIT_DCS_CMD(0xCE, 0xFF),
- _INIT_DCS_CMD(0xB0, 0x00),
- _INIT_DCS_CMD(0xB3, 0x08),
- _INIT_DCS_CMD(0xB0, 0x04),
- _INIT_DCS_CMD(0xB8, 0x68),
- _INIT_DELAY_CMD(150),
- {},
+ return 0;
};
-static const struct panel_init_cmd auo_kd101n80_45na_init_cmd[] = {
- _INIT_DELAY_CMD(24),
- _INIT_DCS_CMD(0x11),
- _INIT_DELAY_CMD(120),
- _INIT_DCS_CMD(0x29),
- _INIT_DELAY_CMD(120),
- {},
-};
+static int auo_kd101n80_45na_init(struct boe_panel *boe)
+{
+ struct mipi_dsi_multi_context ctx = { .dsi = boe->dsi };
-static const struct panel_init_cmd auo_b101uan08_3_init_cmd[] = {
- _INIT_DELAY_CMD(24),
- _INIT_DCS_CMD(0xB0, 0x01),
- _INIT_DCS_CMD(0xC0, 0x48),
- _INIT_DCS_CMD(0xC1, 0x48),
- _INIT_DCS_CMD(0xC2, 0x47),
- _INIT_DCS_CMD(0xC3, 0x47),
- _INIT_DCS_CMD(0xC4, 0x46),
- _INIT_DCS_CMD(0xC5, 0x46),
- _INIT_DCS_CMD(0xC6, 0x45),
- _INIT_DCS_CMD(0xC7, 0x45),
- _INIT_DCS_CMD(0xC8, 0x64),
- _INIT_DCS_CMD(0xC9, 0x64),
- _INIT_DCS_CMD(0xCA, 0x4F),
- _INIT_DCS_CMD(0xCB, 0x4F),
- _INIT_DCS_CMD(0xCC, 0x40),
- _INIT_DCS_CMD(0xCD, 0x40),
- _INIT_DCS_CMD(0xCE, 0x66),
- _INIT_DCS_CMD(0xCF, 0x66),
- _INIT_DCS_CMD(0xD0, 0x4F),
- _INIT_DCS_CMD(0xD1, 0x4F),
- _INIT_DCS_CMD(0xD2, 0x41),
- _INIT_DCS_CMD(0xD3, 0x41),
- _INIT_DCS_CMD(0xD4, 0x48),
- _INIT_DCS_CMD(0xD5, 0x48),
- _INIT_DCS_CMD(0xD6, 0x47),
- _INIT_DCS_CMD(0xD7, 0x47),
- _INIT_DCS_CMD(0xD8, 0x46),
- _INIT_DCS_CMD(0xD9, 0x46),
- _INIT_DCS_CMD(0xDA, 0x45),
- _INIT_DCS_CMD(0xDB, 0x45),
- _INIT_DCS_CMD(0xDC, 0x64),
- _INIT_DCS_CMD(0xDD, 0x64),
- _INIT_DCS_CMD(0xDE, 0x4F),
- _INIT_DCS_CMD(0xDF, 0x4F),
- _INIT_DCS_CMD(0xE0, 0x40),
- _INIT_DCS_CMD(0xE1, 0x40),
- _INIT_DCS_CMD(0xE2, 0x66),
- _INIT_DCS_CMD(0xE3, 0x66),
- _INIT_DCS_CMD(0xE4, 0x4F),
- _INIT_DCS_CMD(0xE5, 0x4F),
- _INIT_DCS_CMD(0xE6, 0x41),
- _INIT_DCS_CMD(0xE7, 0x41),
- _INIT_DELAY_CMD(150),
- {},
-};
+ msleep(24);
-static const struct panel_init_cmd starry_qfh032011_53g_init_cmd[] = {
- _INIT_DCS_CMD(0xB0, 0x01),
- _INIT_DCS_CMD(0xC3, 0x4F),
- _INIT_DCS_CMD(0xC4, 0x40),
- _INIT_DCS_CMD(0xC5, 0x40),
- _INIT_DCS_CMD(0xC6, 0x40),
- _INIT_DCS_CMD(0xC7, 0x40),
- _INIT_DCS_CMD(0xC8, 0x4D),
- _INIT_DCS_CMD(0xC9, 0x52),
- _INIT_DCS_CMD(0xCA, 0x51),
- _INIT_DCS_CMD(0xCD, 0x5D),
- _INIT_DCS_CMD(0xCE, 0x5B),
- _INIT_DCS_CMD(0xCF, 0x4B),
- _INIT_DCS_CMD(0xD0, 0x49),
- _INIT_DCS_CMD(0xD1, 0x47),
- _INIT_DCS_CMD(0xD2, 0x45),
- _INIT_DCS_CMD(0xD3, 0x41),
- _INIT_DCS_CMD(0xD7, 0x50),
- _INIT_DCS_CMD(0xD8, 0x40),
- _INIT_DCS_CMD(0xD9, 0x40),
- _INIT_DCS_CMD(0xDA, 0x40),
- _INIT_DCS_CMD(0xDB, 0x40),
- _INIT_DCS_CMD(0xDC, 0x4E),
- _INIT_DCS_CMD(0xDD, 0x52),
- _INIT_DCS_CMD(0xDE, 0x51),
- _INIT_DCS_CMD(0xE1, 0x5E),
- _INIT_DCS_CMD(0xE2, 0x5C),
- _INIT_DCS_CMD(0xE3, 0x4C),
- _INIT_DCS_CMD(0xE4, 0x4A),
- _INIT_DCS_CMD(0xE5, 0x48),
- _INIT_DCS_CMD(0xE6, 0x46),
- _INIT_DCS_CMD(0xE7, 0x42),
- _INIT_DCS_CMD(0xB0, 0x03),
- _INIT_DCS_CMD(0xBE, 0x03),
- _INIT_DCS_CMD(0xCC, 0x44),
- _INIT_DCS_CMD(0xC8, 0x07),
- _INIT_DCS_CMD(0xC9, 0x05),
- _INIT_DCS_CMD(0xCA, 0x42),
- _INIT_DCS_CMD(0xCD, 0x3E),
- _INIT_DCS_CMD(0xCF, 0x60),
- _INIT_DCS_CMD(0xD2, 0x04),
- _INIT_DCS_CMD(0xD3, 0x04),
- _INIT_DCS_CMD(0xD4, 0x01),
- _INIT_DCS_CMD(0xD5, 0x00),
- _INIT_DCS_CMD(0xD6, 0x03),
- _INIT_DCS_CMD(0xD7, 0x04),
- _INIT_DCS_CMD(0xD9, 0x01),
- _INIT_DCS_CMD(0xDB, 0x01),
- _INIT_DCS_CMD(0xE4, 0xF0),
- _INIT_DCS_CMD(0xE5, 0x0A),
- _INIT_DCS_CMD(0xB0, 0x00),
- _INIT_DCS_CMD(0xCC, 0x08),
- _INIT_DCS_CMD(0xC2, 0x08),
- _INIT_DCS_CMD(0xC4, 0x10),
- _INIT_DCS_CMD(0xB0, 0x02),
- _INIT_DCS_CMD(0xC0, 0x00),
- _INIT_DCS_CMD(0xC1, 0x0A),
- _INIT_DCS_CMD(0xC2, 0x20),
- _INIT_DCS_CMD(0xC3, 0x24),
- _INIT_DCS_CMD(0xC4, 0x23),
- _INIT_DCS_CMD(0xC5, 0x29),
- _INIT_DCS_CMD(0xC6, 0x23),
- _INIT_DCS_CMD(0xC7, 0x1C),
- _INIT_DCS_CMD(0xC8, 0x19),
- _INIT_DCS_CMD(0xC9, 0x17),
- _INIT_DCS_CMD(0xCA, 0x17),
- _INIT_DCS_CMD(0xCB, 0x18),
- _INIT_DCS_CMD(0xCC, 0x1A),
- _INIT_DCS_CMD(0xCD, 0x1E),
- _INIT_DCS_CMD(0xCE, 0x20),
- _INIT_DCS_CMD(0xCF, 0x23),
- _INIT_DCS_CMD(0xD0, 0x07),
- _INIT_DCS_CMD(0xD1, 0x00),
- _INIT_DCS_CMD(0xD2, 0x00),
- _INIT_DCS_CMD(0xD3, 0x0A),
- _INIT_DCS_CMD(0xD4, 0x13),
- _INIT_DCS_CMD(0xD5, 0x1C),
- _INIT_DCS_CMD(0xD6, 0x1A),
- _INIT_DCS_CMD(0xD7, 0x13),
- _INIT_DCS_CMD(0xD8, 0x17),
- _INIT_DCS_CMD(0xD9, 0x1C),
- _INIT_DCS_CMD(0xDA, 0x19),
- _INIT_DCS_CMD(0xDB, 0x17),
- _INIT_DCS_CMD(0xDC, 0x17),
- _INIT_DCS_CMD(0xDD, 0x18),
- _INIT_DCS_CMD(0xDE, 0x1A),
- _INIT_DCS_CMD(0xDF, 0x1E),
- _INIT_DCS_CMD(0xE0, 0x20),
- _INIT_DCS_CMD(0xE1, 0x23),
- _INIT_DCS_CMD(0xE2, 0x07),
- _INIT_DCS_CMD(0X11),
- _INIT_DELAY_CMD(120),
- _INIT_DCS_CMD(0X29),
- _INIT_DELAY_CMD(80),
- {},
-};
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x11);
-static const struct panel_init_cmd starry_himax83102_j02_init_cmd[] = {
- _INIT_DCS_CMD(0xB9, 0x83, 0x10, 0x21, 0x55, 0x00),
- _INIT_DCS_CMD(0xB1, 0x2C, 0xB5, 0xB5, 0x31, 0xF1, 0x31, 0xD7, 0x2F, 0x36, 0x36, 0x36, 0x36, 0x1A, 0x8B, 0x11,
- 0x65, 0x00, 0x88, 0xFA, 0xFF, 0xFF, 0x8F, 0xFF, 0x08, 0x74, 0x33),
- _INIT_DCS_CMD(0xB2, 0x00, 0x47, 0xB0, 0x80, 0x00, 0x12, 0x72, 0x3C, 0xA3, 0x03, 0x03, 0x00, 0x00, 0x88, 0xF5),
- _INIT_DCS_CMD(0xB4, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x63, 0x5C, 0x63, 0x5C, 0x01, 0x9E),
- _INIT_DCS_CMD(0xE9, 0xCD),
- _INIT_DCS_CMD(0xBA, 0x84),
- _INIT_DCS_CMD(0xE9, 0x3F),
- _INIT_DCS_CMD(0xBC, 0x1B, 0x04),
- _INIT_DCS_CMD(0xBE, 0x20),
- _INIT_DCS_CMD(0xBF, 0xFC, 0xC4),
- _INIT_DCS_CMD(0xC0, 0x36, 0x36, 0x22, 0x11, 0x22, 0xA0, 0x61, 0x08, 0xF5, 0x03),
- _INIT_DCS_CMD(0xE9, 0xCC),
- _INIT_DCS_CMD(0xC7, 0x80),
- _INIT_DCS_CMD(0xE9, 0x3F),
- _INIT_DCS_CMD(0xE9, 0xC6),
- _INIT_DCS_CMD(0xC8, 0x97),
- _INIT_DCS_CMD(0xE9, 0x3F),
- _INIT_DCS_CMD(0xC9, 0x00, 0x1E, 0x13, 0x88, 0x01),
- _INIT_DCS_CMD(0xCB, 0x08, 0x13, 0x07, 0x00, 0x0F, 0x33),
- _INIT_DCS_CMD(0xCC, 0x02),
- _INIT_DCS_CMD(0xE9, 0xC4),
- _INIT_DCS_CMD(0xD0, 0x03),
- _INIT_DCS_CMD(0xE9, 0x3F),
- _INIT_DCS_CMD(0xD1, 0x37, 0x06, 0x00, 0x02, 0x04, 0x0C, 0xFF),
- _INIT_DCS_CMD(0xD2, 0x1F, 0x11, 0x1F),
- _INIT_DCS_CMD(0xD3, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x37, 0x47, 0x34, 0x3B, 0x12, 0x12, 0x03,
- 0x03, 0x32, 0x10, 0x10, 0x00, 0x10, 0x32, 0x10, 0x08, 0x00, 0x08, 0x32, 0x17, 0x94, 0x07, 0x94, 0x00, 0x00),
- _INIT_DCS_CMD(0xD5, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x19, 0x19, 0x40, 0x40, 0x1A, 0x1A,
- 0x1B, 0x1B, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x20, 0x21, 0x28, 0x29, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18),
- _INIT_DCS_CMD(0xD6, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x40, 0x40, 0x19, 0x19, 0x1A, 0x1A,
- 0x1B, 0x1B, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x29, 0x28, 0x21, 0x20, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18),
- _INIT_DCS_CMD(0xD8, 0xAA, 0xBA, 0xEA, 0xAA, 0xAA, 0xA0, 0xAA, 0xBA, 0xEA, 0xAA, 0xAA, 0xA0, 0xAA, 0xBA, 0xEA, 0xAA,
- 0xAA, 0xA0, 0xAA, 0xBA, 0xEA, 0xAA, 0xAA, 0xA0, 0xAA, 0xBA, 0xEA, 0xAA, 0xAA, 0xA0, 0xAA, 0xBA, 0xEA, 0xAA, 0xAA, 0xA0),
- _INIT_DCS_CMD(0xE0, 0x00, 0x09, 0x14, 0x1E, 0x26, 0x48, 0x61, 0x67, 0x6C, 0x67, 0x7D, 0x7F, 0x80, 0x8B, 0x87, 0x8F, 0x98, 0xAB,
- 0xAB, 0x55, 0x5C, 0x68, 0x73, 0x00, 0x09, 0x14, 0x1E, 0x26, 0x48, 0x61, 0x67, 0x6C, 0x67, 0x7D, 0x7F, 0x80, 0x8B, 0x87, 0x8F, 0x98, 0xAB, 0xAB, 0x55, 0x5C, 0x68, 0x73),
- _INIT_DCS_CMD(0xE7, 0x0E, 0x10, 0x10, 0x21, 0x2B, 0x9A, 0x02, 0x54, 0x9A, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x12, 0x05, 0x02, 0x02, 0x10),
- _INIT_DCS_CMD(0xBD, 0x01),
- _INIT_DCS_CMD(0xB1, 0x01, 0xBF, 0x11),
- _INIT_DCS_CMD(0xCB, 0x86),
- _INIT_DCS_CMD(0xD2, 0x3C, 0xFA),
- _INIT_DCS_CMD(0xD3, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0C, 0x01),
- _INIT_DCS_CMD(0xE7, 0x02, 0x00, 0x28, 0x01, 0x7E, 0x0F, 0x7E, 0x10, 0xA0, 0x00, 0x00, 0x20, 0x40, 0x50, 0x40),
- _INIT_DCS_CMD(0xBD, 0x02),
- _INIT_DCS_CMD(0xD8, 0xFF, 0xFF, 0xBF, 0xFE, 0xAA, 0xA0, 0xFF, 0xFF, 0xBF, 0xFE, 0xAA, 0xA0),
- _INIT_DCS_CMD(0xE7, 0xFE, 0x04, 0xFE, 0x04, 0xFE, 0x04, 0x03, 0x03, 0x03, 0x26, 0x00, 0x26, 0x81, 0x02, 0x40, 0x00, 0x20, 0x9E, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00),
- _INIT_DCS_CMD(0xBD, 0x03),
- _INIT_DCS_CMD(0xE9, 0xC6),
- _INIT_DCS_CMD(0xB4, 0x03, 0xFF, 0xF8),
- _INIT_DCS_CMD(0xE9, 0x3F),
- _INIT_DCS_CMD(0xD8, 0x00, 0x2A, 0xAA, 0xA8, 0x00, 0x00, 0x00, 0x2A, 0xAA, 0xA8, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x2A, 0xAA, 0xA8,
- 0x00, 0x00, 0x00, 0x2A, 0xAA, 0xA8, 0x00, 0x00),
- _INIT_DCS_CMD(0xBD, 0x00),
- _INIT_DCS_CMD(0xE9, 0xC4),
- _INIT_DCS_CMD(0xBA, 0x96),
- _INIT_DCS_CMD(0xE9, 0x3F),
- _INIT_DCS_CMD(0xBD, 0x01),
- _INIT_DCS_CMD(0xE9, 0xC5),
- _INIT_DCS_CMD(0xBA, 0x4F),
- _INIT_DCS_CMD(0xE9, 0x3F),
- _INIT_DCS_CMD(0xBD, 0x00),
- _INIT_DCS_CMD(0x11),
- _INIT_DELAY_CMD(120),
- _INIT_DCS_CMD(0x29),
- {},
-};
+ mipi_dsi_msleep(&ctx, 120);
-static inline struct boe_panel *to_boe_panel(struct drm_panel *panel)
-{
- return container_of(panel, struct boe_panel, base);
-}
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x29);
+
+ mipi_dsi_msleep(&ctx, 120);
-static int boe_panel_init_dcs_cmd(struct boe_panel *boe)
-{
- struct mipi_dsi_device *dsi = boe->dsi;
- struct drm_panel *panel = &boe->base;
- int i, err = 0;
-
- if (boe->desc->init_cmds) {
- const struct panel_init_cmd *init_cmds = boe->desc->init_cmds;
-
- for (i = 0; init_cmds[i].len != 0; i++) {
- const struct panel_init_cmd *cmd = &init_cmds[i];
-
- switch (cmd->type) {
- case DELAY_CMD:
- msleep(cmd->data[0]);
- err = 0;
- break;
-
- case INIT_DCS_CMD:
- err = mipi_dsi_dcs_write(dsi, cmd->data[0],
- cmd->len <= 1 ? NULL :
- &cmd->data[1],
- cmd->len - 1);
- break;
-
- default:
- err = -EINVAL;
- }
-
- if (err < 0) {
- dev_err(panel->dev,
- "failed to write command %u\n", i);
- return err;
- }
- }
- }
return 0;
-}
+};
-static int boe_panel_enter_sleep_mode(struct boe_panel *boe)
+static int auo_b101uan08_3_init(struct boe_panel *boe)
{
- struct mipi_dsi_device *dsi = boe->dsi;
- int ret;
-
- dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+ struct mipi_dsi_multi_context ctx = { .dsi = boe->dsi };
+
+ msleep(24);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x48);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc1, 0x48);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0x47);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0x47);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0x46);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0x46);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc6, 0x45);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc7, 0x45);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0x64);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x64);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x4f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x4f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcc, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcd, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xce, 0x66);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcf, 0x66);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd0, 0x4f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd1, 0x4f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd2, 0x41);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd3, 0x41);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd4, 0x48);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd5, 0x48);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd6, 0x47);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd7, 0x47);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd8, 0x46);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd9, 0x46);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xda, 0x45);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdb, 0x45);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdc, 0x64);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdd, 0x64);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xde, 0x4f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdf, 0x4f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe0, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe1, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe2, 0x66);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe3, 0x66);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe4, 0x4f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe5, 0x4f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe6, 0x41);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe7, 0x41);
+
+ mipi_dsi_msleep(&ctx, 150);
- ret = mipi_dsi_dcs_set_display_off(dsi);
- if (ret < 0)
- return ret;
+ return 0;
+};
- ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
- if (ret < 0)
- return ret;
+static int starry_qfh032011_53g_init(struct boe_panel *boe)
+{
+ struct mipi_dsi_multi_context ctx = { .dsi = boe->dsi };
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0x4f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc6, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc7, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0x4d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x52);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x51);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcd, 0x5d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xce, 0x5b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcf, 0x4b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd0, 0x49);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd1, 0x47);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd2, 0x45);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd3, 0x41);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd7, 0x50);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd8, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd9, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xda, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdb, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdc, 0x4e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdd, 0x52);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xde, 0x51);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe1, 0x5e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe2, 0x5c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe3, 0x4c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe4, 0x4a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe5, 0x48);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe6, 0x46);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe7, 0x42);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbe, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcc, 0x44);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x42);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcd, 0x3e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcf, 0x60);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd2, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd3, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd4, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd5, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd6, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd7, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd9, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe4, 0xf0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe5, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcc, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc1, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0x20);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0x24);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0x23);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0x29);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc6, 0x23);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc7, 0x1c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0x19);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x17);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x17);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x18);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcc, 0x1a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcd, 0x1e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xce, 0x20);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcf, 0x23);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd0, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd1, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd2, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd3, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd4, 0x13);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd5, 0x1c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd6, 0x1a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd7, 0x13);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd8, 0x17);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd9, 0x1c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xda, 0x19);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdb, 0x17);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdc, 0x17);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdd, 0x18);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xde, 0x1a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdf, 0x1e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe0, 0x20);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe1, 0x23);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe2, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0X11);
+
+ mipi_dsi_msleep(&ctx, 120);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0X29);
+
+ mipi_dsi_msleep(&ctx, 80);
return 0;
+};
+
+static inline struct boe_panel *to_boe_panel(struct drm_panel *panel)
+{
+ return container_of(panel, struct boe_panel, base);
}
static int boe_panel_disable(struct drm_panel *panel)
{
struct boe_panel *boe = to_boe_panel(panel);
- int ret;
+ struct mipi_dsi_multi_context ctx = { .dsi = boe->dsi };
- ret = boe_panel_enter_sleep_mode(boe);
- if (ret < 0) {
- dev_err(panel->dev, "failed to set panel off: %d\n", ret);
- return ret;
- }
+ boe->dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
- msleep(150);
+ mipi_dsi_dcs_set_display_off_multi(&ctx);
+ mipi_dsi_dcs_enter_sleep_mode_multi(&ctx);
- return 0;
+ mipi_dsi_msleep(&ctx, 150);
+
+ return ctx.accum_err;
}
static int boe_panel_unprepare(struct drm_panel *panel)
{
struct boe_panel *boe = to_boe_panel(panel);
- if (!boe->prepared)
- return 0;
-
if (boe->desc->discharge_on_disable) {
regulator_disable(boe->avee);
regulator_disable(boe->avdd);
@@ -1471,8 +1415,6 @@ static int boe_panel_unprepare(struct drm_panel *panel)
regulator_disable(boe->pp3300);
}
- boe->prepared = false;
-
return 0;
}
@@ -1481,9 +1423,6 @@ static int boe_panel_prepare(struct drm_panel *panel)
struct boe_panel *boe = to_boe_panel(panel);
int ret;
- if (boe->prepared)
- return 0;
-
gpiod_set_value(boe->enable_gpio, 0);
usleep_range(1000, 1500);
@@ -1507,7 +1446,11 @@ static int boe_panel_prepare(struct drm_panel *panel)
usleep_range(10000, 11000);
if (boe->desc->lp11_before_reset) {
- mipi_dsi_dcs_nop(boe->dsi);
+ ret = mipi_dsi_dcs_nop(boe->dsi);
+ if (ret < 0) {
+ dev_err(&boe->dsi->dev, "Failed to send NOP: %d\n", ret);
+ goto poweroff;
+ }
usleep_range(1000, 2000);
}
gpiod_set_value(boe->enable_gpio, 1);
@@ -1517,24 +1460,20 @@ static int boe_panel_prepare(struct drm_panel *panel)
gpiod_set_value(boe->enable_gpio, 1);
usleep_range(6000, 10000);
- ret = boe_panel_init_dcs_cmd(boe);
- if (ret < 0) {
- dev_err(panel->dev, "failed to init panel: %d\n", ret);
+ ret = boe->desc->init(boe);
+ if (ret < 0)
goto poweroff;
- }
-
- boe->prepared = true;
return 0;
poweroff:
+ gpiod_set_value(boe->enable_gpio, 0);
regulator_disable(boe->avee);
poweroffavdd:
regulator_disable(boe->avdd);
poweroff1v8:
usleep_range(5000, 7000);
regulator_disable(boe->pp1800);
- gpiod_set_value(boe->enable_gpio, 0);
return ret;
}
@@ -1571,7 +1510,7 @@ static const struct panel_desc boe_tv110c9m_desc = {
| MIPI_DSI_MODE_VIDEO_HSE
| MIPI_DSI_CLOCK_NON_CONTINUOUS
| MIPI_DSI_MODE_VIDEO_BURST,
- .init_cmds = boe_tv110c9m_init_cmd,
+ .init = boe_tv110c9m_init,
};
static const struct drm_display_mode inx_hj110iz_default_mode = {
@@ -1600,7 +1539,7 @@ static const struct panel_desc inx_hj110iz_desc = {
| MIPI_DSI_MODE_VIDEO_HSE
| MIPI_DSI_CLOCK_NON_CONTINUOUS
| MIPI_DSI_MODE_VIDEO_BURST,
- .init_cmds = inx_hj110iz_init_cmd,
+ .init = inx_hj110iz_init,
};
static const struct drm_display_mode boe_tv101wum_nl6_default_mode = {
@@ -1626,7 +1565,7 @@ static const struct panel_desc boe_tv101wum_nl6_desc = {
.format = MIPI_DSI_FMT_RGB888,
.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
MIPI_DSI_MODE_LPM,
- .init_cmds = boe_init_cmd,
+ .init = boe_init,
.discharge_on_disable = false,
};
@@ -1653,7 +1592,7 @@ static const struct panel_desc auo_kd101n80_45na_desc = {
.format = MIPI_DSI_FMT_RGB888,
.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
MIPI_DSI_MODE_LPM,
- .init_cmds = auo_kd101n80_45na_init_cmd,
+ .init = auo_kd101n80_45na_init,
.discharge_on_disable = true,
};
@@ -1681,7 +1620,7 @@ static const struct panel_desc boe_tv101wum_n53_desc = {
.format = MIPI_DSI_FMT_RGB888,
.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
MIPI_DSI_MODE_LPM,
- .init_cmds = boe_init_cmd,
+ .init = boe_init,
};
static const struct drm_display_mode auo_b101uan08_3_default_mode = {
@@ -1708,7 +1647,7 @@ static const struct panel_desc auo_b101uan08_3_desc = {
.format = MIPI_DSI_FMT_RGB888,
.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
MIPI_DSI_MODE_LPM,
- .init_cmds = auo_b101uan08_3_init_cmd,
+ .init = auo_b101uan08_3_init,
.lp11_before_reset = true,
};
@@ -1736,7 +1675,7 @@ static const struct panel_desc boe_tv105wum_nw0_desc = {
.format = MIPI_DSI_FMT_RGB888,
.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
MIPI_DSI_MODE_LPM,
- .init_cmds = boe_init_cmd,
+ .init = boe_init,
.lp11_before_reset = true,
};
@@ -1763,35 +1702,7 @@ static const struct panel_desc starry_qfh032011_53g_desc = {
.format = MIPI_DSI_FMT_RGB888,
.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
MIPI_DSI_MODE_LPM,
- .init_cmds = starry_qfh032011_53g_init_cmd,
- .lp11_before_reset = true,
-};
-
-static const struct drm_display_mode starry_himax83102_j02_default_mode = {
- .clock = 162680,
- .hdisplay = 1200,
- .hsync_start = 1200 + 60,
- .hsync_end = 1200 + 60 + 20,
- .htotal = 1200 + 60 + 20 + 40,
- .vdisplay = 1920,
- .vsync_start = 1920 + 116,
- .vsync_end = 1920 + 116 + 8,
- .vtotal = 1920 + 116 + 8 + 12,
- .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
-};
-
-static const struct panel_desc starry_himax83102_j02_desc = {
- .modes = &starry_himax83102_j02_default_mode,
- .bpc = 8,
- .size = {
- .width_mm = 141,
- .height_mm = 226,
- },
- .lanes = 4,
- .format = MIPI_DSI_FMT_RGB888,
- .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
- MIPI_DSI_MODE_LPM,
- .init_cmds = starry_himax83102_j02_init_cmd,
+ .init = starry_qfh032011_53g_init,
.lp11_before_reset = true,
};
@@ -1922,21 +1833,11 @@ static int boe_panel_probe(struct mipi_dsi_device *dsi)
return ret;
}
-static void boe_panel_shutdown(struct mipi_dsi_device *dsi)
-{
- struct boe_panel *boe = mipi_dsi_get_drvdata(dsi);
-
- drm_panel_disable(&boe->base);
- drm_panel_unprepare(&boe->base);
-}
-
static void boe_panel_remove(struct mipi_dsi_device *dsi)
{
struct boe_panel *boe = mipi_dsi_get_drvdata(dsi);
int ret;
- boe_panel_shutdown(dsi);
-
ret = mipi_dsi_detach(dsi);
if (ret < 0)
dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret);
@@ -1970,9 +1871,6 @@ static const struct of_device_id boe_of_match[] = {
{ .compatible = "starry,2081101qfh032011-53g",
.data = &starry_qfh032011_53g_desc
},
- { .compatible = "starry,himax83102-j02",
- .data = &starry_himax83102_j02_desc
- },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, boe_of_match);
@@ -1984,7 +1882,6 @@ static struct mipi_dsi_driver boe_panel_driver = {
},
.probe = boe_panel_probe,
.remove = boe_panel_remove,
- .shutdown = boe_panel_shutdown,
};
module_mipi_dsi_driver(boe_panel_driver);
diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c
index 6db277efcbb7..3a574a9b46e7 100644
--- a/drivers/gpu/drm/panel/panel-edp.c
+++ b/drivers/gpu/drm/panel/panel-edp.c
@@ -222,11 +222,8 @@ struct edp_panel_entry {
struct panel_edp {
struct drm_panel base;
- bool enabled;
bool no_hpd;
- bool prepared;
-
ktime_t prepared_time;
ktime_t powered_on_time;
ktime_t unprepared_time;
@@ -395,14 +392,9 @@ static int panel_edp_disable(struct drm_panel *panel)
{
struct panel_edp *p = to_panel_edp(panel);
- if (!p->enabled)
- return 0;
-
if (p->desc->delay.disable)
msleep(p->desc->delay.disable);
- p->enabled = false;
-
return 0;
}
@@ -420,17 +412,11 @@ static int panel_edp_suspend(struct device *dev)
static int panel_edp_unprepare(struct drm_panel *panel)
{
- struct panel_edp *p = to_panel_edp(panel);
int ret;
- /* Unpreparing when already unprepared is a no-op */
- if (!p->prepared)
- return 0;
-
ret = pm_runtime_put_sync_suspend(panel->dev);
if (ret < 0)
return ret;
- p->prepared = false;
return 0;
}
@@ -542,21 +528,14 @@ static int panel_edp_resume(struct device *dev)
static int panel_edp_prepare(struct drm_panel *panel)
{
- struct panel_edp *p = to_panel_edp(panel);
int ret;
- /* Preparing when already prepared is a no-op */
- if (p->prepared)
- return 0;
-
ret = pm_runtime_get_sync(panel->dev);
if (ret < 0) {
pm_runtime_put_autosuspend(panel->dev);
return ret;
}
- p->prepared = true;
-
return 0;
}
@@ -565,9 +544,6 @@ static int panel_edp_enable(struct drm_panel *panel)
struct panel_edp *p = to_panel_edp(panel);
unsigned int delay;
- if (p->enabled)
- return 0;
-
delay = p->desc->delay.enable;
/*
@@ -598,8 +574,6 @@ static int panel_edp_enable(struct drm_panel *panel)
panel_edp_wait(p->powered_on_time, p->desc->delay.powered_on_to_enable);
- p->enabled = true;
-
return 0;
}
@@ -869,7 +843,6 @@ static int panel_edp_probe(struct device *dev, const struct panel_desc *desc,
if (!panel)
return -ENOMEM;
- panel->enabled = false;
panel->prepared_time = 0;
panel->desc = desc;
panel->aux = aux;
@@ -971,13 +944,34 @@ err_finished_ddc_init:
return err;
}
-static void panel_edp_remove(struct device *dev)
+static void panel_edp_shutdown(struct device *dev)
{
struct panel_edp *panel = dev_get_drvdata(dev);
- drm_panel_remove(&panel->base);
+ /*
+ * NOTE: the following two calls don't really belong here. It is the
+ * responsibility of a correctly written DRM modeset driver to call
+ * drm_atomic_helper_shutdown() at shutdown time and that should
+ * cause the panel to be disabled / unprepared if needed. For now,
+ * however, we'll keep these calls due to the sheer number of
+ * different DRM modeset drivers used with panel-edp. The fact that
+ * we're calling these and _also_ the drm_atomic_helper_shutdown()
+ * will try to disable/unprepare means that we can get a warning about
+ * trying to disable/unprepare an already disabled/unprepared panel,
+ * but that's something we'll have to live with until we've confirmed
+ * that all DRM modeset drivers are properly calling
+ * drm_atomic_helper_shutdown().
+ */
drm_panel_disable(&panel->base);
drm_panel_unprepare(&panel->base);
+}
+
+static void panel_edp_remove(struct device *dev)
+{
+ struct panel_edp *panel = dev_get_drvdata(dev);
+
+ drm_panel_remove(&panel->base);
+ panel_edp_shutdown(dev);
pm_runtime_dont_use_autosuspend(dev);
pm_runtime_disable(dev);
@@ -988,14 +982,6 @@ static void panel_edp_remove(struct device *dev)
panel->drm_edid = NULL;
}
-static void panel_edp_shutdown(struct device *dev)
-{
- struct panel_edp *panel = dev_get_drvdata(dev);
-
- drm_panel_disable(&panel->base);
- drm_panel_unprepare(&panel->base);
-}
-
static const struct display_timing auo_b101ean01_timing = {
.pixelclock = { 65300000, 72500000, 75000000 },
.hactive = { 1280, 1280, 1280 },
@@ -1059,33 +1045,6 @@ static const struct panel_desc auo_b116xak01 = {
},
};
-static const struct drm_display_mode auo_b133han05_mode = {
- .clock = 142600,
- .hdisplay = 1920,
- .hsync_start = 1920 + 58,
- .hsync_end = 1920 + 58 + 42,
- .htotal = 1920 + 58 + 42 + 60,
- .vdisplay = 1080,
- .vsync_start = 1080 + 3,
- .vsync_end = 1080 + 3 + 5,
- .vtotal = 1080 + 3 + 5 + 54,
-};
-
-static const struct panel_desc auo_b133han05 = {
- .modes = &auo_b133han05_mode,
- .num_modes = 1,
- .bpc = 8,
- .size = {
- .width = 293,
- .height = 165,
- },
- .delay = {
- .hpd_reliable = 100,
- .enable = 20,
- .unprepare = 50,
- },
-};
-
static const struct drm_display_mode auo_b133htn01_mode = {
.clock = 150660,
.hdisplay = 1920,
@@ -1135,33 +1094,6 @@ static const struct panel_desc auo_b133xtn01 = {
},
};
-static const struct drm_display_mode auo_b140han06_mode = {
- .clock = 141000,
- .hdisplay = 1920,
- .hsync_start = 1920 + 16,
- .hsync_end = 1920 + 16 + 16,
- .htotal = 1920 + 16 + 16 + 152,
- .vdisplay = 1080,
- .vsync_start = 1080 + 3,
- .vsync_end = 1080 + 3 + 14,
- .vtotal = 1080 + 3 + 14 + 19,
-};
-
-static const struct panel_desc auo_b140han06 = {
- .modes = &auo_b140han06_mode,
- .num_modes = 1,
- .bpc = 8,
- .size = {
- .width = 309,
- .height = 174,
- },
- .delay = {
- .hpd_reliable = 100,
- .enable = 20,
- .unprepare = 50,
- },
-};
-
static const struct drm_display_mode boe_nv101wxmn51_modes[] = {
{
.clock = 71900,
@@ -1428,33 +1360,6 @@ static const struct panel_desc innolux_p120zdg_bf1 = {
},
};
-static const struct drm_display_mode ivo_m133nwf4_r0_mode = {
- .clock = 138778,
- .hdisplay = 1920,
- .hsync_start = 1920 + 24,
- .hsync_end = 1920 + 24 + 48,
- .htotal = 1920 + 24 + 48 + 88,
- .vdisplay = 1080,
- .vsync_start = 1080 + 3,
- .vsync_end = 1080 + 3 + 12,
- .vtotal = 1080 + 3 + 12 + 17,
- .flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC,
-};
-
-static const struct panel_desc ivo_m133nwf4_r0 = {
- .modes = &ivo_m133nwf4_r0_mode,
- .num_modes = 1,
- .bpc = 8,
- .size = {
- .width = 294,
- .height = 165,
- },
- .delay = {
- .hpd_absent = 200,
- .unprepare = 500,
- },
-};
-
static const struct drm_display_mode kingdisplay_kd116n21_30nv_a010_mode = {
.clock = 81000,
.hdisplay = 1366,
@@ -1703,98 +1608,40 @@ static const struct panel_desc sharp_lq123p1jx31 = {
},
};
-static const struct drm_display_mode sharp_lq140m1jw46_mode[] = {
- {
- .clock = 346500,
- .hdisplay = 1920,
- .hsync_start = 1920 + 48,
- .hsync_end = 1920 + 48 + 32,
- .htotal = 1920 + 48 + 32 + 80,
- .vdisplay = 1080,
- .vsync_start = 1080 + 3,
- .vsync_end = 1080 + 3 + 5,
- .vtotal = 1080 + 3 + 5 + 69,
- .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
- }, {
- .clock = 144370,
- .hdisplay = 1920,
- .hsync_start = 1920 + 48,
- .hsync_end = 1920 + 48 + 32,
- .htotal = 1920 + 48 + 32 + 80,
- .vdisplay = 1080,
- .vsync_start = 1080 + 3,
- .vsync_end = 1080 + 3 + 5,
- .vtotal = 1080 + 3 + 5 + 69,
- .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
- },
-};
-
-static const struct panel_desc sharp_lq140m1jw46 = {
- .modes = sharp_lq140m1jw46_mode,
- .num_modes = ARRAY_SIZE(sharp_lq140m1jw46_mode),
- .bpc = 8,
- .size = {
- .width = 309,
- .height = 174,
- },
- .delay = {
- .hpd_absent = 80,
- .enable = 50,
- .unprepare = 500,
- },
-};
-
-static const struct drm_display_mode starry_kr122ea0sra_mode = {
- .clock = 147000,
- .hdisplay = 1920,
- .hsync_start = 1920 + 16,
- .hsync_end = 1920 + 16 + 16,
- .htotal = 1920 + 16 + 16 + 32,
- .vdisplay = 1200,
- .vsync_start = 1200 + 15,
- .vsync_end = 1200 + 15 + 2,
- .vtotal = 1200 + 15 + 2 + 18,
- .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
-};
-
-static const struct panel_desc starry_kr122ea0sra = {
- .modes = &starry_kr122ea0sra_mode,
- .num_modes = 1,
- .size = {
- .width = 263,
- .height = 164,
- },
- .delay = {
- /* TODO: should be hpd-absent and no-hpd should be set? */
- .hpd_reliable = 10 + 200,
- .enable = 50,
- .unprepare = 10 + 500,
- },
-};
-
static const struct of_device_id platform_of_match[] = {
{
/* Must be first */
.compatible = "edp-panel",
- }, {
+ },
+ /*
+ * Do not add panels to the list below unless they cannot be handled by
+ * the generic edp-panel compatible.
+ *
+ * The only two valid reasons are:
+ * - Because of the panel issues (e.g. broken EDID or broken
+ * identification).
+ * - Because the eDP drivers didn't wire up the AUX bus properly.
+ * NOTE that, though this is a marginally valid reason,
+ * some justification needs to be made for why the platform can't
+ * wire up the AUX bus properly.
+ *
+ * In all other cases the platform should use the aux-bus and declare
+ * the panel using the 'edp-panel' compatible as a device on the AUX
+ * bus.
+ */
+ {
.compatible = "auo,b101ean01",
.data = &auo_b101ean01,
}, {
.compatible = "auo,b116xa01",
.data = &auo_b116xak01,
}, {
- .compatible = "auo,b133han05",
- .data = &auo_b133han05,
- }, {
.compatible = "auo,b133htn01",
.data = &auo_b133htn01,
}, {
.compatible = "auo,b133xtn01",
.data = &auo_b133xtn01,
}, {
- .compatible = "auo,b140han06",
- .data = &auo_b140han06,
- }, {
.compatible = "boe,nv101wxmn51",
.data = &boe_nv101wxmn51,
}, {
@@ -1822,9 +1669,6 @@ static const struct of_device_id platform_of_match[] = {
.compatible = "innolux,p120zdg-bf1",
.data = &innolux_p120zdg_bf1,
}, {
- .compatible = "ivo,m133nwf4-r0",
- .data = &ivo_m133nwf4_r0,
- }, {
.compatible = "kingdisplay,kd116n21-30nv-a010",
.data = &kingdisplay_kd116n21_30nv_a010,
}, {
@@ -1855,12 +1699,6 @@ static const struct of_device_id platform_of_match[] = {
.compatible = "sharp,lq123p1jx31",
.data = &sharp_lq123p1jx31,
}, {
- .compatible = "sharp,lq140m1jw46",
- .data = &sharp_lq140m1jw46,
- }, {
- .compatible = "starry,kr122ea0sra",
- .data = &starry_kr122ea0sra,
- }, {
/* sentinel */
}
};
@@ -1911,6 +1749,12 @@ static const struct panel_delay delay_200_500_e80_d50 = {
.disable = 50,
};
+static const struct panel_delay delay_80_500_e50 = {
+ .hpd_absent = 80,
+ .unprepare = 500,
+ .enable = 50,
+};
+
static const struct panel_delay delay_100_500_e200 = {
.hpd_absent = 100,
.unprepare = 500,
@@ -1983,8 +1827,10 @@ static const struct edp_panel_entry edp_panels[] = {
EDP_PANEL_ENTRY('A', 'U', 'O', 0x1062, &delay_200_500_e50, "B120XAN01.0"),
EDP_PANEL_ENTRY('A', 'U', 'O', 0x125c, &delay_200_500_e50, "Unknown"),
EDP_PANEL_ENTRY('A', 'U', 'O', 0x145c, &delay_200_500_e50, "B116XAB01.4"),
+ EDP_PANEL_ENTRY('A', 'U', 'O', 0x1999, &delay_200_500_e50, "Unknown"),
EDP_PANEL_ENTRY('A', 'U', 'O', 0x1e9b, &delay_200_500_e50, "B133UAN02.1"),
EDP_PANEL_ENTRY('A', 'U', 'O', 0x1ea5, &delay_200_500_e50, "B116XAK01.6"),
+ EDP_PANEL_ENTRY('A', 'U', 'O', 0x203d, &delay_200_500_e50, "B140HTN02.0"),
EDP_PANEL_ENTRY('A', 'U', 'O', 0x208d, &delay_200_500_e50, "B140HTN02.1"),
EDP_PANEL_ENTRY('A', 'U', 'O', 0x235c, &delay_200_500_e50, "B116XTN02.3"),
EDP_PANEL_ENTRY('A', 'U', 'O', 0x239b, &delay_200_500_e50, "B116XAN06.1"),
@@ -2005,6 +1851,8 @@ static const struct edp_panel_entry edp_panels[] = {
EDP_PANEL_ENTRY('B', 'O', 'E', 0x0607, &delay_200_500_e200, "Unknown"),
EDP_PANEL_ENTRY('B', 'O', 'E', 0x0608, &delay_200_500_e50, "NT116WHM-N11"),
+ EDP_PANEL_ENTRY('B', 'O', 'E', 0x0609, &delay_200_500_e50_po2e200, "NT116WHM-N21 V4.1"),
+ EDP_PANEL_ENTRY('B', 'O', 'E', 0x0623, &delay_200_500_e200, "NT116WHM-N21 V4.0"),
EDP_PANEL_ENTRY('B', 'O', 'E', 0x0668, &delay_200_500_e200, "Unknown"),
EDP_PANEL_ENTRY('B', 'O', 'E', 0x068f, &delay_200_500_e200, "Unknown"),
EDP_PANEL_ENTRY('B', 'O', 'E', 0x06e5, &delay_200_500_e200, "Unknown"),
@@ -2020,6 +1868,7 @@ static const struct edp_panel_entry edp_panels[] = {
EDP_PANEL_ENTRY('B', 'O', 'E', 0x0771, &delay_200_500_e200, "Unknown"),
EDP_PANEL_ENTRY('B', 'O', 'E', 0x0786, &delay_200_500_p2e80, "NV116WHM-T01"),
EDP_PANEL_ENTRY('B', 'O', 'E', 0x0797, &delay_200_500_e200, "Unknown"),
+ EDP_PANEL_ENTRY('B', 'O', 'E', 0x07a8, &delay_200_500_e50_po2e200, "NT116WHM-N21"),
EDP_PANEL_ENTRY('B', 'O', 'E', 0x07d1, &boe_nv133fhm_n61.delay, "NV133FHM-N61"),
EDP_PANEL_ENTRY('B', 'O', 'E', 0x07d3, &delay_200_500_e200, "Unknown"),
EDP_PANEL_ENTRY('B', 'O', 'E', 0x07f6, &delay_200_500_e200, "NT140FHM-N44"),
@@ -2067,6 +1916,7 @@ static const struct edp_panel_entry edp_panels[] = {
EDP_PANEL_ENTRY('C', 'M', 'N', 0x1157, &delay_200_500_e80_d50, "N116BGE-EA2"),
EDP_PANEL_ENTRY('C', 'M', 'N', 0x115b, &delay_200_500_e80_d50, "N116BCN-EB1"),
EDP_PANEL_ENTRY('C', 'M', 'N', 0x115e, &delay_200_500_e80_d50, "N116BCA-EA1"),
+ EDP_PANEL_ENTRY('C', 'M', 'N', 0x1160, &delay_200_500_e80_d50, "N116BCJ-EAK"),
EDP_PANEL_ENTRY('C', 'M', 'N', 0x1247, &delay_200_500_e80_d50, "N120ACA-EA1"),
EDP_PANEL_ENTRY('C', 'M', 'N', 0x142b, &delay_200_500_e80_d50, "N140HCA-EAC"),
EDP_PANEL_ENTRY('C', 'M', 'N', 0x142e, &delay_200_500_e80_d50, "N140BGA-EA4"),
@@ -2094,6 +1944,7 @@ static const struct edp_panel_entry edp_panels[] = {
EDP_PANEL_ENTRY('K', 'D', 'B', 0x0624, &kingdisplay_kd116n21_30nv_a010.delay, "116N21-30NV-A010"),
EDP_PANEL_ENTRY('K', 'D', 'B', 0x1118, &delay_200_500_e50, "KD116N29-30NK-A005"),
EDP_PANEL_ENTRY('K', 'D', 'B', 0x1120, &delay_200_500_e80_d50, "116N29-30NK-C007"),
+ EDP_PANEL_ENTRY('K', 'D', 'B', 0x1212, &delay_200_500_e50, "KD116N0930A16"),
EDP_PANEL_ENTRY('K', 'D', 'C', 0x044f, &delay_200_500_e50, "KD116N9-30NH-F3"),
EDP_PANEL_ENTRY('K', 'D', 'C', 0x05f1, &delay_200_500_e80_d50, "KD116N5-30NV-G7"),
@@ -2112,7 +1963,8 @@ static const struct edp_panel_entry edp_panels[] = {
EDP_PANEL_ENTRY('S', 'D', 'C', 0x416d, &delay_100_500_e200, "ATNA45AF01"),
EDP_PANEL_ENTRY('S', 'H', 'P', 0x1511, &delay_200_500_e50, "LQ140M1JW48"),
- EDP_PANEL_ENTRY('S', 'H', 'P', 0x1523, &sharp_lq140m1jw46.delay, "LQ140M1JW46"),
+ EDP_PANEL_ENTRY('S', 'H', 'P', 0x1523, &delay_80_500_e50, "LQ140M1JW46"),
+ EDP_PANEL_ENTRY('S', 'H', 'P', 0x153a, &delay_200_500_e50, "LQ140T1JH01"),
EDP_PANEL_ENTRY('S', 'H', 'P', 0x154c, &delay_200_500_p2e100, "LQ116M1JW10"),
EDP_PANEL_ENTRY('S', 'T', 'A', 0x0100, &delay_100_500_e200, "2081116HHD028001-51D"),
diff --git a/drivers/gpu/drm/panel/panel-himax-hx83102.c b/drivers/gpu/drm/panel/panel-himax-hx83102.c
new file mode 100644
index 000000000000..6e4b7e4644ce
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-himax-hx83102.c
@@ -0,0 +1,706 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for panels based on Himax HX83102 controller, such as:
+ *
+ * - Starry 10.51" WUXGA MIPI-DSI panel
+ *
+ * Based on drivers/gpu/drm/panel/panel-himax-hx8394.c
+ */
+
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+
+#include <drm/drm_connector.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_panel.h>
+
+#include <video/mipi_display.h>
+
+/* Manufacturer specific DSI commands */
+#define HX83102_SETPOWER 0xb1
+#define HX83102_SETDISP 0xb2
+#define HX83102_SETCYC 0xb4
+#define HX83102_SETEXTC 0xb9
+#define HX83102_SETMIPI 0xba
+#define HX83102_SETVDC 0xbc
+#define HX83102_SETBANK 0xbd
+#define HX83102_UNKNOWN_BE 0xbe
+#define HX83102_SETPTBA 0xbf
+#define HX83102_SETSTBA 0xc0
+#define HX83102_SETTCON 0xc7
+#define HX83102_SETRAMDMY 0xc8
+#define HX83102_SETPWM 0xc9
+#define HX83102_SETCLOCK 0xcb
+#define HX83102_SETPANEL 0xcc
+#define HX83102_SETCASCADE 0xd0
+#define HX83102_SETPCTRL 0xd1
+#define HX83102_UNKNOWN_D2 0xd2
+#define HX83102_SETGIP0 0xd3
+#define HX83102_SETGIP1 0xd5
+#define HX83102_SETGIP2 0xd6
+#define HX83102_SETGIP3 0xd8
+#define HX83102_SETGMA 0xe0
+#define HX83102_UNKNOWN_E1 0xe1
+#define HX83102_SETTP1 0xe7
+#define HX83102_SETSPCCMD 0xe9
+
+struct hx83102 {
+ struct drm_panel base;
+ struct mipi_dsi_device *dsi;
+
+ const struct hx83102_panel_desc *desc;
+
+ enum drm_panel_orientation orientation;
+ struct regulator *pp1800;
+ struct regulator *avee;
+ struct regulator *avdd;
+ struct gpio_desc *enable_gpio;
+};
+
+struct hx83102_panel_desc {
+ const struct drm_display_mode *modes;
+
+ /**
+ * @width_mm: width of the panel's active display area
+ * @height_mm: height of the panel's active display area
+ */
+ struct {
+ unsigned int width_mm;
+ unsigned int height_mm;
+ } size;
+
+ int (*init)(struct hx83102 *ctx);
+};
+
+static inline struct hx83102 *panel_to_hx83102(struct drm_panel *panel)
+{
+ return container_of(panel, struct hx83102, base);
+}
+
+static void hx83102_enable_extended_cmds(struct mipi_dsi_multi_context *dsi_ctx, bool enable)
+{
+ if (enable)
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX83102_SETEXTC, 0x83, 0x10, 0x21, 0x55, 0x00);
+ else
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX83102_SETEXTC, 0x00, 0x00, 0x00);
+}
+
+static int starry_himax83102_j02_init(struct hx83102 *ctx)
+{
+ struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi };
+
+ hx83102_enable_extended_cmds(&dsi_ctx, true);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x2c, 0xb5, 0xb5, 0x31, 0xf1,
+ 0x31, 0xd7, 0x2f, 0x36, 0x36, 0x36, 0x36, 0x1a, 0x8b, 0x11,
+ 0x65, 0x00, 0x88, 0xfa, 0xff, 0xff, 0x8f, 0xff, 0x08, 0x74,
+ 0x33);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETDISP, 0x00, 0x47, 0xb0, 0x80, 0x00,
+ 0x12, 0x72, 0x3c, 0xa3, 0x03, 0x03, 0x00, 0x00, 0x88, 0xf5);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x76, 0x76, 0x76, 0x76, 0x76,
+ 0x76, 0x63, 0x5c, 0x63, 0x5c, 0x01, 0x9e);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcd);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x84);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETVDC, 0x1b, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_BE, 0x20);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPTBA, 0xfc, 0xc4);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSTBA, 0x36, 0x36, 0x22, 0x11, 0x22,
+ 0xa0, 0x61, 0x08, 0xf5, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcc);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTCON, 0x80);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc6);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETRAMDMY, 0x97);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPWM, 0x00, 0x1e, 0x13, 0x88, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x08, 0x13, 0x07, 0x00, 0x0f, 0x33);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPANEL, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc4);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCASCADE, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPCTRL, 0x37, 0x06, 0x00, 0x02, 0x04, 0x0c,
+ 0xff);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_D2, 0x1f, 0x11, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x08, 0x37, 0x47, 0x34, 0x3b, 0x12, 0x12, 0x03, 0x03,
+ 0x32, 0x10, 0x10, 0x00, 0x10, 0x32, 0x10, 0x08, 0x00, 0x08, 0x32,
+ 0x17, 0x94, 0x07, 0x94, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP1, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x19, 0x19, 0x40, 0x40, 0x1a, 0x1a, 0x1b,
+ 0x1b, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x20, 0x21,
+ 0x28, 0x29, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP2, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x40, 0x40, 0x19, 0x19, 0x1a, 0x1a, 0x1b,
+ 0x1b, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x29, 0x28,
+ 0x21, 0x20, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xaa, 0xba, 0xea, 0xaa, 0xaa, 0xa0,
+ 0xaa, 0xba, 0xea, 0xaa, 0xaa, 0xa0, 0xaa, 0xba, 0xea, 0xaa, 0xaa,
+ 0xa0, 0xaa, 0xba, 0xea, 0xaa, 0xaa, 0xa0, 0xaa, 0xba, 0xea, 0xaa,
+ 0xaa, 0xa0, 0xaa, 0xba, 0xea, 0xaa, 0xaa, 0xa0);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGMA, 0x00, 0x09, 0x14, 0x1e, 0x26, 0x48,
+ 0x61, 0x67, 0x6c, 0x67, 0x7d, 0x7f, 0x80, 0x8b, 0x87, 0x8f, 0x98,
+ 0xab, 0xab, 0x55, 0x5c, 0x68, 0x73, 0x00, 0x09, 0x14, 0x1e, 0x26,
+ 0x48, 0x61, 0x67, 0x6c, 0x67, 0x7d, 0x7f, 0x80, 0x8b, 0x87, 0x8f,
+ 0x98, 0xab, 0xab, 0x55, 0x5c, 0x68, 0x73);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0x0e, 0x10, 0x10, 0x21, 0x2b, 0x9a,
+ 0x02, 0x54, 0x9a, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x12, 0x05,
+ 0x02, 0x02, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x01, 0xbf, 0x11);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x86);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_D2, 0x3c, 0xfa);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x0c, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0x02, 0x00, 0x28, 0x01, 0x7e, 0x0f,
+ 0x7e, 0x10, 0xa0, 0x00, 0x00, 0x20, 0x40, 0x50, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xff, 0xff, 0xbf, 0xfe, 0xaa, 0xa0,
+ 0xff, 0xff, 0xbf, 0xfe, 0xaa, 0xa0);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0xfe, 0x04, 0xfe, 0x04, 0xfe, 0x04,
+ 0x03, 0x03, 0x03, 0x26, 0x00, 0x26, 0x81, 0x02, 0x40, 0x00, 0x20,
+ 0x9e, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc6);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x03, 0xff, 0xf8);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0x00, 0x2a, 0xaa, 0xa8, 0x00, 0x00,
+ 0x00, 0x2a, 0xaa, 0xa8, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfc, 0x00,
+ 0x00, 0x00, 0x3f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x2a, 0xaa, 0xa8,
+ 0x00, 0x00, 0x00, 0x2a, 0xaa, 0xa8, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc4);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x96);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc5);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x4f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00);
+
+ return dsi_ctx.accum_err;
+};
+
+static int boe_nv110wum_init(struct hx83102 *ctx)
+{
+ struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi };
+
+ msleep(60);
+
+ hx83102_enable_extended_cmds(&dsi_ctx, true);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x2c, 0xaf, 0xaf, 0x2b, 0xeb, 0x42,
+ 0xe1, 0x4d, 0x36, 0x36, 0x36, 0x36, 0x1a, 0x8b, 0x11, 0x65, 0x00,
+ 0x88, 0xfa, 0xff, 0xff, 0x8f, 0xff, 0x08, 0x9a, 0x33);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETDISP, 0x00, 0x47, 0xb0, 0x80, 0x00, 0x12,
+ 0x71, 0x3c, 0xa3, 0x11, 0x00, 0x00, 0x00, 0x88, 0xf5, 0x22, 0x8f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x49, 0x49, 0x32, 0x32, 0x14, 0x32,
+ 0x84, 0x6e, 0x84, 0x6e, 0x01, 0x9c);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcd);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x84);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETVDC, 0x1b, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_BE, 0x20);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPTBA, 0xfc, 0x84);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSTBA, 0x36, 0x36, 0x22, 0x00, 0x00, 0xa0,
+ 0x61, 0x08, 0xf5, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcc);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTCON, 0x80);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc6);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETRAMDMY, 0x97);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPWM, 0x00, 0x1e, 0x30, 0xd4, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x08, 0x13, 0x07, 0x00, 0x0f, 0x34);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPANEL, 0x02, 0x03, 0x44);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc4);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCASCADE, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPCTRL, 0x37, 0x06, 0x00, 0x02, 0x04, 0x0c, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_D2, 0x1f, 0x11, 0x1f, 0x11);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x06, 0x00, 0x00, 0x00, 0x00, 0x04,
+ 0x08, 0x04, 0x08, 0x37, 0x37, 0x64, 0x4b, 0x11, 0x11, 0x03, 0x03, 0x32,
+ 0x10, 0x0e, 0x00, 0x0e, 0x32, 0x10, 0x0a, 0x00, 0x0a, 0x32, 0x17, 0x98,
+ 0x07, 0x98, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP1, 0x18, 0x18, 0x18, 0x18, 0x1e, 0x1e,
+ 0x1e, 0x1e, 0x1f, 0x1f, 0x1f, 0x1f, 0x24, 0x24, 0x24, 0x24, 0x07, 0x06,
+ 0x07, 0x06, 0x05, 0x04, 0x05, 0x04, 0x03, 0x02, 0x03, 0x02, 0x01, 0x00,
+ 0x01, 0x00, 0x21, 0x20, 0x21, 0x20, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0,
+ 0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGMA, 0x00, 0x05, 0x0d, 0x14, 0x1b, 0x2c,
+ 0x44, 0x49, 0x51, 0x4c, 0x67, 0x6c, 0x71, 0x80, 0x7d, 0x84, 0x8d, 0xa0,
+ 0xa0, 0x4f, 0x58, 0x64, 0x73, 0x00, 0x05, 0x0d, 0x14, 0x1b, 0x2c, 0x44,
+ 0x49, 0x51, 0x4c, 0x67, 0x6c, 0x71, 0x80, 0x7d, 0x84, 0x8d, 0xa0, 0xa0,
+ 0x4f, 0x58, 0x64, 0x73);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0x07, 0x10, 0x10, 0x1a, 0x26, 0x9e,
+ 0x00, 0x53, 0x9b, 0x14, 0x14);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_E1, 0x11, 0x00, 0x00, 0x89, 0x30, 0x80,
+ 0x07, 0x80, 0x02, 0x58, 0x00, 0x14, 0x02, 0x58, 0x02, 0x58, 0x02, 0x00,
+ 0x02, 0x2c, 0x00, 0x20, 0x02, 0x02, 0x00, 0x08, 0x00, 0x0c, 0x05, 0x0e,
+ 0x04, 0x94, 0x18, 0x00, 0x10, 0xf0, 0x03, 0x0c, 0x20, 0x00, 0x06, 0x0b,
+ 0x0b, 0x33, 0x0e);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xa0,
+ 0xff, 0xff, 0xff, 0xff, 0xfa, 0xa0);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x01, 0xbf, 0x11);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x86);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_D2, 0x96);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc9);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x84);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xd1);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_E1, 0xf6, 0x2b, 0x34, 0x2b, 0x74, 0x3b,
+ 0x74, 0x6b, 0x74);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0x02, 0x00, 0x2b, 0x01, 0x7e, 0x0f,
+ 0x7e, 0x10, 0xa0, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x02, 0x00, 0xbb, 0x11);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xff, 0xaf, 0xff, 0xff, 0xfa, 0xa0,
+ 0xff, 0xaf, 0xff, 0xff, 0xfa, 0xa0);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01,
+ 0x00, 0x00, 0x00, 0x23, 0x00, 0x23, 0x81, 0x02, 0x40, 0x00, 0x20, 0x65,
+ 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xaa, 0xaf, 0xaa, 0xaa, 0xa0, 0x00,
+ 0xaa, 0xaf, 0xaa, 0xaa, 0xa0, 0x00, 0xaa, 0xaf, 0xaa, 0xaa, 0xa0, 0x00,
+ 0xaa, 0xaf, 0xaa, 0xaa, 0xa0, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc6);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x03, 0xff, 0xf8);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_E1, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc4);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x96);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc5);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x4f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00);
+ hx83102_enable_extended_cmds(&dsi_ctx, false);
+
+ mipi_dsi_msleep(&dsi_ctx, 50);
+
+ return dsi_ctx.accum_err;
+};
+
+static int ivo_t109nw41_init(struct hx83102 *ctx)
+{
+ struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi };
+
+ msleep(60);
+
+ hx83102_enable_extended_cmds(&dsi_ctx, true);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x2c, 0xed, 0xed, 0x0f, 0xcf, 0x42,
+ 0xf5, 0x39, 0x36, 0x36, 0x36, 0x36, 0x32, 0x8b, 0x11, 0x65, 0x00, 0x88,
+ 0xfa, 0xff, 0xff, 0x8f, 0xff, 0x08, 0xd6, 0x33);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETDISP, 0x00, 0x47, 0xb0, 0x80, 0x00, 0x12,
+ 0x71, 0x3c, 0xa3, 0x22, 0x20, 0x00, 0x00, 0x88, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x35, 0x35, 0x43, 0x43, 0x35, 0x35,
+ 0x30, 0x7a, 0x30, 0x7a, 0x01, 0x9d);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcd);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x84);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETVDC, 0x1b, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_BE, 0x20);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPTBA, 0xfc, 0xc4);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSTBA, 0x34, 0x34, 0x22, 0x11, 0x22, 0xa0,
+ 0x31, 0x08, 0xf5, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcc);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTCON, 0x80);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xd3);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTCON, 0x22);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc6);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETRAMDMY, 0x97);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPWM, 0x00, 0x1e, 0x13, 0x88, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x08, 0x13, 0x07, 0x00, 0x0f, 0x34);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPANEL, 0x02, 0x03, 0x44);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc4);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCASCADE, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPCTRL, 0x07, 0x06, 0x00, 0x02, 0x04, 0x2c,
+ 0xff);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x06, 0x00, 0x00, 0x00, 0x00, 0x08,
+ 0x08, 0x08, 0x08, 0x37, 0x07, 0x64, 0x7c, 0x11, 0x11, 0x03, 0x03, 0x32,
+ 0x10, 0x0e, 0x00, 0x0e, 0x32, 0x17, 0x97, 0x07, 0x97, 0x32, 0x00, 0x02,
+ 0x00, 0x02, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP1, 0x25, 0x24, 0x25, 0x24, 0x18, 0x18,
+ 0x18, 0x18, 0x07, 0x06, 0x07, 0x06, 0x05, 0x04, 0x05, 0x04, 0x03, 0x02,
+ 0x03, 0x02, 0x01, 0x00, 0x01, 0x00, 0x1e, 0x1e, 0x1e, 0x1e, 0x1f, 0x1f,
+ 0x1f, 0x1f, 0x21, 0x20, 0x21, 0x20, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGMA, 0x04, 0x04, 0x06, 0x0a, 0x0a, 0x05,
+ 0x12, 0x14, 0x17, 0x13, 0x2c, 0x33, 0x39, 0x4b, 0x4c, 0x56, 0x61, 0x78,
+ 0x7a, 0x41, 0x50, 0x68, 0x73, 0x04, 0x04, 0x06, 0x0a, 0x0a, 0x05, 0x12,
+ 0x14, 0x17, 0x13, 0x2c, 0x33, 0x39, 0x4b, 0x4c, 0x56, 0x61, 0x78, 0x7a,
+ 0x41, 0x50, 0x68, 0x73);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0x07, 0x10, 0x10, 0x1a, 0x26, 0x9e,
+ 0x00, 0x4f, 0xa0, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x12, 0x0a, 0x02,
+ 0x02, 0x00, 0x33, 0x02, 0x04, 0x18, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x01, 0x7f, 0x11, 0xfd);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x86);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x00, 0x00, 0x04, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0x02, 0x00, 0x2b, 0x01, 0x7e, 0x0f,
+ 0x7e, 0x10, 0xa0, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPTBA, 0xf2);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x03, 0x07, 0x00, 0x10, 0x79);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xa0,
+ 0xff, 0xff, 0xff, 0xff, 0xfa, 0xa0);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01,
+ 0x00, 0x00, 0x00, 0x23, 0x00, 0x23, 0x81, 0x02, 0x40, 0x00, 0x20, 0x6e,
+ 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xa0,
+ 0xff, 0xff, 0xff, 0xff, 0xfa, 0xa0, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc6);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x03, 0xff, 0xf8);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_E1, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_D2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc4);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x96);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc5);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x4f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00);
+ hx83102_enable_extended_cmds(&dsi_ctx, false);
+
+ mipi_dsi_msleep(&dsi_ctx, 60);
+
+ return dsi_ctx.accum_err;
+};
+
+static const struct drm_display_mode starry_mode = {
+ .clock = 162680,
+ .hdisplay = 1200,
+ .hsync_start = 1200 + 60,
+ .hsync_end = 1200 + 60 + 20,
+ .htotal = 1200 + 60 + 20 + 40,
+ .vdisplay = 1920,
+ .vsync_start = 1920 + 116,
+ .vsync_end = 1920 + 116 + 8,
+ .vtotal = 1920 + 116 + 8 + 12,
+ .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+};
+
+static const struct hx83102_panel_desc starry_desc = {
+ .modes = &starry_mode,
+ .size = {
+ .width_mm = 141,
+ .height_mm = 226,
+ },
+ .init = starry_himax83102_j02_init,
+};
+
+static const struct drm_display_mode boe_tv110wum_default_mode = {
+ .clock = 167700,
+ .hdisplay = 1200,
+ .hsync_start = 1200 + 75,
+ .hsync_end = 1200 + 75 + 20,
+ .htotal = 1200 + 75 + 20 + 65,
+ .vdisplay = 1920,
+ .vsync_start = 1920 + 115,
+ .vsync_end = 1920 + 115 + 8,
+ .vtotal = 1920 + 115 + 8 + 12,
+ .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+};
+
+static const struct hx83102_panel_desc boe_nv110wum_desc = {
+ .modes = &boe_tv110wum_default_mode,
+ .size = {
+ .width_mm = 147,
+ .height_mm = 235,
+ },
+ .init = boe_nv110wum_init,
+};
+
+static const struct drm_display_mode ivo_t109nw41_default_mode = {
+ .clock = 167700,
+ .hdisplay = 1200,
+ .hsync_start = 1200 + 75,
+ .hsync_end = 1200 + 75 + 20,
+ .htotal = 1200 + 75 + 20 + 65,
+ .vdisplay = 1920,
+ .vsync_start = 1920 + 115,
+ .vsync_end = 1920 + 115 + 8,
+ .vtotal = 1920 + 115 + 8 + 12,
+ .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+};
+
+static const struct hx83102_panel_desc ivo_t109nw41_desc = {
+ .modes = &ivo_t109nw41_default_mode,
+ .size = {
+ .width_mm = 147,
+ .height_mm = 235,
+ },
+ .init = ivo_t109nw41_init,
+};
+
+static int hx83102_enable(struct drm_panel *panel)
+{
+ msleep(130);
+ return 0;
+}
+
+static int hx83102_disable(struct drm_panel *panel)
+{
+ struct hx83102 *ctx = panel_to_hx83102(panel);
+ struct mipi_dsi_device *dsi = ctx->dsi;
+ struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
+
+ dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+ mipi_dsi_dcs_set_display_off_multi(&dsi_ctx);
+ mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx);
+
+ mipi_dsi_msleep(&dsi_ctx, 150);
+
+ return dsi_ctx.accum_err;
+}
+
+static int hx83102_unprepare(struct drm_panel *panel)
+{
+ struct hx83102 *ctx = panel_to_hx83102(panel);
+
+ gpiod_set_value(ctx->enable_gpio, 0);
+ usleep_range(1000, 2000);
+ regulator_disable(ctx->avee);
+ regulator_disable(ctx->avdd);
+ usleep_range(5000, 7000);
+ regulator_disable(ctx->pp1800);
+
+ return 0;
+}
+
+static int hx83102_prepare(struct drm_panel *panel)
+{
+ struct hx83102 *ctx = panel_to_hx83102(panel);
+ struct mipi_dsi_device *dsi = ctx->dsi;
+ struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
+
+ gpiod_set_value(ctx->enable_gpio, 0);
+ usleep_range(1000, 1500);
+
+ dsi_ctx.accum_err = regulator_enable(ctx->pp1800);
+ if (dsi_ctx.accum_err)
+ return dsi_ctx.accum_err;
+
+ usleep_range(3000, 5000);
+
+ dsi_ctx.accum_err = regulator_enable(ctx->avdd);
+ if (dsi_ctx.accum_err)
+ goto poweroff1v8;
+ dsi_ctx.accum_err = regulator_enable(ctx->avee);
+ if (dsi_ctx.accum_err)
+ goto poweroffavdd;
+
+ usleep_range(10000, 11000);
+
+ mipi_dsi_dcs_nop_multi(&dsi_ctx);
+ if (dsi_ctx.accum_err)
+ goto poweroff;
+
+ usleep_range(1000, 2000);
+
+ gpiod_set_value(ctx->enable_gpio, 1);
+ usleep_range(1000, 2000);
+ gpiod_set_value(ctx->enable_gpio, 0);
+ usleep_range(1000, 2000);
+ gpiod_set_value(ctx->enable_gpio, 1);
+ usleep_range(6000, 10000);
+
+ dsi_ctx.accum_err = ctx->desc->init(ctx);
+
+ mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);
+ mipi_dsi_msleep(&dsi_ctx, 120);
+ mipi_dsi_dcs_set_display_on_multi(&dsi_ctx);
+ if (dsi_ctx.accum_err)
+ goto poweroff;
+
+ return 0;
+
+poweroff:
+ gpiod_set_value(ctx->enable_gpio, 0);
+ regulator_disable(ctx->avee);
+poweroffavdd:
+ regulator_disable(ctx->avdd);
+poweroff1v8:
+ usleep_range(5000, 7000);
+ regulator_disable(ctx->pp1800);
+
+ return dsi_ctx.accum_err;
+}
+
+static int hx83102_get_modes(struct drm_panel *panel,
+ struct drm_connector *connector)
+{
+ struct hx83102 *ctx = panel_to_hx83102(panel);
+ const struct drm_display_mode *m = ctx->desc->modes;
+ struct drm_display_mode *mode;
+
+ mode = drm_mode_duplicate(connector->dev, m);
+
+ mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+ drm_mode_set_name(mode);
+ drm_mode_probed_add(connector, mode);
+
+ connector->display_info.width_mm = ctx->desc->size.width_mm;
+ connector->display_info.height_mm = ctx->desc->size.height_mm;
+ connector->display_info.bpc = 8;
+
+ return 1;
+}
+
+static enum drm_panel_orientation hx83102_get_orientation(struct drm_panel *panel)
+{
+ struct hx83102 *ctx = panel_to_hx83102(panel);
+
+ return ctx->orientation;
+}
+
+static const struct drm_panel_funcs hx83102_drm_funcs = {
+ .disable = hx83102_disable,
+ .unprepare = hx83102_unprepare,
+ .prepare = hx83102_prepare,
+ .enable = hx83102_enable,
+ .get_modes = hx83102_get_modes,
+ .get_orientation = hx83102_get_orientation,
+};
+
+static int hx83102_panel_add(struct hx83102 *ctx)
+{
+ struct device *dev = &ctx->dsi->dev;
+ int err;
+
+ ctx->avdd = devm_regulator_get(dev, "avdd");
+ if (IS_ERR(ctx->avdd))
+ return PTR_ERR(ctx->avdd);
+
+ ctx->avee = devm_regulator_get(dev, "avee");
+ if (IS_ERR(ctx->avee))
+ return PTR_ERR(ctx->avee);
+
+ ctx->pp1800 = devm_regulator_get(dev, "pp1800");
+ if (IS_ERR(ctx->pp1800))
+ return PTR_ERR(ctx->pp1800);
+
+ ctx->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
+ if (IS_ERR(ctx->enable_gpio))
+ return dev_err_probe(dev, PTR_ERR(ctx->enable_gpio), "Cannot get enable GPIO\n");
+
+ ctx->base.prepare_prev_first = true;
+
+ drm_panel_init(&ctx->base, dev, &hx83102_drm_funcs,
+ DRM_MODE_CONNECTOR_DSI);
+ err = of_drm_get_panel_orientation(dev->of_node, &ctx->orientation);
+ if (err < 0)
+ return dev_err_probe(dev, err, "failed to get orientation\n");
+
+ err = drm_panel_of_backlight(&ctx->base);
+ if (err)
+ return err;
+
+ ctx->base.funcs = &hx83102_drm_funcs;
+ ctx->base.dev = &ctx->dsi->dev;
+
+ drm_panel_add(&ctx->base);
+
+ return 0;
+}
+
+static int hx83102_probe(struct mipi_dsi_device *dsi)
+{
+ struct hx83102 *ctx;
+ int ret;
+ const struct hx83102_panel_desc *desc;
+
+ ctx = devm_kzalloc(&dsi->dev, sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ desc = of_device_get_match_data(&dsi->dev);
+ dsi->lanes = 4;
+ dsi->format = MIPI_DSI_FMT_RGB888;
+ dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
+ MIPI_DSI_MODE_LPM;
+ ctx->desc = desc;
+ ctx->dsi = dsi;
+ ret = hx83102_panel_add(ctx);
+ if (ret < 0)
+ return ret;
+
+ mipi_dsi_set_drvdata(dsi, ctx);
+
+ ret = mipi_dsi_attach(dsi);
+ if (ret)
+ drm_panel_remove(&ctx->base);
+
+ return ret;
+}
+
+static void hx83102_remove(struct mipi_dsi_device *dsi)
+{
+ struct hx83102 *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);
+
+ if (ctx->base.dev)
+ drm_panel_remove(&ctx->base);
+}
+
+static const struct of_device_id hx83102_of_match[] = {
+ { .compatible = "boe,nv110wum-l60",
+ .data = &boe_nv110wum_desc
+ },
+ { .compatible = "ivo,t109nw41",
+ .data = &ivo_t109nw41_desc
+ },
+ { .compatible = "starry,himax83102-j02",
+ .data = &starry_desc
+ },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, hx83102_of_match);
+
+static struct mipi_dsi_driver hx83102_driver = {
+ .probe = hx83102_probe,
+ .remove = hx83102_remove,
+ .driver = {
+ .name = "panel-himax-hx83102",
+ .of_match_table = hx83102_of_match,
+ },
+};
+module_mipi_dsi_driver(hx83102_driver);
+
+MODULE_AUTHOR("Cong Yang <yangcong5@huaqin.corp-partner.google.com>");
+MODULE_DESCRIPTION("DRM driver for Himax HX83102 based MIPI DSI panels");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/panel/panel-himax-hx8394.c b/drivers/gpu/drm/panel/panel-himax-hx8394.c
index ff0dc08b9829..cb9f46e853de 100644
--- a/drivers/gpu/drm/panel/panel-himax-hx8394.c
+++ b/drivers/gpu/drm/panel/panel-himax-hx8394.c
@@ -370,8 +370,7 @@ static int hx8394_enable(struct drm_panel *panel)
sleep_in:
/* This will probably fail, but let's try orderly power off anyway. */
- ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
- if (!ret)
+ if (!mipi_dsi_dcs_enter_sleep_mode(dsi))
msleep(50);
return ret;
diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9341.c b/drivers/gpu/drm/panel/panel-ilitek-ili9341.c
index b933380b7eb7..775d5d5e828c 100644
--- a/drivers/gpu/drm/panel/panel-ilitek-ili9341.c
+++ b/drivers/gpu/drm/panel/panel-ilitek-ili9341.c
@@ -32,7 +32,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_dma.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
@@ -651,7 +651,7 @@ static int ili9341_dbi_probe(struct spi_device *spi, struct gpio_desc *dc,
spi_set_drvdata(spi, drm);
- drm_fbdev_generic_setup(drm, 0);
+ drm_fbdev_dma_setup(drm, 0);
return 0;
}
@@ -723,7 +723,8 @@ static int ili9341_probe(struct spi_device *spi)
if (!strcmp(id->name, "sf-tc240t-9370-t"))
return ili9341_dpi_probe(spi, dc, reset);
- else if (!strcmp(id->name, "yx240qv29"))
+
+ if (!strcmp(id->name, "yx240qv29"))
return ili9341_dbi_probe(spi, dc, reset);
return -ENODEV;
diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9806e.c b/drivers/gpu/drm/panel/panel-ilitek-ili9806e.c
new file mode 100644
index 000000000000..e4a44cd26c4d
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-ilitek-ili9806e.c
@@ -0,0 +1,402 @@
+// 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>
+#include <drm/drm_panel.h>
+#include <drm/drm_probe_helper.h>
+
+#include <video/mipi_display.h>
+
+struct panel_desc {
+ const struct drm_display_mode *display_mode;
+ unsigned long mode_flags;
+ enum mipi_dsi_pixel_format format;
+ unsigned int lanes;
+ void (*init_sequence)(struct mipi_dsi_multi_context *ctx);
+};
+
+struct ili9806e_panel {
+ struct drm_panel panel;
+ struct mipi_dsi_device *dsi;
+ struct gpio_desc *reset_gpio;
+ struct regulator_bulk_data supplies[2];
+ const struct 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)
+{
+ struct mipi_dsi_multi_context ctx = { .dsi = ili9806e->dsi };
+
+ if (ili9806e->desc->init_sequence)
+ ili9806e->desc->init_sequence(&ctx);
+
+ mipi_dsi_dcs_exit_sleep_mode_multi(&ctx);
+ mipi_dsi_msleep(&ctx, 120);
+ mipi_dsi_dcs_set_display_on_multi(&ctx);
+
+ return ctx.accum_err;
+}
+
+static int ili9806e_off(struct ili9806e_panel *panel)
+{
+ struct mipi_dsi_multi_context ctx = { .dsi = panel->dsi };
+
+ mipi_dsi_dcs_set_display_off_multi(&ctx);
+ mipi_dsi_dcs_enter_sleep_mode_multi(&ctx);
+ mipi_dsi_msleep(&ctx, 120);
+
+ return ctx.accum_err;
+}
+
+static int ili9806e_prepare(struct drm_panel *panel)
+{
+ struct ili9806e_panel *ctx = to_ili9806e_panel(panel);
+ int ret;
+
+ ret = ili9806e_power_on(ctx);
+ if (ret < 0)
+ return ret;
+
+ ret = ili9806e_on(ctx);
+ if (ret < 0) {
+ ili9806e_power_off(ctx);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int ili9806e_unprepare(struct drm_panel *panel)
+{
+ struct ili9806e_panel *ctx = to_ili9806e_panel(panel);
+ struct mipi_dsi_device *dsi = ctx->dsi;
+ int ret;
+
+ ili9806e_off(ctx);
+
+ ret = ili9806e_power_off(ctx);
+ if (ret < 0)
+ dev_err(&dsi->dev, "power off failed: %d\n", ret);
+
+ return ret;
+}
+
+static int ili9806e_get_modes(struct drm_panel *panel,
+ struct drm_connector *connector)
+{
+ struct ili9806e_panel *ctx = to_ili9806e_panel(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)
+{
+ struct ili9806e_panel *ctx = to_ili9806e_panel(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 int ili9806e_dsi_probe(struct mipi_dsi_device *dsi)
+{
+ struct device *dev = &dsi->dev;
+ struct ili9806e_panel *ctx;
+ int i, ret;
+
+ ctx = devm_kzalloc(dev, sizeof(*ctx), 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;
+
+ dsi->mode_flags = ctx->desc->mode_flags;
+ dsi->format = ctx->desc->format;
+ dsi->lanes = ctx->desc->lanes;
+
+ drm_panel_init(&ctx->panel, dev, &ili9806e_funcs,
+ DRM_MODE_CONNECTOR_DSI);
+
+ ret = of_drm_get_panel_orientation(dev->of_node, &ctx->orientation);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to get orientation\n");
+
+ ret = drm_panel_of_backlight(&ctx->panel);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to get backlight\n");
+
+ ctx->panel.prepare_prev_first = true;
+ drm_panel_add(&ctx->panel);
+
+ 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);
+ return ret;
+ }
+
+ return 0;
+}
+
+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);
+}
+
+static void com35h3p70ulc_init(struct mipi_dsi_multi_context *ctx)
+{
+ /* Switch to page 1 */
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0xff, 0x98, 0x06, 0x04, 0x01);
+ /* Interface Settings */
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x08, 0x18);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x21, 0x01);
+ /* Panel Settings */
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x30, 0x03);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x31, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x60, 0x0d);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x61, 0x08);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x62, 0x08);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x63, 0x09);
+ /* Power Control */
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x40, 0x30);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x41, 0x44);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x42, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x43, 0x89);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x44, 0x8e);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x45, 0xd9);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x46, 0x33);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x47, 0x33);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x50, 0x90);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x51, 0x90);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x56, 0x00);
+ /* Gamma Settings */
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xa0, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xa1, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xa2, 0x13);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xa3, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xa4, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xa5, 0x0d);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xa6, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xa7, 0x0b);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xa8, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xa9, 0x06);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xaa, 0x15);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xab, 0x07);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xac, 0x12);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xad, 0x28);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xae, 0x20);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xaf, 0x14);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xc0, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xc1, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xc2, 0x13);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xc3, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xc4, 0x09);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xc5, 0x0d);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xc6, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xc7, 0x0b);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xc8, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xc9, 0x06);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xca, 0x14);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xcb, 0x07);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xcc, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xcd, 0x21);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xce, 0x17);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xcf, 0x0a);
+
+ /* Switch to page 7 */
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0xff, 0x98, 0x06, 0x04, 0x07);
+ /* Power Control */
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x06, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x18, 0x1d);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x17, 0x32);
+
+ /* Switch to page 6 */
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0xff, 0x98, 0x06, 0x04, 0x06);
+ /* GIP settings */
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x00, 0x20);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x01, 0x02);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x02, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x03, 0x02);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x04, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x05, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x06, 0x88);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x07, 0x04);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x08, 0x03);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x09, 0x80);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x0a, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x0b, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x0c, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x0d, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x0e, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x0f, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x10, 0x55);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x11, 0x50);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x12, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x13, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x14, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x15, 0x43);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x16, 0x0b);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x17, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x18, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x19, 0x10);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x1a, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x1b, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x1c, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x1d, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x20, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x21, 0x23);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x22, 0x45);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x23, 0x67);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x24, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x25, 0x23);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x26, 0x45);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x27, 0x67);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x30, 0x02);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x31, 0x22);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x32, 0x22);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x33, 0x88);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x34, 0xaa);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x35, 0xbb);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x36, 0x66);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x37, 0x22);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x38, 0x22);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x39, 0x22);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x3a, 0x22);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x3b, 0x22);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x3c, 0x22);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x3d, 0x22);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x3e, 0x22);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x3f, 0x22);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x40, 0x22);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x53, 0x12);
+
+ /* Switch to page 0 */
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0xff, 0x98, 0x06, 0x04, 0x00);
+ /* Interface Pixel format */
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x3a, 0x60);
+};
+
+static const struct drm_display_mode com35h3p70ulc_default_mode = {
+ .clock = 22400,
+ .hdisplay = 480,
+ .hsync_start = 480 + 16,
+ .hsync_end = 480 + 16 + 16,
+ .htotal = 480 + 16 + 16 + 16,
+ .vdisplay = 640,
+ .vsync_start = 640 + 52,
+ .vsync_end = 640 + 52 + 4,
+ .vtotal = 640 + 52 + 4 + 16,
+ .width_mm = 53,
+ .height_mm = 71,
+};
+
+static const struct panel_desc com35h3p70ulc_desc = {
+ .init_sequence = com35h3p70ulc_init,
+ .display_mode = &com35h3p70ulc_default_mode,
+ .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
+ MIPI_DSI_MODE_LPM,
+ .format = MIPI_DSI_FMT_RGB888,
+ .lanes = 2,
+};
+
+static const struct of_device_id ili9806e_of_match[] = {
+ { .compatible = "ortustech,com35h3p70ulc", .data = &com35h3p70ulc_desc },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ili9806e_of_match);
+
+static struct mipi_dsi_driver ili9806e_dsi_driver = {
+ .driver = {
+ .name = "ili9806e-dsi",
+ .of_match_table = ili9806e_of_match,
+ },
+ .probe = ili9806e_dsi_probe,
+ .remove = ili9806e_dsi_remove,
+};
+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_LICENSE("GPL");
diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c b/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c
index 267a5307041c..266a087fe14c 100644
--- a/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c
+++ b/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c
@@ -15,6 +15,8 @@
#include <video/mipi_display.h>
+struct ili9882t;
+
/*
* Use this descriptor struct to describe different panels using the
* Ilitek ILI9882T display controller.
@@ -34,7 +36,7 @@ struct panel_desc {
unsigned long mode_flags;
enum mipi_dsi_pixel_format format;
- const struct panel_init_cmd *init_cmds;
+ int (*init)(struct ili9882t *boe);
unsigned int lanes;
};
@@ -52,371 +54,363 @@ struct ili9882t {
struct gpio_desc *enable_gpio;
};
-enum dsi_cmd_type {
- INIT_DCS_CMD,
- DELAY_CMD,
-};
-
-struct panel_init_cmd {
- enum dsi_cmd_type type;
- size_t len;
- const char *data;
-};
-
-#define _INIT_DCS_CMD(...) { \
- .type = INIT_DCS_CMD, \
- .len = sizeof((char[]){__VA_ARGS__}), \
- .data = (char[]){__VA_ARGS__} }
-
-#define _INIT_DELAY_CMD(...) { \
- .type = DELAY_CMD,\
- .len = sizeof((char[]){__VA_ARGS__}), \
- .data = (char[]){__VA_ARGS__} }
-
/* ILI9882-specific commands, add new commands as you decode them */
#define ILI9882T_DCS_SWITCH_PAGE 0xFF
-#define _INIT_SWITCH_PAGE_CMD(page) \
- _INIT_DCS_CMD(ILI9882T_DCS_SWITCH_PAGE, 0x98, 0x82, (page))
-
-static const struct panel_init_cmd starry_ili9882t_init_cmd[] = {
- _INIT_DELAY_CMD(5),
- _INIT_SWITCH_PAGE_CMD(0x01),
- _INIT_DCS_CMD(0x00, 0x42),
- _INIT_DCS_CMD(0x01, 0x11),
- _INIT_DCS_CMD(0x02, 0x00),
- _INIT_DCS_CMD(0x03, 0x00),
-
- _INIT_DCS_CMD(0x04, 0x01),
- _INIT_DCS_CMD(0x05, 0x11),
- _INIT_DCS_CMD(0x06, 0x00),
- _INIT_DCS_CMD(0x07, 0x00),
-
- _INIT_DCS_CMD(0x08, 0x80),
- _INIT_DCS_CMD(0x09, 0x81),
- _INIT_DCS_CMD(0x0A, 0x71),
- _INIT_DCS_CMD(0x0B, 0x00),
-
- _INIT_DCS_CMD(0x0C, 0x00),
- _INIT_DCS_CMD(0x0E, 0x1A),
-
- _INIT_DCS_CMD(0x24, 0x00),
- _INIT_DCS_CMD(0x25, 0x00),
- _INIT_DCS_CMD(0x26, 0x00),
- _INIT_DCS_CMD(0x27, 0x00),
-
- _INIT_DCS_CMD(0x2C, 0xD4),
- _INIT_DCS_CMD(0xB9, 0x40),
-
- _INIT_DCS_CMD(0xB0, 0x11),
-
- _INIT_DCS_CMD(0xE6, 0x32),
- _INIT_DCS_CMD(0xD1, 0x30),
-
- _INIT_DCS_CMD(0xD6, 0x55),
-
- _INIT_DCS_CMD(0xD0, 0x01),
- _INIT_DCS_CMD(0xE3, 0x93),
- _INIT_DCS_CMD(0xE4, 0x00),
- _INIT_DCS_CMD(0xE5, 0x80),
-
- _INIT_DCS_CMD(0x31, 0x07),
- _INIT_DCS_CMD(0x32, 0x07),
- _INIT_DCS_CMD(0x33, 0x07),
- _INIT_DCS_CMD(0x34, 0x07),
- _INIT_DCS_CMD(0x35, 0x07),
- _INIT_DCS_CMD(0x36, 0x01),
- _INIT_DCS_CMD(0x37, 0x00),
- _INIT_DCS_CMD(0x38, 0x28),
- _INIT_DCS_CMD(0x39, 0x29),
- _INIT_DCS_CMD(0x3A, 0x11),
- _INIT_DCS_CMD(0x3B, 0x13),
- _INIT_DCS_CMD(0x3C, 0x15),
- _INIT_DCS_CMD(0x3D, 0x17),
- _INIT_DCS_CMD(0x3E, 0x09),
- _INIT_DCS_CMD(0x3F, 0x0D),
- _INIT_DCS_CMD(0x40, 0x02),
- _INIT_DCS_CMD(0x41, 0x02),
- _INIT_DCS_CMD(0x42, 0x02),
- _INIT_DCS_CMD(0x43, 0x02),
- _INIT_DCS_CMD(0x44, 0x02),
- _INIT_DCS_CMD(0x45, 0x02),
- _INIT_DCS_CMD(0x46, 0x02),
-
- _INIT_DCS_CMD(0x47, 0x07),
- _INIT_DCS_CMD(0x48, 0x07),
- _INIT_DCS_CMD(0x49, 0x07),
- _INIT_DCS_CMD(0x4A, 0x07),
- _INIT_DCS_CMD(0x4B, 0x07),
- _INIT_DCS_CMD(0x4C, 0x01),
- _INIT_DCS_CMD(0x4D, 0x00),
- _INIT_DCS_CMD(0x4E, 0x28),
- _INIT_DCS_CMD(0x4F, 0x29),
- _INIT_DCS_CMD(0x50, 0x10),
- _INIT_DCS_CMD(0x51, 0x12),
- _INIT_DCS_CMD(0x52, 0x14),
- _INIT_DCS_CMD(0x53, 0x16),
- _INIT_DCS_CMD(0x54, 0x08),
- _INIT_DCS_CMD(0x55, 0x0C),
- _INIT_DCS_CMD(0x56, 0x02),
- _INIT_DCS_CMD(0x57, 0x02),
- _INIT_DCS_CMD(0x58, 0x02),
- _INIT_DCS_CMD(0x59, 0x02),
- _INIT_DCS_CMD(0x5A, 0x02),
- _INIT_DCS_CMD(0x5B, 0x02),
- _INIT_DCS_CMD(0x5C, 0x02),
-
- _INIT_DCS_CMD(0x61, 0x07),
- _INIT_DCS_CMD(0x62, 0x07),
- _INIT_DCS_CMD(0x63, 0x07),
- _INIT_DCS_CMD(0x64, 0x07),
- _INIT_DCS_CMD(0x65, 0x07),
- _INIT_DCS_CMD(0x66, 0x01),
- _INIT_DCS_CMD(0x67, 0x00),
- _INIT_DCS_CMD(0x68, 0x28),
- _INIT_DCS_CMD(0x69, 0x29),
- _INIT_DCS_CMD(0x6A, 0x16),
- _INIT_DCS_CMD(0x6B, 0x14),
- _INIT_DCS_CMD(0x6C, 0x12),
- _INIT_DCS_CMD(0x6D, 0x10),
- _INIT_DCS_CMD(0x6E, 0x0C),
- _INIT_DCS_CMD(0x6F, 0x08),
- _INIT_DCS_CMD(0x70, 0x02),
- _INIT_DCS_CMD(0x71, 0x02),
- _INIT_DCS_CMD(0x72, 0x02),
- _INIT_DCS_CMD(0x73, 0x02),
- _INIT_DCS_CMD(0x74, 0x02),
- _INIT_DCS_CMD(0x75, 0x02),
- _INIT_DCS_CMD(0x76, 0x02),
-
- _INIT_DCS_CMD(0x77, 0x07),
- _INIT_DCS_CMD(0x78, 0x07),
- _INIT_DCS_CMD(0x79, 0x07),
- _INIT_DCS_CMD(0x7A, 0x07),
- _INIT_DCS_CMD(0x7B, 0x07),
- _INIT_DCS_CMD(0x7C, 0x01),
- _INIT_DCS_CMD(0x7D, 0x00),
- _INIT_DCS_CMD(0x7E, 0x28),
- _INIT_DCS_CMD(0x7F, 0x29),
- _INIT_DCS_CMD(0x80, 0x17),
- _INIT_DCS_CMD(0x81, 0x15),
- _INIT_DCS_CMD(0x82, 0x13),
- _INIT_DCS_CMD(0x83, 0x11),
- _INIT_DCS_CMD(0x84, 0x0D),
- _INIT_DCS_CMD(0x85, 0x09),
- _INIT_DCS_CMD(0x86, 0x02),
- _INIT_DCS_CMD(0x87, 0x07),
- _INIT_DCS_CMD(0x88, 0x07),
- _INIT_DCS_CMD(0x89, 0x07),
- _INIT_DCS_CMD(0x8A, 0x07),
- _INIT_DCS_CMD(0x8B, 0x07),
- _INIT_DCS_CMD(0x8C, 0x07),
-
- _INIT_SWITCH_PAGE_CMD(0x02),
- _INIT_DCS_CMD(0x29, 0x3A),
- _INIT_DCS_CMD(0x2A, 0x3B),
-
- _INIT_DCS_CMD(0x06, 0x01),
- _INIT_DCS_CMD(0x07, 0x01),
- _INIT_DCS_CMD(0x08, 0x0C),
- _INIT_DCS_CMD(0x09, 0x44),
-
- _INIT_DCS_CMD(0x3C, 0x0A),
- _INIT_DCS_CMD(0x39, 0x11),
- _INIT_DCS_CMD(0x3D, 0x00),
- _INIT_DCS_CMD(0x3A, 0x0C),
- _INIT_DCS_CMD(0x3B, 0x44),
-
- _INIT_DCS_CMD(0x53, 0x1F),
- _INIT_DCS_CMD(0x5E, 0x40),
- _INIT_DCS_CMD(0x84, 0x00),
-
- _INIT_SWITCH_PAGE_CMD(0x03),
- _INIT_DCS_CMD(0x20, 0x01),
- _INIT_DCS_CMD(0x21, 0x3C),
- _INIT_DCS_CMD(0x22, 0xFA),
-
- _INIT_SWITCH_PAGE_CMD(0x0A),
- _INIT_DCS_CMD(0xE0, 0x01),
- _INIT_DCS_CMD(0xE2, 0x01),
- _INIT_DCS_CMD(0xE5, 0x91),
- _INIT_DCS_CMD(0xE6, 0x3C),
- _INIT_DCS_CMD(0xE7, 0x00),
- _INIT_DCS_CMD(0xE8, 0xFA),
-
- _INIT_SWITCH_PAGE_CMD(0x12),
- _INIT_DCS_CMD(0x87, 0x2C),
-
- _INIT_SWITCH_PAGE_CMD(0x05),
- _INIT_DCS_CMD(0x73, 0xE5),
- _INIT_DCS_CMD(0x7F, 0x6B),
- _INIT_DCS_CMD(0x6D, 0xA4),
- _INIT_DCS_CMD(0x79, 0x54),
- _INIT_DCS_CMD(0x69, 0x97),
- _INIT_DCS_CMD(0x6A, 0x97),
- _INIT_DCS_CMD(0xA5, 0x3F),
- _INIT_DCS_CMD(0x61, 0xDA),
- _INIT_DCS_CMD(0xA7, 0xF1),
- _INIT_DCS_CMD(0x5F, 0x01),
- _INIT_DCS_CMD(0x62, 0x3F),
- _INIT_DCS_CMD(0x1D, 0x90),
- _INIT_DCS_CMD(0x86, 0x87),
-
- _INIT_SWITCH_PAGE_CMD(0x06),
- _INIT_DCS_CMD(0xC0, 0x80),
- _INIT_DCS_CMD(0xC1, 0x07),
- _INIT_DCS_CMD(0xCA, 0x58),
- _INIT_DCS_CMD(0xCB, 0x02),
- _INIT_DCS_CMD(0xCE, 0x58),
- _INIT_DCS_CMD(0xCF, 0x02),
- _INIT_DCS_CMD(0x67, 0x60),
- _INIT_DCS_CMD(0x10, 0x00),
- _INIT_DCS_CMD(0x92, 0x22),
- _INIT_DCS_CMD(0xD3, 0x08),
- _INIT_DCS_CMD(0xD6, 0x55),
- _INIT_DCS_CMD(0xDC, 0x38),
-
- _INIT_SWITCH_PAGE_CMD(0x08),
- _INIT_DCS_CMD(0xE0, 0x00, 0x10, 0x2A, 0x4D, 0x61, 0x56, 0x6A, 0x6E, 0x79, 0x76, 0x8F, 0x95, 0x98, 0xAE, 0xAA, 0xB2, 0xBB, 0xCE, 0xC6, 0xBD, 0xD5, 0xE2, 0xE8),
- _INIT_DCS_CMD(0xE1, 0x00, 0x10, 0x2A, 0x4D, 0x61, 0x56, 0x6A, 0x6E, 0x79, 0x76, 0x8F, 0x95, 0x98, 0xAE, 0xAA, 0xB2, 0xBB, 0xCE, 0xC6, 0xBD, 0xD5, 0xE2, 0xE8),
-
- _INIT_SWITCH_PAGE_CMD(0x04),
- _INIT_DCS_CMD(0xBA, 0x81),
-
- _INIT_SWITCH_PAGE_CMD(0x0C),
- _INIT_DCS_CMD(0x00, 0x02),
- _INIT_DCS_CMD(0x01, 0x00),
- _INIT_DCS_CMD(0x02, 0x03),
- _INIT_DCS_CMD(0x03, 0x01),
- _INIT_DCS_CMD(0x04, 0x03),
- _INIT_DCS_CMD(0x05, 0x02),
- _INIT_DCS_CMD(0x06, 0x04),
- _INIT_DCS_CMD(0x07, 0x03),
- _INIT_DCS_CMD(0x08, 0x03),
- _INIT_DCS_CMD(0x09, 0x04),
- _INIT_DCS_CMD(0x0A, 0x04),
- _INIT_DCS_CMD(0x0B, 0x05),
- _INIT_DCS_CMD(0x0C, 0x04),
- _INIT_DCS_CMD(0x0D, 0x06),
- _INIT_DCS_CMD(0x0E, 0x05),
- _INIT_DCS_CMD(0x0F, 0x07),
- _INIT_DCS_CMD(0x10, 0x04),
- _INIT_DCS_CMD(0x11, 0x08),
- _INIT_DCS_CMD(0x12, 0x05),
- _INIT_DCS_CMD(0x13, 0x09),
- _INIT_DCS_CMD(0x14, 0x05),
- _INIT_DCS_CMD(0x15, 0x0A),
- _INIT_DCS_CMD(0x16, 0x06),
- _INIT_DCS_CMD(0x17, 0x0B),
- _INIT_DCS_CMD(0x18, 0x05),
- _INIT_DCS_CMD(0x19, 0x0C),
- _INIT_DCS_CMD(0x1A, 0x06),
- _INIT_DCS_CMD(0x1B, 0x0D),
- _INIT_DCS_CMD(0x1C, 0x06),
- _INIT_DCS_CMD(0x1D, 0x0E),
- _INIT_DCS_CMD(0x1E, 0x07),
- _INIT_DCS_CMD(0x1F, 0x0F),
- _INIT_DCS_CMD(0x20, 0x06),
- _INIT_DCS_CMD(0x21, 0x10),
- _INIT_DCS_CMD(0x22, 0x07),
- _INIT_DCS_CMD(0x23, 0x11),
- _INIT_DCS_CMD(0x24, 0x07),
- _INIT_DCS_CMD(0x25, 0x12),
- _INIT_DCS_CMD(0x26, 0x08),
- _INIT_DCS_CMD(0x27, 0x13),
- _INIT_DCS_CMD(0x28, 0x07),
- _INIT_DCS_CMD(0x29, 0x14),
- _INIT_DCS_CMD(0x2A, 0x08),
- _INIT_DCS_CMD(0x2B, 0x15),
- _INIT_DCS_CMD(0x2C, 0x08),
- _INIT_DCS_CMD(0x2D, 0x16),
- _INIT_DCS_CMD(0x2E, 0x09),
- _INIT_DCS_CMD(0x2F, 0x17),
- _INIT_DCS_CMD(0x30, 0x08),
- _INIT_DCS_CMD(0x31, 0x18),
- _INIT_DCS_CMD(0x32, 0x09),
- _INIT_DCS_CMD(0x33, 0x19),
- _INIT_DCS_CMD(0x34, 0x09),
- _INIT_DCS_CMD(0x35, 0x1A),
- _INIT_DCS_CMD(0x36, 0x0A),
- _INIT_DCS_CMD(0x37, 0x1B),
- _INIT_DCS_CMD(0x38, 0x0A),
- _INIT_DCS_CMD(0x39, 0x1C),
- _INIT_DCS_CMD(0x3A, 0x0A),
- _INIT_DCS_CMD(0x3B, 0x1D),
- _INIT_DCS_CMD(0x3C, 0x0A),
- _INIT_DCS_CMD(0x3D, 0x1E),
- _INIT_DCS_CMD(0x3E, 0x0A),
- _INIT_DCS_CMD(0x3F, 0x1F),
-
- _INIT_SWITCH_PAGE_CMD(0x04),
- _INIT_DCS_CMD(0xBA, 0x01),
-
- _INIT_SWITCH_PAGE_CMD(0x0E),
- _INIT_DCS_CMD(0x02, 0x0C),
- _INIT_DCS_CMD(0x20, 0x10),
- _INIT_DCS_CMD(0x25, 0x16),
- _INIT_DCS_CMD(0x26, 0xE0),
- _INIT_DCS_CMD(0x27, 0x00),
- _INIT_DCS_CMD(0x29, 0x71),
- _INIT_DCS_CMD(0x2A, 0x46),
- _INIT_DCS_CMD(0x2B, 0x1F),
- _INIT_DCS_CMD(0x2D, 0xC7),
- _INIT_DCS_CMD(0x31, 0x02),
- _INIT_DCS_CMD(0x32, 0xDF),
- _INIT_DCS_CMD(0x33, 0x5A),
- _INIT_DCS_CMD(0x34, 0xC0),
- _INIT_DCS_CMD(0x35, 0x5A),
- _INIT_DCS_CMD(0x36, 0xC0),
- _INIT_DCS_CMD(0x38, 0x65),
- _INIT_DCS_CMD(0x80, 0x3E),
- _INIT_DCS_CMD(0x81, 0xA0),
- _INIT_DCS_CMD(0xB0, 0x01),
- _INIT_DCS_CMD(0xB1, 0xCC),
- _INIT_DCS_CMD(0xC0, 0x12),
- _INIT_DCS_CMD(0xC2, 0xCC),
- _INIT_DCS_CMD(0xC3, 0xCC),
- _INIT_DCS_CMD(0xC4, 0xCC),
- _INIT_DCS_CMD(0xC5, 0xCC),
- _INIT_DCS_CMD(0xC6, 0xCC),
- _INIT_DCS_CMD(0xC7, 0xCC),
- _INIT_DCS_CMD(0xC8, 0xCC),
- _INIT_DCS_CMD(0xC9, 0xCC),
- _INIT_DCS_CMD(0x30, 0x00),
- _INIT_DCS_CMD(0x00, 0x81),
- _INIT_DCS_CMD(0x08, 0x02),
- _INIT_DCS_CMD(0x09, 0x00),
- _INIT_DCS_CMD(0x07, 0x21),
- _INIT_DCS_CMD(0x04, 0x10),
-
- _INIT_SWITCH_PAGE_CMD(0x1E),
- _INIT_DCS_CMD(0x60, 0x00),
- _INIT_DCS_CMD(0x64, 0x00),
- _INIT_DCS_CMD(0x6D, 0x00),
-
- _INIT_SWITCH_PAGE_CMD(0x0B),
- _INIT_DCS_CMD(0xA6, 0x44),
- _INIT_DCS_CMD(0xA7, 0xB6),
- _INIT_DCS_CMD(0xA8, 0x03),
- _INIT_DCS_CMD(0xA9, 0x03),
- _INIT_DCS_CMD(0xAA, 0x51),
- _INIT_DCS_CMD(0xAB, 0x51),
- _INIT_DCS_CMD(0xAC, 0x04),
- _INIT_DCS_CMD(0xBD, 0x92),
- _INIT_DCS_CMD(0xBE, 0xA1),
-
- _INIT_SWITCH_PAGE_CMD(0x05),
- _INIT_DCS_CMD(0x86, 0x87),
-
- _INIT_SWITCH_PAGE_CMD(0x06),
- _INIT_DCS_CMD(0x92, 0x22),
-
- _INIT_SWITCH_PAGE_CMD(0x00),
- _INIT_DCS_CMD(MIPI_DCS_EXIT_SLEEP_MODE),
- _INIT_DELAY_CMD(120),
- _INIT_DCS_CMD(MIPI_DCS_SET_DISPLAY_ON),
- _INIT_DELAY_CMD(20),
- {},
+#define ili9882t_switch_page(ctx, page) \
+ mipi_dsi_dcs_write_seq_multi(ctx, ILI9882T_DCS_SWITCH_PAGE, \
+ 0x98, 0x82, (page))
+
+static int starry_ili9882t_init(struct ili9882t *ili)
+{
+ struct mipi_dsi_multi_context ctx = { .dsi = ili->dsi };
+
+ usleep_range(5000, 5100);
+
+ ili9882t_switch_page(&ctx, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x00, 0x42);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x01, 0x11);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x02, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x03, 0x00);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x04, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x05, 0x11);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x06, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x00);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x08, 0x80);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x09, 0x81);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0a, 0x71);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0b, 0x00);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0c, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0e, 0x1a);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x24, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x25, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x26, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x27, 0x00);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2c, 0xd4);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0x40);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x11);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe6, 0x32);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd1, 0x30);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd6, 0x55);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd0, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe3, 0x93);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe4, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe5, 0x80);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x31, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x32, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x33, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x34, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x35, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x36, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x37, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x38, 0x28);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x39, 0x29);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3a, 0x11);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3b, 0x13);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3c, 0x15);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3d, 0x17);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3e, 0x09);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3f, 0x0d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x40, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x41, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x42, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x43, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x44, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x45, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x46, 0x02);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x47, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x48, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x49, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x4a, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x4b, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x4c, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x4d, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x4e, 0x28);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x4f, 0x29);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x50, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x51, 0x12);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x52, 0x14);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x53, 0x16);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x54, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x55, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x56, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x57, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x58, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x59, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5a, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5b, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5c, 0x02);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x61, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x62, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x63, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x64, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x65, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x66, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x67, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x68, 0x28);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x69, 0x29);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x6a, 0x16);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x6b, 0x14);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x6c, 0x12);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x6d, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x6e, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x6f, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x70, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x71, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x72, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x73, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x74, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x75, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x76, 0x02);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x77, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x78, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x79, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x7a, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x7b, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x7c, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x7d, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x7e, 0x28);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x7f, 0x29);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x80, 0x17);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x81, 0x15);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x82, 0x13);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x83, 0x11);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x84, 0x0d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x85, 0x09);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x86, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x87, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x88, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x89, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x8a, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x8b, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x8c, 0x07);
+
+ ili9882t_switch_page(&ctx, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x29, 0x3a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2a, 0x3b);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x06, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x08, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x09, 0x44);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3c, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x39, 0x11);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3d, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3a, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3b, 0x44);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x53, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5e, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x84, 0x00);
+
+ ili9882t_switch_page(&ctx, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x20, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x21, 0x3c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x22, 0xfa);
+
+ ili9882t_switch_page(&ctx, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe0, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe2, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe5, 0x91);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe6, 0x3c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe7, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe8, 0xfa);
+
+ ili9882t_switch_page(&ctx, 0x12);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x87, 0x2c);
+
+ ili9882t_switch_page(&ctx, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x73, 0xe5);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x7f, 0x6b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x6d, 0xa4);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x79, 0x54);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x69, 0x97);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x6a, 0x97);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xa5, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x61, 0xda);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xa7, 0xf1);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x5f, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x62, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1d, 0x90);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x86, 0x87);
+
+ ili9882t_switch_page(&ctx, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x80);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc1, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x58);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xce, 0x58);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcf, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x67, 0x60);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x10, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x92, 0x22);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd3, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd6, 0x55);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xdc, 0x38);
+
+ ili9882t_switch_page(&ctx, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe0, 0x00, 0x10, 0x2a, 0x4d, 0x61, 0x56, 0x6a, 0x6e,
+ 0x79, 0x76, 0x8f, 0x95, 0x98, 0xae, 0xaa, 0xb2, 0xbb, 0xce,
+ 0xc6, 0xbd, 0xd5, 0xe2, 0xe8);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe1, 0x00, 0x10, 0x2a, 0x4d, 0x61, 0x56, 0x6a, 0x6e,
+ 0x79, 0x76, 0x8f, 0x95, 0x98, 0xae, 0xaa, 0xb2, 0xbb, 0xce,
+ 0xc6, 0xbd, 0xd5, 0xe2, 0xe8);
+
+ ili9882t_switch_page(&ctx, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x81);
+
+ ili9882t_switch_page(&ctx, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x00, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x01, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x02, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x03, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x04, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x05, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x06, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x08, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x09, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0a, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0b, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0c, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0d, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0e, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x0f, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x10, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x11, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x12, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x13, 0x09);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x14, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x15, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x16, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x17, 0x0b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x18, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x19, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1a, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1b, 0x0d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1c, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1d, 0x0e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1e, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x1f, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x20, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x21, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x22, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x23, 0x11);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x24, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x25, 0x12);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x26, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x27, 0x13);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x28, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x29, 0x14);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2a, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2b, 0x15);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2c, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2d, 0x16);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2e, 0x09);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2f, 0x17);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x30, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x31, 0x18);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x32, 0x09);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x33, 0x19);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x34, 0x09);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x35, 0x1a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x36, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x37, 0x1b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x38, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x39, 0x1c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3a, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3b, 0x1d);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3c, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3d, 0x1e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3e, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x3f, 0x1f);
+
+ ili9882t_switch_page(&ctx, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x01);
+
+ ili9882t_switch_page(&ctx, 0x0e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x02, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x20, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x25, 0x16);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x26, 0xe0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x27, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x29, 0x71);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2a, 0x46);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2b, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x2d, 0xc7);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x31, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x32, 0xdf);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x33, 0x5a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x34, 0xc0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x35, 0x5a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x36, 0xc0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x38, 0x65);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x80, 0x3e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x81, 0xa0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0xcc);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x12);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0xcc);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0xcc);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0xcc);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0xcc);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc6, 0xcc);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc7, 0xcc);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0xcc);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0xcc);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x30, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x00, 0x81);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x08, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x09, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x21);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x04, 0x10);
+
+ ili9882t_switch_page(&ctx, 0x1e);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x60, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x64, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x6d, 0x00);
+
+ ili9882t_switch_page(&ctx, 0x0b);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xa6, 0x44);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xa7, 0xb6);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xa8, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xa9, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xaa, 0x51);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xab, 0x51);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xac, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbd, 0x92);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbe, 0xa1);
+
+ ili9882t_switch_page(&ctx, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x86, 0x87);
+
+ ili9882t_switch_page(&ctx, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x92, 0x22);
+
+ ili9882t_switch_page(&ctx, 0x00);
+ mipi_dsi_dcs_exit_sleep_mode_multi(&ctx);
+
+ mipi_dsi_msleep(&ctx, 120);
+
+ mipi_dsi_dcs_set_display_on_multi(&ctx);
+
+ mipi_dsi_msleep(&ctx, 20);
+
+ return ctx.accum_err;
};
static inline struct ili9882t *to_ili9882t(struct drm_panel *panel)
@@ -424,97 +418,21 @@ static inline struct ili9882t *to_ili9882t(struct drm_panel *panel)
return container_of(panel, struct ili9882t, base);
}
-static int ili9882t_init_dcs_cmd(struct ili9882t *ili)
-{
- struct mipi_dsi_device *dsi = ili->dsi;
- struct drm_panel *panel = &ili->base;
- int i, err = 0;
-
- if (ili->desc->init_cmds) {
- const struct panel_init_cmd *init_cmds = ili->desc->init_cmds;
-
- for (i = 0; init_cmds[i].len != 0; i++) {
- const struct panel_init_cmd *cmd = &init_cmds[i];
-
- switch (cmd->type) {
- case DELAY_CMD:
- msleep(cmd->data[0]);
- err = 0;
- break;
-
- case INIT_DCS_CMD:
- err = mipi_dsi_dcs_write(dsi, cmd->data[0],
- cmd->len <= 1 ? NULL :
- &cmd->data[1],
- cmd->len - 1);
- break;
-
- default:
- err = -EINVAL;
- }
-
- if (err < 0) {
- dev_err(panel->dev,
- "failed to write command %u\n", i);
- return err;
- }
- }
- }
- return 0;
-}
-
-static int ili9882t_switch_page(struct mipi_dsi_device *dsi, u8 page)
-{
- int ret;
- const struct panel_init_cmd cmd = _INIT_SWITCH_PAGE_CMD(page);
-
- ret = mipi_dsi_dcs_write(dsi, cmd.data[0],
- cmd.len <= 1 ? NULL :
- &cmd.data[1],
- cmd.len - 1);
- if (ret) {
- dev_err(&dsi->dev,
- "error switching panel controller page (%d)\n", ret);
- return ret;
- }
-
- return 0;
-}
-
-static int ili9882t_enter_sleep_mode(struct ili9882t *ili)
-{
- struct mipi_dsi_device *dsi = ili->dsi;
- int ret;
-
- dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
-
- ret = mipi_dsi_dcs_set_display_off(dsi);
- if (ret < 0)
- return ret;
-
- ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
static int ili9882t_disable(struct drm_panel *panel)
{
struct ili9882t *ili = to_ili9882t(panel);
- struct mipi_dsi_device *dsi = ili->dsi;
- int ret;
+ struct mipi_dsi_multi_context ctx = { .dsi = ili->dsi };
- ili9882t_switch_page(dsi, 0x00);
- ret = ili9882t_enter_sleep_mode(ili);
- if (ret < 0) {
- dev_err(panel->dev, "failed to set panel off: %d\n", ret);
- return ret;
- }
+ ili9882t_switch_page(&ctx, 0x00);
- msleep(150);
+ ili->dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
- return 0;
+ mipi_dsi_dcs_set_display_off_multi(&ctx);
+ mipi_dsi_dcs_enter_sleep_mode_multi(&ctx);
+
+ mipi_dsi_msleep(&ctx, 150);
+
+ return ctx.accum_err;
}
static int ili9882t_unprepare(struct drm_panel *panel)
@@ -560,7 +478,11 @@ static int ili9882t_prepare(struct drm_panel *panel)
usleep_range(10000, 11000);
// MIPI needs to keep the LP11 state before the lcm_reset pin is pulled high
- mipi_dsi_dcs_nop(ili->dsi);
+ ret = mipi_dsi_dcs_nop(ili->dsi);
+ if (ret < 0) {
+ dev_err(&ili->dsi->dev, "Failed to send NOP: %d\n", ret);
+ goto poweroff;
+ }
usleep_range(1000, 2000);
gpiod_set_value(ili->enable_gpio, 1);
@@ -570,22 +492,20 @@ static int ili9882t_prepare(struct drm_panel *panel)
gpiod_set_value(ili->enable_gpio, 1);
usleep_range(6000, 10000);
- ret = ili9882t_init_dcs_cmd(ili);
- if (ret < 0) {
- dev_err(panel->dev, "failed to init panel: %d\n", ret);
+ ret = ili->desc->init(ili);
+ if (ret < 0)
goto poweroff;
- }
return 0;
poweroff:
+ gpiod_set_value(ili->enable_gpio, 0);
regulator_disable(ili->avee);
poweroffavdd:
regulator_disable(ili->avdd);
poweroff1v8:
usleep_range(5000, 7000);
regulator_disable(ili->pp1800);
- gpiod_set_value(ili->enable_gpio, 0);
return ret;
}
@@ -620,7 +540,7 @@ static const struct panel_desc starry_ili9882t_desc = {
.format = MIPI_DSI_FMT_RGB888,
.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
MIPI_DSI_MODE_LPM,
- .init_cmds = starry_ili9882t_init_cmd,
+ .init = starry_ili9882t_init,
};
static int ili9882t_get_modes(struct drm_panel *panel,
diff --git a/drivers/gpu/drm/panel/panel-innolux-ej030na.c b/drivers/gpu/drm/panel/panel-innolux-ej030na.c
index 8fdbda59be48..f85b7a4cbb42 100644
--- a/drivers/gpu/drm/panel/panel-innolux-ej030na.c
+++ b/drivers/gpu/drm/panel/panel-innolux-ej030na.c
@@ -306,4 +306,5 @@ module_spi_driver(ej030na_driver);
MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
MODULE_AUTHOR("Christophe Branchereau <cbranchereau@gmail.com>");
+MODULE_DESCRIPTION("Innolux/Chimei EJ030NA TFT LCD panel driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/panel/panel-innolux-p079zca.c b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
index 485178a99910..d95c0d4f3e35 100644
--- a/drivers/gpu/drm/panel/panel-innolux-p079zca.c
+++ b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
@@ -17,14 +17,7 @@
#include <drm/drm_modes.h>
#include <drm/drm_panel.h>
-struct panel_init_cmd {
- size_t len;
- const char *data;
-};
-
-#define _INIT_CMD(...) { \
- .len = sizeof((char[]){__VA_ARGS__}), \
- .data = (char[]){__VA_ARGS__} }
+struct innolux_panel;
struct panel_desc {
const struct drm_display_mode *mode;
@@ -36,7 +29,7 @@ struct panel_desc {
unsigned long flags;
enum mipi_dsi_pixel_format format;
- const struct panel_init_cmd *init_cmds;
+ int (*init)(struct innolux_panel *innolux);
unsigned int lanes;
const char * const *supply_names;
unsigned int num_supplies;
@@ -51,9 +44,6 @@ struct innolux_panel {
struct regulator_bulk_data *supplies;
struct gpio_desc *enable_gpio;
-
- bool prepared;
- bool enabled;
};
static inline struct innolux_panel *to_innolux_panel(struct drm_panel *panel)
@@ -61,26 +51,11 @@ static inline struct innolux_panel *to_innolux_panel(struct drm_panel *panel)
return container_of(panel, struct innolux_panel, base);
}
-static int innolux_panel_disable(struct drm_panel *panel)
-{
- struct innolux_panel *innolux = to_innolux_panel(panel);
-
- if (!innolux->enabled)
- return 0;
-
- innolux->enabled = false;
-
- return 0;
-}
-
static int innolux_panel_unprepare(struct drm_panel *panel)
{
struct innolux_panel *innolux = to_innolux_panel(panel);
int err;
- if (!innolux->prepared)
- return 0;
-
err = mipi_dsi_dcs_set_display_off(innolux->link);
if (err < 0)
dev_err(panel->dev, "failed to set display off: %d\n", err);
@@ -104,8 +79,6 @@ static int innolux_panel_unprepare(struct drm_panel *panel)
if (err < 0)
return err;
- innolux->prepared = false;
-
return 0;
}
@@ -114,9 +87,6 @@ static int innolux_panel_prepare(struct drm_panel *panel)
struct innolux_panel *innolux = to_innolux_panel(panel);
int err;
- if (innolux->prepared)
- return 0;
-
gpiod_set_value_cansleep(innolux->enable_gpio, 0);
err = regulator_bulk_enable(innolux->desc->num_supplies,
@@ -132,32 +102,10 @@ static int innolux_panel_prepare(struct drm_panel *panel)
/* p079zca: t4, p097pfg: t5 */
usleep_range(20000, 21000);
- if (innolux->desc->init_cmds) {
- const struct panel_init_cmd *cmds =
- innolux->desc->init_cmds;
- unsigned int i;
-
- for (i = 0; cmds[i].len != 0; i++) {
- const struct panel_init_cmd *cmd = &cmds[i];
-
- err = mipi_dsi_generic_write(innolux->link, cmd->data,
- cmd->len);
- if (err < 0) {
- dev_err(panel->dev, "failed to write command %u\n", i);
- goto poweroff;
- }
-
- /*
- * Included by random guessing, because without this
- * (or at least, some delay), the panel sometimes
- * didn't appear to pick up the command sequence.
- */
- err = mipi_dsi_dcs_nop(innolux->link);
- if (err < 0) {
- dev_err(panel->dev, "failed to send DCS nop: %d\n", err);
- goto poweroff;
- }
- }
+ if (innolux->desc->init) {
+ err = innolux->desc->init(innolux);
+ if (err < 0)
+ goto poweroff;
}
err = mipi_dsi_dcs_exit_sleep_mode(innolux->link);
@@ -178,8 +126,6 @@ static int innolux_panel_prepare(struct drm_panel *panel)
/* T7: 5ms */
usleep_range(5000, 6000);
- innolux->prepared = true;
-
return 0;
poweroff:
@@ -189,18 +135,6 @@ poweroff:
return err;
}
-static int innolux_panel_enable(struct drm_panel *panel)
-{
- struct innolux_panel *innolux = to_innolux_panel(panel);
-
- if (innolux->enabled)
- return 0;
-
- innolux->enabled = true;
-
- return 0;
-}
-
static const char * const innolux_p079zca_supply_names[] = {
"power",
};
@@ -250,119 +184,137 @@ static const struct drm_display_mode innolux_p097pfg_mode = {
.vtotal = 2048 + 100 + 2 + 18,
};
+static void innolux_panel_write_multi(struct mipi_dsi_multi_context *ctx,
+ const void *payload, size_t size)
+{
+ mipi_dsi_generic_write_multi(ctx, payload, size);
+
+ /*
+ * Included by random guessing, because without this
+ * (or at least, some delay), the panel sometimes
+ * didn't appear to pick up the command sequence.
+ */
+ mipi_dsi_dcs_nop_multi(ctx);
+}
+
+#define innolux_panel_init_cmd_multi(ctx, seq...) \
+ do { \
+ static const u8 d[] = { seq }; \
+ innolux_panel_write_multi(ctx, d, ARRAY_SIZE(d)); \
+ } while (0)
+
+#define innolux_panel_switch_page(ctx, page) \
+ innolux_panel_init_cmd_multi(ctx, 0xf0, 0x55, 0xaa, 0x52, 0x08, (page))
+
/*
* Display manufacturer failed to provide init sequencing according to
* https://chromium-review.googlesource.com/c/chromiumos/third_party/coreboot/+/892065/
* so the init sequence stems from a register dump of a working panel.
*/
-static const struct panel_init_cmd innolux_p097pfg_init_cmds[] = {
- /* page 0 */
- _INIT_CMD(0xF0, 0x55, 0xAA, 0x52, 0x08, 0x00),
- _INIT_CMD(0xB1, 0xE8, 0x11),
- _INIT_CMD(0xB2, 0x25, 0x02),
- _INIT_CMD(0xB5, 0x08, 0x00),
- _INIT_CMD(0xBC, 0x0F, 0x00),
- _INIT_CMD(0xB8, 0x03, 0x06, 0x00, 0x00),
- _INIT_CMD(0xBD, 0x01, 0x90, 0x14, 0x14),
- _INIT_CMD(0x6F, 0x01),
- _INIT_CMD(0xC0, 0x03),
- _INIT_CMD(0x6F, 0x02),
- _INIT_CMD(0xC1, 0x0D),
- _INIT_CMD(0xD9, 0x01, 0x09, 0x70),
- _INIT_CMD(0xC5, 0x12, 0x21, 0x00),
- _INIT_CMD(0xBB, 0x93, 0x93),
-
- /* page 1 */
- _INIT_CMD(0xF0, 0x55, 0xAA, 0x52, 0x08, 0x01),
- _INIT_CMD(0xB3, 0x3C, 0x3C),
- _INIT_CMD(0xB4, 0x0F, 0x0F),
- _INIT_CMD(0xB9, 0x45, 0x45),
- _INIT_CMD(0xBA, 0x14, 0x14),
- _INIT_CMD(0xCA, 0x02),
- _INIT_CMD(0xCE, 0x04),
- _INIT_CMD(0xC3, 0x9B, 0x9B),
- _INIT_CMD(0xD8, 0xC0, 0x03),
- _INIT_CMD(0xBC, 0x82, 0x01),
- _INIT_CMD(0xBD, 0x9E, 0x01),
-
- /* page 2 */
- _INIT_CMD(0xF0, 0x55, 0xAA, 0x52, 0x08, 0x02),
- _INIT_CMD(0xB0, 0x82),
- _INIT_CMD(0xD1, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x82, 0x00, 0xA5,
- 0x00, 0xC1, 0x00, 0xEA, 0x01, 0x0D, 0x01, 0x40),
- _INIT_CMD(0xD2, 0x01, 0x6A, 0x01, 0xA8, 0x01, 0xDC, 0x02, 0x29,
- 0x02, 0x67, 0x02, 0x68, 0x02, 0xA8, 0x02, 0xF0),
- _INIT_CMD(0xD3, 0x03, 0x19, 0x03, 0x49, 0x03, 0x67, 0x03, 0x8C,
- 0x03, 0xA6, 0x03, 0xC7, 0x03, 0xDE, 0x03, 0xEC),
- _INIT_CMD(0xD4, 0x03, 0xFF, 0x03, 0xFF),
- _INIT_CMD(0xE0, 0x00, 0x00, 0x00, 0x86, 0x00, 0xC5, 0x00, 0xE5,
- 0x00, 0xFF, 0x01, 0x26, 0x01, 0x45, 0x01, 0x75),
- _INIT_CMD(0xE1, 0x01, 0x9C, 0x01, 0xD5, 0x02, 0x05, 0x02, 0x4D,
- 0x02, 0x86, 0x02, 0x87, 0x02, 0xC3, 0x03, 0x03),
- _INIT_CMD(0xE2, 0x03, 0x2A, 0x03, 0x56, 0x03, 0x72, 0x03, 0x94,
- 0x03, 0xAC, 0x03, 0xCB, 0x03, 0xE0, 0x03, 0xED),
- _INIT_CMD(0xE3, 0x03, 0xFF, 0x03, 0xFF),
-
- /* page 3 */
- _INIT_CMD(0xF0, 0x55, 0xAA, 0x52, 0x08, 0x03),
- _INIT_CMD(0xB0, 0x00, 0x00, 0x00, 0x00),
- _INIT_CMD(0xB1, 0x00, 0x00, 0x00, 0x00),
- _INIT_CMD(0xB2, 0x00, 0x00, 0x06, 0x04, 0x01, 0x40, 0x85),
- _INIT_CMD(0xB3, 0x10, 0x07, 0xFC, 0x04, 0x01, 0x40, 0x80),
- _INIT_CMD(0xB6, 0xF0, 0x08, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01,
- 0x40, 0x80),
- _INIT_CMD(0xBA, 0xC5, 0x07, 0x00, 0x04, 0x11, 0x25, 0x8C),
- _INIT_CMD(0xBB, 0xC5, 0x07, 0x00, 0x03, 0x11, 0x25, 0x8C),
- _INIT_CMD(0xC0, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x80, 0x80),
- _INIT_CMD(0xC1, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x80, 0x80),
- _INIT_CMD(0xC4, 0x00, 0x00),
- _INIT_CMD(0xEF, 0x41),
-
- /* page 4 */
- _INIT_CMD(0xF0, 0x55, 0xAA, 0x52, 0x08, 0x04),
- _INIT_CMD(0xEC, 0x4C),
-
- /* page 5 */
- _INIT_CMD(0xF0, 0x55, 0xAA, 0x52, 0x08, 0x05),
- _INIT_CMD(0xB0, 0x13, 0x03, 0x03, 0x01),
- _INIT_CMD(0xB1, 0x30, 0x00),
- _INIT_CMD(0xB2, 0x02, 0x02, 0x00),
- _INIT_CMD(0xB3, 0x82, 0x23, 0x82, 0x9D),
- _INIT_CMD(0xB4, 0xC5, 0x75, 0x24, 0x57),
- _INIT_CMD(0xB5, 0x00, 0xD4, 0x72, 0x11, 0x11, 0xAB, 0x0A),
- _INIT_CMD(0xB6, 0x00, 0x00, 0xD5, 0x72, 0x24, 0x56),
- _INIT_CMD(0xB7, 0x5C, 0xDC, 0x5C, 0x5C),
- _INIT_CMD(0xB9, 0x0C, 0x00, 0x00, 0x01, 0x00),
- _INIT_CMD(0xC0, 0x75, 0x11, 0x11, 0x54, 0x05),
- _INIT_CMD(0xC6, 0x00, 0x00, 0x00, 0x00),
- _INIT_CMD(0xD0, 0x00, 0x48, 0x08, 0x00, 0x00),
- _INIT_CMD(0xD1, 0x00, 0x48, 0x09, 0x00, 0x00),
-
- /* page 6 */
- _INIT_CMD(0xF0, 0x55, 0xAA, 0x52, 0x08, 0x06),
- _INIT_CMD(0xB0, 0x02, 0x32, 0x32, 0x08, 0x2F),
- _INIT_CMD(0xB1, 0x2E, 0x15, 0x14, 0x13, 0x12),
- _INIT_CMD(0xB2, 0x11, 0x10, 0x00, 0x3D, 0x3D),
- _INIT_CMD(0xB3, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D),
- _INIT_CMD(0xB4, 0x3D, 0x32),
- _INIT_CMD(0xB5, 0x03, 0x32, 0x32, 0x09, 0x2F),
- _INIT_CMD(0xB6, 0x2E, 0x1B, 0x1A, 0x19, 0x18),
- _INIT_CMD(0xB7, 0x17, 0x16, 0x01, 0x3D, 0x3D),
- _INIT_CMD(0xB8, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D),
- _INIT_CMD(0xB9, 0x3D, 0x32),
- _INIT_CMD(0xC0, 0x01, 0x32, 0x32, 0x09, 0x2F),
- _INIT_CMD(0xC1, 0x2E, 0x1A, 0x1B, 0x16, 0x17),
- _INIT_CMD(0xC2, 0x18, 0x19, 0x03, 0x3D, 0x3D),
- _INIT_CMD(0xC3, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D),
- _INIT_CMD(0xC4, 0x3D, 0x32),
- _INIT_CMD(0xC5, 0x00, 0x32, 0x32, 0x08, 0x2F),
- _INIT_CMD(0xC6, 0x2E, 0x14, 0x15, 0x10, 0x11),
- _INIT_CMD(0xC7, 0x12, 0x13, 0x02, 0x3D, 0x3D),
- _INIT_CMD(0xC8, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D),
- _INIT_CMD(0xC9, 0x3D, 0x32),
-
- {},
-};
+static int innolux_p097pfg_init(struct innolux_panel *innolux)
+{
+ struct mipi_dsi_multi_context ctx = { .dsi = innolux->link };
+
+ innolux_panel_switch_page(&ctx, 0x00);
+ innolux_panel_init_cmd_multi(&ctx, 0xb1, 0xe8, 0x11);
+ innolux_panel_init_cmd_multi(&ctx, 0xb2, 0x25, 0x02);
+ innolux_panel_init_cmd_multi(&ctx, 0xb5, 0x08, 0x00);
+ innolux_panel_init_cmd_multi(&ctx, 0xbc, 0x0f, 0x00);
+ innolux_panel_init_cmd_multi(&ctx, 0xb8, 0x03, 0x06, 0x00, 0x00);
+ innolux_panel_init_cmd_multi(&ctx, 0xbd, 0x01, 0x90, 0x14, 0x14);
+ innolux_panel_init_cmd_multi(&ctx, 0x6f, 0x01);
+ innolux_panel_init_cmd_multi(&ctx, 0xc0, 0x03);
+ innolux_panel_init_cmd_multi(&ctx, 0x6f, 0x02);
+ innolux_panel_init_cmd_multi(&ctx, 0xc1, 0x0d);
+ innolux_panel_init_cmd_multi(&ctx, 0xd9, 0x01, 0x09, 0x70);
+ innolux_panel_init_cmd_multi(&ctx, 0xc5, 0x12, 0x21, 0x00);
+ innolux_panel_init_cmd_multi(&ctx, 0xbb, 0x93, 0x93);
+
+ innolux_panel_switch_page(&ctx, 0x01);
+ innolux_panel_init_cmd_multi(&ctx, 0xb3, 0x3c, 0x3c);
+ innolux_panel_init_cmd_multi(&ctx, 0xb4, 0x0f, 0x0f);
+ innolux_panel_init_cmd_multi(&ctx, 0xb9, 0x45, 0x45);
+ innolux_panel_init_cmd_multi(&ctx, 0xba, 0x14, 0x14);
+ innolux_panel_init_cmd_multi(&ctx, 0xca, 0x02);
+ innolux_panel_init_cmd_multi(&ctx, 0xce, 0x04);
+ innolux_panel_init_cmd_multi(&ctx, 0xc3, 0x9b, 0x9b);
+ innolux_panel_init_cmd_multi(&ctx, 0xd8, 0xc0, 0x03);
+ innolux_panel_init_cmd_multi(&ctx, 0xbc, 0x82, 0x01);
+ innolux_panel_init_cmd_multi(&ctx, 0xbd, 0x9e, 0x01);
+
+ innolux_panel_switch_page(&ctx, 0x02);
+ innolux_panel_init_cmd_multi(&ctx, 0xb0, 0x82);
+ innolux_panel_init_cmd_multi(&ctx, 0xd1, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x82, 0x00, 0xa5,
+ 0x00, 0xc1, 0x00, 0xea, 0x01, 0x0d, 0x01, 0x40);
+ innolux_panel_init_cmd_multi(&ctx, 0xd2, 0x01, 0x6a, 0x01, 0xa8, 0x01, 0xdc, 0x02, 0x29,
+ 0x02, 0x67, 0x02, 0x68, 0x02, 0xa8, 0x02, 0xf0);
+ innolux_panel_init_cmd_multi(&ctx, 0xd3, 0x03, 0x19, 0x03, 0x49, 0x03, 0x67, 0x03, 0x8c,
+ 0x03, 0xa6, 0x03, 0xc7, 0x03, 0xde, 0x03, 0xec);
+ innolux_panel_init_cmd_multi(&ctx, 0xd4, 0x03, 0xff, 0x03, 0xff);
+ innolux_panel_init_cmd_multi(&ctx, 0xe0, 0x00, 0x00, 0x00, 0x86, 0x00, 0xc5, 0x00, 0xe5,
+ 0x00, 0xff, 0x01, 0x26, 0x01, 0x45, 0x01, 0x75);
+ innolux_panel_init_cmd_multi(&ctx, 0xe1, 0x01, 0x9c, 0x01, 0xd5, 0x02, 0x05, 0x02, 0x4d,
+ 0x02, 0x86, 0x02, 0x87, 0x02, 0xc3, 0x03, 0x03);
+ innolux_panel_init_cmd_multi(&ctx, 0xe2, 0x03, 0x2a, 0x03, 0x56, 0x03, 0x72, 0x03, 0x94,
+ 0x03, 0xac, 0x03, 0xcb, 0x03, 0xe0, 0x03, 0xed);
+ innolux_panel_init_cmd_multi(&ctx, 0xe3, 0x03, 0xff, 0x03, 0xff);
+
+ innolux_panel_switch_page(&ctx, 0x03);
+ innolux_panel_init_cmd_multi(&ctx, 0xb0, 0x00, 0x00, 0x00, 0x00);
+ innolux_panel_init_cmd_multi(&ctx, 0xb1, 0x00, 0x00, 0x00, 0x00);
+ innolux_panel_init_cmd_multi(&ctx, 0xb2, 0x00, 0x00, 0x06, 0x04, 0x01, 0x40, 0x85);
+ innolux_panel_init_cmd_multi(&ctx, 0xb3, 0x10, 0x07, 0xfc, 0x04, 0x01, 0x40, 0x80);
+ innolux_panel_init_cmd_multi(&ctx, 0xb6, 0xf0, 0x08, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01,
+ 0x40, 0x80);
+ innolux_panel_init_cmd_multi(&ctx, 0xba, 0xc5, 0x07, 0x00, 0x04, 0x11, 0x25, 0x8c);
+ innolux_panel_init_cmd_multi(&ctx, 0xbb, 0xc5, 0x07, 0x00, 0x03, 0x11, 0x25, 0x8c);
+ innolux_panel_init_cmd_multi(&ctx, 0xc0, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x80, 0x80);
+ innolux_panel_init_cmd_multi(&ctx, 0xc1, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x80, 0x80);
+ innolux_panel_init_cmd_multi(&ctx, 0xc4, 0x00, 0x00);
+ innolux_panel_init_cmd_multi(&ctx, 0xef, 0x41);
+
+ innolux_panel_switch_page(&ctx, 0x04);
+ innolux_panel_init_cmd_multi(&ctx, 0xec, 0x4c);
+
+ innolux_panel_switch_page(&ctx, 0x05);
+ innolux_panel_init_cmd_multi(&ctx, 0xb0, 0x13, 0x03, 0x03, 0x01);
+ innolux_panel_init_cmd_multi(&ctx, 0xb1, 0x30, 0x00);
+ innolux_panel_init_cmd_multi(&ctx, 0xb2, 0x02, 0x02, 0x00);
+ innolux_panel_init_cmd_multi(&ctx, 0xb3, 0x82, 0x23, 0x82, 0x9d);
+ innolux_panel_init_cmd_multi(&ctx, 0xb4, 0xc5, 0x75, 0x24, 0x57);
+ innolux_panel_init_cmd_multi(&ctx, 0xb5, 0x00, 0xd4, 0x72, 0x11, 0x11, 0xab, 0x0a);
+ innolux_panel_init_cmd_multi(&ctx, 0xb6, 0x00, 0x00, 0xd5, 0x72, 0x24, 0x56);
+ innolux_panel_init_cmd_multi(&ctx, 0xb7, 0x5c, 0xdc, 0x5c, 0x5c);
+ innolux_panel_init_cmd_multi(&ctx, 0xb9, 0x0c, 0x00, 0x00, 0x01, 0x00);
+ innolux_panel_init_cmd_multi(&ctx, 0xc0, 0x75, 0x11, 0x11, 0x54, 0x05);
+ innolux_panel_init_cmd_multi(&ctx, 0xc6, 0x00, 0x00, 0x00, 0x00);
+ innolux_panel_init_cmd_multi(&ctx, 0xd0, 0x00, 0x48, 0x08, 0x00, 0x00);
+ innolux_panel_init_cmd_multi(&ctx, 0xd1, 0x00, 0x48, 0x09, 0x00, 0x00);
+
+ innolux_panel_switch_page(&ctx, 0x06);
+ innolux_panel_init_cmd_multi(&ctx, 0xb0, 0x02, 0x32, 0x32, 0x08, 0x2f);
+ innolux_panel_init_cmd_multi(&ctx, 0xb1, 0x2e, 0x15, 0x14, 0x13, 0x12);
+ innolux_panel_init_cmd_multi(&ctx, 0xb2, 0x11, 0x10, 0x00, 0x3d, 0x3d);
+ innolux_panel_init_cmd_multi(&ctx, 0xb3, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d);
+ innolux_panel_init_cmd_multi(&ctx, 0xb4, 0x3d, 0x32);
+ innolux_panel_init_cmd_multi(&ctx, 0xb5, 0x03, 0x32, 0x32, 0x09, 0x2f);
+ innolux_panel_init_cmd_multi(&ctx, 0xb6, 0x2e, 0x1b, 0x1a, 0x19, 0x18);
+ innolux_panel_init_cmd_multi(&ctx, 0xb7, 0x17, 0x16, 0x01, 0x3d, 0x3d);
+ innolux_panel_init_cmd_multi(&ctx, 0xb8, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d);
+ innolux_panel_init_cmd_multi(&ctx, 0xb9, 0x3d, 0x32);
+ innolux_panel_init_cmd_multi(&ctx, 0xc0, 0x01, 0x32, 0x32, 0x09, 0x2f);
+ innolux_panel_init_cmd_multi(&ctx, 0xc1, 0x2e, 0x1a, 0x1b, 0x16, 0x17);
+ innolux_panel_init_cmd_multi(&ctx, 0xc2, 0x18, 0x19, 0x03, 0x3d, 0x3d);
+ innolux_panel_init_cmd_multi(&ctx, 0xc3, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d);
+ innolux_panel_init_cmd_multi(&ctx, 0xc4, 0x3d, 0x32);
+ innolux_panel_init_cmd_multi(&ctx, 0xc5, 0x00, 0x32, 0x32, 0x08, 0x2f);
+ innolux_panel_init_cmd_multi(&ctx, 0xc6, 0x2e, 0x14, 0x15, 0x10, 0x11);
+ innolux_panel_init_cmd_multi(&ctx, 0xc7, 0x12, 0x13, 0x02, 0x3d, 0x3d);
+ innolux_panel_init_cmd_multi(&ctx, 0xc8, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d);
+ innolux_panel_init_cmd_multi(&ctx, 0xc9, 0x3d, 0x32);
+
+ return ctx.accum_err;
+}
static const struct panel_desc innolux_p097pfg_panel_desc = {
.mode = &innolux_p097pfg_mode,
@@ -374,7 +326,7 @@ static const struct panel_desc innolux_p097pfg_panel_desc = {
.flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
MIPI_DSI_MODE_LPM,
.format = MIPI_DSI_FMT_RGB888,
- .init_cmds = innolux_p097pfg_init_cmds,
+ .init = innolux_p097pfg_init,
.lanes = 4,
.supply_names = innolux_p097pfg_supply_names,
.num_supplies = ARRAY_SIZE(innolux_p097pfg_supply_names),
@@ -407,10 +359,8 @@ static int innolux_panel_get_modes(struct drm_panel *panel,
}
static const struct drm_panel_funcs innolux_panel_funcs = {
- .disable = innolux_panel_disable,
.unprepare = innolux_panel_unprepare,
.prepare = innolux_panel_prepare,
- .enable = innolux_panel_enable,
.get_modes = innolux_panel_get_modes,
};
@@ -510,13 +460,6 @@ static void innolux_panel_remove(struct mipi_dsi_device *dsi)
struct innolux_panel *innolux = mipi_dsi_get_drvdata(dsi);
int err;
- err = drm_panel_unprepare(&innolux->base);
- if (err < 0)
- dev_err(&dsi->dev, "failed to unprepare panel: %d\n", err);
-
- err = drm_panel_disable(&innolux->base);
- if (err < 0)
- dev_err(&dsi->dev, "failed to disable panel: %d\n", err);
err = mipi_dsi_detach(dsi);
if (err < 0)
@@ -525,14 +468,6 @@ static void innolux_panel_remove(struct mipi_dsi_device *dsi)
innolux_panel_del(innolux);
}
-static void innolux_panel_shutdown(struct mipi_dsi_device *dsi)
-{
- struct innolux_panel *innolux = mipi_dsi_get_drvdata(dsi);
-
- drm_panel_unprepare(&innolux->base);
- drm_panel_disable(&innolux->base);
-}
-
static struct mipi_dsi_driver innolux_panel_driver = {
.driver = {
.name = "panel-innolux-p079zca",
@@ -540,7 +475,6 @@ static struct mipi_dsi_driver innolux_panel_driver = {
},
.probe = innolux_panel_probe,
.remove = innolux_panel_remove,
- .shutdown = innolux_panel_shutdown,
};
module_mipi_dsi_driver(innolux_panel_driver);
diff --git a/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c b/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c
index 4879835fe101..c6b669866fed 100644
--- a/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c
+++ b/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c
@@ -19,25 +19,30 @@
#include <linux/of.h>
#include <linux/regulator/consumer.h>
-#define JD9365DA_INIT_CMD_LEN 2
-
-struct jadard_init_cmd {
- u8 data[JD9365DA_INIT_CMD_LEN];
-};
+struct jadard;
struct jadard_panel_desc {
const struct drm_display_mode mode;
unsigned int lanes;
enum mipi_dsi_pixel_format format;
- const struct jadard_init_cmd *init_cmds;
+ int (*init)(struct jadard *jadard);
u32 num_init_cmds;
+ bool lp11_before_reset;
+ bool reset_before_power_off_vcioo;
+ unsigned int vcioo_to_lp11_delay_ms;
+ unsigned int lp11_to_reset_delay_ms;
+ unsigned int exit_sleep_to_display_on_delay_ms;
+ unsigned int display_on_delay_ms;
+ unsigned int backlight_off_to_display_off_delay_ms;
+ unsigned int display_off_to_enter_sleep_delay_ms;
+ unsigned int enter_sleep_to_reset_down_delay_ms;
};
struct jadard {
struct drm_panel panel;
struct mipi_dsi_device *dsi;
const struct jadard_panel_desc *desc;
-
+ enum drm_panel_orientation orientation;
struct regulator *vdd;
struct regulator *vccio;
struct gpio_desc *reset;
@@ -50,51 +55,43 @@ static inline struct jadard *panel_to_jadard(struct drm_panel *panel)
static int jadard_enable(struct drm_panel *panel)
{
- struct device *dev = panel->dev;
struct jadard *jadard = panel_to_jadard(panel);
- const struct jadard_panel_desc *desc = jadard->desc;
- struct mipi_dsi_device *dsi = jadard->dsi;
- unsigned int i;
- int err;
+ struct mipi_dsi_multi_context dsi_ctx = { .dsi = jadard->dsi };
- msleep(10);
-
- for (i = 0; i < desc->num_init_cmds; i++) {
- const struct jadard_init_cmd *cmd = &desc->init_cmds[i];
+ msleep(120);
- err = mipi_dsi_dcs_write_buffer(dsi, cmd->data, JD9365DA_INIT_CMD_LEN);
- if (err < 0)
- return err;
- }
+ mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);
- msleep(120);
+ if (jadard->desc->exit_sleep_to_display_on_delay_ms)
+ mipi_dsi_msleep(&dsi_ctx, jadard->desc->exit_sleep_to_display_on_delay_ms);
- err = mipi_dsi_dcs_exit_sleep_mode(dsi);
- if (err < 0)
- DRM_DEV_ERROR(dev, "failed to exit sleep mode ret = %d\n", err);
+ mipi_dsi_dcs_set_display_on_multi(&dsi_ctx);
- err = mipi_dsi_dcs_set_display_on(dsi);
- if (err < 0)
- DRM_DEV_ERROR(dev, "failed to set display on ret = %d\n", err);
+ if (jadard->desc->display_on_delay_ms)
+ mipi_dsi_msleep(&dsi_ctx, jadard->desc->display_on_delay_ms);
- return 0;
+ return dsi_ctx.accum_err;
}
static int jadard_disable(struct drm_panel *panel)
{
- struct device *dev = panel->dev;
struct jadard *jadard = panel_to_jadard(panel);
- int ret;
+ struct mipi_dsi_multi_context dsi_ctx = { .dsi = jadard->dsi };
- ret = mipi_dsi_dcs_set_display_off(jadard->dsi);
- if (ret < 0)
- DRM_DEV_ERROR(dev, "failed to set display off: %d\n", ret);
+ if (jadard->desc->backlight_off_to_display_off_delay_ms)
+ mipi_dsi_msleep(&dsi_ctx, jadard->desc->backlight_off_to_display_off_delay_ms);
- ret = mipi_dsi_dcs_enter_sleep_mode(jadard->dsi);
- if (ret < 0)
- DRM_DEV_ERROR(dev, "failed to enter sleep mode: %d\n", ret);
+ mipi_dsi_dcs_set_display_off_multi(&dsi_ctx);
- return 0;
+ if (jadard->desc->display_off_to_enter_sleep_delay_ms)
+ mipi_dsi_msleep(&dsi_ctx, jadard->desc->display_off_to_enter_sleep_delay_ms);
+
+ mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx);
+
+ if (jadard->desc->enter_sleep_to_reset_down_delay_ms)
+ mipi_dsi_msleep(&dsi_ctx, jadard->desc->enter_sleep_to_reset_down_delay_ms);
+
+ return dsi_ctx.accum_err;
}
static int jadard_prepare(struct drm_panel *panel)
@@ -110,6 +107,18 @@ static int jadard_prepare(struct drm_panel *panel)
if (ret)
return ret;
+ if (jadard->desc->vcioo_to_lp11_delay_ms)
+ msleep(jadard->desc->vcioo_to_lp11_delay_ms);
+
+ if (jadard->desc->lp11_before_reset) {
+ ret = mipi_dsi_dcs_nop(jadard->dsi);
+ if (ret)
+ return ret;
+ }
+
+ if (jadard->desc->lp11_to_reset_delay_ms)
+ msleep(jadard->desc->lp11_to_reset_delay_ms);
+
gpiod_set_value(jadard->reset, 1);
msleep(5);
@@ -117,7 +126,11 @@ static int jadard_prepare(struct drm_panel *panel)
msleep(10);
gpiod_set_value(jadard->reset, 1);
- msleep(120);
+ msleep(130);
+
+ ret = jadard->desc->init(jadard);
+ if (ret)
+ return ret;
return 0;
}
@@ -129,6 +142,12 @@ static int jadard_unprepare(struct drm_panel *panel)
gpiod_set_value(jadard->reset, 1);
msleep(120);
+ if (jadard->desc->reset_before_power_off_vcioo) {
+ gpiod_set_value(jadard->reset, 0);
+
+ usleep_range(1000, 2000);
+ }
+
regulator_disable(jadard->vdd);
regulator_disable(jadard->vccio);
@@ -159,184 +178,197 @@ static int jadard_get_modes(struct drm_panel *panel,
return 1;
}
+static enum drm_panel_orientation jadard_panel_get_orientation(struct drm_panel *panel)
+{
+ struct jadard *jadard = panel_to_jadard(panel);
+
+ return jadard->orientation;
+}
+
static const struct drm_panel_funcs jadard_funcs = {
.disable = jadard_disable,
.unprepare = jadard_unprepare,
.prepare = jadard_prepare,
.enable = jadard_enable,
.get_modes = jadard_get_modes,
+ .get_orientation = jadard_panel_get_orientation,
};
-static const struct jadard_init_cmd radxa_display_8hd_ad002_init_cmds[] = {
- { .data = { 0xE0, 0x00 } },
- { .data = { 0xE1, 0x93 } },
- { .data = { 0xE2, 0x65 } },
- { .data = { 0xE3, 0xF8 } },
- { .data = { 0x80, 0x03 } },
- { .data = { 0xE0, 0x01 } },
- { .data = { 0x00, 0x00 } },
- { .data = { 0x01, 0x7E } },
- { .data = { 0x03, 0x00 } },
- { .data = { 0x04, 0x65 } },
- { .data = { 0x0C, 0x74 } },
- { .data = { 0x17, 0x00 } },
- { .data = { 0x18, 0xB7 } },
- { .data = { 0x19, 0x00 } },
- { .data = { 0x1A, 0x00 } },
- { .data = { 0x1B, 0xB7 } },
- { .data = { 0x1C, 0x00 } },
- { .data = { 0x24, 0xFE } },
- { .data = { 0x37, 0x19 } },
- { .data = { 0x38, 0x05 } },
- { .data = { 0x39, 0x00 } },
- { .data = { 0x3A, 0x01 } },
- { .data = { 0x3B, 0x01 } },
- { .data = { 0x3C, 0x70 } },
- { .data = { 0x3D, 0xFF } },
- { .data = { 0x3E, 0xFF } },
- { .data = { 0x3F, 0xFF } },
- { .data = { 0x40, 0x06 } },
- { .data = { 0x41, 0xA0 } },
- { .data = { 0x43, 0x1E } },
- { .data = { 0x44, 0x0F } },
- { .data = { 0x45, 0x28 } },
- { .data = { 0x4B, 0x04 } },
- { .data = { 0x55, 0x02 } },
- { .data = { 0x56, 0x01 } },
- { .data = { 0x57, 0xA9 } },
- { .data = { 0x58, 0x0A } },
- { .data = { 0x59, 0x0A } },
- { .data = { 0x5A, 0x37 } },
- { .data = { 0x5B, 0x19 } },
- { .data = { 0x5D, 0x78 } },
- { .data = { 0x5E, 0x63 } },
- { .data = { 0x5F, 0x54 } },
- { .data = { 0x60, 0x49 } },
- { .data = { 0x61, 0x45 } },
- { .data = { 0x62, 0x38 } },
- { .data = { 0x63, 0x3D } },
- { .data = { 0x64, 0x28 } },
- { .data = { 0x65, 0x43 } },
- { .data = { 0x66, 0x41 } },
- { .data = { 0x67, 0x43 } },
- { .data = { 0x68, 0x62 } },
- { .data = { 0x69, 0x50 } },
- { .data = { 0x6A, 0x57 } },
- { .data = { 0x6B, 0x49 } },
- { .data = { 0x6C, 0x44 } },
- { .data = { 0x6D, 0x37 } },
- { .data = { 0x6E, 0x23 } },
- { .data = { 0x6F, 0x10 } },
- { .data = { 0x70, 0x78 } },
- { .data = { 0x71, 0x63 } },
- { .data = { 0x72, 0x54 } },
- { .data = { 0x73, 0x49 } },
- { .data = { 0x74, 0x45 } },
- { .data = { 0x75, 0x38 } },
- { .data = { 0x76, 0x3D } },
- { .data = { 0x77, 0x28 } },
- { .data = { 0x78, 0x43 } },
- { .data = { 0x79, 0x41 } },
- { .data = { 0x7A, 0x43 } },
- { .data = { 0x7B, 0x62 } },
- { .data = { 0x7C, 0x50 } },
- { .data = { 0x7D, 0x57 } },
- { .data = { 0x7E, 0x49 } },
- { .data = { 0x7F, 0x44 } },
- { .data = { 0x80, 0x37 } },
- { .data = { 0x81, 0x23 } },
- { .data = { 0x82, 0x10 } },
- { .data = { 0xE0, 0x02 } },
- { .data = { 0x00, 0x47 } },
- { .data = { 0x01, 0x47 } },
- { .data = { 0x02, 0x45 } },
- { .data = { 0x03, 0x45 } },
- { .data = { 0x04, 0x4B } },
- { .data = { 0x05, 0x4B } },
- { .data = { 0x06, 0x49 } },
- { .data = { 0x07, 0x49 } },
- { .data = { 0x08, 0x41 } },
- { .data = { 0x09, 0x1F } },
- { .data = { 0x0A, 0x1F } },
- { .data = { 0x0B, 0x1F } },
- { .data = { 0x0C, 0x1F } },
- { .data = { 0x0D, 0x1F } },
- { .data = { 0x0E, 0x1F } },
- { .data = { 0x0F, 0x5F } },
- { .data = { 0x10, 0x5F } },
- { .data = { 0x11, 0x57 } },
- { .data = { 0x12, 0x77 } },
- { .data = { 0x13, 0x35 } },
- { .data = { 0x14, 0x1F } },
- { .data = { 0x15, 0x1F } },
- { .data = { 0x16, 0x46 } },
- { .data = { 0x17, 0x46 } },
- { .data = { 0x18, 0x44 } },
- { .data = { 0x19, 0x44 } },
- { .data = { 0x1A, 0x4A } },
- { .data = { 0x1B, 0x4A } },
- { .data = { 0x1C, 0x48 } },
- { .data = { 0x1D, 0x48 } },
- { .data = { 0x1E, 0x40 } },
- { .data = { 0x1F, 0x1F } },
- { .data = { 0x20, 0x1F } },
- { .data = { 0x21, 0x1F } },
- { .data = { 0x22, 0x1F } },
- { .data = { 0x23, 0x1F } },
- { .data = { 0x24, 0x1F } },
- { .data = { 0x25, 0x5F } },
- { .data = { 0x26, 0x5F } },
- { .data = { 0x27, 0x57 } },
- { .data = { 0x28, 0x77 } },
- { .data = { 0x29, 0x35 } },
- { .data = { 0x2A, 0x1F } },
- { .data = { 0x2B, 0x1F } },
- { .data = { 0x58, 0x40 } },
- { .data = { 0x59, 0x00 } },
- { .data = { 0x5A, 0x00 } },
- { .data = { 0x5B, 0x10 } },
- { .data = { 0x5C, 0x06 } },
- { .data = { 0x5D, 0x40 } },
- { .data = { 0x5E, 0x01 } },
- { .data = { 0x5F, 0x02 } },
- { .data = { 0x60, 0x30 } },
- { .data = { 0x61, 0x01 } },
- { .data = { 0x62, 0x02 } },
- { .data = { 0x63, 0x03 } },
- { .data = { 0x64, 0x6B } },
- { .data = { 0x65, 0x05 } },
- { .data = { 0x66, 0x0C } },
- { .data = { 0x67, 0x73 } },
- { .data = { 0x68, 0x09 } },
- { .data = { 0x69, 0x03 } },
- { .data = { 0x6A, 0x56 } },
- { .data = { 0x6B, 0x08 } },
- { .data = { 0x6C, 0x00 } },
- { .data = { 0x6D, 0x04 } },
- { .data = { 0x6E, 0x04 } },
- { .data = { 0x6F, 0x88 } },
- { .data = { 0x70, 0x00 } },
- { .data = { 0x71, 0x00 } },
- { .data = { 0x72, 0x06 } },
- { .data = { 0x73, 0x7B } },
- { .data = { 0x74, 0x00 } },
- { .data = { 0x75, 0xF8 } },
- { .data = { 0x76, 0x00 } },
- { .data = { 0x77, 0xD5 } },
- { .data = { 0x78, 0x2E } },
- { .data = { 0x79, 0x12 } },
- { .data = { 0x7A, 0x03 } },
- { .data = { 0x7B, 0x00 } },
- { .data = { 0x7C, 0x00 } },
- { .data = { 0x7D, 0x03 } },
- { .data = { 0x7E, 0x7B } },
- { .data = { 0xE0, 0x04 } },
- { .data = { 0x00, 0x0E } },
- { .data = { 0x02, 0xB3 } },
- { .data = { 0x09, 0x60 } },
- { .data = { 0x0E, 0x2A } },
- { .data = { 0x36, 0x59 } },
- { .data = { 0xE0, 0x00 } },
+static int radxa_display_8hd_ad002_init_cmds(struct jadard *jadard)
+{
+ struct mipi_dsi_multi_context dsi_ctx = { .dsi = jadard->dsi };
+
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xE0, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xE1, 0x93);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xE2, 0x65);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xE3, 0xF8);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x80, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xE0, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x01, 0x7E);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x03, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x04, 0x65);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0C, 0x74);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x17, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x18, 0xB7);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x19, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1A, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1B, 0xB7);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1C, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x24, 0xFE);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x37, 0x19);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x38, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x39, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3A, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3B, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3C, 0x70);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3D, 0xFF);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3E, 0xFF);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3F, 0xFF);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x40, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x41, 0xA0);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x43, 0x1E);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x44, 0x0F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x45, 0x28);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4B, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x55, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x56, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x57, 0xA9);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x58, 0x0A);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x59, 0x0A);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5A, 0x37);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5B, 0x19);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5D, 0x78);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5E, 0x63);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5F, 0x54);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x60, 0x49);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x61, 0x45);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x62, 0x38);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x63, 0x3D);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x64, 0x28);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x65, 0x43);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x66, 0x41);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x67, 0x43);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x68, 0x62);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x69, 0x50);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6A, 0x57);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6B, 0x49);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6C, 0x44);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6D, 0x37);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6E, 0x23);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6F, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x70, 0x78);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x71, 0x63);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x72, 0x54);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x73, 0x49);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x74, 0x45);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x75, 0x38);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x76, 0x3D);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x77, 0x28);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x78, 0x43);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x79, 0x41);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7A, 0x43);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7B, 0x62);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7C, 0x50);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7D, 0x57);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7E, 0x49);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7F, 0x44);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x80, 0x37);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x81, 0x23);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x82, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xE0, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x47);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x01, 0x47);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x02, 0x45);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x03, 0x45);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x04, 0x4B);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x05, 0x4B);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x06, 0x49);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x07, 0x49);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x08, 0x41);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x09, 0x1F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0A, 0x1F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0B, 0x1F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0C, 0x1F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0D, 0x1F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0E, 0x1F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0F, 0x5F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x10, 0x5F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x11, 0x57);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x12, 0x77);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x13, 0x35);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x14, 0x1F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x15, 0x1F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x16, 0x46);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x17, 0x46);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x18, 0x44);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x19, 0x44);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1A, 0x4A);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1B, 0x4A);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1C, 0x48);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1D, 0x48);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1E, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1F, 0x1F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x20, 0x1F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x21, 0x1F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x22, 0x1F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x23, 0x1F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x24, 0x1F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x25, 0x5F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x26, 0x5F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x27, 0x57);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x28, 0x77);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x29, 0x35);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2A, 0x1F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2B, 0x1F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x58, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x59, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5A, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5B, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5C, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5D, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5E, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5F, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x60, 0x30);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x61, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x62, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x63, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x64, 0x6B);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x65, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x66, 0x0C);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x67, 0x73);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x68, 0x09);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x69, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6A, 0x56);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6B, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6C, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6D, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6E, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6F, 0x88);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x70, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x71, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x72, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x73, 0x7B);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x74, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x75, 0xF8);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x76, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x77, 0xD5);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x78, 0x2E);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x79, 0x12);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7A, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7B, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7C, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7D, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7E, 0x7B);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xE0, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x0E);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x02, 0xB3);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x09, 0x60);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0E, 0x2A);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x36, 0x59);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xE0, 0x00);
+
+ return dsi_ctx.accum_err;
};
static const struct jadard_panel_desc radxa_display_8hd_ad002_desc = {
@@ -359,205 +391,209 @@ static const struct jadard_panel_desc radxa_display_8hd_ad002_desc = {
},
.lanes = 4,
.format = MIPI_DSI_FMT_RGB888,
- .init_cmds = radxa_display_8hd_ad002_init_cmds,
- .num_init_cmds = ARRAY_SIZE(radxa_display_8hd_ad002_init_cmds),
+ .init = radxa_display_8hd_ad002_init_cmds,
};
-static const struct jadard_init_cmd cz101b4001_init_cmds[] = {
- { .data = { 0xE0, 0x00 } },
- { .data = { 0xE1, 0x93 } },
- { .data = { 0xE2, 0x65 } },
- { .data = { 0xE3, 0xF8 } },
- { .data = { 0x80, 0x03 } },
- { .data = { 0xE0, 0x01 } },
- { .data = { 0x00, 0x00 } },
- { .data = { 0x01, 0x3B } },
- { .data = { 0x0C, 0x74 } },
- { .data = { 0x17, 0x00 } },
- { .data = { 0x18, 0xAF } },
- { .data = { 0x19, 0x00 } },
- { .data = { 0x1A, 0x00 } },
- { .data = { 0x1B, 0xAF } },
- { .data = { 0x1C, 0x00 } },
- { .data = { 0x35, 0x26 } },
- { .data = { 0x37, 0x09 } },
- { .data = { 0x38, 0x04 } },
- { .data = { 0x39, 0x00 } },
- { .data = { 0x3A, 0x01 } },
- { .data = { 0x3C, 0x78 } },
- { .data = { 0x3D, 0xFF } },
- { .data = { 0x3E, 0xFF } },
- { .data = { 0x3F, 0x7F } },
- { .data = { 0x40, 0x06 } },
- { .data = { 0x41, 0xA0 } },
- { .data = { 0x42, 0x81 } },
- { .data = { 0x43, 0x14 } },
- { .data = { 0x44, 0x23 } },
- { .data = { 0x45, 0x28 } },
- { .data = { 0x55, 0x02 } },
- { .data = { 0x57, 0x69 } },
- { .data = { 0x59, 0x0A } },
- { .data = { 0x5A, 0x2A } },
- { .data = { 0x5B, 0x17 } },
- { .data = { 0x5D, 0x7F } },
- { .data = { 0x5E, 0x6B } },
- { .data = { 0x5F, 0x5C } },
- { .data = { 0x60, 0x4F } },
- { .data = { 0x61, 0x4D } },
- { .data = { 0x62, 0x3F } },
- { .data = { 0x63, 0x42 } },
- { .data = { 0x64, 0x2B } },
- { .data = { 0x65, 0x44 } },
- { .data = { 0x66, 0x43 } },
- { .data = { 0x67, 0x43 } },
- { .data = { 0x68, 0x63 } },
- { .data = { 0x69, 0x52 } },
- { .data = { 0x6A, 0x5A } },
- { .data = { 0x6B, 0x4F } },
- { .data = { 0x6C, 0x4E } },
- { .data = { 0x6D, 0x20 } },
- { .data = { 0x6E, 0x0F } },
- { .data = { 0x6F, 0x00 } },
- { .data = { 0x70, 0x7F } },
- { .data = { 0x71, 0x6B } },
- { .data = { 0x72, 0x5C } },
- { .data = { 0x73, 0x4F } },
- { .data = { 0x74, 0x4D } },
- { .data = { 0x75, 0x3F } },
- { .data = { 0x76, 0x42 } },
- { .data = { 0x77, 0x2B } },
- { .data = { 0x78, 0x44 } },
- { .data = { 0x79, 0x43 } },
- { .data = { 0x7A, 0x43 } },
- { .data = { 0x7B, 0x63 } },
- { .data = { 0x7C, 0x52 } },
- { .data = { 0x7D, 0x5A } },
- { .data = { 0x7E, 0x4F } },
- { .data = { 0x7F, 0x4E } },
- { .data = { 0x80, 0x20 } },
- { .data = { 0x81, 0x0F } },
- { .data = { 0x82, 0x00 } },
- { .data = { 0xE0, 0x02 } },
- { .data = { 0x00, 0x02 } },
- { .data = { 0x01, 0x02 } },
- { .data = { 0x02, 0x00 } },
- { .data = { 0x03, 0x00 } },
- { .data = { 0x04, 0x1E } },
- { .data = { 0x05, 0x1E } },
- { .data = { 0x06, 0x1F } },
- { .data = { 0x07, 0x1F } },
- { .data = { 0x08, 0x1F } },
- { .data = { 0x09, 0x17 } },
- { .data = { 0x0A, 0x17 } },
- { .data = { 0x0B, 0x37 } },
- { .data = { 0x0C, 0x37 } },
- { .data = { 0x0D, 0x47 } },
- { .data = { 0x0E, 0x47 } },
- { .data = { 0x0F, 0x45 } },
- { .data = { 0x10, 0x45 } },
- { .data = { 0x11, 0x4B } },
- { .data = { 0x12, 0x4B } },
- { .data = { 0x13, 0x49 } },
- { .data = { 0x14, 0x49 } },
- { .data = { 0x15, 0x1F } },
- { .data = { 0x16, 0x01 } },
- { .data = { 0x17, 0x01 } },
- { .data = { 0x18, 0x00 } },
- { .data = { 0x19, 0x00 } },
- { .data = { 0x1A, 0x1E } },
- { .data = { 0x1B, 0x1E } },
- { .data = { 0x1C, 0x1F } },
- { .data = { 0x1D, 0x1F } },
- { .data = { 0x1E, 0x1F } },
- { .data = { 0x1F, 0x17 } },
- { .data = { 0x20, 0x17 } },
- { .data = { 0x21, 0x37 } },
- { .data = { 0x22, 0x37 } },
- { .data = { 0x23, 0x46 } },
- { .data = { 0x24, 0x46 } },
- { .data = { 0x25, 0x44 } },
- { .data = { 0x26, 0x44 } },
- { .data = { 0x27, 0x4A } },
- { .data = { 0x28, 0x4A } },
- { .data = { 0x29, 0x48 } },
- { .data = { 0x2A, 0x48 } },
- { .data = { 0x2B, 0x1F } },
- { .data = { 0x2C, 0x01 } },
- { .data = { 0x2D, 0x01 } },
- { .data = { 0x2E, 0x00 } },
- { .data = { 0x2F, 0x00 } },
- { .data = { 0x30, 0x1F } },
- { .data = { 0x31, 0x1F } },
- { .data = { 0x32, 0x1E } },
- { .data = { 0x33, 0x1E } },
- { .data = { 0x34, 0x1F } },
- { .data = { 0x35, 0x17 } },
- { .data = { 0x36, 0x17 } },
- { .data = { 0x37, 0x37 } },
- { .data = { 0x38, 0x37 } },
- { .data = { 0x39, 0x08 } },
- { .data = { 0x3A, 0x08 } },
- { .data = { 0x3B, 0x0A } },
- { .data = { 0x3C, 0x0A } },
- { .data = { 0x3D, 0x04 } },
- { .data = { 0x3E, 0x04 } },
- { .data = { 0x3F, 0x06 } },
- { .data = { 0x40, 0x06 } },
- { .data = { 0x41, 0x1F } },
- { .data = { 0x42, 0x02 } },
- { .data = { 0x43, 0x02 } },
- { .data = { 0x44, 0x00 } },
- { .data = { 0x45, 0x00 } },
- { .data = { 0x46, 0x1F } },
- { .data = { 0x47, 0x1F } },
- { .data = { 0x48, 0x1E } },
- { .data = { 0x49, 0x1E } },
- { .data = { 0x4A, 0x1F } },
- { .data = { 0x4B, 0x17 } },
- { .data = { 0x4C, 0x17 } },
- { .data = { 0x4D, 0x37 } },
- { .data = { 0x4E, 0x37 } },
- { .data = { 0x4F, 0x09 } },
- { .data = { 0x50, 0x09 } },
- { .data = { 0x51, 0x0B } },
- { .data = { 0x52, 0x0B } },
- { .data = { 0x53, 0x05 } },
- { .data = { 0x54, 0x05 } },
- { .data = { 0x55, 0x07 } },
- { .data = { 0x56, 0x07 } },
- { .data = { 0x57, 0x1F } },
- { .data = { 0x58, 0x40 } },
- { .data = { 0x5B, 0x30 } },
- { .data = { 0x5C, 0x16 } },
- { .data = { 0x5D, 0x34 } },
- { .data = { 0x5E, 0x05 } },
- { .data = { 0x5F, 0x02 } },
- { .data = { 0x63, 0x00 } },
- { .data = { 0x64, 0x6A } },
- { .data = { 0x67, 0x73 } },
- { .data = { 0x68, 0x1D } },
- { .data = { 0x69, 0x08 } },
- { .data = { 0x6A, 0x6A } },
- { .data = { 0x6B, 0x08 } },
- { .data = { 0x6C, 0x00 } },
- { .data = { 0x6D, 0x00 } },
- { .data = { 0x6E, 0x00 } },
- { .data = { 0x6F, 0x88 } },
- { .data = { 0x75, 0xFF } },
- { .data = { 0x77, 0xDD } },
- { .data = { 0x78, 0x3F } },
- { .data = { 0x79, 0x15 } },
- { .data = { 0x7A, 0x17 } },
- { .data = { 0x7D, 0x14 } },
- { .data = { 0x7E, 0x82 } },
- { .data = { 0xE0, 0x04 } },
- { .data = { 0x00, 0x0E } },
- { .data = { 0x02, 0xB3 } },
- { .data = { 0x09, 0x61 } },
- { .data = { 0x0E, 0x48 } },
- { .data = { 0xE0, 0x00 } },
- { .data = { 0xE6, 0x02 } },
- { .data = { 0xE7, 0x0C } },
+static int cz101b4001_init_cmds(struct jadard *jadard)
+{
+ struct mipi_dsi_multi_context dsi_ctx = { .dsi = jadard->dsi };
+
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xE0, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xE1, 0x93);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xE2, 0x65);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xE3, 0xF8);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x80, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xE0, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x01, 0x3B);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0C, 0x74);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x17, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x18, 0xAF);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x19, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1A, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1B, 0xAF);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1C, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x35, 0x26);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x37, 0x09);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x38, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x39, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3A, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3C, 0x78);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3D, 0xFF);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3E, 0xFF);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3F, 0x7F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x40, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x41, 0xA0);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x42, 0x81);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x43, 0x14);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x44, 0x23);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x45, 0x28);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x55, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x57, 0x69);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x59, 0x0A);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5A, 0x2A);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5B, 0x17);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5D, 0x7F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5E, 0x6B);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5F, 0x5C);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x60, 0x4F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x61, 0x4D);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x62, 0x3F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x63, 0x42);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x64, 0x2B);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x65, 0x44);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x66, 0x43);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x67, 0x43);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x68, 0x63);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x69, 0x52);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6A, 0x5A);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6B, 0x4F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6C, 0x4E);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6D, 0x20);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6E, 0x0F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6F, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x70, 0x7F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x71, 0x6B);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x72, 0x5C);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x73, 0x4F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x74, 0x4D);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x75, 0x3F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x76, 0x42);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x77, 0x2B);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x78, 0x44);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x79, 0x43);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7A, 0x43);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7B, 0x63);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7C, 0x52);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7D, 0x5A);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7E, 0x4F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7F, 0x4E);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x80, 0x20);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x81, 0x0F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x82, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xE0, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x01, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x02, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x03, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x04, 0x1E);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x05, 0x1E);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x06, 0x1F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x07, 0x1F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x08, 0x1F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x09, 0x17);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0A, 0x17);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0B, 0x37);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0C, 0x37);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0D, 0x47);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0E, 0x47);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0F, 0x45);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x10, 0x45);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x11, 0x4B);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x12, 0x4B);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x13, 0x49);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x14, 0x49);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x15, 0x1F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x16, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x17, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x18, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x19, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1A, 0x1E);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1B, 0x1E);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1C, 0x1F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1D, 0x1F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1E, 0x1F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1F, 0x17);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x20, 0x17);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x21, 0x37);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x22, 0x37);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x23, 0x46);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x24, 0x46);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x25, 0x44);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x26, 0x44);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x27, 0x4A);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x28, 0x4A);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x29, 0x48);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2A, 0x48);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2B, 0x1F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2C, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2D, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2E, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2F, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x30, 0x1F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x31, 0x1F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x32, 0x1E);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x33, 0x1E);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x34, 0x1F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x35, 0x17);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x36, 0x17);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x37, 0x37);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x38, 0x37);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x39, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3A, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3B, 0x0A);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3C, 0x0A);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3D, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3E, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3F, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x40, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x41, 0x1F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x42, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x43, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x44, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x45, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x46, 0x1F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x47, 0x1F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x48, 0x1E);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x49, 0x1E);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4A, 0x1F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4B, 0x17);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4C, 0x17);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4D, 0x37);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4E, 0x37);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4F, 0x09);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x50, 0x09);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x51, 0x0B);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x52, 0x0B);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x53, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x54, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x55, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x56, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x57, 0x1F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x58, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5B, 0x30);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5C, 0x16);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5D, 0x34);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5E, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5F, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x63, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x64, 0x6A);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x67, 0x73);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x68, 0x1D);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x69, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6A, 0x6A);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6B, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6C, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6D, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6E, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6F, 0x88);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x75, 0xFF);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x77, 0xDD);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x78, 0x3F);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x79, 0x15);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7A, 0x17);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7D, 0x14);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7E, 0x82);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xE0, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x0E);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x02, 0xB3);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x09, 0x61);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0E, 0x48);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xE0, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xE6, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xE7, 0x0C);
+
+ return dsi_ctx.accum_err;
};
static const struct jadard_panel_desc cz101b4001_desc = {
@@ -580,8 +616,238 @@ static const struct jadard_panel_desc cz101b4001_desc = {
},
.lanes = 4,
.format = MIPI_DSI_FMT_RGB888,
- .init_cmds = cz101b4001_init_cmds,
- .num_init_cmds = ARRAY_SIZE(cz101b4001_init_cmds),
+ .init = cz101b4001_init_cmds,
+};
+
+static int kingdisplay_kd101ne3_init_cmds(struct jadard *jadard)
+{
+ struct mipi_dsi_multi_context dsi_ctx = { .dsi = jadard->dsi };
+
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe0, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe1, 0x93);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe2, 0x65);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe3, 0xf8);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x80, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe0, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0c, 0x74);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x17, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x18, 0xc7);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x19, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1a, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1b, 0xc7);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1c, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x24, 0xfe);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x37, 0x19);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x35, 0x28);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x38, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x39, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3a, 0x12);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3c, 0x7e);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3d, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3e, 0xff);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3f, 0x7f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x40, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x41, 0xa0);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x43, 0x1e);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x44, 0x0b);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x55, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x57, 0x6a);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x59, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5a, 0x2e);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5b, 0x1a);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5c, 0x15);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5d, 0x7f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5e, 0x61);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5f, 0x50);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x60, 0x43);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x61, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x62, 0x32);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x63, 0x35);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x64, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x65, 0x38);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x66, 0x36);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x67, 0x36);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x68, 0x54);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x69, 0x42);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6a, 0x48);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6b, 0x39);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6c, 0x34);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6d, 0x26);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6e, 0x14);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x70, 0x7f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x71, 0x61);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x72, 0x50);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x73, 0x43);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x74, 0x3f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x75, 0x32);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x76, 0x35);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x77, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x78, 0x38);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x79, 0x36);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7a, 0x36);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7b, 0x54);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7c, 0x42);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7d, 0x48);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7e, 0x39);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7f, 0x34);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x80, 0x26);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x81, 0x14);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x82, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe0, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x52);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x01, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x02, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x03, 0x50);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x04, 0x77);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x05, 0x57);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x06, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x07, 0x4e);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x08, 0x4c);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x09, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0a, 0x4a);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0b, 0x48);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0c, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0d, 0x46);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0e, 0x44);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0f, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x10, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x11, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x12, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x13, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x14, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x15, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x16, 0x53);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x17, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x18, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x19, 0x51);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1a, 0x77);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1b, 0x57);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1c, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1d, 0x4f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1e, 0x4d);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1f, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x20, 0x4b);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x21, 0x49);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x22, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x23, 0x47);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x24, 0x45);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x25, 0x41);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x26, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x27, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x28, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x29, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2a, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2b, 0x5f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2c, 0x13);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2d, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2e, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2f, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x30, 0x17);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x31, 0x17);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x32, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x33, 0x0d);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x34, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x35, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x36, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x37, 0x07);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x38, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x39, 0x09);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3a, 0x0b);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3b, 0x11);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3c, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3d, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3e, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3f, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x40, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x41, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x42, 0x12);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x43, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x44, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x45, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x46, 0x17);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x47, 0x17);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x48, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x49, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4a, 0x0e);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4b, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4c, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4d, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4e, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4f, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x50, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x51, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x52, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x53, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x54, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x55, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x56, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x57, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x58, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5b, 0x10);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5c, 0x06);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5d, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5e, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5f, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x60, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x61, 0x03);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x62, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x63, 0x6c);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x64, 0x6c);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x65, 0x75);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x66, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x67, 0xb4);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x68, 0x08);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x69, 0x6c);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6a, 0x6c);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6b, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6d, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6e, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x88);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x75, 0xbb);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x76, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x77, 0x05);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x78, 0x2a);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe0, 0x04);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x0e);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x02, 0xb3);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x09, 0x61);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0e, 0x48);
+ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe0, 0x00);
+
+ return dsi_ctx.accum_err;
+};
+
+static const struct jadard_panel_desc kingdisplay_kd101ne3_40ti_desc = {
+ .mode = {
+ .clock = (800 + 24 + 24 + 24) * (1280 + 30 + 4 + 8) * 60 / 1000,
+
+ .hdisplay = 800,
+ .hsync_start = 800 + 24,
+ .hsync_end = 800 + 24 + 24,
+ .htotal = 800 + 24 + 24 + 24,
+
+ .vdisplay = 1280,
+ .vsync_start = 1280 + 30,
+ .vsync_end = 1280 + 30 + 4,
+ .vtotal = 1280 + 30 + 4 + 8,
+
+ .width_mm = 135,
+ .height_mm = 216,
+ .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+ },
+ .lanes = 4,
+ .format = MIPI_DSI_FMT_RGB888,
+ .init = kingdisplay_kd101ne3_init_cmds,
+ .lp11_before_reset = true,
+ .reset_before_power_off_vcioo = true,
+ .vcioo_to_lp11_delay_ms = 5,
+ .lp11_to_reset_delay_ms = 10,
+ .exit_sleep_to_display_on_delay_ms = 120,
+ .display_on_delay_ms = 20,
+ .backlight_off_to_display_off_delay_ms = 100,
+ .display_off_to_enter_sleep_delay_ms = 50,
+ .enter_sleep_to_reset_down_delay_ms = 100,
};
static int jadard_dsi_probe(struct mipi_dsi_device *dsi)
@@ -622,6 +888,10 @@ static int jadard_dsi_probe(struct mipi_dsi_device *dsi)
drm_panel_init(&jadard->panel, dev, &jadard_funcs,
DRM_MODE_CONNECTOR_DSI);
+ ret = of_drm_get_panel_orientation(dev->of_node, &jadard->orientation);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "failed to get orientation\n");
+
ret = drm_panel_of_backlight(&jadard->panel);
if (ret)
return ret;
@@ -653,6 +923,10 @@ static const struct of_device_id jadard_of_match[] = {
.data = &cz101b4001_desc
},
{
+ .compatible = "kingdisplay,kd101ne3-40ti",
+ .data = &kingdisplay_kd101ne3_40ti_desc
+ },
+ {
.compatible = "radxa,display-10hd-ad001",
.data = &cz101b4001_desc
},
diff --git a/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c b/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c
index f9a69f347068..b1ce186de261 100644
--- a/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c
+++ b/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c
@@ -37,9 +37,6 @@ struct jdi_panel {
struct gpio_desc *dcdc_en_gpio;
struct backlight_device *backlight;
- bool prepared;
- bool enabled;
-
const struct drm_display_mode *mode;
};
@@ -176,13 +173,8 @@ static int jdi_panel_disable(struct drm_panel *panel)
{
struct jdi_panel *jdi = to_jdi_panel(panel);
- if (!jdi->enabled)
- return 0;
-
backlight_disable(jdi->backlight);
- jdi->enabled = false;
-
return 0;
}
@@ -192,9 +184,6 @@ static int jdi_panel_unprepare(struct drm_panel *panel)
struct device *dev = &jdi->dsi->dev;
int ret;
- if (!jdi->prepared)
- return 0;
-
jdi_panel_off(jdi);
ret = regulator_bulk_disable(ARRAY_SIZE(jdi->supplies), jdi->supplies);
@@ -207,8 +196,6 @@ static int jdi_panel_unprepare(struct drm_panel *panel)
gpiod_set_value(jdi->dcdc_en_gpio, 0);
- jdi->prepared = false;
-
return 0;
}
@@ -218,9 +205,6 @@ static int jdi_panel_prepare(struct drm_panel *panel)
struct device *dev = &jdi->dsi->dev;
int ret;
- if (jdi->prepared)
- return 0;
-
ret = regulator_bulk_enable(ARRAY_SIZE(jdi->supplies), jdi->supplies);
if (ret < 0) {
dev_err(dev, "regulator enable failed, %d\n", ret);
@@ -250,8 +234,6 @@ static int jdi_panel_prepare(struct drm_panel *panel)
goto poweroff;
}
- jdi->prepared = true;
-
return 0;
poweroff:
@@ -272,13 +254,8 @@ static int jdi_panel_enable(struct drm_panel *panel)
{
struct jdi_panel *jdi = to_jdi_panel(panel);
- if (jdi->enabled)
- return 0;
-
backlight_enable(jdi->backlight);
- jdi->enabled = true;
-
return 0;
}
@@ -475,10 +452,6 @@ static void jdi_panel_remove(struct mipi_dsi_device *dsi)
struct jdi_panel *jdi = mipi_dsi_get_drvdata(dsi);
int ret;
- ret = jdi_panel_disable(&jdi->base);
- if (ret < 0)
- dev_err(&dsi->dev, "failed to disable panel: %d\n", ret);
-
ret = mipi_dsi_detach(dsi);
if (ret < 0)
dev_err(&dsi->dev, "failed to detach from DSI host: %d\n",
@@ -487,13 +460,6 @@ static void jdi_panel_remove(struct mipi_dsi_device *dsi)
jdi_panel_del(jdi);
}
-static void jdi_panel_shutdown(struct mipi_dsi_device *dsi)
-{
- struct jdi_panel *jdi = mipi_dsi_get_drvdata(dsi);
-
- jdi_panel_disable(&jdi->base);
-}
-
static struct mipi_dsi_driver jdi_panel_driver = {
.driver = {
.name = "panel-jdi-lt070me05000",
@@ -501,7 +467,6 @@ static struct mipi_dsi_driver jdi_panel_driver = {
},
.probe = jdi_panel_probe,
.remove = jdi_panel_remove,
- .shutdown = jdi_panel_shutdown,
};
module_mipi_dsi_driver(jdi_panel_driver);
diff --git a/drivers/gpu/drm/panel/panel-khadas-ts050.c b/drivers/gpu/drm/panel/panel-khadas-ts050.c
index c54be0cc3f08..14932cb3defc 100644
--- a/drivers/gpu/drm/panel/panel-khadas-ts050.c
+++ b/drivers/gpu/drm/panel/panel-khadas-ts050.c
@@ -26,9 +26,6 @@ struct khadas_ts050_panel {
struct gpio_desc *reset_gpio;
struct gpio_desc *enable_gpio;
struct khadas_ts050_panel_data *panel_data;
-
- bool prepared;
- bool enabled;
};
struct khadas_ts050_panel_cmd {
@@ -642,9 +639,6 @@ static int khadas_ts050_panel_prepare(struct drm_panel *panel)
unsigned int i;
int err;
- if (khadas_ts050->prepared)
- return 0;
-
gpiod_set_value_cansleep(khadas_ts050->enable_gpio, 0);
err = regulator_enable(khadas_ts050->supply);
@@ -708,8 +702,6 @@ static int khadas_ts050_panel_prepare(struct drm_panel *panel)
usleep_range(10000, 11000);
- khadas_ts050->prepared = true;
-
return 0;
poweroff:
@@ -726,11 +718,6 @@ static int khadas_ts050_panel_unprepare(struct drm_panel *panel)
struct khadas_ts050_panel *khadas_ts050 = to_khadas_ts050_panel(panel);
int err;
- if (!khadas_ts050->prepared)
- return 0;
-
- khadas_ts050->prepared = false;
-
err = mipi_dsi_dcs_enter_sleep_mode(khadas_ts050->link);
if (err < 0)
dev_err(panel->dev, "failed to enter sleep mode: %d\n", err);
@@ -747,31 +734,17 @@ static int khadas_ts050_panel_unprepare(struct drm_panel *panel)
return 0;
}
-static int khadas_ts050_panel_enable(struct drm_panel *panel)
-{
- struct khadas_ts050_panel *khadas_ts050 = to_khadas_ts050_panel(panel);
-
- khadas_ts050->enabled = true;
-
- return 0;
-}
-
static int khadas_ts050_panel_disable(struct drm_panel *panel)
{
struct khadas_ts050_panel *khadas_ts050 = to_khadas_ts050_panel(panel);
int err;
- if (!khadas_ts050->enabled)
- return 0;
-
err = mipi_dsi_dcs_set_display_off(khadas_ts050->link);
if (err < 0)
dev_err(panel->dev, "failed to set display off: %d\n", err);
usleep_range(10000, 11000);
- khadas_ts050->enabled = false;
-
return 0;
}
@@ -815,7 +788,6 @@ static int khadas_ts050_panel_get_modes(struct drm_panel *panel,
static const struct drm_panel_funcs khadas_ts050_panel_funcs = {
.prepare = khadas_ts050_panel_prepare,
.unprepare = khadas_ts050_panel_unprepare,
- .enable = khadas_ts050_panel_enable,
.disable = khadas_ts050_panel_disable,
.get_modes = khadas_ts050_panel_get_modes,
};
@@ -908,16 +880,6 @@ static void khadas_ts050_panel_remove(struct mipi_dsi_device *dsi)
dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err);
drm_panel_remove(&khadas_ts050->base);
- drm_panel_disable(&khadas_ts050->base);
- drm_panel_unprepare(&khadas_ts050->base);
-}
-
-static void khadas_ts050_panel_shutdown(struct mipi_dsi_device *dsi)
-{
- struct khadas_ts050_panel *khadas_ts050 = mipi_dsi_get_drvdata(dsi);
-
- drm_panel_disable(&khadas_ts050->base);
- drm_panel_unprepare(&khadas_ts050->base);
}
static struct mipi_dsi_driver khadas_ts050_panel_driver = {
@@ -927,7 +889,6 @@ static struct mipi_dsi_driver khadas_ts050_panel_driver = {
},
.probe = khadas_ts050_panel_probe,
.remove = khadas_ts050_panel_remove,
- .shutdown = khadas_ts050_panel_shutdown,
};
module_mipi_dsi_driver(khadas_ts050_panel_driver);
diff --git a/drivers/gpu/drm/panel/panel-kingdisplay-kd097d04.c b/drivers/gpu/drm/panel/panel-kingdisplay-kd097d04.c
index 17f8d80cf2b3..d6b912277196 100644
--- a/drivers/gpu/drm/panel/panel-kingdisplay-kd097d04.c
+++ b/drivers/gpu/drm/panel/panel-kingdisplay-kd097d04.c
@@ -23,9 +23,6 @@ struct kingdisplay_panel {
struct regulator *supply;
struct gpio_desc *enable_gpio;
-
- bool prepared;
- bool enabled;
};
struct kingdisplay_panel_cmd {
@@ -185,15 +182,10 @@ static int kingdisplay_panel_disable(struct drm_panel *panel)
struct kingdisplay_panel *kingdisplay = to_kingdisplay_panel(panel);
int err;
- if (!kingdisplay->enabled)
- return 0;
-
err = mipi_dsi_dcs_set_display_off(kingdisplay->link);
if (err < 0)
dev_err(panel->dev, "failed to set display off: %d\n", err);
- kingdisplay->enabled = false;
-
return 0;
}
@@ -202,9 +194,6 @@ static int kingdisplay_panel_unprepare(struct drm_panel *panel)
struct kingdisplay_panel *kingdisplay = to_kingdisplay_panel(panel);
int err;
- if (!kingdisplay->prepared)
- return 0;
-
err = mipi_dsi_dcs_enter_sleep_mode(kingdisplay->link);
if (err < 0) {
dev_err(panel->dev, "failed to enter sleep mode: %d\n", err);
@@ -220,8 +209,6 @@ static int kingdisplay_panel_unprepare(struct drm_panel *panel)
if (err < 0)
return err;
- kingdisplay->prepared = false;
-
return 0;
}
@@ -231,9 +218,6 @@ static int kingdisplay_panel_prepare(struct drm_panel *panel)
int err, regulator_err;
unsigned int i;
- if (kingdisplay->prepared)
- return 0;
-
gpiod_set_value_cansleep(kingdisplay->enable_gpio, 0);
err = regulator_enable(kingdisplay->supply);
@@ -275,8 +259,6 @@ static int kingdisplay_panel_prepare(struct drm_panel *panel)
/* T7: 10ms */
usleep_range(10000, 11000);
- kingdisplay->prepared = true;
-
return 0;
poweroff:
@@ -289,18 +271,6 @@ poweroff:
return err;
}
-static int kingdisplay_panel_enable(struct drm_panel *panel)
-{
- struct kingdisplay_panel *kingdisplay = to_kingdisplay_panel(panel);
-
- if (kingdisplay->enabled)
- return 0;
-
- kingdisplay->enabled = true;
-
- return 0;
-}
-
static const struct drm_display_mode default_mode = {
.clock = 229000,
.hdisplay = 1536,
@@ -341,7 +311,6 @@ static const struct drm_panel_funcs kingdisplay_panel_funcs = {
.disable = kingdisplay_panel_disable,
.unprepare = kingdisplay_panel_unprepare,
.prepare = kingdisplay_panel_prepare,
- .enable = kingdisplay_panel_enable,
.get_modes = kingdisplay_panel_get_modes,
};
@@ -420,14 +389,6 @@ static void kingdisplay_panel_remove(struct mipi_dsi_device *dsi)
struct kingdisplay_panel *kingdisplay = mipi_dsi_get_drvdata(dsi);
int err;
- err = drm_panel_unprepare(&kingdisplay->base);
- if (err < 0)
- dev_err(&dsi->dev, "failed to unprepare panel: %d\n", err);
-
- err = drm_panel_disable(&kingdisplay->base);
- if (err < 0)
- dev_err(&dsi->dev, "failed to disable panel: %d\n", err);
-
err = mipi_dsi_detach(dsi);
if (err < 0)
dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err);
@@ -435,14 +396,6 @@ static void kingdisplay_panel_remove(struct mipi_dsi_device *dsi)
kingdisplay_panel_del(kingdisplay);
}
-static void kingdisplay_panel_shutdown(struct mipi_dsi_device *dsi)
-{
- struct kingdisplay_panel *kingdisplay = mipi_dsi_get_drvdata(dsi);
-
- drm_panel_unprepare(&kingdisplay->base);
- drm_panel_disable(&kingdisplay->base);
-}
-
static struct mipi_dsi_driver kingdisplay_panel_driver = {
.driver = {
.name = "panel-kingdisplay-kd097d04",
@@ -450,7 +403,6 @@ static struct mipi_dsi_driver kingdisplay_panel_driver = {
},
.probe = kingdisplay_panel_probe,
.remove = kingdisplay_panel_remove,
- .shutdown = kingdisplay_panel_shutdown,
};
module_mipi_dsi_driver(kingdisplay_panel_driver);
diff --git a/drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c b/drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c
index 1a26205701b5..292aa26a456d 100644
--- a/drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c
+++ b/drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c
@@ -36,7 +36,6 @@ struct ltk050h3146w {
struct regulator *vci;
struct regulator *iovcc;
const struct ltk050h3146w_desc *panel_desc;
- bool prepared;
};
static const struct ltk050h3146w_cmd page1_cmds[] = {
@@ -521,9 +520,6 @@ static int ltk050h3146w_unprepare(struct drm_panel *panel)
struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
int ret;
- if (!ctx->prepared)
- return 0;
-
ret = mipi_dsi_dcs_set_display_off(dsi);
if (ret < 0) {
dev_err(ctx->dev, "failed to set display off: %d\n", ret);
@@ -539,8 +535,6 @@ static int ltk050h3146w_unprepare(struct drm_panel *panel)
regulator_disable(ctx->iovcc);
regulator_disable(ctx->vci);
- ctx->prepared = false;
-
return 0;
}
@@ -550,9 +544,6 @@ static int ltk050h3146w_prepare(struct drm_panel *panel)
struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
int ret;
- if (ctx->prepared)
- return 0;
-
dev_dbg(ctx->dev, "Resetting the panel\n");
ret = regulator_enable(ctx->vci);
if (ret < 0) {
@@ -593,8 +584,6 @@ static int ltk050h3146w_prepare(struct drm_panel *panel)
msleep(50);
- ctx->prepared = true;
-
return 0;
disable_iovcc:
@@ -684,27 +673,11 @@ static int ltk050h3146w_probe(struct mipi_dsi_device *dsi)
return 0;
}
-static void ltk050h3146w_shutdown(struct mipi_dsi_device *dsi)
-{
- struct ltk050h3146w *ctx = mipi_dsi_get_drvdata(dsi);
- int ret;
-
- ret = drm_panel_unprepare(&ctx->panel);
- if (ret < 0)
- dev_err(&dsi->dev, "Failed to unprepare panel: %d\n", ret);
-
- ret = drm_panel_disable(&ctx->panel);
- if (ret < 0)
- dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret);
-}
-
static void ltk050h3146w_remove(struct mipi_dsi_device *dsi)
{
struct ltk050h3146w *ctx = mipi_dsi_get_drvdata(dsi);
int ret;
- ltk050h3146w_shutdown(dsi);
-
ret = mipi_dsi_detach(dsi);
if (ret < 0)
dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
@@ -736,7 +709,6 @@ static struct mipi_dsi_driver ltk050h3146w_driver = {
},
.probe = ltk050h3146w_probe,
.remove = ltk050h3146w_remove,
- .shutdown = ltk050h3146w_shutdown,
};
module_mipi_dsi_driver(ltk050h3146w_driver);
diff --git a/drivers/gpu/drm/panel/panel-leadtek-ltk500hd1829.c b/drivers/gpu/drm/panel/panel-leadtek-ltk500hd1829.c
index a4c9a5cb9811..6b18cf00fd4a 100644
--- a/drivers/gpu/drm/panel/panel-leadtek-ltk500hd1829.c
+++ b/drivers/gpu/drm/panel/panel-leadtek-ltk500hd1829.c
@@ -40,7 +40,6 @@ struct ltk500hd1829 {
struct regulator *vcc;
struct regulator *iovcc;
const struct ltk500hd1829_desc *panel_desc;
- bool prepared;
};
static const struct ltk500hd1829_cmd ltk101b4029w_init[] = {
@@ -492,9 +491,6 @@ static int ltk500hd1829_unprepare(struct drm_panel *panel)
struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
int ret;
- if (!ctx->prepared)
- return 0;
-
ret = mipi_dsi_dcs_set_display_off(dsi);
if (ret < 0)
dev_err(panel->dev, "failed to set display off: %d\n", ret);
@@ -510,8 +506,6 @@ static int ltk500hd1829_unprepare(struct drm_panel *panel)
regulator_disable(ctx->iovcc);
regulator_disable(ctx->vcc);
- ctx->prepared = false;
-
return 0;
}
@@ -522,9 +516,6 @@ static int ltk500hd1829_prepare(struct drm_panel *panel)
unsigned int i;
int ret;
- if (ctx->prepared)
- return 0;
-
ret = regulator_enable(ctx->vcc);
if (ret < 0) {
dev_err(ctx->dev, "Failed to enable vci supply: %d\n", ret);
@@ -568,8 +559,6 @@ static int ltk500hd1829_prepare(struct drm_panel *panel)
goto disable_iovcc;
}
- ctx->prepared = true;
-
return 0;
disable_iovcc:
@@ -673,27 +662,11 @@ static int ltk500hd1829_probe(struct mipi_dsi_device *dsi)
return 0;
}
-static void ltk500hd1829_shutdown(struct mipi_dsi_device *dsi)
-{
- struct ltk500hd1829 *ctx = mipi_dsi_get_drvdata(dsi);
- int ret;
-
- ret = drm_panel_unprepare(&ctx->panel);
- if (ret < 0)
- dev_err(&dsi->dev, "Failed to unprepare panel: %d\n", ret);
-
- ret = drm_panel_disable(&ctx->panel);
- if (ret < 0)
- dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret);
-}
-
static void ltk500hd1829_remove(struct mipi_dsi_device *dsi)
{
struct ltk500hd1829 *ctx = mipi_dsi_get_drvdata(dsi);
int ret;
- ltk500hd1829_shutdown(dsi);
-
ret = mipi_dsi_detach(dsi);
if (ret < 0)
dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret);
@@ -721,7 +694,6 @@ static struct mipi_dsi_driver ltk500hd1829_driver = {
},
.probe = ltk500hd1829_probe,
.remove = ltk500hd1829_remove,
- .shutdown = ltk500hd1829_shutdown,
};
module_mipi_dsi_driver(ltk500hd1829_driver);
diff --git a/drivers/gpu/drm/panel/panel-lg-sw43408.c b/drivers/gpu/drm/panel/panel-lg-sw43408.c
index 2b3a73696dce..f3dcc39670ea 100644
--- a/drivers/gpu/drm/panel/panel-lg-sw43408.c
+++ b/drivers/gpu/drm/panel/panel-lg-sw43408.c
@@ -40,83 +40,83 @@ static inline struct sw43408_panel *to_panel_info(struct drm_panel *panel)
static int sw43408_unprepare(struct drm_panel *panel)
{
- struct sw43408_panel *ctx = to_panel_info(panel);
+ struct sw43408_panel *sw43408 = to_panel_info(panel);
+ struct mipi_dsi_multi_context ctx = { .dsi = sw43408->link };
int ret;
- ret = mipi_dsi_dcs_set_display_off(ctx->link);
- if (ret < 0)
- dev_err(panel->dev, "set_display_off cmd failed ret = %d\n", ret);
+ mipi_dsi_dcs_set_display_off_multi(&ctx);
- ret = mipi_dsi_dcs_enter_sleep_mode(ctx->link);
- if (ret < 0)
- dev_err(panel->dev, "enter_sleep cmd failed ret = %d\n", ret);
+ mipi_dsi_dcs_enter_sleep_mode_multi(&ctx);
- msleep(100);
+ mipi_dsi_msleep(&ctx, 100);
- gpiod_set_value(ctx->reset_gpio, 1);
+ gpiod_set_value(sw43408->reset_gpio, 1);
+
+ ret = regulator_bulk_disable(ARRAY_SIZE(sw43408->supplies), sw43408->supplies);
- return regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+ return ret ? : ctx.accum_err;
}
static int sw43408_program(struct drm_panel *panel)
{
- struct sw43408_panel *ctx = to_panel_info(panel);
+ struct sw43408_panel *sw43408 = to_panel_info(panel);
+ struct mipi_dsi_multi_context ctx = { .dsi = sw43408->link };
struct drm_dsc_picture_parameter_set pps;
- mipi_dsi_dcs_write_seq(ctx->link, MIPI_DCS_SET_GAMMA_CURVE, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, MIPI_DCS_SET_GAMMA_CURVE, 0x02);
- mipi_dsi_dcs_set_tear_on(ctx->link, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
+ mipi_dsi_dcs_set_tear_on_multi(&ctx, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
- mipi_dsi_dcs_write_seq(ctx->link, 0x53, 0x0c, 0x30);
- mipi_dsi_dcs_write_seq(ctx->link, 0x55, 0x00, 0x70, 0xdf, 0x00, 0x70, 0xdf);
- mipi_dsi_dcs_write_seq(ctx->link, 0xf7, 0x01, 0x49, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x53, 0x0c, 0x30);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x55, 0x00, 0x70, 0xdf, 0x00, 0x70, 0xdf);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xf7, 0x01, 0x49, 0x0c);
- mipi_dsi_dcs_exit_sleep_mode(ctx->link);
+ mipi_dsi_dcs_exit_sleep_mode_multi(&ctx);
- msleep(135);
+ mipi_dsi_msleep(&ctx, 135);
/* COMPRESSION_MODE moved after setting the PPS */
- mipi_dsi_dcs_write_seq(ctx->link, 0xb0, 0xac);
- mipi_dsi_dcs_write_seq(ctx->link, 0xe5,
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0xac);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe5,
0x00, 0x3a, 0x00, 0x3a, 0x00, 0x0e, 0x10);
- mipi_dsi_dcs_write_seq(ctx->link, 0xb5,
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb5,
0x75, 0x60, 0x2d, 0x5d, 0x80, 0x00, 0x0a, 0x0b,
0x00, 0x05, 0x0b, 0x00, 0x80, 0x0d, 0x0e, 0x40,
0x00, 0x0c, 0x00, 0x16, 0x00, 0xb8, 0x00, 0x80,
0x0d, 0x0e, 0x40, 0x00, 0x0c, 0x00, 0x16, 0x00,
0xb8, 0x00, 0x81, 0x00, 0x03, 0x03, 0x03, 0x01,
0x01);
- msleep(85);
- mipi_dsi_dcs_write_seq(ctx->link, 0xcd,
+ mipi_dsi_msleep(&ctx, 85);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcd,
0x00, 0x00, 0x00, 0x19, 0x19, 0x19, 0x19, 0x19,
0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
0x16, 0x16);
- mipi_dsi_dcs_write_seq(ctx->link, 0xcb, 0x80, 0x5c, 0x07, 0x03, 0x28);
- mipi_dsi_dcs_write_seq(ctx->link, 0xc0, 0x02, 0x02, 0x0f);
- mipi_dsi_dcs_write_seq(ctx->link, 0x55, 0x04, 0x61, 0xdb, 0x04, 0x70, 0xdb);
- mipi_dsi_dcs_write_seq(ctx->link, 0xb0, 0xca);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x80, 0x5c, 0x07, 0x03, 0x28);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x02, 0x02, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0x55, 0x04, 0x61, 0xdb, 0x04, 0x70, 0xdb);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0xca);
+
+ mipi_dsi_dcs_set_display_on_multi(&ctx);
- mipi_dsi_dcs_set_display_on(ctx->link);
+ mipi_dsi_msleep(&ctx, 50);
- msleep(50);
+ sw43408->link->mode_flags &= ~MIPI_DSI_MODE_LPM;
- ctx->link->mode_flags &= ~MIPI_DSI_MODE_LPM;
+ drm_dsc_pps_payload_pack(&pps, sw43408->link->dsc);
- drm_dsc_pps_payload_pack(&pps, ctx->link->dsc);
- mipi_dsi_picture_parameter_set(ctx->link, &pps);
+ mipi_dsi_picture_parameter_set_multi(&ctx, &pps);
- ctx->link->mode_flags |= MIPI_DSI_MODE_LPM;
+ sw43408->link->mode_flags |= MIPI_DSI_MODE_LPM;
/*
* This panel uses PPS selectors with offset:
* PPS 1 if pps_identifier is 0
* PPS 2 if pps_identifier is 1
*/
- mipi_dsi_compression_mode_ext(ctx->link, true,
- MIPI_DSI_COMPRESSION_DSC, 1);
-
- return 0;
+ mipi_dsi_compression_mode_ext_multi(&ctx, true,
+ MIPI_DSI_COMPRESSION_DSC, 1);
+ return ctx.accum_err;
}
static int sw43408_prepare(struct drm_panel *panel)
diff --git a/drivers/gpu/drm/panel/panel-lincolntech-lcd197.c b/drivers/gpu/drm/panel/panel-lincolntech-lcd197.c
new file mode 100644
index 000000000000..032c542aab0f
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-lincolntech-lcd197.c
@@ -0,0 +1,262 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2024 BayLibre, SAS
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
+ */
+
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+
+#include <video/mipi_display.h>
+
+#include <drm/drm_device.h>
+#include <drm/drm_probe_helper.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+struct lincoln_lcd197_panel {
+ struct drm_panel panel;
+ struct mipi_dsi_device *dsi;
+ struct regulator *supply;
+ struct gpio_desc *enable_gpio;
+ struct gpio_desc *reset_gpio;
+};
+
+static inline
+struct lincoln_lcd197_panel *to_lincoln_lcd197_panel(struct drm_panel *panel)
+{
+ return container_of(panel, struct lincoln_lcd197_panel, panel);
+}
+
+static int lincoln_lcd197_panel_prepare(struct drm_panel *panel)
+{
+ struct lincoln_lcd197_panel *lcd = to_lincoln_lcd197_panel(panel);
+ struct mipi_dsi_multi_context ctx = { .dsi = lcd->dsi };
+ int err;
+
+ gpiod_set_value_cansleep(lcd->enable_gpio, 0);
+ err = regulator_enable(lcd->supply);
+ if (err < 0)
+ return err;
+
+ gpiod_set_value_cansleep(lcd->enable_gpio, 1);
+ usleep_range(1000, 2000);
+ gpiod_set_value_cansleep(lcd->reset_gpio, 1);
+ usleep_range(5000, 6000);
+ gpiod_set_value_cansleep(lcd->reset_gpio, 0);
+ msleep(50);
+
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0xff, 0x83, 0x99);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd2, 0x55);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0x02, 0x04, 0x70, 0x90, 0x01,
+ 0x32, 0x33, 0x11, 0x11, 0x4d, 0x57, 0x56, 0x73,
+ 0x02, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb2, 0x00, 0x80, 0x80, 0xae, 0x0a,
+ 0x0e, 0x75, 0x11, 0x00, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb4, 0x00, 0xff, 0x04, 0xa4, 0x02,
+ 0xa0, 0x00, 0x00, 0x10, 0x00, 0x00, 0x02, 0x00,
+ 0x24, 0x02, 0x04, 0x0a, 0x21, 0x03, 0x00, 0x00,
+ 0x08, 0xa6, 0x88, 0x04, 0xa4, 0x02, 0xa0, 0x00,
+ 0x00, 0x10, 0x00, 0x00, 0x02, 0x00, 0x24, 0x02,
+ 0x04, 0x0a, 0x00, 0x00, 0x08, 0xa6, 0x00, 0x08,
+ 0x11);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd3, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x18, 0x18, 0x32, 0x10, 0x09, 0x00, 0x09,
+ 0x32, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x11, 0x00, 0x02, 0x02, 0x03, 0x00,
+ 0x00, 0x00, 0x0a, 0x40);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd5, 0x18, 0x18, 0x18, 0x18, 0x21,
+ 0x20, 0x18, 0x18, 0x19, 0x19, 0x19, 0x19, 0x18,
+ 0x18, 0x18, 0x18, 0x03, 0x02, 0x01, 0x00, 0x2f,
+ 0x2f, 0x30, 0x30, 0x31, 0x31, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd6, 0x18, 0x18, 0x18, 0x18, 0x20,
+ 0x21, 0x19, 0x19, 0x18, 0x18, 0x19, 0x19, 0x18,
+ 0x18, 0x18, 0x18, 0x00, 0x01, 0x02, 0x03, 0x2f,
+ 0x2f, 0x30, 0x30, 0x31, 0x31, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbd, 0x01);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd8, 0x0a, 0xbe, 0xfa, 0xa0, 0x0a,
+ 0xbe, 0xfa, 0xa0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd8, 0x0f, 0xff, 0xff, 0xe0, 0x0f,
+ 0xff, 0xff, 0xe0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbd, 0x02);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xd8, 0x0f, 0xff, 0xff, 0xe0, 0x0f,
+ 0xff, 0xff, 0xe0);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xe0, 0x01, 0x11, 0x1c, 0x17, 0x39,
+ 0x43, 0x54, 0x51, 0x5a, 0x64, 0x6c, 0x74, 0x7a,
+ 0x83, 0x8d, 0x92, 0x99, 0xa4, 0xa9, 0xb4, 0xaa,
+ 0xba, 0xbe, 0x63, 0x5e, 0x69, 0x73, 0x01, 0x11,
+ 0x1c, 0x17, 0x39, 0x43, 0x54, 0x51, 0x5a, 0x64,
+ 0x6c, 0x74, 0x7a, 0x83, 0x8d, 0x92, 0x99, 0xa4,
+ 0xa7, 0xb2, 0xa9, 0xba, 0xbe, 0x63, 0x5e, 0x69,
+ 0x73);
+ mipi_dsi_usleep_range(&ctx, 200, 300);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x92, 0x92);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xcc, 0x00);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xbf, 0x40, 0x41, 0x50, 0x49);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc6, 0xff, 0xf9);
+ mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x25, 0x5a);
+ mipi_dsi_dcs_write_seq_multi(&ctx, MIPI_DCS_SET_ADDRESS_MODE, 0x02);
+ mipi_dsi_dcs_exit_sleep_mode_multi(&ctx);
+ mipi_dsi_msleep(&ctx, 120);
+
+ if (ctx.accum_err) {
+ gpiod_set_value_cansleep(lcd->enable_gpio, 0);
+ gpiod_set_value_cansleep(lcd->reset_gpio, 1);
+ regulator_disable(lcd->supply);
+ }
+
+ return ctx.accum_err;
+}
+
+static int lincoln_lcd197_panel_unprepare(struct drm_panel *panel)
+{
+ struct lincoln_lcd197_panel *lcd = to_lincoln_lcd197_panel(panel);
+ struct mipi_dsi_multi_context ctx = { .dsi = lcd->dsi };
+
+ mipi_dsi_dcs_enter_sleep_mode_multi(&ctx);
+ mipi_dsi_usleep_range(&ctx, 5000, 6000);
+ gpiod_set_value_cansleep(lcd->enable_gpio, 0);
+ gpiod_set_value_cansleep(lcd->reset_gpio, 1);
+ regulator_disable(lcd->supply);
+
+ return ctx.accum_err;
+}
+
+static int lincoln_lcd197_panel_enable(struct drm_panel *panel)
+{
+ struct lincoln_lcd197_panel *lcd = to_lincoln_lcd197_panel(panel);
+ struct mipi_dsi_multi_context ctx = { .dsi = lcd->dsi };
+
+ mipi_dsi_dcs_set_display_on_multi(&ctx);
+ mipi_dsi_msleep(&ctx, 20);
+
+ return ctx.accum_err;
+}
+
+static int lincoln_lcd197_panel_disable(struct drm_panel *panel)
+{
+ struct lincoln_lcd197_panel *lcd = to_lincoln_lcd197_panel(panel);
+ struct mipi_dsi_multi_context ctx = { .dsi = lcd->dsi };
+
+ mipi_dsi_dcs_set_display_off_multi(&ctx);
+ mipi_dsi_msleep(&ctx, 50);
+
+ return ctx.accum_err;
+}
+
+static const struct drm_display_mode lcd197_mode = {
+ .clock = 154002,
+ .hdisplay = 1080,
+ .hsync_start = 1080 + 20,
+ .hsync_end = 1080 + 20 + 6,
+ .htotal = 1080 + 204,
+ .vdisplay = 1920,
+ .vsync_start = 1920 + 4,
+ .vsync_end = 1920 + 4 + 4,
+ .vtotal = 1920 + 79,
+ .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
+ .width_mm = 79,
+ .height_mm = 125,
+ .type = DRM_MODE_TYPE_DRIVER,
+};
+
+static int lincoln_lcd197_panel_get_modes(struct drm_panel *panel,
+ struct drm_connector *connector)
+{
+ return drm_connector_helper_get_modes_fixed(connector, &lcd197_mode);
+}
+
+static const struct drm_panel_funcs lincoln_lcd197_panel_funcs = {
+ .prepare = lincoln_lcd197_panel_prepare,
+ .unprepare = lincoln_lcd197_panel_unprepare,
+ .enable = lincoln_lcd197_panel_enable,
+ .disable = lincoln_lcd197_panel_disable,
+ .get_modes = lincoln_lcd197_panel_get_modes,
+};
+
+static int lincoln_lcd197_panel_probe(struct mipi_dsi_device *dsi)
+{
+ struct lincoln_lcd197_panel *lcd;
+ struct device *dev = &dsi->dev;
+ int err;
+
+ dsi->lanes = 4;
+ dsi->format = MIPI_DSI_FMT_RGB888;
+ dsi->mode_flags = (MIPI_DSI_MODE_VIDEO |
+ MIPI_DSI_MODE_VIDEO_BURST);
+
+ lcd = devm_kzalloc(&dsi->dev, sizeof(*lcd), GFP_KERNEL);
+ if (!lcd)
+ return -ENOMEM;
+
+ mipi_dsi_set_drvdata(dsi, lcd);
+ lcd->dsi = dsi;
+
+ lcd->supply = devm_regulator_get(dev, "power");
+ if (IS_ERR(lcd->supply))
+ return dev_err_probe(dev, PTR_ERR(lcd->supply),
+ "failed to get power supply");
+
+ lcd->enable_gpio = devm_gpiod_get(dev, "enable",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(lcd->enable_gpio))
+ return dev_err_probe(dev, PTR_ERR(lcd->enable_gpio),
+ "failed to get enable gpio");
+
+ lcd->reset_gpio = devm_gpiod_get(dev, "reset",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(lcd->reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(lcd->reset_gpio),
+ "failed to get reset gpio");
+
+ drm_panel_init(&lcd->panel, dev,
+ &lincoln_lcd197_panel_funcs, DRM_MODE_CONNECTOR_DSI);
+
+ err = drm_panel_of_backlight(&lcd->panel);
+ if (err)
+ return err;
+
+ drm_panel_add(&lcd->panel);
+ err = mipi_dsi_attach(dsi);
+ if (err)
+ drm_panel_remove(&lcd->panel);
+
+ return err;
+}
+
+static void lincoln_lcd197_panel_remove(struct mipi_dsi_device *dsi)
+{
+ struct lincoln_lcd197_panel *lcd = mipi_dsi_get_drvdata(dsi);
+ int err;
+
+ err = mipi_dsi_detach(dsi);
+ if (err < 0)
+ dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err);
+
+ drm_panel_remove(&lcd->panel);
+}
+
+static const struct of_device_id lincoln_lcd197_of_match[] = {
+ { .compatible = "lincolntech,lcd197", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, lincoln_lcd197_of_match);
+
+static struct mipi_dsi_driver lincoln_lcd197_panel_driver = {
+ .driver = {
+ .name = "panel-lincolntech-lcd197",
+ .of_match_table = lincoln_lcd197_of_match,
+ },
+ .probe = lincoln_lcd197_panel_probe,
+ .remove = lincoln_lcd197_panel_remove,
+};
+module_mipi_dsi_driver(lincoln_lcd197_panel_driver);
+
+MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
+MODULE_DESCRIPTION("Lincoln Technologies LCD197 panel driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/panel/panel-newvision-nv3052c.c b/drivers/gpu/drm/panel/panel-newvision-nv3052c.c
index 1aab0c9ae52f..c5d3ead38555 100644
--- a/drivers/gpu/drm/panel/panel-newvision-nv3052c.c
+++ b/drivers/gpu/drm/panel/panel-newvision-nv3052c.c
@@ -433,6 +433,202 @@ static const struct nv3052c_reg fs035vg158_panel_regs[] = {
{ 0x36, 0x0a }, // bgr = 1, ss = 1, gs = 0
};
+
+static const struct nv3052c_reg wl_355608_a8_panel_regs[] = {
+ // EXTC Command set enable, select page 1
+ { 0xff, 0x30 }, { 0xff, 0x52 }, { 0xff, 0x01 },
+ // Mostly unknown registers
+ { 0xe3, 0x00 },
+ { 0x40, 0x00 },
+ { 0x03, 0x40 },
+ { 0x04, 0x00 },
+ { 0x05, 0x03 },
+ { 0x08, 0x00 },
+ { 0x09, 0x07 },
+ { 0x0a, 0x01 },
+ { 0x0b, 0x32 },
+ { 0x0c, 0x32 },
+ { 0x0d, 0x0b },
+ { 0x0e, 0x00 },
+ { 0x23, 0xa0 },
+ { 0x24, 0x0c },
+ { 0x25, 0x06 },
+ { 0x26, 0x14 },
+ { 0x27, 0x14 },
+ { 0x38, 0xcc }, // VCOM_ADJ1
+ { 0x39, 0xd7 }, // VCOM_ADJ2
+ { 0x3a, 0x44 }, // VCOM_ADJ3
+ { 0x28, 0x40 },
+ { 0x29, 0x01 },
+ { 0x2a, 0xdf },
+ { 0x49, 0x3c },
+ { 0x91, 0x77 }, // EXTPW_CTRL2
+ { 0x92, 0x77 }, // EXTPW_CTRL3
+ { 0xa0, 0x55 },
+ { 0xa1, 0x50 },
+ { 0xa4, 0x9c },
+ { 0xa7, 0x02 },
+ { 0xa8, 0x01 },
+ { 0xa9, 0x01 },
+ { 0xaa, 0xfc },
+ { 0xab, 0x28 },
+ { 0xac, 0x06 },
+ { 0xad, 0x06 },
+ { 0xae, 0x06 },
+ { 0xaf, 0x03 },
+ { 0xb0, 0x08 },
+ { 0xb1, 0x26 },
+ { 0xb2, 0x28 },
+ { 0xb3, 0x28 },
+ { 0xb4, 0x33 },
+ { 0xb5, 0x08 },
+ { 0xb6, 0x26 },
+ { 0xb7, 0x08 },
+ { 0xb8, 0x26 },
+ { 0xf0, 0x00 },
+ { 0xf6, 0xc0 },
+ // EXTC Command set enable, select page 2
+ { 0xff, 0x30 }, { 0xff, 0x52 }, { 0xff, 0x02 },
+ // Set gray scale voltage to adjust gamma
+ { 0xb0, 0x0b }, // PGAMVR0
+ { 0xb1, 0x16 }, // PGAMVR1
+ { 0xb2, 0x17 }, // PGAMVR2
+ { 0xb3, 0x2c }, // PGAMVR3
+ { 0xb4, 0x32 }, // PGAMVR4
+ { 0xb5, 0x3b }, // PGAMVR5
+ { 0xb6, 0x29 }, // PGAMPR0
+ { 0xb7, 0x40 }, // PGAMPR1
+ { 0xb8, 0x0d }, // PGAMPK0
+ { 0xb9, 0x05 }, // PGAMPK1
+ { 0xba, 0x12 }, // PGAMPK2
+ { 0xbb, 0x10 }, // PGAMPK3
+ { 0xbc, 0x12 }, // PGAMPK4
+ { 0xbd, 0x15 }, // PGAMPK5
+ { 0xbe, 0x19 }, // PGAMPK6
+ { 0xbf, 0x0e }, // PGAMPK7
+ { 0xc0, 0x16 }, // PGAMPK8
+ { 0xc1, 0x0a }, // PGAMPK9
+ // Set gray scale voltage to adjust gamma
+ { 0xd0, 0x0c }, // NGAMVR0
+ { 0xd1, 0x17 }, // NGAMVR0
+ { 0xd2, 0x14 }, // NGAMVR1
+ { 0xd3, 0x2e }, // NGAMVR2
+ { 0xd4, 0x32 }, // NGAMVR3
+ { 0xd5, 0x3c }, // NGAMVR4
+ { 0xd6, 0x22 }, // NGAMPR0
+ { 0xd7, 0x3d }, // NGAMPR1
+ { 0xd8, 0x0d }, // NGAMPK0
+ { 0xd9, 0x07 }, // NGAMPK1
+ { 0xda, 0x13 }, // NGAMPK2
+ { 0xdb, 0x13 }, // NGAMPK3
+ { 0xdc, 0x11 }, // NGAMPK4
+ { 0xdd, 0x15 }, // NGAMPK5
+ { 0xde, 0x19 }, // NGAMPK6
+ { 0xdf, 0x10 }, // NGAMPK7
+ { 0xe0, 0x17 }, // NGAMPK8
+ { 0xe1, 0x0a }, // NGAMPK9
+ // EXTC Command set enable, select page 3
+ { 0xff, 0x30 }, { 0xff, 0x52 }, { 0xff, 0x03 },
+ // Set various timing settings
+ { 0x00, 0x2a }, // GIP_VST_1
+ { 0x01, 0x2a }, // GIP_VST_2
+ { 0x02, 0x2a }, // GIP_VST_3
+ { 0x03, 0x2a }, // GIP_VST_4
+ { 0x04, 0x61 }, // GIP_VST_5
+ { 0x05, 0x80 }, // GIP_VST_6
+ { 0x06, 0xc7 }, // GIP_VST_7
+ { 0x07, 0x01 }, // GIP_VST_8
+ { 0x08, 0x03 }, // GIP_VST_9
+ { 0x09, 0x04 }, // GIP_VST_10
+ { 0x70, 0x22 }, // GIP_ECLK1
+ { 0x71, 0x80 }, // GIP_ECLK2
+ { 0x30, 0x2a }, // GIP_CLK_1
+ { 0x31, 0x2a }, // GIP_CLK_2
+ { 0x32, 0x2a }, // GIP_CLK_3
+ { 0x33, 0x2a }, // GIP_CLK_4
+ { 0x34, 0x61 }, // GIP_CLK_5
+ { 0x35, 0xc5 }, // GIP_CLK_6
+ { 0x36, 0x80 }, // GIP_CLK_7
+ { 0x37, 0x23 }, // GIP_CLK_8
+ { 0x40, 0x03 }, // GIP_CLKA_1
+ { 0x41, 0x04 }, // GIP_CLKA_2
+ { 0x42, 0x05 }, // GIP_CLKA_3
+ { 0x43, 0x06 }, // GIP_CLKA_4
+ { 0x44, 0x11 }, // GIP_CLKA_5
+ { 0x45, 0xe8 }, // GIP_CLKA_6
+ { 0x46, 0xe9 }, // GIP_CLKA_7
+ { 0x47, 0x11 }, // GIP_CLKA_8
+ { 0x48, 0xea }, // GIP_CLKA_9
+ { 0x49, 0xeb }, // GIP_CLKA_10
+ { 0x50, 0x07 }, // GIP_CLKB_1
+ { 0x51, 0x08 }, // GIP_CLKB_2
+ { 0x52, 0x09 }, // GIP_CLKB_3
+ { 0x53, 0x0a }, // GIP_CLKB_4
+ { 0x54, 0x11 }, // GIP_CLKB_5
+ { 0x55, 0xec }, // GIP_CLKB_6
+ { 0x56, 0xed }, // GIP_CLKB_7
+ { 0x57, 0x11 }, // GIP_CLKB_8
+ { 0x58, 0xef }, // GIP_CLKB_9
+ { 0x59, 0xf0 }, // GIP_CLKB_10
+ // Map internal GOA signals to GOA output pad
+ { 0xb1, 0x01 }, // PANELD2U2
+ { 0xb4, 0x15 }, // PANELD2U5
+ { 0xb5, 0x16 }, // PANELD2U6
+ { 0xb6, 0x09 }, // PANELD2U7
+ { 0xb7, 0x0f }, // PANELD2U8
+ { 0xb8, 0x0d }, // PANELD2U9
+ { 0xb9, 0x0b }, // PANELD2U10
+ { 0xba, 0x00 }, // PANELD2U11
+ { 0xc7, 0x02 }, // PANELD2U24
+ { 0xca, 0x17 }, // PANELD2U27
+ { 0xcb, 0x18 }, // PANELD2U28
+ { 0xcc, 0x0a }, // PANELD2U29
+ { 0xcd, 0x10 }, // PANELD2U30
+ { 0xce, 0x0e }, // PANELD2U31
+ { 0xcf, 0x0c }, // PANELD2U32
+ { 0xd0, 0x00 }, // PANELD2U33
+ // Map internal GOA signals to GOA output pad
+ { 0x81, 0x00 }, // PANELU2D2
+ { 0x84, 0x15 }, // PANELU2D5
+ { 0x85, 0x16 }, // PANELU2D6
+ { 0x86, 0x10 }, // PANELU2D7
+ { 0x87, 0x0a }, // PANELU2D8
+ { 0x88, 0x0c }, // PANELU2D9
+ { 0x89, 0x0e }, // PANELU2D10
+ { 0x8a, 0x02 }, // PANELU2D11
+ { 0x97, 0x00 }, // PANELU2D24
+ { 0x9a, 0x17 }, // PANELU2D27
+ { 0x9b, 0x18 }, // PANELU2D28
+ { 0x9c, 0x0f }, // PANELU2D29
+ { 0x9d, 0x09 }, // PANELU2D30
+ { 0x9e, 0x0b }, // PANELU2D31
+ { 0x9f, 0x0d }, // PANELU2D32
+ { 0xa0, 0x01 }, // PANELU2D33
+ // EXTC Command set enable, select page 2
+ { 0xff, 0x30 }, { 0xff, 0x52 }, { 0xff, 0x02 },
+ // Unknown registers
+ { 0x01, 0x01 },
+ { 0x02, 0xda },
+ { 0x03, 0xba },
+ { 0x04, 0xa8 },
+ { 0x05, 0x9a },
+ { 0x06, 0x70 },
+ { 0x07, 0xff },
+ { 0x08, 0x91 },
+ { 0x09, 0x90 },
+ { 0x0a, 0xff },
+ { 0x0b, 0x8f },
+ { 0x0c, 0x60 },
+ { 0x0d, 0x58 },
+ { 0x0e, 0x48 },
+ { 0x0f, 0x38 },
+ { 0x10, 0x2b },
+ // EXTC Command set enable, select page 0
+ { 0xff, 0x30 }, { 0xff, 0x52 }, { 0xff, 0x00 },
+ // Display Access Control
+ { 0x36, 0x0a }, // bgr = 1, ss = 1, gs = 0
+};
+
static inline struct nv3052c *to_nv3052c(struct drm_panel *panel)
{
return container_of(panel, struct nv3052c, panel);
@@ -670,6 +866,21 @@ static const struct drm_display_mode fs035vg158_modes[] = {
},
};
+static const struct drm_display_mode wl_355608_a8_mode[] = {
+ {
+ .clock = 24000,
+ .hdisplay = 640,
+ .hsync_start = 640 + 64,
+ .hsync_end = 640 + 64 + 20,
+ .htotal = 640 + 64 + 20 + 46,
+ .vdisplay = 480,
+ .vsync_start = 480 + 21,
+ .vsync_end = 480 + 21 + 4,
+ .vtotal = 480 + 21 + 4 + 15,
+ .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
+ },
+};
+
static const struct nv3052c_panel_info ltk035c5444t_panel_info = {
.display_modes = ltk035c5444t_modes,
.num_modes = ARRAY_SIZE(ltk035c5444t_modes),
@@ -692,9 +903,21 @@ static const struct nv3052c_panel_info fs035vg158_panel_info = {
.panel_regs_len = ARRAY_SIZE(fs035vg158_panel_regs),
};
+static const struct nv3052c_panel_info wl_355608_a8_panel_info = {
+ .display_modes = wl_355608_a8_mode,
+ .num_modes = ARRAY_SIZE(wl_355608_a8_mode),
+ .width_mm = 150,
+ .height_mm = 94,
+ .bus_format = MEDIA_BUS_FMT_RGB888_1X24,
+ .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE,
+ .panel_regs = wl_355608_a8_panel_regs,
+ .panel_regs_len = ARRAY_SIZE(wl_355608_a8_panel_regs),
+};
+
static const struct spi_device_id nv3052c_ids[] = {
{ "ltk035c5444t", },
{ "fs035vg158", },
+ { "wl-355608-a8", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(spi, nv3052c_ids);
@@ -702,6 +925,7 @@ MODULE_DEVICE_TABLE(spi, nv3052c_ids);
static const struct of_device_id nv3052c_of_match[] = {
{ .compatible = "leadtek,ltk035c5444t", .data = &ltk035c5444t_panel_info },
{ .compatible = "fascontek,fs035vg158", .data = &fs035vg158_panel_info },
+ { .compatible = "wl-355608-a8", .data = &wl_355608_a8_panel_info },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, nv3052c_of_match);
@@ -719,4 +943,6 @@ module_spi_driver(nv3052c_driver);
MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
MODULE_AUTHOR("Christophe Branchereau <cbranchereau@gmail.com>");
+MODULE_AUTHOR("Ryan Walklin <ryan@testtoast.com");
+MODULE_DESCRIPTION("NewVision NV3052C IPS LCD panel driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/panel/panel-novatek-nt36672a.c b/drivers/gpu/drm/panel/panel-novatek-nt36672a.c
index 3886372415c2..c2abd20e0734 100644
--- a/drivers/gpu/drm/panel/panel-novatek-nt36672a.c
+++ b/drivers/gpu/drm/panel/panel-novatek-nt36672a.c
@@ -72,8 +72,6 @@ struct nt36672a_panel {
struct regulator_bulk_data supplies[ARRAY_SIZE(nt36672a_regulator_names)];
struct gpio_desc *reset_gpio;
-
- bool prepared;
};
static inline struct nt36672a_panel *to_nt36672a_panel(struct drm_panel *panel)
@@ -119,9 +117,6 @@ static int nt36672a_panel_unprepare(struct drm_panel *panel)
struct nt36672a_panel *pinfo = to_nt36672a_panel(panel);
int ret;
- if (!pinfo->prepared)
- return 0;
-
/* send off cmds */
ret = nt36672a_send_cmds(panel, pinfo->desc->off_cmds,
pinfo->desc->num_off_cmds);
@@ -147,8 +142,6 @@ static int nt36672a_panel_unprepare(struct drm_panel *panel)
if (ret < 0)
dev_err(panel->dev, "power_off failed ret = %d\n", ret);
- pinfo->prepared = false;
-
return ret;
}
@@ -179,9 +172,6 @@ static int nt36672a_panel_prepare(struct drm_panel *panel)
struct nt36672a_panel *pinfo = to_nt36672a_panel(panel);
int err;
- if (pinfo->prepared)
- return 0;
-
err = nt36672a_panel_power_on(pinfo);
if (err < 0)
goto poweroff;
@@ -221,8 +211,6 @@ static int nt36672a_panel_prepare(struct drm_panel *panel)
msleep(120);
- pinfo->prepared = true;
-
return 0;
poweroff:
@@ -668,14 +656,6 @@ static void nt36672a_panel_remove(struct mipi_dsi_device *dsi)
struct nt36672a_panel *pinfo = mipi_dsi_get_drvdata(dsi);
int err;
- err = drm_panel_unprepare(&pinfo->base);
- if (err < 0)
- dev_err(&dsi->dev, "failed to unprepare panel: %d\n", err);
-
- err = drm_panel_disable(&pinfo->base);
- if (err < 0)
- dev_err(&dsi->dev, "failed to disable panel: %d\n", err);
-
err = mipi_dsi_detach(dsi);
if (err < 0)
dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err);
@@ -683,14 +663,6 @@ static void nt36672a_panel_remove(struct mipi_dsi_device *dsi)
drm_panel_remove(&pinfo->base);
}
-static void nt36672a_panel_shutdown(struct mipi_dsi_device *dsi)
-{
- struct nt36672a_panel *pinfo = mipi_dsi_get_drvdata(dsi);
-
- drm_panel_disable(&pinfo->base);
- drm_panel_unprepare(&pinfo->base);
-}
-
static const struct of_device_id tianma_fhd_video_of_match[] = {
{ .compatible = "tianma,fhd-video", .data = &tianma_fhd_video_panel_desc },
{ },
@@ -704,7 +676,6 @@ static struct mipi_dsi_driver nt36672a_panel_driver = {
},
.probe = nt36672a_panel_probe,
.remove = nt36672a_panel_remove,
- .shutdown = nt36672a_panel_shutdown,
};
module_mipi_dsi_driver(nt36672a_panel_driver);
diff --git a/drivers/gpu/drm/panel/panel-novatek-nt36672e.c b/drivers/gpu/drm/panel/panel-novatek-nt36672e.c
index 20b7bfe4aa12..e81a70147259 100644
--- a/drivers/gpu/drm/panel/panel-novatek-nt36672e.c
+++ b/drivers/gpu/drm/panel/panel-novatek-nt36672e.c
@@ -33,7 +33,7 @@ struct panel_desc {
enum mipi_dsi_pixel_format format;
unsigned int lanes;
const char *panel_name;
- int (*init_sequence)(struct mipi_dsi_device *dsi);
+ void (*init_sequence)(struct mipi_dsi_multi_context *ctx);
};
struct nt36672e_panel {
@@ -49,295 +49,293 @@ static inline struct nt36672e_panel *to_nt36672e_panel(struct drm_panel *panel)
return container_of(panel, struct nt36672e_panel, panel);
}
-static int nt36672e_1080x2408_60hz_init(struct mipi_dsi_device *dsi)
+static void nt36672e_1080x2408_60hz_init(struct mipi_dsi_multi_context *ctx)
{
- mipi_dsi_dcs_write_seq(dsi, 0xff, 0x10);
- mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
- mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0xc0, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0xc1, 0x89, 0x28, 0x00, 0x08, 0x00, 0xaa, 0x02,
- 0x0e, 0x00, 0x2b, 0x00, 0x07, 0x0d, 0xb7, 0x0c, 0xb7);
-
- mipi_dsi_dcs_write_seq(dsi, 0xc2, 0x1b, 0xa0);
- mipi_dsi_dcs_write_seq(dsi, 0xff, 0x20);
- mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
- mipi_dsi_dcs_write_seq(dsi, 0x01, 0x66);
- mipi_dsi_dcs_write_seq(dsi, 0x06, 0x40);
- mipi_dsi_dcs_write_seq(dsi, 0x07, 0x38);
- mipi_dsi_dcs_write_seq(dsi, 0x2f, 0x83);
- mipi_dsi_dcs_write_seq(dsi, 0x69, 0x91);
- mipi_dsi_dcs_write_seq(dsi, 0x95, 0xd1);
- mipi_dsi_dcs_write_seq(dsi, 0x96, 0xd1);
- mipi_dsi_dcs_write_seq(dsi, 0xf2, 0x64);
- mipi_dsi_dcs_write_seq(dsi, 0xf3, 0x54);
- mipi_dsi_dcs_write_seq(dsi, 0xf4, 0x64);
- mipi_dsi_dcs_write_seq(dsi, 0xf5, 0x54);
- mipi_dsi_dcs_write_seq(dsi, 0xf6, 0x64);
- mipi_dsi_dcs_write_seq(dsi, 0xf7, 0x54);
- mipi_dsi_dcs_write_seq(dsi, 0xf8, 0x64);
- mipi_dsi_dcs_write_seq(dsi, 0xf9, 0x54);
- mipi_dsi_dcs_write_seq(dsi, 0xff, 0x24);
- mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
- mipi_dsi_dcs_write_seq(dsi, 0x01, 0x0f);
- mipi_dsi_dcs_write_seq(dsi, 0x03, 0x0c);
- mipi_dsi_dcs_write_seq(dsi, 0x05, 0x1d);
- mipi_dsi_dcs_write_seq(dsi, 0x08, 0x2f);
- mipi_dsi_dcs_write_seq(dsi, 0x09, 0x2e);
- mipi_dsi_dcs_write_seq(dsi, 0x0a, 0x2d);
- mipi_dsi_dcs_write_seq(dsi, 0x0b, 0x2c);
- mipi_dsi_dcs_write_seq(dsi, 0x11, 0x17);
- mipi_dsi_dcs_write_seq(dsi, 0x12, 0x13);
- mipi_dsi_dcs_write_seq(dsi, 0x13, 0x15);
- mipi_dsi_dcs_write_seq(dsi, 0x15, 0x14);
- mipi_dsi_dcs_write_seq(dsi, 0x16, 0x16);
- mipi_dsi_dcs_write_seq(dsi, 0x17, 0x18);
- mipi_dsi_dcs_write_seq(dsi, 0x1b, 0x01);
- mipi_dsi_dcs_write_seq(dsi, 0x1d, 0x1d);
- mipi_dsi_dcs_write_seq(dsi, 0x20, 0x2f);
- mipi_dsi_dcs_write_seq(dsi, 0x21, 0x2e);
- mipi_dsi_dcs_write_seq(dsi, 0x22, 0x2d);
- mipi_dsi_dcs_write_seq(dsi, 0x23, 0x2c);
- mipi_dsi_dcs_write_seq(dsi, 0x29, 0x17);
- mipi_dsi_dcs_write_seq(dsi, 0x2a, 0x13);
- mipi_dsi_dcs_write_seq(dsi, 0x2b, 0x15);
- mipi_dsi_dcs_write_seq(dsi, 0x2f, 0x14);
- mipi_dsi_dcs_write_seq(dsi, 0x30, 0x16);
- mipi_dsi_dcs_write_seq(dsi, 0x31, 0x18);
- mipi_dsi_dcs_write_seq(dsi, 0x32, 0x04);
- mipi_dsi_dcs_write_seq(dsi, 0x34, 0x10);
- mipi_dsi_dcs_write_seq(dsi, 0x35, 0x1f);
- mipi_dsi_dcs_write_seq(dsi, 0x36, 0x1f);
- mipi_dsi_dcs_write_seq(dsi, 0x4d, 0x14);
- mipi_dsi_dcs_write_seq(dsi, 0x4e, 0x36);
- mipi_dsi_dcs_write_seq(dsi, 0x4f, 0x36);
- mipi_dsi_dcs_write_seq(dsi, 0x53, 0x36);
- mipi_dsi_dcs_write_seq(dsi, 0x71, 0x30);
- mipi_dsi_dcs_write_seq(dsi, 0x79, 0x11);
- mipi_dsi_dcs_write_seq(dsi, 0x7a, 0x82);
- mipi_dsi_dcs_write_seq(dsi, 0x7b, 0x8f);
- mipi_dsi_dcs_write_seq(dsi, 0x7d, 0x04);
- mipi_dsi_dcs_write_seq(dsi, 0x80, 0x04);
- mipi_dsi_dcs_write_seq(dsi, 0x81, 0x04);
- mipi_dsi_dcs_write_seq(dsi, 0x82, 0x13);
- mipi_dsi_dcs_write_seq(dsi, 0x84, 0x31);
- mipi_dsi_dcs_write_seq(dsi, 0x85, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0x86, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0x87, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0x90, 0x13);
- mipi_dsi_dcs_write_seq(dsi, 0x92, 0x31);
- mipi_dsi_dcs_write_seq(dsi, 0x93, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0x94, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0x95, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0x9c, 0xf4);
- mipi_dsi_dcs_write_seq(dsi, 0x9d, 0x01);
- mipi_dsi_dcs_write_seq(dsi, 0xa0, 0x0f);
- mipi_dsi_dcs_write_seq(dsi, 0xa2, 0x0f);
- mipi_dsi_dcs_write_seq(dsi, 0xa3, 0x02);
- mipi_dsi_dcs_write_seq(dsi, 0xa4, 0x04);
- mipi_dsi_dcs_write_seq(dsi, 0xa5, 0x04);
- mipi_dsi_dcs_write_seq(dsi, 0xc6, 0xc0);
- mipi_dsi_dcs_write_seq(dsi, 0xc9, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0xd9, 0x80);
- mipi_dsi_dcs_write_seq(dsi, 0xe9, 0x02);
- mipi_dsi_dcs_write_seq(dsi, 0xff, 0x25);
- mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
- mipi_dsi_dcs_write_seq(dsi, 0x18, 0x22);
- mipi_dsi_dcs_write_seq(dsi, 0x19, 0xe4);
- mipi_dsi_dcs_write_seq(dsi, 0x21, 0x40);
- mipi_dsi_dcs_write_seq(dsi, 0x66, 0xd8);
- mipi_dsi_dcs_write_seq(dsi, 0x68, 0x50);
- mipi_dsi_dcs_write_seq(dsi, 0x69, 0x10);
- mipi_dsi_dcs_write_seq(dsi, 0x6b, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0x6d, 0x0d);
- mipi_dsi_dcs_write_seq(dsi, 0x6e, 0x48);
- mipi_dsi_dcs_write_seq(dsi, 0x72, 0x41);
- mipi_dsi_dcs_write_seq(dsi, 0x73, 0x4a);
- mipi_dsi_dcs_write_seq(dsi, 0x74, 0xd0);
- mipi_dsi_dcs_write_seq(dsi, 0x77, 0x62);
- mipi_dsi_dcs_write_seq(dsi, 0x79, 0x7e);
- mipi_dsi_dcs_write_seq(dsi, 0x7d, 0x03);
- mipi_dsi_dcs_write_seq(dsi, 0x7e, 0x15);
- mipi_dsi_dcs_write_seq(dsi, 0x7f, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0x84, 0x4d);
- mipi_dsi_dcs_write_seq(dsi, 0xcf, 0x80);
- mipi_dsi_dcs_write_seq(dsi, 0xd6, 0x80);
- mipi_dsi_dcs_write_seq(dsi, 0xd7, 0x80);
- mipi_dsi_dcs_write_seq(dsi, 0xef, 0x20);
- mipi_dsi_dcs_write_seq(dsi, 0xf0, 0x84);
- mipi_dsi_dcs_write_seq(dsi, 0xff, 0x26);
- mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
- mipi_dsi_dcs_write_seq(dsi, 0x81, 0x0f);
- mipi_dsi_dcs_write_seq(dsi, 0x83, 0x01);
- mipi_dsi_dcs_write_seq(dsi, 0x84, 0x03);
- mipi_dsi_dcs_write_seq(dsi, 0x85, 0x01);
- mipi_dsi_dcs_write_seq(dsi, 0x86, 0x03);
- mipi_dsi_dcs_write_seq(dsi, 0x87, 0x01);
- mipi_dsi_dcs_write_seq(dsi, 0x88, 0x05);
- mipi_dsi_dcs_write_seq(dsi, 0x8a, 0x1a);
- mipi_dsi_dcs_write_seq(dsi, 0x8b, 0x11);
- mipi_dsi_dcs_write_seq(dsi, 0x8c, 0x24);
- mipi_dsi_dcs_write_seq(dsi, 0x8e, 0x42);
- mipi_dsi_dcs_write_seq(dsi, 0x8f, 0x11);
- mipi_dsi_dcs_write_seq(dsi, 0x90, 0x11);
- mipi_dsi_dcs_write_seq(dsi, 0x91, 0x11);
- mipi_dsi_dcs_write_seq(dsi, 0x9a, 0x80);
- mipi_dsi_dcs_write_seq(dsi, 0x9b, 0x04);
- mipi_dsi_dcs_write_seq(dsi, 0x9c, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0x9d, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0x9e, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0xff, 0x27);
- mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
- mipi_dsi_dcs_write_seq(dsi, 0x01, 0x68);
- mipi_dsi_dcs_write_seq(dsi, 0x20, 0x81);
- mipi_dsi_dcs_write_seq(dsi, 0x21, 0x6a);
- mipi_dsi_dcs_write_seq(dsi, 0x25, 0x81);
- mipi_dsi_dcs_write_seq(dsi, 0x26, 0x94);
- mipi_dsi_dcs_write_seq(dsi, 0x6e, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0x6f, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0x70, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0x71, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0x72, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0x75, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0x76, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0x77, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0x7d, 0x09);
- mipi_dsi_dcs_write_seq(dsi, 0x7e, 0x67);
- mipi_dsi_dcs_write_seq(dsi, 0x80, 0x23);
- mipi_dsi_dcs_write_seq(dsi, 0x82, 0x09);
- mipi_dsi_dcs_write_seq(dsi, 0x83, 0x67);
- mipi_dsi_dcs_write_seq(dsi, 0x88, 0x01);
- mipi_dsi_dcs_write_seq(dsi, 0x89, 0x10);
- mipi_dsi_dcs_write_seq(dsi, 0xa5, 0x10);
- mipi_dsi_dcs_write_seq(dsi, 0xa6, 0x23);
- mipi_dsi_dcs_write_seq(dsi, 0xa7, 0x01);
- mipi_dsi_dcs_write_seq(dsi, 0xb6, 0x40);
- mipi_dsi_dcs_write_seq(dsi, 0xe5, 0x02);
- mipi_dsi_dcs_write_seq(dsi, 0xe6, 0xd3);
- mipi_dsi_dcs_write_seq(dsi, 0xeb, 0x03);
- mipi_dsi_dcs_write_seq(dsi, 0xec, 0x28);
- mipi_dsi_dcs_write_seq(dsi, 0xff, 0x2a);
- mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
- mipi_dsi_dcs_write_seq(dsi, 0x00, 0x91);
- mipi_dsi_dcs_write_seq(dsi, 0x03, 0x20);
- mipi_dsi_dcs_write_seq(dsi, 0x07, 0x50);
- mipi_dsi_dcs_write_seq(dsi, 0x0a, 0x70);
- mipi_dsi_dcs_write_seq(dsi, 0x0c, 0x04);
- mipi_dsi_dcs_write_seq(dsi, 0x0d, 0x40);
- mipi_dsi_dcs_write_seq(dsi, 0x0f, 0x01);
- mipi_dsi_dcs_write_seq(dsi, 0x11, 0xe0);
- mipi_dsi_dcs_write_seq(dsi, 0x15, 0x0f);
- mipi_dsi_dcs_write_seq(dsi, 0x16, 0xa4);
- mipi_dsi_dcs_write_seq(dsi, 0x19, 0x0f);
- mipi_dsi_dcs_write_seq(dsi, 0x1a, 0x78);
- mipi_dsi_dcs_write_seq(dsi, 0x1b, 0x23);
- mipi_dsi_dcs_write_seq(dsi, 0x1d, 0x36);
- mipi_dsi_dcs_write_seq(dsi, 0x1e, 0x3e);
- mipi_dsi_dcs_write_seq(dsi, 0x1f, 0x3e);
- mipi_dsi_dcs_write_seq(dsi, 0x20, 0x3e);
- mipi_dsi_dcs_write_seq(dsi, 0x28, 0xfd);
- mipi_dsi_dcs_write_seq(dsi, 0x29, 0x12);
- mipi_dsi_dcs_write_seq(dsi, 0x2a, 0xe1);
- mipi_dsi_dcs_write_seq(dsi, 0x2d, 0x0a);
- mipi_dsi_dcs_write_seq(dsi, 0x30, 0x49);
- mipi_dsi_dcs_write_seq(dsi, 0x33, 0x96);
- mipi_dsi_dcs_write_seq(dsi, 0x34, 0xff);
- mipi_dsi_dcs_write_seq(dsi, 0x35, 0x40);
- mipi_dsi_dcs_write_seq(dsi, 0x36, 0xde);
- mipi_dsi_dcs_write_seq(dsi, 0x37, 0xf9);
- mipi_dsi_dcs_write_seq(dsi, 0x38, 0x45);
- mipi_dsi_dcs_write_seq(dsi, 0x39, 0xd9);
- mipi_dsi_dcs_write_seq(dsi, 0x3a, 0x49);
- mipi_dsi_dcs_write_seq(dsi, 0x4a, 0xf0);
- mipi_dsi_dcs_write_seq(dsi, 0x7a, 0x09);
- mipi_dsi_dcs_write_seq(dsi, 0x7b, 0x40);
- mipi_dsi_dcs_write_seq(dsi, 0x7f, 0xf0);
- mipi_dsi_dcs_write_seq(dsi, 0x83, 0x0f);
- mipi_dsi_dcs_write_seq(dsi, 0x84, 0xa4);
- mipi_dsi_dcs_write_seq(dsi, 0x87, 0x0f);
- mipi_dsi_dcs_write_seq(dsi, 0x88, 0x78);
- mipi_dsi_dcs_write_seq(dsi, 0x89, 0x23);
- mipi_dsi_dcs_write_seq(dsi, 0x8b, 0x36);
- mipi_dsi_dcs_write_seq(dsi, 0x8c, 0x7d);
- mipi_dsi_dcs_write_seq(dsi, 0x8d, 0x7d);
- mipi_dsi_dcs_write_seq(dsi, 0x8e, 0x7d);
- mipi_dsi_dcs_write_seq(dsi, 0xff, 0x20);
- mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
- mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x00, 0x00, 0x00, 0x17, 0x00, 0x49, 0x00,
- 0x6a, 0x00, 0x89, 0x00, 0x9f, 0x00, 0xb6, 0x00, 0xc8);
- mipi_dsi_dcs_write_seq(dsi, 0xb1, 0x00, 0xd9, 0x01, 0x10, 0x01, 0x3a, 0x01,
- 0x7a, 0x01, 0xa9, 0x01, 0xf2, 0x02, 0x2d, 0x02, 0x2e);
- mipi_dsi_dcs_write_seq(dsi, 0xb2, 0x02, 0x64, 0x02, 0xa3, 0x02, 0xca, 0x03,
- 0x00, 0x03, 0x1e, 0x03, 0x4a, 0x03, 0x59, 0x03, 0x6a);
- mipi_dsi_dcs_write_seq(dsi, 0xb3, 0x03, 0x7d, 0x03, 0x93, 0x03, 0xab, 0x03,
- 0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0xb4, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x51, 0x00,
- 0x71, 0x00, 0x90, 0x00, 0xa7, 0x00, 0xbf, 0x00, 0xd1);
- mipi_dsi_dcs_write_seq(dsi, 0xb5, 0x00, 0xe2, 0x01, 0x1a, 0x01, 0x43, 0x01,
- 0x83, 0x01, 0xb2, 0x01, 0xfa, 0x02, 0x34, 0x02, 0x36);
- mipi_dsi_dcs_write_seq(dsi, 0xb6, 0x02, 0x6b, 0x02, 0xa8, 0x02, 0xd0, 0x03,
- 0x03, 0x03, 0x21, 0x03, 0x4d, 0x03, 0x5b, 0x03, 0x6b);
- mipi_dsi_dcs_write_seq(dsi, 0xb7, 0x03, 0x7e, 0x03, 0x94, 0x03, 0xac, 0x03,
- 0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0xb8, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x51, 0x00,
- 0x72, 0x00, 0x92, 0x00, 0xa8, 0x00, 0xbf, 0x00, 0xd1);
- mipi_dsi_dcs_write_seq(dsi, 0xb9, 0x00, 0xe2, 0x01, 0x18, 0x01, 0x42, 0x01,
- 0x81, 0x01, 0xaf, 0x01, 0xf5, 0x02, 0x2f, 0x02, 0x31);
- mipi_dsi_dcs_write_seq(dsi, 0xba, 0x02, 0x68, 0x02, 0xa6, 0x02, 0xcd, 0x03,
- 0x01, 0x03, 0x1f, 0x03, 0x4a, 0x03, 0x59, 0x03, 0x6a);
- mipi_dsi_dcs_write_seq(dsi, 0xbb, 0x03, 0x7d, 0x03, 0x93, 0x03, 0xab, 0x03,
- 0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0xff, 0x21);
- mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
- mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x00, 0x00, 0x00, 0x17, 0x00, 0x49, 0x00,
- 0x6a, 0x00, 0x89, 0x00, 0x9f, 0x00, 0xb6, 0x00, 0xc8);
- mipi_dsi_dcs_write_seq(dsi, 0xb1, 0x00, 0xd9, 0x01, 0x10, 0x01, 0x3a, 0x01,
- 0x7a, 0x01, 0xa9, 0x01, 0xf2, 0x02, 0x2d, 0x02, 0x2e);
- mipi_dsi_dcs_write_seq(dsi, 0xb2, 0x02, 0x64, 0x02, 0xa3, 0x02, 0xca, 0x03,
- 0x00, 0x03, 0x1e, 0x03, 0x4a, 0x03, 0x59, 0x03, 0x6a);
- mipi_dsi_dcs_write_seq(dsi, 0xb3, 0x03, 0x7d, 0x03, 0x93, 0x03, 0xab, 0x03,
- 0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0xb4, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x51, 0x00,
- 0x71, 0x00, 0x90, 0x00, 0xa7, 0x00, 0xbf, 0x00, 0xd1);
- mipi_dsi_dcs_write_seq(dsi, 0xb5, 0x00, 0xe2, 0x01, 0x1a, 0x01, 0x43, 0x01,
- 0x83, 0x01, 0xb2, 0x01, 0xfa, 0x02, 0x34, 0x02, 0x36);
- mipi_dsi_dcs_write_seq(dsi, 0xb6, 0x02, 0x6b, 0x02, 0xa8, 0x02, 0xd0, 0x03,
- 0x03, 0x03, 0x21, 0x03, 0x4d, 0x03, 0x5b, 0x03, 0x6b);
- mipi_dsi_dcs_write_seq(dsi, 0xb7, 0x03, 0x7e, 0x03, 0x94, 0x03, 0xac, 0x03,
- 0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0xb8, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x51, 0x00,
- 0x72, 0x00, 0x92, 0x00, 0xa8, 0x00, 0xbf, 0x00, 0xd1);
- mipi_dsi_dcs_write_seq(dsi, 0xb9, 0x00, 0xe2, 0x01, 0x18, 0x01, 0x42, 0x01,
- 0x81, 0x01, 0xaf, 0x01, 0xf5, 0x02, 0x2f, 0x02, 0x31);
- mipi_dsi_dcs_write_seq(dsi, 0xba, 0x02, 0x68, 0x02, 0xa6, 0x02, 0xcd, 0x03,
- 0x01, 0x03, 0x1f, 0x03, 0x4a, 0x03, 0x59, 0x03, 0x6a);
- mipi_dsi_dcs_write_seq(dsi, 0xbb, 0x03, 0x7d, 0x03, 0x93, 0x03, 0xab, 0x03,
- 0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00);
- mipi_dsi_dcs_write_seq(dsi, 0xff, 0x2c);
- mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
- mipi_dsi_dcs_write_seq(dsi, 0x61, 0x1f);
- mipi_dsi_dcs_write_seq(dsi, 0x62, 0x1f);
- mipi_dsi_dcs_write_seq(dsi, 0x7e, 0x03);
- mipi_dsi_dcs_write_seq(dsi, 0x6a, 0x14);
- mipi_dsi_dcs_write_seq(dsi, 0x6b, 0x36);
- mipi_dsi_dcs_write_seq(dsi, 0x6c, 0x36);
- mipi_dsi_dcs_write_seq(dsi, 0x6d, 0x36);
- mipi_dsi_dcs_write_seq(dsi, 0x53, 0x04);
- mipi_dsi_dcs_write_seq(dsi, 0x54, 0x04);
- mipi_dsi_dcs_write_seq(dsi, 0x55, 0x04);
- mipi_dsi_dcs_write_seq(dsi, 0x56, 0x0f);
- mipi_dsi_dcs_write_seq(dsi, 0x58, 0x0f);
- mipi_dsi_dcs_write_seq(dsi, 0x59, 0x0f);
- mipi_dsi_dcs_write_seq(dsi, 0xff, 0xf0);
- mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
- mipi_dsi_dcs_write_seq(dsi, 0x5a, 0x00);
-
- mipi_dsi_dcs_write_seq(dsi, 0xff, 0x10);
- mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
- mipi_dsi_dcs_write_seq(dsi, 0x51, 0xff);
- mipi_dsi_dcs_write_seq(dsi, 0x53, 0x24);
- mipi_dsi_dcs_write_seq(dsi, 0x55, 0x01);
-
- return 0;
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0x10);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb0, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xc0, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xc1, 0x89, 0x28, 0x00, 0x08, 0x00, 0xaa, 0x02,
+ 0x0e, 0x00, 0x2b, 0x00, 0x07, 0x0d, 0xb7, 0x0c, 0xb7);
+
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xc2, 0x1b, 0xa0);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0x20);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x01, 0x66);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x06, 0x40);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x07, 0x38);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x2f, 0x83);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x69, 0x91);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x95, 0xd1);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x96, 0xd1);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xf2, 0x64);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xf3, 0x54);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xf4, 0x64);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xf5, 0x54);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xf6, 0x64);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xf7, 0x54);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xf8, 0x64);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xf9, 0x54);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0x24);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x01, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x03, 0x0c);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x05, 0x1d);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x08, 0x2f);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x09, 0x2e);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x0a, 0x2d);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x0b, 0x2c);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x11, 0x17);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x12, 0x13);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x13, 0x15);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x15, 0x14);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x16, 0x16);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x17, 0x18);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x1b, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x1d, 0x1d);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x20, 0x2f);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x21, 0x2e);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x22, 0x2d);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x23, 0x2c);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x29, 0x17);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x2a, 0x13);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x2b, 0x15);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x2f, 0x14);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x30, 0x16);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x31, 0x18);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x32, 0x04);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x34, 0x10);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x35, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x36, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x4d, 0x14);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x4e, 0x36);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x4f, 0x36);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x53, 0x36);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x71, 0x30);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x79, 0x11);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x7a, 0x82);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x7b, 0x8f);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x7d, 0x04);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x80, 0x04);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x81, 0x04);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x82, 0x13);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x84, 0x31);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x85, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x86, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x87, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x90, 0x13);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x92, 0x31);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x93, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x94, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x95, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x9c, 0xf4);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x9d, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xa0, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xa2, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xa3, 0x02);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xa4, 0x04);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xa5, 0x04);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xc6, 0xc0);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xc9, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xd9, 0x80);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xe9, 0x02);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0x25);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x18, 0x22);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x19, 0xe4);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x21, 0x40);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x66, 0xd8);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x68, 0x50);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x69, 0x10);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x6b, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x6d, 0x0d);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x6e, 0x48);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x72, 0x41);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x73, 0x4a);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x74, 0xd0);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x77, 0x62);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x79, 0x7e);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x7d, 0x03);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x7e, 0x15);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x7f, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x84, 0x4d);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xcf, 0x80);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xd6, 0x80);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xd7, 0x80);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xef, 0x20);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xf0, 0x84);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0x26);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x81, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x83, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x84, 0x03);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x85, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x86, 0x03);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x87, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x88, 0x05);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x8a, 0x1a);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x8b, 0x11);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x8c, 0x24);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x8e, 0x42);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x8f, 0x11);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x90, 0x11);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x91, 0x11);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x9a, 0x80);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x9b, 0x04);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x9c, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x9d, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x9e, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0x27);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x01, 0x68);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x20, 0x81);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x21, 0x6a);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x25, 0x81);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x26, 0x94);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x6e, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x6f, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x70, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x71, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x72, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x75, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x76, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x77, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x7d, 0x09);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x7e, 0x67);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x80, 0x23);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x82, 0x09);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x83, 0x67);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x88, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x89, 0x10);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xa5, 0x10);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xa6, 0x23);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xa7, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb6, 0x40);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xe5, 0x02);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xe6, 0xd3);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xeb, 0x03);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xec, 0x28);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0x2a);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x00, 0x91);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x03, 0x20);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x07, 0x50);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x0a, 0x70);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x0c, 0x04);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x0d, 0x40);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x0f, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x11, 0xe0);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x15, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x16, 0xa4);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x19, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x1a, 0x78);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x1b, 0x23);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x1d, 0x36);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x1e, 0x3e);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x1f, 0x3e);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x20, 0x3e);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x28, 0xfd);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x29, 0x12);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x2a, 0xe1);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x2d, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x30, 0x49);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x33, 0x96);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x34, 0xff);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x35, 0x40);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x36, 0xde);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x37, 0xf9);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x38, 0x45);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x39, 0xd9);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x3a, 0x49);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x4a, 0xf0);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x7a, 0x09);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x7b, 0x40);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x7f, 0xf0);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x83, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x84, 0xa4);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x87, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x88, 0x78);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x89, 0x23);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x8b, 0x36);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x8c, 0x7d);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x8d, 0x7d);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x8e, 0x7d);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0x20);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb0, 0x00, 0x00, 0x00, 0x17, 0x00, 0x49, 0x00,
+ 0x6a, 0x00, 0x89, 0x00, 0x9f, 0x00, 0xb6, 0x00, 0xc8);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb1, 0x00, 0xd9, 0x01, 0x10, 0x01, 0x3a, 0x01,
+ 0x7a, 0x01, 0xa9, 0x01, 0xf2, 0x02, 0x2d, 0x02, 0x2e);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb2, 0x02, 0x64, 0x02, 0xa3, 0x02, 0xca, 0x03,
+ 0x00, 0x03, 0x1e, 0x03, 0x4a, 0x03, 0x59, 0x03, 0x6a);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb3, 0x03, 0x7d, 0x03, 0x93, 0x03, 0xab, 0x03,
+ 0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb4, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x51, 0x00,
+ 0x71, 0x00, 0x90, 0x00, 0xa7, 0x00, 0xbf, 0x00, 0xd1);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb5, 0x00, 0xe2, 0x01, 0x1a, 0x01, 0x43, 0x01,
+ 0x83, 0x01, 0xb2, 0x01, 0xfa, 0x02, 0x34, 0x02, 0x36);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb6, 0x02, 0x6b, 0x02, 0xa8, 0x02, 0xd0, 0x03,
+ 0x03, 0x03, 0x21, 0x03, 0x4d, 0x03, 0x5b, 0x03, 0x6b);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb7, 0x03, 0x7e, 0x03, 0x94, 0x03, 0xac, 0x03,
+ 0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb8, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x51, 0x00,
+ 0x72, 0x00, 0x92, 0x00, 0xa8, 0x00, 0xbf, 0x00, 0xd1);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb9, 0x00, 0xe2, 0x01, 0x18, 0x01, 0x42, 0x01,
+ 0x81, 0x01, 0xaf, 0x01, 0xf5, 0x02, 0x2f, 0x02, 0x31);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xba, 0x02, 0x68, 0x02, 0xa6, 0x02, 0xcd, 0x03,
+ 0x01, 0x03, 0x1f, 0x03, 0x4a, 0x03, 0x59, 0x03, 0x6a);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xbb, 0x03, 0x7d, 0x03, 0x93, 0x03, 0xab, 0x03,
+ 0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0x21);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb0, 0x00, 0x00, 0x00, 0x17, 0x00, 0x49, 0x00,
+ 0x6a, 0x00, 0x89, 0x00, 0x9f, 0x00, 0xb6, 0x00, 0xc8);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb1, 0x00, 0xd9, 0x01, 0x10, 0x01, 0x3a, 0x01,
+ 0x7a, 0x01, 0xa9, 0x01, 0xf2, 0x02, 0x2d, 0x02, 0x2e);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb2, 0x02, 0x64, 0x02, 0xa3, 0x02, 0xca, 0x03,
+ 0x00, 0x03, 0x1e, 0x03, 0x4a, 0x03, 0x59, 0x03, 0x6a);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb3, 0x03, 0x7d, 0x03, 0x93, 0x03, 0xab, 0x03,
+ 0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb4, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x51, 0x00,
+ 0x71, 0x00, 0x90, 0x00, 0xa7, 0x00, 0xbf, 0x00, 0xd1);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb5, 0x00, 0xe2, 0x01, 0x1a, 0x01, 0x43, 0x01,
+ 0x83, 0x01, 0xb2, 0x01, 0xfa, 0x02, 0x34, 0x02, 0x36);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb6, 0x02, 0x6b, 0x02, 0xa8, 0x02, 0xd0, 0x03,
+ 0x03, 0x03, 0x21, 0x03, 0x4d, 0x03, 0x5b, 0x03, 0x6b);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb7, 0x03, 0x7e, 0x03, 0x94, 0x03, 0xac, 0x03,
+ 0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb8, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x51, 0x00,
+ 0x72, 0x00, 0x92, 0x00, 0xa8, 0x00, 0xbf, 0x00, 0xd1);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xb9, 0x00, 0xe2, 0x01, 0x18, 0x01, 0x42, 0x01,
+ 0x81, 0x01, 0xaf, 0x01, 0xf5, 0x02, 0x2f, 0x02, 0x31);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xba, 0x02, 0x68, 0x02, 0xa6, 0x02, 0xcd, 0x03,
+ 0x01, 0x03, 0x1f, 0x03, 0x4a, 0x03, 0x59, 0x03, 0x6a);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xbb, 0x03, 0x7d, 0x03, 0x93, 0x03, 0xab, 0x03,
+ 0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0x2c);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x61, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x62, 0x1f);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x7e, 0x03);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x6a, 0x14);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x6b, 0x36);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x6c, 0x36);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x6d, 0x36);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x53, 0x04);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x54, 0x04);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x55, 0x04);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x56, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x58, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x59, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0xf0);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x5a, 0x00);
+
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0x10);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x51, 0xff);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x53, 0x24);
+ mipi_dsi_dcs_write_seq_multi(ctx, 0x55, 0x01);
}
static int nt36672e_power_on(struct nt36672e_panel *ctx)
@@ -379,68 +377,46 @@ static int nt36672e_power_off(struct nt36672e_panel *ctx)
return ret;
}
-static int nt36672e_on(struct nt36672e_panel *ctx)
+static int nt36672e_on(struct nt36672e_panel *nt36672e)
{
- struct mipi_dsi_device *dsi = ctx->dsi;
- const struct panel_desc *desc = ctx->desc;
- int ret = 0;
+ struct mipi_dsi_multi_context ctx = { .dsi = nt36672e->dsi };
+ const struct panel_desc *desc = nt36672e->desc;
- dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+ nt36672e->dsi->mode_flags |= MIPI_DSI_MODE_LPM;
- if (desc->init_sequence) {
- ret = desc->init_sequence(dsi);
- if (ret < 0) {
- dev_err(&dsi->dev, "panel init sequence failed: %d\n", ret);
- return ret;
- }
- }
+ if (desc->init_sequence)
+ desc->init_sequence(&ctx);
- ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
- if (ret < 0) {
- dev_err(&dsi->dev, "Failed to exit sleep mode: %d\n", ret);
- return ret;
- }
- msleep(120);
+ mipi_dsi_dcs_exit_sleep_mode_multi(&ctx);
+ mipi_dsi_msleep(&ctx, 120);
- ret = mipi_dsi_dcs_set_display_on(dsi);
- if (ret < 0) {
- dev_err(&dsi->dev, "Failed to set display on: %d\n", ret);
- return ret;
- }
- msleep(100);
+ mipi_dsi_dcs_set_display_on_multi(&ctx);
- return 0;
+ mipi_dsi_msleep(&ctx, 100);
+
+ return ctx.accum_err;
}
-static int nt36672e_off(struct nt36672e_panel *ctx)
+static int nt36672e_off(struct nt36672e_panel *panel)
{
- struct mipi_dsi_device *dsi = ctx->dsi;
- int ret = 0;
+ struct mipi_dsi_multi_context ctx = { .dsi = panel->dsi };
- dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+ panel->dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
- ret = mipi_dsi_dcs_set_display_off(dsi);
- if (ret < 0) {
- dev_err(&dsi->dev, "Failed to set display off: %d\n", ret);
- return ret;
- }
- msleep(20);
+ mipi_dsi_dcs_set_display_off_multi(&ctx);
+ mipi_dsi_msleep(&ctx, 20);
- ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
- if (ret < 0) {
- dev_err(&dsi->dev, "Failed to enter sleep mode: %d\n", ret);
- return ret;
- }
- msleep(60);
+ mipi_dsi_dcs_enter_sleep_mode_multi(&ctx);
+ mipi_dsi_msleep(&ctx, 60);
- return 0;
+ return ctx.accum_err;
}
static int nt36672e_panel_prepare(struct drm_panel *panel)
{
struct nt36672e_panel *ctx = to_nt36672e_panel(panel);
struct mipi_dsi_device *dsi = ctx->dsi;
- int ret = 0;
+ int ret;
ret = nt36672e_power_on(ctx);
if (ret < 0)
@@ -448,7 +424,6 @@ static int nt36672e_panel_prepare(struct drm_panel *panel)
ret = nt36672e_on(ctx);
if (ret < 0) {
- dev_err(&dsi->dev, "Failed to initialize panel: %d\n", ret);
if (nt36672e_power_off(ctx))
dev_err(&dsi->dev, "power off failed\n");
return ret;
@@ -461,11 +436,9 @@ static int nt36672e_panel_unprepare(struct drm_panel *panel)
{
struct nt36672e_panel *ctx = to_nt36672e_panel(panel);
struct mipi_dsi_device *dsi = ctx->dsi;
- int ret = 0;
+ int ret;
- ret = nt36672e_off(ctx);
- if (ret < 0)
- dev_err(&dsi->dev, "Failed to un-initialize panel: %d\n", ret);
+ nt36672e_off(ctx);
ret = nt36672e_power_off(ctx);
if (ret < 0)
diff --git a/drivers/gpu/drm/panel/panel-novatek-nt39016.c b/drivers/gpu/drm/panel/panel-novatek-nt39016.c
index 059260262b5a..9fa7654e2b67 100644
--- a/drivers/gpu/drm/panel/panel-novatek-nt39016.c
+++ b/drivers/gpu/drm/panel/panel-novatek-nt39016.c
@@ -356,4 +356,5 @@ module_spi_driver(nt39016_driver);
MODULE_AUTHOR("Maarten ter Huurne <maarten@treewalker.org>");
MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
+MODULE_DESCRIPTION("Novatek NT39016 TFT LCD panel driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c b/drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c
index 4819ada69482..94ae8c8270b8 100644
--- a/drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c
+++ b/drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c
@@ -64,9 +64,6 @@ struct lcd_olinuxino {
struct i2c_client *client;
struct mutex mutex;
- bool prepared;
- bool enabled;
-
struct regulator *supply;
struct gpio_desc *enable_gpio;
@@ -78,30 +75,13 @@ static inline struct lcd_olinuxino *to_lcd_olinuxino(struct drm_panel *panel)
return container_of(panel, struct lcd_olinuxino, panel);
}
-static int lcd_olinuxino_disable(struct drm_panel *panel)
-{
- struct lcd_olinuxino *lcd = to_lcd_olinuxino(panel);
-
- if (!lcd->enabled)
- return 0;
-
- lcd->enabled = false;
-
- return 0;
-}
-
static int lcd_olinuxino_unprepare(struct drm_panel *panel)
{
struct lcd_olinuxino *lcd = to_lcd_olinuxino(panel);
- if (!lcd->prepared)
- return 0;
-
gpiod_set_value_cansleep(lcd->enable_gpio, 0);
regulator_disable(lcd->supply);
- lcd->prepared = false;
-
return 0;
}
@@ -110,27 +90,11 @@ static int lcd_olinuxino_prepare(struct drm_panel *panel)
struct lcd_olinuxino *lcd = to_lcd_olinuxino(panel);
int ret;
- if (lcd->prepared)
- return 0;
-
ret = regulator_enable(lcd->supply);
if (ret < 0)
return ret;
gpiod_set_value_cansleep(lcd->enable_gpio, 1);
- lcd->prepared = true;
-
- return 0;
-}
-
-static int lcd_olinuxino_enable(struct drm_panel *panel)
-{
- struct lcd_olinuxino *lcd = to_lcd_olinuxino(panel);
-
- if (lcd->enabled)
- return 0;
-
- lcd->enabled = true;
return 0;
}
@@ -195,10 +159,8 @@ static int lcd_olinuxino_get_modes(struct drm_panel *panel,
}
static const struct drm_panel_funcs lcd_olinuxino_funcs = {
- .disable = lcd_olinuxino_disable,
.unprepare = lcd_olinuxino_unprepare,
.prepare = lcd_olinuxino_prepare,
- .enable = lcd_olinuxino_enable,
.get_modes = lcd_olinuxino_get_modes,
};
@@ -264,9 +226,6 @@ static int lcd_olinuxino_probe(struct i2c_client *client)
lcd->eeprom.num_modes = 4;
}
- lcd->enabled = false;
- lcd->prepared = false;
-
lcd->supply = devm_regulator_get(dev, "power");
if (IS_ERR(lcd->supply))
return PTR_ERR(lcd->supply);
@@ -292,9 +251,6 @@ static void lcd_olinuxino_remove(struct i2c_client *client)
struct lcd_olinuxino *panel = i2c_get_clientdata(client);
drm_panel_remove(&panel->panel);
-
- drm_panel_disable(&panel->panel);
- drm_panel_unprepare(&panel->panel);
}
static const struct of_device_id lcd_olinuxino_of_ids[] = {
diff --git a/drivers/gpu/drm/panel/panel-orisetech-ota5601a.c b/drivers/gpu/drm/panel/panel-orisetech-ota5601a.c
index c415dacf1816..fc87f61d4400 100644
--- a/drivers/gpu/drm/panel/panel-orisetech-ota5601a.c
+++ b/drivers/gpu/drm/panel/panel-orisetech-ota5601a.c
@@ -360,4 +360,5 @@ static struct spi_driver ota5601a_driver = {
module_spi_driver(ota5601a_driver);
MODULE_AUTHOR("Christophe Branchereau <cbranchereau@gmail.com>");
+MODULE_DESCRIPTION("Orisetech OTA5601A TFT LCD panel driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/panel/panel-osd-osd101t2587-53ts.c b/drivers/gpu/drm/panel/panel-osd-osd101t2587-53ts.c
index 493e0504f6f7..dbea84f51514 100644
--- a/drivers/gpu/drm/panel/panel-osd-osd101t2587-53ts.c
+++ b/drivers/gpu/drm/panel/panel-osd-osd101t2587-53ts.c
@@ -21,9 +21,6 @@ struct osd101t2587_panel {
struct regulator *supply;
- bool prepared;
- bool enabled;
-
const struct drm_display_mode *default_mode;
};
@@ -37,13 +34,8 @@ static int osd101t2587_panel_disable(struct drm_panel *panel)
struct osd101t2587_panel *osd101t2587 = ti_osd_panel(panel);
int ret;
- if (!osd101t2587->enabled)
- return 0;
-
ret = mipi_dsi_shutdown_peripheral(osd101t2587->dsi);
- osd101t2587->enabled = false;
-
return ret;
}
@@ -51,11 +43,7 @@ static int osd101t2587_panel_unprepare(struct drm_panel *panel)
{
struct osd101t2587_panel *osd101t2587 = ti_osd_panel(panel);
- if (!osd101t2587->prepared)
- return 0;
-
regulator_disable(osd101t2587->supply);
- osd101t2587->prepared = false;
return 0;
}
@@ -63,16 +51,8 @@ static int osd101t2587_panel_unprepare(struct drm_panel *panel)
static int osd101t2587_panel_prepare(struct drm_panel *panel)
{
struct osd101t2587_panel *osd101t2587 = ti_osd_panel(panel);
- int ret;
- if (osd101t2587->prepared)
- return 0;
-
- ret = regulator_enable(osd101t2587->supply);
- if (!ret)
- osd101t2587->prepared = true;
-
- return ret;
+ return regulator_enable(osd101t2587->supply);
}
static int osd101t2587_panel_enable(struct drm_panel *panel)
@@ -80,15 +60,10 @@ static int osd101t2587_panel_enable(struct drm_panel *panel)
struct osd101t2587_panel *osd101t2587 = ti_osd_panel(panel);
int ret;
- if (osd101t2587->enabled)
- return 0;
-
ret = mipi_dsi_turn_on_peripheral(osd101t2587->dsi);
if (ret)
return ret;
- osd101t2587->enabled = true;
-
return ret;
}
@@ -211,11 +186,6 @@ static void osd101t2587_panel_remove(struct mipi_dsi_device *dsi)
struct osd101t2587_panel *osd101t2587 = mipi_dsi_get_drvdata(dsi);
int ret;
- ret = drm_panel_disable(&osd101t2587->base);
- if (ret < 0)
- dev_warn(&dsi->dev, "failed to disable panel: %d\n", ret);
-
- drm_panel_unprepare(&osd101t2587->base);
drm_panel_remove(&osd101t2587->base);
ret = mipi_dsi_detach(dsi);
@@ -223,14 +193,6 @@ static void osd101t2587_panel_remove(struct mipi_dsi_device *dsi)
dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret);
}
-static void osd101t2587_panel_shutdown(struct mipi_dsi_device *dsi)
-{
- struct osd101t2587_panel *osd101t2587 = mipi_dsi_get_drvdata(dsi);
-
- drm_panel_disable(&osd101t2587->base);
- drm_panel_unprepare(&osd101t2587->base);
-}
-
static struct mipi_dsi_driver osd101t2587_panel_driver = {
.driver = {
.name = "panel-osd-osd101t2587-53ts",
@@ -238,7 +200,6 @@ static struct mipi_dsi_driver osd101t2587_panel_driver = {
},
.probe = osd101t2587_panel_probe,
.remove = osd101t2587_panel_remove,
- .shutdown = osd101t2587_panel_shutdown,
};
module_mipi_dsi_driver(osd101t2587_panel_driver);
diff --git a/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c b/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c
index 8ba6d8287938..d1c5c9bc3c56 100644
--- a/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c
+++ b/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c
@@ -32,9 +32,6 @@ struct wuxga_nt_panel {
struct regulator *supply;
- bool prepared;
- bool enabled;
-
ktime_t earliest_wake;
const struct drm_display_mode *mode;
@@ -53,28 +50,16 @@ static int wuxga_nt_panel_on(struct wuxga_nt_panel *wuxga_nt)
static int wuxga_nt_panel_disable(struct drm_panel *panel)
{
struct wuxga_nt_panel *wuxga_nt = to_wuxga_nt_panel(panel);
- int mipi_ret, bl_ret = 0;
-
- if (!wuxga_nt->enabled)
- return 0;
-
- mipi_ret = mipi_dsi_shutdown_peripheral(wuxga_nt->dsi);
- wuxga_nt->enabled = false;
-
- return mipi_ret ? mipi_ret : bl_ret;
+ return mipi_dsi_shutdown_peripheral(wuxga_nt->dsi);
}
static int wuxga_nt_panel_unprepare(struct drm_panel *panel)
{
struct wuxga_nt_panel *wuxga_nt = to_wuxga_nt_panel(panel);
- if (!wuxga_nt->prepared)
- return 0;
-
regulator_disable(wuxga_nt->supply);
wuxga_nt->earliest_wake = ktime_add_ms(ktime_get_real(), MIN_POFF_MS);
- wuxga_nt->prepared = false;
return 0;
}
@@ -85,9 +70,6 @@ static int wuxga_nt_panel_prepare(struct drm_panel *panel)
int ret;
s64 enablewait;
- if (wuxga_nt->prepared)
- return 0;
-
/*
* If the user re-enabled the panel before the required off-time then
* we need to wait the remaining period before re-enabling regulator
@@ -117,8 +99,6 @@ static int wuxga_nt_panel_prepare(struct drm_panel *panel)
goto poweroff;
}
- wuxga_nt->prepared = true;
-
return 0;
poweroff:
@@ -127,18 +107,6 @@ poweroff:
return ret;
}
-static int wuxga_nt_panel_enable(struct drm_panel *panel)
-{
- struct wuxga_nt_panel *wuxga_nt = to_wuxga_nt_panel(panel);
-
- if (wuxga_nt->enabled)
- return 0;
-
- wuxga_nt->enabled = true;
-
- return 0;
-}
-
static const struct drm_display_mode default_mode = {
.clock = 164402,
.hdisplay = 1920,
@@ -178,7 +146,6 @@ static const struct drm_panel_funcs wuxga_nt_panel_funcs = {
.disable = wuxga_nt_panel_disable,
.unprepare = wuxga_nt_panel_unprepare,
.prepare = wuxga_nt_panel_prepare,
- .enable = wuxga_nt_panel_enable,
.get_modes = wuxga_nt_panel_get_modes,
};
@@ -255,10 +222,6 @@ static void wuxga_nt_panel_remove(struct mipi_dsi_device *dsi)
struct wuxga_nt_panel *wuxga_nt = mipi_dsi_get_drvdata(dsi);
int ret;
- ret = drm_panel_disable(&wuxga_nt->base);
- if (ret < 0)
- dev_err(&dsi->dev, "failed to disable panel: %d\n", ret);
-
ret = mipi_dsi_detach(dsi);
if (ret < 0)
dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret);
@@ -266,13 +229,6 @@ static void wuxga_nt_panel_remove(struct mipi_dsi_device *dsi)
wuxga_nt_panel_del(wuxga_nt);
}
-static void wuxga_nt_panel_shutdown(struct mipi_dsi_device *dsi)
-{
- struct wuxga_nt_panel *wuxga_nt = mipi_dsi_get_drvdata(dsi);
-
- drm_panel_disable(&wuxga_nt->base);
-}
-
static struct mipi_dsi_driver wuxga_nt_panel_driver = {
.driver = {
.name = "panel-panasonic-vvx10f034n00",
@@ -280,7 +236,6 @@ static struct mipi_dsi_driver wuxga_nt_panel_driver = {
},
.probe = wuxga_nt_panel_probe,
.remove = wuxga_nt_panel_remove,
- .shutdown = wuxga_nt_panel_shutdown,
};
module_mipi_dsi_driver(wuxga_nt_panel_driver);
diff --git a/drivers/gpu/drm/panel/panel-raydium-rm67191.c b/drivers/gpu/drm/panel/panel-raydium-rm67191.c
index dbb1ed4efbed..b2029e035635 100644
--- a/drivers/gpu/drm/panel/panel-raydium-rm67191.c
+++ b/drivers/gpu/drm/panel/panel-raydium-rm67191.c
@@ -205,7 +205,6 @@ struct rad_panel {
unsigned int num_supplies;
bool prepared;
- bool enabled;
};
static const struct drm_display_mode default_mode = {
@@ -267,9 +266,6 @@ static int rad_panel_prepare(struct drm_panel *panel)
struct rad_panel *rad = to_rad_panel(panel);
int ret;
- if (rad->prepared)
- return 0;
-
ret = regulator_bulk_enable(rad->num_supplies, rad->supplies);
if (ret)
return ret;
@@ -291,9 +287,6 @@ static int rad_panel_unprepare(struct drm_panel *panel)
struct rad_panel *rad = to_rad_panel(panel);
int ret;
- if (!rad->prepared)
- return 0;
-
/*
* Right after asserting the reset, we need to release it, so that the
* touch driver can have an active connection with the touch controller
@@ -322,9 +315,6 @@ static int rad_panel_enable(struct drm_panel *panel)
int color_format = color_format_from_dsi_format(dsi->format);
int ret;
- if (rad->enabled)
- return 0;
-
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
ret = rad_panel_push_cmd_list(dsi);
@@ -389,8 +379,6 @@ static int rad_panel_enable(struct drm_panel *panel)
backlight_enable(rad->backlight);
- rad->enabled = true;
-
return 0;
fail:
@@ -406,9 +394,6 @@ static int rad_panel_disable(struct drm_panel *panel)
struct device *dev = &dsi->dev;
int ret;
- if (!rad->enabled)
- return 0;
-
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
backlight_disable(rad->backlight);
@@ -429,8 +414,6 @@ static int rad_panel_disable(struct drm_panel *panel)
return ret;
}
- rad->enabled = false;
-
return 0;
}
@@ -629,14 +612,6 @@ static void rad_panel_remove(struct mipi_dsi_device *dsi)
drm_panel_remove(&rad->panel);
}
-static void rad_panel_shutdown(struct mipi_dsi_device *dsi)
-{
- struct rad_panel *rad = mipi_dsi_get_drvdata(dsi);
-
- rad_panel_disable(&rad->panel);
- rad_panel_unprepare(&rad->panel);
-}
-
static const struct of_device_id rad_of_match[] = {
{ .compatible = "raydium,rm67191", },
{ /* sentinel */ }
@@ -650,7 +625,6 @@ static struct mipi_dsi_driver rad_panel_driver = {
},
.probe = rad_panel_probe,
.remove = rad_panel_remove,
- .shutdown = rad_panel_shutdown,
};
module_mipi_dsi_driver(rad_panel_driver);
diff --git a/drivers/gpu/drm/panel/panel-raydium-rm692e5.c b/drivers/gpu/drm/panel/panel-raydium-rm692e5.c
index a613ba5b816c..ea1b728e85a2 100644
--- a/drivers/gpu/drm/panel/panel-raydium-rm692e5.c
+++ b/drivers/gpu/drm/panel/panel-raydium-rm692e5.c
@@ -23,7 +23,6 @@ struct rm692e5_panel {
struct drm_dsc_config dsc;
struct regulator_bulk_data supplies[3];
struct gpio_desc *reset_gpio;
- bool prepared;
};
static inline struct rm692e5_panel *to_rm692e5_panel(struct drm_panel *panel)
@@ -41,194 +40,145 @@ static void rm692e5_reset(struct rm692e5_panel *ctx)
usleep_range(10000, 11000);
}
-static int rm692e5_on(struct rm692e5_panel *ctx)
+static void rm692e5_on(struct mipi_dsi_multi_context *dsi_ctx)
{
- struct mipi_dsi_device *dsi = ctx->dsi;
- struct device *dev = &dsi->dev;
- int ret;
-
- dsi->mode_flags |= MIPI_DSI_MODE_LPM;
-
- mipi_dsi_generic_write_seq(dsi, 0xfe, 0x41);
- mipi_dsi_generic_write_seq(dsi, 0xd6, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xfe, 0x16);
- mipi_dsi_generic_write_seq(dsi, 0x8a, 0x87);
- mipi_dsi_generic_write_seq(dsi, 0xfe, 0x71);
- mipi_dsi_generic_write_seq(dsi, 0x82, 0x01);
- mipi_dsi_generic_write_seq(dsi, 0xc6, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xc7, 0x2c);
- mipi_dsi_generic_write_seq(dsi, 0xc8, 0x64);
- mipi_dsi_generic_write_seq(dsi, 0xc9, 0x3c);
- mipi_dsi_generic_write_seq(dsi, 0xca, 0x80);
- mipi_dsi_generic_write_seq(dsi, 0xcb, 0x02);
- mipi_dsi_generic_write_seq(dsi, 0xcc, 0x02);
- mipi_dsi_generic_write_seq(dsi, 0xfe, 0x38);
- mipi_dsi_generic_write_seq(dsi, 0x18, 0x13);
- mipi_dsi_generic_write_seq(dsi, 0xfe, 0xf4);
- mipi_dsi_generic_write_seq(dsi, 0x00, 0xff);
- mipi_dsi_generic_write_seq(dsi, 0x01, 0xff);
- mipi_dsi_generic_write_seq(dsi, 0x02, 0xcf);
- mipi_dsi_generic_write_seq(dsi, 0x03, 0xbc);
- mipi_dsi_generic_write_seq(dsi, 0x04, 0xb9);
- mipi_dsi_generic_write_seq(dsi, 0x05, 0x99);
- mipi_dsi_generic_write_seq(dsi, 0x06, 0x02);
- mipi_dsi_generic_write_seq(dsi, 0x07, 0x0a);
- mipi_dsi_generic_write_seq(dsi, 0x08, 0xe0);
- mipi_dsi_generic_write_seq(dsi, 0x09, 0x4c);
- mipi_dsi_generic_write_seq(dsi, 0x0a, 0xeb);
- mipi_dsi_generic_write_seq(dsi, 0x0b, 0xe8);
- mipi_dsi_generic_write_seq(dsi, 0x0c, 0x32);
- mipi_dsi_generic_write_seq(dsi, 0x0d, 0x07);
- mipi_dsi_generic_write_seq(dsi, 0xfe, 0xf4);
- mipi_dsi_generic_write_seq(dsi, 0x0d, 0xc0);
- mipi_dsi_generic_write_seq(dsi, 0x0e, 0xff);
- mipi_dsi_generic_write_seq(dsi, 0x0f, 0xff);
- mipi_dsi_generic_write_seq(dsi, 0x10, 0x33);
- mipi_dsi_generic_write_seq(dsi, 0x11, 0x6f);
- mipi_dsi_generic_write_seq(dsi, 0x12, 0x6e);
- mipi_dsi_generic_write_seq(dsi, 0x13, 0xa6);
- mipi_dsi_generic_write_seq(dsi, 0x14, 0x80);
- mipi_dsi_generic_write_seq(dsi, 0x15, 0x02);
- mipi_dsi_generic_write_seq(dsi, 0x16, 0x38);
- mipi_dsi_generic_write_seq(dsi, 0x17, 0xd3);
- mipi_dsi_generic_write_seq(dsi, 0x18, 0x3a);
- mipi_dsi_generic_write_seq(dsi, 0x19, 0xba);
- mipi_dsi_generic_write_seq(dsi, 0x1a, 0xcc);
- mipi_dsi_generic_write_seq(dsi, 0x1b, 0x01);
-
- ret = mipi_dsi_dcs_nop(dsi);
- if (ret < 0) {
- dev_err(dev, "Failed to nop: %d\n", ret);
- return ret;
- }
- msleep(32);
-
- mipi_dsi_generic_write_seq(dsi, 0xfe, 0x38);
- mipi_dsi_generic_write_seq(dsi, 0x18, 0x13);
- mipi_dsi_generic_write_seq(dsi, 0xfe, 0xd1);
- mipi_dsi_generic_write_seq(dsi, 0xd3, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xd0, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xd2, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xd4, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xb4, 0x01);
- mipi_dsi_generic_write_seq(dsi, 0xfe, 0xf9);
- mipi_dsi_generic_write_seq(dsi, 0x00, 0xaf);
- mipi_dsi_generic_write_seq(dsi, 0x1d, 0x37);
- mipi_dsi_generic_write_seq(dsi, 0x44, 0x0a, 0x7b);
- mipi_dsi_generic_write_seq(dsi, 0xfe, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xfa, 0x01);
- mipi_dsi_generic_write_seq(dsi, 0xc2, 0x08);
- mipi_dsi_generic_write_seq(dsi, 0x35, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0x51, 0x05, 0x42);
-
- ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
- if (ret < 0) {
- dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
- return ret;
- }
- msleep(100);
-
- ret = mipi_dsi_dcs_set_display_on(dsi);
- if (ret < 0) {
- dev_err(dev, "Failed to set display on: %d\n", ret);
- return ret;
- }
-
- return 0;
+ dsi_ctx->dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xfe, 0x41);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xd6, 0x00);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xfe, 0x16);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x8a, 0x87);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xfe, 0x71);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x82, 0x01);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xc6, 0x00);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xc7, 0x2c);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xc8, 0x64);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xc9, 0x3c);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xca, 0x80);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xcb, 0x02);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xcc, 0x02);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xfe, 0x38);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x18, 0x13);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xfe, 0xf4);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x00, 0xff);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x01, 0xff);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x02, 0xcf);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x03, 0xbc);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x04, 0xb9);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x05, 0x99);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x06, 0x02);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x07, 0x0a);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x08, 0xe0);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x09, 0x4c);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x0a, 0xeb);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x0b, 0xe8);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x0c, 0x32);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x0d, 0x07);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xfe, 0xf4);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x0d, 0xc0);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x0e, 0xff);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x0f, 0xff);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x10, 0x33);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x11, 0x6f);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x12, 0x6e);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x13, 0xa6);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x14, 0x80);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x15, 0x02);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x16, 0x38);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x17, 0xd3);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x18, 0x3a);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x19, 0xba);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x1a, 0xcc);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x1b, 0x01);
+
+ mipi_dsi_dcs_nop_multi(dsi_ctx);
+
+ mipi_dsi_msleep(dsi_ctx, 32);
+
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xfe, 0x38);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x18, 0x13);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xfe, 0xd1);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xd3, 0x00);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xd0, 0x00);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xd2, 0x00);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xd4, 0x00);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xb4, 0x01);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xfe, 0xf9);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x00, 0xaf);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x1d, 0x37);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x44, 0x0a, 0x7b);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xfe, 0x00);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xfa, 0x01);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xc2, 0x08);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x35, 0x00);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x51, 0x05, 0x42);
+
+ mipi_dsi_dcs_exit_sleep_mode_multi(dsi_ctx);
+ mipi_dsi_msleep(dsi_ctx, 100);
+ mipi_dsi_dcs_set_display_on_multi(dsi_ctx);
}
static int rm692e5_disable(struct drm_panel *panel)
{
struct rm692e5_panel *ctx = to_rm692e5_panel(panel);
struct mipi_dsi_device *dsi = ctx->dsi;
- struct device *dev = &dsi->dev;
- int ret;
+ struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
- mipi_dsi_generic_write_seq(dsi, 0xfe, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xfe, 0x00);
- ret = mipi_dsi_dcs_set_display_off(dsi);
- if (ret < 0) {
- dev_err(dev, "Failed to set display off: %d\n", ret);
- return ret;
- }
+ mipi_dsi_dcs_set_display_off_multi(&dsi_ctx);
- ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
- if (ret < 0) {
- dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
- return ret;
- }
- msleep(100);
+ mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx);
- return 0;
+ mipi_dsi_msleep(&dsi_ctx, 100);
+
+ return dsi_ctx.accum_err;
}
static int rm692e5_prepare(struct drm_panel *panel)
{
struct rm692e5_panel *ctx = to_rm692e5_panel(panel);
struct drm_dsc_picture_parameter_set pps;
- struct device *dev = &ctx->dsi->dev;
- int ret;
-
- if (ctx->prepared)
- return 0;
+ struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi };
- ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
- if (ret < 0) {
- dev_err(dev, "Failed to enable regulators: %d\n", ret);
- return ret;
- }
+ dsi_ctx.accum_err = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+ if (dsi_ctx.accum_err)
+ return dsi_ctx.accum_err;
rm692e5_reset(ctx);
- ret = rm692e5_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(ctx->supplies), ctx->supplies);
- return ret;
- }
+ rm692e5_on(&dsi_ctx);
drm_dsc_pps_payload_pack(&pps, &ctx->dsc);
- ret = mipi_dsi_picture_parameter_set(ctx->dsi, &pps);
- if (ret < 0) {
- dev_err(panel->dev, "failed to transmit PPS: %d\n", ret);
- return ret;
- }
-
- ret = mipi_dsi_compression_mode(ctx->dsi, true);
- if (ret < 0) {
- dev_err(dev, "failed to enable compression mode: %d\n", ret);
- return ret;
- }
+ mipi_dsi_picture_parameter_set_multi(&dsi_ctx, &pps);
+ mipi_dsi_compression_mode_ext_multi(&dsi_ctx, true, MIPI_DSI_COMPRESSION_DSC, 0);
+ mipi_dsi_msleep(&dsi_ctx, 28);
- msleep(28);
-
- mipi_dsi_generic_write_seq(ctx->dsi, 0xfe, 0x40);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xfe, 0x40);
/* 0x05 -> 90Hz, 0x00 -> 60Hz */
- mipi_dsi_generic_write_seq(ctx->dsi, 0xbd, 0x05);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbd, 0x05);
- mipi_dsi_generic_write_seq(ctx->dsi, 0xfe, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xfe, 0x00);
- ctx->prepared = true;
+ if (dsi_ctx.accum_err) {
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+ regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+ }
- return 0;
+ return dsi_ctx.accum_err;
}
static int rm692e5_unprepare(struct drm_panel *panel)
{
struct rm692e5_panel *ctx = to_rm692e5_panel(panel);
- if (!ctx->prepared)
- return 0;
-
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
- ctx->prepared = false;
return 0;
}
diff --git a/drivers/gpu/drm/panel/panel-samsung-atna33xc20.c b/drivers/gpu/drm/panel/panel-samsung-atna33xc20.c
index a9f0d214a900..9a482a744b8c 100644
--- a/drivers/gpu/drm/panel/panel-samsung-atna33xc20.c
+++ b/drivers/gpu/drm/panel/panel-samsung-atna33xc20.c
@@ -25,8 +25,6 @@
struct atana33xc20_panel {
struct drm_panel base;
- bool prepared;
- bool enabled;
bool el3_was_on;
bool no_hpd;
@@ -143,13 +141,8 @@ static int atana33xc20_disable(struct drm_panel *panel)
{
struct atana33xc20_panel *p = to_atana33xc20(panel);
- /* Disabling when already disabled is a no-op */
- if (!p->enabled)
- return 0;
-
gpiod_set_value_cansleep(p->el_on3_gpio, 0);
p->el_on3_off_time = ktime_get_boottime();
- p->enabled = false;
/*
* Keep track of the fact that EL_ON3 was on but we haven't power
@@ -173,10 +166,6 @@ static int atana33xc20_enable(struct drm_panel *panel)
{
struct atana33xc20_panel *p = to_atana33xc20(panel);
- /* Enabling when already enabled is a no-op */
- if (p->enabled)
- return 0;
-
/*
* Once EL_ON3 drops we absolutely need a power cycle before the next
* enable or the backlight will never come on again. The code ensures
@@ -195,20 +184,14 @@ static int atana33xc20_enable(struct drm_panel *panel)
atana33xc20_wait(p->powered_on_time, 400);
gpiod_set_value_cansleep(p->el_on3_gpio, 1);
- p->enabled = true;
return 0;
}
static int atana33xc20_unprepare(struct drm_panel *panel)
{
- struct atana33xc20_panel *p = to_atana33xc20(panel);
int ret;
- /* Unpreparing when already unprepared is a no-op */
- if (!p->prepared)
- return 0;
-
/*
* Purposely do a put_sync, don't use autosuspend. The panel's tcon
* seems to sometimes crash when you stop giving it data and this is
@@ -220,26 +203,19 @@ static int atana33xc20_unprepare(struct drm_panel *panel)
ret = pm_runtime_put_sync_suspend(panel->dev);
if (ret < 0)
return ret;
- p->prepared = false;
return 0;
}
static int atana33xc20_prepare(struct drm_panel *panel)
{
- struct atana33xc20_panel *p = to_atana33xc20(panel);
int ret;
- /* Preparing when already prepared is a no-op */
- if (p->prepared)
- return 0;
-
ret = pm_runtime_get_sync(panel->dev);
if (ret < 0) {
pm_runtime_put_autosuspend(panel->dev);
return ret;
}
- p->prepared = true;
return 0;
}
@@ -351,21 +327,10 @@ static void atana33xc20_remove(struct dp_aux_ep_device *aux_ep)
struct atana33xc20_panel *panel = dev_get_drvdata(dev);
drm_panel_remove(&panel->base);
- drm_panel_disable(&panel->base);
- drm_panel_unprepare(&panel->base);
drm_edid_free(panel->drm_edid);
}
-static void atana33xc20_shutdown(struct dp_aux_ep_device *aux_ep)
-{
- struct device *dev = &aux_ep->dev;
- struct atana33xc20_panel *panel = dev_get_drvdata(dev);
-
- drm_panel_disable(&panel->base);
- drm_panel_unprepare(&panel->base);
-}
-
static const struct of_device_id atana33xc20_dt_match[] = {
{ .compatible = "samsung,atna33xc20", },
{ /* sentinal */ }
@@ -386,7 +351,6 @@ static struct dp_aux_ep_driver atana33xc20_driver = {
},
.probe = atana33xc20_probe,
.remove = atana33xc20_remove,
- .shutdown = atana33xc20_shutdown,
};
static int __init atana33xc20_init(void)
diff --git a/drivers/gpu/drm/panel/panel-seiko-43wvf1g.c b/drivers/gpu/drm/panel/panel-seiko-43wvf1g.c
index 658c7c040570..8a3fe531c641 100644
--- a/drivers/gpu/drm/panel/panel-seiko-43wvf1g.c
+++ b/drivers/gpu/drm/panel/panel-seiko-43wvf1g.c
@@ -44,8 +44,6 @@ struct seiko_panel_desc {
struct seiko_panel {
struct drm_panel base;
- bool prepared;
- bool enabled;
const struct seiko_panel_desc *desc;
struct regulator *dvdd;
struct regulator *avdd;
@@ -122,25 +120,10 @@ static int seiko_panel_get_fixed_modes(struct seiko_panel *panel,
return num;
}
-static int seiko_panel_disable(struct drm_panel *panel)
-{
- struct seiko_panel *p = to_seiko_panel(panel);
-
- if (!p->enabled)
- return 0;
-
- p->enabled = false;
-
- return 0;
-}
-
static int seiko_panel_unprepare(struct drm_panel *panel)
{
struct seiko_panel *p = to_seiko_panel(panel);
- if (!p->prepared)
- return 0;
-
gpiod_set_value_cansleep(p->enable_gpio, 0);
regulator_disable(p->avdd);
@@ -150,8 +133,6 @@ static int seiko_panel_unprepare(struct drm_panel *panel)
regulator_disable(p->dvdd);
- p->prepared = false;
-
return 0;
}
@@ -160,9 +141,6 @@ static int seiko_panel_prepare(struct drm_panel *panel)
struct seiko_panel *p = to_seiko_panel(panel);
int err;
- if (p->prepared)
- return 0;
-
err = regulator_enable(p->dvdd);
if (err < 0) {
dev_err(panel->dev, "failed to enable dvdd: %d\n", err);
@@ -180,8 +158,6 @@ static int seiko_panel_prepare(struct drm_panel *panel)
gpiod_set_value_cansleep(p->enable_gpio, 1);
- p->prepared = true;
-
return 0;
disable_dvdd:
@@ -189,18 +165,6 @@ disable_dvdd:
return err;
}
-static int seiko_panel_enable(struct drm_panel *panel)
-{
- struct seiko_panel *p = to_seiko_panel(panel);
-
- if (p->enabled)
- return 0;
-
- p->enabled = true;
-
- return 0;
-}
-
static int seiko_panel_get_modes(struct drm_panel *panel,
struct drm_connector *connector)
{
@@ -228,10 +192,8 @@ static int seiko_panel_get_timings(struct drm_panel *panel,
}
static const struct drm_panel_funcs seiko_panel_funcs = {
- .disable = seiko_panel_disable,
.unprepare = seiko_panel_unprepare,
.prepare = seiko_panel_prepare,
- .enable = seiko_panel_enable,
.get_modes = seiko_panel_get_modes,
.get_timings = seiko_panel_get_timings,
};
@@ -246,8 +208,6 @@ static int seiko_panel_probe(struct device *dev,
if (!panel)
return -ENOMEM;
- panel->enabled = false;
- panel->prepared = false;
panel->desc = desc;
panel->dvdd = devm_regulator_get(dev, "dvdd");
@@ -283,14 +243,6 @@ static void seiko_panel_remove(struct platform_device *pdev)
struct seiko_panel *panel = platform_get_drvdata(pdev);
drm_panel_remove(&panel->base);
- drm_panel_disable(&panel->base);
-}
-
-static void seiko_panel_shutdown(struct platform_device *pdev)
-{
- struct seiko_panel *panel = platform_get_drvdata(pdev);
-
- drm_panel_disable(&panel->base);
}
static const struct display_timing seiko_43wvf1g_timing = {
@@ -346,7 +298,6 @@ static struct platform_driver seiko_panel_platform_driver = {
},
.probe = seiko_panel_platform_probe,
.remove_new = seiko_panel_remove,
- .shutdown = seiko_panel_shutdown,
};
module_platform_driver(seiko_panel_platform_driver);
diff --git a/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c b/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
index 14851408a5e1..a0d76d588da1 100644
--- a/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
+++ b/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
@@ -24,9 +24,6 @@ struct sharp_panel {
struct regulator *supply;
- bool prepared;
- bool enabled;
-
const struct drm_display_mode *mode;
};
@@ -85,26 +82,11 @@ static __maybe_unused int sharp_panel_read(struct sharp_panel *sharp,
return err;
}
-static int sharp_panel_disable(struct drm_panel *panel)
-{
- struct sharp_panel *sharp = to_sharp_panel(panel);
-
- if (!sharp->enabled)
- return 0;
-
- sharp->enabled = false;
-
- return 0;
-}
-
static int sharp_panel_unprepare(struct drm_panel *panel)
{
struct sharp_panel *sharp = to_sharp_panel(panel);
int err;
- if (!sharp->prepared)
- return 0;
-
sharp_wait_frames(sharp, 4);
err = mipi_dsi_dcs_set_display_off(sharp->link1);
@@ -119,8 +101,6 @@ static int sharp_panel_unprepare(struct drm_panel *panel)
regulator_disable(sharp->supply);
- sharp->prepared = false;
-
return 0;
}
@@ -164,9 +144,6 @@ static int sharp_panel_prepare(struct drm_panel *panel)
u8 format = MIPI_DCS_PIXEL_FMT_24BIT;
int err;
- if (sharp->prepared)
- return 0;
-
err = regulator_enable(sharp->supply);
if (err < 0)
return err;
@@ -235,8 +212,6 @@ static int sharp_panel_prepare(struct drm_panel *panel)
goto poweroff;
}
- sharp->prepared = true;
-
/* wait for 6 frames before continuing */
sharp_wait_frames(sharp, 6);
@@ -247,18 +222,6 @@ poweroff:
return err;
}
-static int sharp_panel_enable(struct drm_panel *panel)
-{
- struct sharp_panel *sharp = to_sharp_panel(panel);
-
- if (sharp->enabled)
- return 0;
-
- sharp->enabled = true;
-
- return 0;
-}
-
static const struct drm_display_mode default_mode = {
.clock = 278000,
.hdisplay = 2560,
@@ -295,10 +258,8 @@ static int sharp_panel_get_modes(struct drm_panel *panel,
}
static const struct drm_panel_funcs sharp_panel_funcs = {
- .disable = sharp_panel_disable,
.unprepare = sharp_panel_unprepare,
.prepare = sharp_panel_prepare,
- .enable = sharp_panel_enable,
.get_modes = sharp_panel_get_modes,
};
@@ -396,32 +357,13 @@ static void sharp_panel_remove(struct mipi_dsi_device *dsi)
struct sharp_panel *sharp = mipi_dsi_get_drvdata(dsi);
int err;
- /* only detach from host for the DSI-LINK2 interface */
- if (!sharp) {
- mipi_dsi_detach(dsi);
- return;
- }
-
- err = drm_panel_disable(&sharp->base);
- if (err < 0)
- dev_err(&dsi->dev, "failed to disable panel: %d\n", err);
-
err = mipi_dsi_detach(dsi);
if (err < 0)
dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err);
- sharp_panel_del(sharp);
-}
-
-static void sharp_panel_shutdown(struct mipi_dsi_device *dsi)
-{
- struct sharp_panel *sharp = mipi_dsi_get_drvdata(dsi);
-
- /* nothing to do for DSI-LINK2 */
- if (!sharp)
- return;
-
- drm_panel_disable(&sharp->base);
+ /* only detach from host for the DSI-LINK2 interface */
+ if (sharp)
+ sharp_panel_del(sharp);
}
static struct mipi_dsi_driver sharp_panel_driver = {
@@ -431,7 +373,6 @@ static struct mipi_dsi_driver sharp_panel_driver = {
},
.probe = sharp_panel_probe,
.remove = sharp_panel_remove,
- .shutdown = sharp_panel_shutdown,
};
module_mipi_dsi_driver(sharp_panel_driver);
diff --git a/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c b/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c
index 855e64444daa..729cbb0d8403 100644
--- a/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c
+++ b/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c
@@ -26,8 +26,6 @@ struct sharp_nt_panel {
struct regulator *supply;
struct gpio_desc *reset_gpio;
-
- bool prepared;
};
static inline struct sharp_nt_panel *to_sharp_nt_panel(struct drm_panel *panel)
@@ -99,9 +97,6 @@ static int sharp_nt_panel_unprepare(struct drm_panel *panel)
struct sharp_nt_panel *sharp_nt = to_sharp_nt_panel(panel);
int ret;
- if (!sharp_nt->prepared)
- return 0;
-
ret = sharp_nt_panel_off(sharp_nt);
if (ret < 0) {
dev_err(panel->dev, "failed to set panel off: %d\n", ret);
@@ -112,8 +107,6 @@ static int sharp_nt_panel_unprepare(struct drm_panel *panel)
if (sharp_nt->reset_gpio)
gpiod_set_value(sharp_nt->reset_gpio, 0);
- sharp_nt->prepared = false;
-
return 0;
}
@@ -122,9 +115,6 @@ static int sharp_nt_panel_prepare(struct drm_panel *panel)
struct sharp_nt_panel *sharp_nt = to_sharp_nt_panel(panel);
int ret;
- if (sharp_nt->prepared)
- return 0;
-
ret = regulator_enable(sharp_nt->supply);
if (ret < 0)
return ret;
@@ -152,8 +142,6 @@ static int sharp_nt_panel_prepare(struct drm_panel *panel)
goto poweroff;
}
- sharp_nt->prepared = true;
-
return 0;
poweroff:
@@ -279,10 +267,6 @@ static void sharp_nt_panel_remove(struct mipi_dsi_device *dsi)
struct sharp_nt_panel *sharp_nt = mipi_dsi_get_drvdata(dsi);
int ret;
- ret = drm_panel_disable(&sharp_nt->base);
- if (ret < 0)
- dev_err(&dsi->dev, "failed to disable panel: %d\n", ret);
-
ret = mipi_dsi_detach(dsi);
if (ret < 0)
dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret);
@@ -290,13 +274,6 @@ static void sharp_nt_panel_remove(struct mipi_dsi_device *dsi)
sharp_nt_panel_del(sharp_nt);
}
-static void sharp_nt_panel_shutdown(struct mipi_dsi_device *dsi)
-{
- struct sharp_nt_panel *sharp_nt = mipi_dsi_get_drvdata(dsi);
-
- drm_panel_disable(&sharp_nt->base);
-}
-
static const struct of_device_id sharp_nt_of_match[] = {
{ .compatible = "sharp,ls043t1le01-qhd", },
{ }
@@ -310,7 +287,6 @@ static struct mipi_dsi_driver sharp_nt_panel_driver = {
},
.probe = sharp_nt_panel_probe,
.remove = sharp_nt_panel_remove,
- .shutdown = sharp_nt_panel_shutdown,
};
module_mipi_dsi_driver(sharp_nt_panel_driver);
diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
index dcb6d0b6ced0..bf40057c5cf3 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -138,9 +138,6 @@ struct panel_desc {
struct panel_simple {
struct drm_panel base;
- bool enabled;
-
- bool prepared;
ktime_t unprepared_time;
@@ -290,14 +287,9 @@ static int panel_simple_disable(struct drm_panel *panel)
{
struct panel_simple *p = to_panel_simple(panel);
- if (!p->enabled)
- return 0;
-
if (p->desc->delay.disable)
msleep(p->desc->delay.disable);
- p->enabled = false;
-
return 0;
}
@@ -317,18 +309,12 @@ static int panel_simple_suspend(struct device *dev)
static int panel_simple_unprepare(struct drm_panel *panel)
{
- struct panel_simple *p = to_panel_simple(panel);
int ret;
- /* Unpreparing when already unprepared is a no-op */
- if (!p->prepared)
- return 0;
-
pm_runtime_mark_last_busy(panel->dev);
ret = pm_runtime_put_autosuspend(panel->dev);
if (ret < 0)
return ret;
- p->prepared = false;
return 0;
}
@@ -356,21 +342,14 @@ static int panel_simple_resume(struct device *dev)
static int panel_simple_prepare(struct drm_panel *panel)
{
- struct panel_simple *p = to_panel_simple(panel);
int ret;
- /* Preparing when already prepared is a no-op */
- if (p->prepared)
- return 0;
-
ret = pm_runtime_get_sync(panel->dev);
if (ret < 0) {
pm_runtime_put_autosuspend(panel->dev);
return ret;
}
- p->prepared = true;
-
return 0;
}
@@ -378,14 +357,9 @@ static int panel_simple_enable(struct drm_panel *panel)
{
struct panel_simple *p = to_panel_simple(panel);
- if (p->enabled)
- return 0;
-
if (p->desc->delay.enable)
msleep(p->desc->delay.enable);
- p->enabled = true;
-
return 0;
}
@@ -609,7 +583,6 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc)
if (!panel)
return -ENOMEM;
- panel->enabled = false;
panel->desc = desc;
panel->supply = devm_regulator_get(dev, "power");
@@ -743,26 +716,39 @@ free_ddc:
return err;
}
-static void panel_simple_remove(struct device *dev)
+static void panel_simple_shutdown(struct device *dev)
{
struct panel_simple *panel = dev_get_drvdata(dev);
- drm_panel_remove(&panel->base);
+ /*
+ * NOTE: the following two calls don't really belong here. It is the
+ * responsibility of a correctly written DRM modeset driver to call
+ * drm_atomic_helper_shutdown() at shutdown time and that should
+ * cause the panel to be disabled / unprepared if needed. For now,
+ * however, we'll keep these calls due to the sheer number of
+ * different DRM modeset drivers used with panel-simple. The fact that
+ * we're calling these and _also_ the drm_atomic_helper_shutdown()
+ * will try to disable/unprepare means that we can get a warning about
+ * trying to disable/unprepare an already disabled/unprepared panel,
+ * but that's something we'll have to live with until we've confirmed
+ * that all DRM modeset drivers are properly calling
+ * drm_atomic_helper_shutdown().
+ */
drm_panel_disable(&panel->base);
drm_panel_unprepare(&panel->base);
-
- pm_runtime_dont_use_autosuspend(dev);
- pm_runtime_disable(dev);
- if (panel->ddc)
- put_device(&panel->ddc->dev);
}
-static void panel_simple_shutdown(struct device *dev)
+static void panel_simple_remove(struct device *dev)
{
struct panel_simple *panel = dev_get_drvdata(dev);
- drm_panel_disable(&panel->base);
- drm_panel_unprepare(&panel->base);
+ drm_panel_remove(&panel->base);
+ panel_simple_shutdown(dev);
+
+ pm_runtime_dont_use_autosuspend(dev);
+ pm_runtime_disable(dev);
+ if (panel->ddc)
+ put_device(&panel->ddc->dev);
}
static const struct drm_display_mode ampire_am_1280800n3tzqw_t00h_mode = {
@@ -1081,6 +1067,30 @@ static const struct panel_desc auo_g104sn02 = {
.connector_type = DRM_MODE_CONNECTOR_LVDS,
};
+static const struct drm_display_mode auo_g104stn01_mode = {
+ .clock = 40000,
+ .hdisplay = 800,
+ .hsync_start = 800 + 40,
+ .hsync_end = 800 + 40 + 88,
+ .htotal = 800 + 40 + 88 + 128,
+ .vdisplay = 600,
+ .vsync_start = 600 + 1,
+ .vsync_end = 600 + 1 + 23,
+ .vtotal = 600 + 1 + 23 + 4,
+};
+
+static const struct panel_desc auo_g104stn01 = {
+ .modes = &auo_g104stn01_mode,
+ .num_modes = 1,
+ .bpc = 8,
+ .size = {
+ .width = 211,
+ .height = 158,
+ },
+ .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+ .connector_type = DRM_MODE_CONNECTOR_LVDS,
+};
+
static const struct display_timing auo_g121ean01_timing = {
.pixelclock = { 60000000, 74400000, 90000000 },
.hactive = { 1280, 1280, 1280 },
@@ -2752,6 +2762,7 @@ static const struct display_timing koe_tx26d202vm0bwa_timing = {
.vfront_porch = { 3, 5, 10 },
.vback_porch = { 2, 5, 10 },
.vsync_len = { 5, 5, 5 },
+ .flags = DISPLAY_FLAGS_DE_HIGH,
};
static const struct panel_desc koe_tx26d202vm0bwa = {
@@ -2870,6 +2881,35 @@ static const struct panel_desc lg_lb070wv8 = {
.connector_type = DRM_MODE_CONNECTOR_LVDS,
};
+static const struct drm_display_mode lincolntech_lcd185_101ct_mode = {
+ .clock = 155127,
+ .hdisplay = 1920,
+ .hsync_start = 1920 + 128,
+ .hsync_end = 1920 + 128 + 20,
+ .htotal = 1920 + 128 + 20 + 12,
+ .vdisplay = 1200,
+ .vsync_start = 1200 + 19,
+ .vsync_end = 1200 + 19 + 4,
+ .vtotal = 1200 + 19 + 4 + 20,
+};
+
+static const struct panel_desc lincolntech_lcd185_101ct = {
+ .modes = &lincolntech_lcd185_101ct_mode,
+ .bpc = 8,
+ .num_modes = 1,
+ .size = {
+ .width = 217,
+ .height = 136,
+ },
+ .delay = {
+ .prepare = 50,
+ .disable = 50,
+ },
+ .bus_flags = DRM_BUS_FLAG_DE_HIGH,
+ .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+ .connector_type = DRM_MODE_CONNECTOR_LVDS,
+};
+
static const struct display_timing logictechno_lt161010_2nh_timing = {
.pixelclock = { 26400000, 33300000, 46800000 },
.hactive = { 800, 800, 800 },
@@ -3026,6 +3066,64 @@ static const struct panel_desc logicpd_type_28 = {
.connector_type = DRM_MODE_CONNECTOR_DPI,
};
+static const struct drm_display_mode microtips_mf_101hiebcaf0_c_mode = {
+ .clock = 150275,
+ .hdisplay = 1920,
+ .hsync_start = 1920 + 32,
+ .hsync_end = 1920 + 32 + 52,
+ .htotal = 1920 + 32 + 52 + 24,
+ .vdisplay = 1200,
+ .vsync_start = 1200 + 24,
+ .vsync_end = 1200 + 24 + 8,
+ .vtotal = 1200 + 24 + 8 + 3,
+};
+
+static const struct panel_desc microtips_mf_101hiebcaf0_c = {
+ .modes = &microtips_mf_101hiebcaf0_c_mode,
+ .bpc = 8,
+ .num_modes = 1,
+ .size = {
+ .width = 217,
+ .height = 136,
+ },
+ .delay = {
+ .prepare = 50,
+ .disable = 50,
+ },
+ .bus_flags = DRM_BUS_FLAG_DE_HIGH,
+ .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+ .connector_type = DRM_MODE_CONNECTOR_LVDS,
+};
+
+static const struct drm_display_mode microtips_mf_103hieb0ga0_mode = {
+ .clock = 93301,
+ .hdisplay = 1920,
+ .hsync_start = 1920 + 72,
+ .hsync_end = 1920 + 72 + 72,
+ .htotal = 1920 + 72 + 72 + 72,
+ .vdisplay = 720,
+ .vsync_start = 720 + 3,
+ .vsync_end = 720 + 3 + 3,
+ .vtotal = 720 + 3 + 3 + 2,
+};
+
+static const struct panel_desc microtips_mf_103hieb0ga0 = {
+ .modes = &microtips_mf_103hieb0ga0_mode,
+ .bpc = 8,
+ .num_modes = 1,
+ .size = {
+ .width = 244,
+ .height = 92,
+ },
+ .delay = {
+ .prepare = 50,
+ .disable = 50,
+ },
+ .bus_flags = DRM_BUS_FLAG_DE_HIGH,
+ .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+ .connector_type = DRM_MODE_CONNECTOR_LVDS,
+};
+
static const struct drm_display_mode mitsubishi_aa070mc01_mode = {
.clock = 30400,
.hdisplay = 800,
@@ -3567,6 +3665,32 @@ static const struct panel_desc powertip_ph800480t013_idf02 = {
.connector_type = DRM_MODE_CONNECTOR_DPI,
};
+static const struct drm_display_mode primeview_pm070wl4_mode = {
+ .clock = 32000,
+ .hdisplay = 800,
+ .hsync_start = 800 + 42,
+ .hsync_end = 800 + 42 + 128,
+ .htotal = 800 + 42 + 128 + 86,
+ .vdisplay = 480,
+ .vsync_start = 480 + 10,
+ .vsync_end = 480 + 10 + 2,
+ .vtotal = 480 + 10 + 2 + 33,
+ .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
+};
+
+static const struct panel_desc primeview_pm070wl4 = {
+ .modes = &primeview_pm070wl4_mode,
+ .num_modes = 1,
+ .bpc = 6,
+ .size = {
+ .width = 152,
+ .height = 91,
+ },
+ .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE,
+ .bus_format = MEDIA_BUS_FMT_RGB666_1X18,
+ .connector_type = DRM_MODE_CONNECTOR_DPI,
+};
+
static const struct drm_display_mode qd43003c0_40_mode = {
.clock = 9000,
.hdisplay = 480,
@@ -4435,6 +4559,9 @@ static const struct of_device_id platform_of_match[] = {
.compatible = "auo,g104sn02",
.data = &auo_g104sn02,
}, {
+ .compatible = "auo,g104stn01",
+ .data = &auo_g104stn01,
+ }, {
.compatible = "auo,g121ean01",
.data = &auo_g121ean01,
}, {
@@ -4645,6 +4772,9 @@ static const struct of_device_id platform_of_match[] = {
.compatible = "lg,lb070wv8",
.data = &lg_lb070wv8,
}, {
+ .compatible = "lincolntech,lcd185-101ct",
+ .data = &lincolntech_lcd185_101ct,
+ }, {
.compatible = "logicpd,type28",
.data = &logicpd_type_28,
}, {
@@ -4663,6 +4793,12 @@ static const struct of_device_id platform_of_match[] = {
.compatible = "logictechno,lttd800480070-l6wh-rt",
.data = &logictechno_lttd800480070_l6wh_rt,
}, {
+ .compatible = "microtips,mf-101hiebcaf0",
+ .data = &microtips_mf_101hiebcaf0_c,
+ }, {
+ .compatible = "microtips,mf-103hieb0ga0",
+ .data = &microtips_mf_103hieb0ga0,
+ }, {
.compatible = "mitsubishi,aa070mc01-ca1",
.data = &mitsubishi_aa070mc01,
}, {
@@ -4726,6 +4862,9 @@ static const struct of_device_id platform_of_match[] = {
.compatible = "powertip,ph800480t013-idf02",
.data = &powertip_ph800480t013_idf02,
}, {
+ .compatible = "primeview,pm070wl4",
+ .data = &primeview_pm070wl4,
+ }, {
.compatible = "qiaodian,qd43003c0-40",
.data = &qd43003c0_40,
}, {
diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7703.c b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
index 7d8302cca091..67e8e45498cb 100644
--- a/drivers/gpu/drm/panel/panel-sitronix-st7703.c
+++ b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
@@ -58,7 +58,6 @@ struct st7703 {
struct gpio_desc *reset_gpio;
struct regulator *vcc;
struct regulator *iovcc;
- bool prepared;
struct dentry *debugfs;
const struct st7703_panel_desc *desc;
@@ -70,7 +69,7 @@ struct st7703_panel_desc {
unsigned int lanes;
unsigned long mode_flags;
enum mipi_dsi_pixel_format format;
- int (*init_sequence)(struct st7703 *ctx);
+ void (*init_sequence)(struct mipi_dsi_multi_context *dsi_ctx);
};
static inline struct st7703 *panel_to_st7703(struct drm_panel *panel)
@@ -78,62 +77,58 @@ static inline struct st7703 *panel_to_st7703(struct drm_panel *panel)
return container_of(panel, struct st7703, panel);
}
-static int jh057n_init_sequence(struct st7703 *ctx)
+static void jh057n_init_sequence(struct mipi_dsi_multi_context *dsi_ctx)
{
- struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
-
/*
* Init sequence was supplied by the panel vendor. Most of the commands
* resemble the ST7703 but the number of parameters often don't match
* so it's likely a clone.
*/
- mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETEXTC,
- 0xF1, 0x12, 0x83);
- mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETRGBIF,
- 0x10, 0x10, 0x05, 0x05, 0x03, 0xFF, 0x00, 0x00,
- 0x00, 0x00);
- mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETSCR,
- 0x73, 0x73, 0x50, 0x50, 0x00, 0x00, 0x08, 0x70,
- 0x00);
- mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETVDC, 0x4E);
- mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0B);
- mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETCYC, 0x80);
- mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETDISP, 0xF0, 0x12, 0x30);
- mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETEQ,
- 0x07, 0x07, 0x0B, 0x0B, 0x03, 0x0B, 0x00, 0x00,
- 0x00, 0x00, 0xFF, 0x00, 0xC0, 0x10);
- mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETBGP, 0x08, 0x08);
- msleep(20);
-
- mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETVCOM, 0x3F, 0x3F);
- mipi_dsi_generic_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
- mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETGIP1,
- 0x82, 0x10, 0x06, 0x05, 0x9E, 0x0A, 0xA5, 0x12,
- 0x31, 0x23, 0x37, 0x83, 0x04, 0xBC, 0x27, 0x38,
- 0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x75, 0x75, 0x31, 0x88,
- 0x88, 0x88, 0x88, 0x88, 0x88, 0x13, 0x88, 0x64,
- 0x64, 0x20, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
- 0x02, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
- mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETGIP2,
- 0x02, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x02, 0x46, 0x02, 0x88,
- 0x88, 0x88, 0x88, 0x88, 0x88, 0x64, 0x88, 0x13,
- 0x57, 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
- 0x75, 0x88, 0x23, 0x14, 0x00, 0x00, 0x02, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0A,
- 0xA5, 0x00, 0x00, 0x00, 0x00);
- mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETGAMMA,
- 0x00, 0x09, 0x0E, 0x29, 0x2D, 0x3C, 0x41, 0x37,
- 0x07, 0x0B, 0x0D, 0x10, 0x11, 0x0F, 0x10, 0x11,
- 0x18, 0x00, 0x09, 0x0E, 0x29, 0x2D, 0x3C, 0x41,
- 0x37, 0x07, 0x0B, 0x0D, 0x10, 0x11, 0x0F, 0x10,
- 0x11, 0x18);
- msleep(20);
-
- return 0;
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETEXTC,
+ 0xF1, 0x12, 0x83);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETRGBIF,
+ 0x10, 0x10, 0x05, 0x05, 0x03, 0xFF, 0x00, 0x00,
+ 0x00, 0x00);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETSCR,
+ 0x73, 0x73, 0x50, 0x50, 0x00, 0x00, 0x08, 0x70,
+ 0x00);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETVDC, 0x4E);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETPANEL, 0x0B);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETCYC, 0x80);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETDISP, 0xF0, 0x12, 0x30);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETEQ,
+ 0x07, 0x07, 0x0B, 0x0B, 0x03, 0x0B, 0x00, 0x00,
+ 0x00, 0x00, 0xFF, 0x00, 0xC0, 0x10);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETBGP, 0x08, 0x08);
+ mipi_dsi_msleep(dsi_ctx, 20);
+
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETVCOM, 0x3F, 0x3F);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP1,
+ 0x82, 0x10, 0x06, 0x05, 0x9E, 0x0A, 0xA5, 0x12,
+ 0x31, 0x23, 0x37, 0x83, 0x04, 0xBC, 0x27, 0x38,
+ 0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x75, 0x75, 0x31, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x13, 0x88, 0x64,
+ 0x64, 0x20, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x02, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP2,
+ 0x02, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x46, 0x02, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x64, 0x88, 0x13,
+ 0x57, 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x75, 0x88, 0x23, 0x14, 0x00, 0x00, 0x02, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0A,
+ 0xA5, 0x00, 0x00, 0x00, 0x00);
+ mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETGAMMA,
+ 0x00, 0x09, 0x0E, 0x29, 0x2D, 0x3C, 0x41, 0x37,
+ 0x07, 0x0B, 0x0D, 0x10, 0x11, 0x0F, 0x10, 0x11,
+ 0x18, 0x00, 0x09, 0x0E, 0x29, 0x2D, 0x3C, 0x41,
+ 0x37, 0x07, 0x0B, 0x0D, 0x10, 0x11, 0x0F, 0x10,
+ 0x11, 0x18);
+ mipi_dsi_msleep(dsi_ctx, 20);
}
static const struct drm_display_mode jh057n00900_mode = {
@@ -160,163 +155,159 @@ static const struct st7703_panel_desc jh057n00900_panel_desc = {
.init_sequence = jh057n_init_sequence,
};
-static int xbd599_init_sequence(struct st7703 *ctx)
+static void xbd599_init_sequence(struct mipi_dsi_multi_context *dsi_ctx)
{
- struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
-
/*
* Init sequence was supplied by the panel vendor.
*/
/* Magic sequence to unlock user commands below. */
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEXTC, 0xF1, 0x12, 0x83);
-
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETMIPI,
- 0x33, /* VC_main = 0, Lane_Number = 3 (4 lanes) */
- 0x81, /* DSI_LDO_SEL = 1.7V, RTERM = 90 Ohm */
- 0x05, /* IHSRX = x6 (Low High Speed driving ability) */
- 0xF9, /* TX_CLK_SEL = fDSICLK/16 */
- 0x0E, /* HFP_OSC (min. HFP number in DSI mode) */
- 0x0E, /* HBP_OSC (min. HBP number in DSI mode) */
- /* The rest is undocumented in ST7703 datasheet */
- 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x44, 0x25, 0x00, 0x91, 0x0a, 0x00, 0x00, 0x02,
- 0x4F, 0x11, 0x00, 0x00, 0x37);
-
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER_EXT,
- 0x25, /* PCCS = 2, ECP_DC_DIV = 1/4 HSYNC */
- 0x22, /* DT = 15ms XDK_ECP = x2 */
- 0x20, /* PFM_DC_DIV = /1 */
- 0x03 /* ECP_SYNC_EN = 1, VGX_SYNC_EN = 1 */);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEXTC, 0xF1, 0x12, 0x83);
+
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETMIPI,
+ 0x33, /* VC_main = 0, Lane_Number = 3 (4 lanes) */
+ 0x81, /* DSI_LDO_SEL = 1.7V, RTERM = 90 Ohm */
+ 0x05, /* IHSRX = x6 (Low High Speed driving ability) */
+ 0xF9, /* TX_CLK_SEL = fDSICLK/16 */
+ 0x0E, /* HFP_OSC (min. HFP number in DSI mode) */
+ 0x0E, /* HBP_OSC (min. HBP number in DSI mode) */
+ /* The rest is undocumented in ST7703 datasheet */
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x44, 0x25, 0x00, 0x91, 0x0a, 0x00, 0x00, 0x02,
+ 0x4F, 0x11, 0x00, 0x00, 0x37);
+
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER_EXT,
+ 0x25, /* PCCS = 2, ECP_DC_DIV = 1/4 HSYNC */
+ 0x22, /* DT = 15ms XDK_ECP = x2 */
+ 0x20, /* PFM_DC_DIV = /1 */
+ 0x03 /* ECP_SYNC_EN = 1, VGX_SYNC_EN = 1 */);
/* RGB I/F porch timing */
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETRGBIF,
- 0x10, /* VBP_RGB_GEN */
- 0x10, /* VFP_RGB_GEN */
- 0x05, /* DE_BP_RGB_GEN */
- 0x05, /* DE_FP_RGB_GEN */
- /* The rest is undocumented in ST7703 datasheet */
- 0x03, 0xFF,
- 0x00, 0x00,
- 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETRGBIF,
+ 0x10, /* VBP_RGB_GEN */
+ 0x10, /* VFP_RGB_GEN */
+ 0x05, /* DE_BP_RGB_GEN */
+ 0x05, /* DE_FP_RGB_GEN */
+ /* The rest is undocumented in ST7703 datasheet */
+ 0x03, 0xFF,
+ 0x00, 0x00,
+ 0x00, 0x00);
/* Source driving settings. */
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETSCR,
- 0x73, /* N_POPON */
- 0x73, /* N_NOPON */
- 0x50, /* I_POPON */
- 0x50, /* I_NOPON */
- 0x00, /* SCR[31,24] */
- 0xC0, /* SCR[23,16] */
- 0x08, /* SCR[15,8] */
- 0x70, /* SCR[7,0] */
- 0x00 /* Undocumented */);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETSCR,
+ 0x73, /* N_POPON */
+ 0x73, /* N_NOPON */
+ 0x50, /* I_POPON */
+ 0x50, /* I_NOPON */
+ 0x00, /* SCR[31,24] */
+ 0xC0, /* SCR[23,16] */
+ 0x08, /* SCR[15,8] */
+ 0x70, /* SCR[7,0] */
+ 0x00 /* Undocumented */);
/* NVDDD_SEL = -1.8V, VDDD_SEL = out of range (possibly 1.9V?) */
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVDC, 0x4E);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVDC, 0x4E);
/*
* SS_PANEL = 1 (reverse scan), GS_PANEL = 0 (normal scan)
* REV_PANEL = 1 (normally black panel), BGR_PANEL = 1 (BGR)
*/
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0B);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPANEL, 0x0B);
/* Zig-Zag Type C column inversion. */
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETCYC, 0x80);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETCYC, 0x80);
/* Set display resolution. */
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETDISP,
- 0xF0, /* NL = 240 */
- 0x12, /* RES_V_LSB = 0, BLK_CON = VSSD,
- * RESO_SEL = 720RGB
- */
- 0xF0 /* WHITE_GND_EN = 1 (GND),
- * WHITE_FRAME_SEL = 7 frames,
- * ISC = 0 frames
- */);
-
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEQ,
- 0x00, /* PNOEQ */
- 0x00, /* NNOEQ */
- 0x0B, /* PEQGND */
- 0x0B, /* NEQGND */
- 0x10, /* PEQVCI */
- 0x10, /* NEQVCI */
- 0x00, /* PEQVCI1 */
- 0x00, /* NEQVCI1 */
- 0x00, /* reserved */
- 0x00, /* reserved */
- 0xFF, /* reserved */
- 0x00, /* reserved */
- 0xC0, /* ESD_DET_DATA_WHITE = 1, ESD_WHITE_EN = 1 */
- 0x10 /* SLPIN_OPTION = 1 (no need vsync after sleep-in)
- * VEDIO_NO_CHECK_EN = 0
- * ESD_WHITE_GND_EN = 0
- * ESD_DET_TIME_SEL = 0 frames
- */);
-
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETECO, 0x01, 0x00, 0xFF, 0xFF, 0x00);
-
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER,
- 0x74, /* VBTHS, VBTLS: VGH = 17V, VBL = -11V */
- 0x00, /* FBOFF_VGH = 0, FBOFF_VGL = 0 */
- 0x32, /* VRP */
- 0x32, /* VRN */
- 0x77, /* reserved */
- 0xF1, /* APS = 1 (small),
- * VGL_DET_EN = 1, VGH_DET_EN = 1,
- * VGL_TURBO = 1, VGH_TURBO = 1
- */
- 0xFF, /* VGH1_L_DIV, VGL1_L_DIV (1.5MHz) */
- 0xFF, /* VGH1_R_DIV, VGL1_R_DIV (1.5MHz) */
- 0xCC, /* VGH2_L_DIV, VGL2_L_DIV (2.6MHz) */
- 0xCC, /* VGH2_R_DIV, VGL2_R_DIV (2.6MHz) */
- 0x77, /* VGH3_L_DIV, VGL3_L_DIV (4.5MHz) */
- 0x77 /* VGH3_R_DIV, VGL3_R_DIV (4.5MHz) */);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETDISP,
+ 0xF0, /* NL = 240 */
+ 0x12, /* RES_V_LSB = 0, BLK_CON = VSSD,
+ * RESO_SEL = 720RGB
+ */
+ 0xF0 /* WHITE_GND_EN = 1 (GND),
+ * WHITE_FRAME_SEL = 7 frames,
+ * ISC = 0 frames
+ */);
+
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEQ,
+ 0x00, /* PNOEQ */
+ 0x00, /* NNOEQ */
+ 0x0B, /* PEQGND */
+ 0x0B, /* NEQGND */
+ 0x10, /* PEQVCI */
+ 0x10, /* NEQVCI */
+ 0x00, /* PEQVCI1 */
+ 0x00, /* NEQVCI1 */
+ 0x00, /* reserved */
+ 0x00, /* reserved */
+ 0xFF, /* reserved */
+ 0x00, /* reserved */
+ 0xC0, /* ESD_DET_DATA_WHITE = 1, ESD_WHITE_EN = 1 */
+ 0x10 /* SLPIN_OPTION = 1 (no need vsync after sleep-in)
+ * VEDIO_NO_CHECK_EN = 0
+ * ESD_WHITE_GND_EN = 0
+ * ESD_DET_TIME_SEL = 0 frames
+ */);
+
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETECO, 0x01, 0x00, 0xFF, 0xFF, 0x00);
+
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER,
+ 0x74, /* VBTHS, VBTLS: VGH = 17V, VBL = -11V */
+ 0x00, /* FBOFF_VGH = 0, FBOFF_VGL = 0 */
+ 0x32, /* VRP */
+ 0x32, /* VRN */
+ 0x77, /* reserved */
+ 0xF1, /* APS = 1 (small),
+ * VGL_DET_EN = 1, VGH_DET_EN = 1,
+ * VGL_TURBO = 1, VGH_TURBO = 1
+ */
+ 0xFF, /* VGH1_L_DIV, VGL1_L_DIV (1.5MHz) */
+ 0xFF, /* VGH1_R_DIV, VGL1_R_DIV (1.5MHz) */
+ 0xCC, /* VGH2_L_DIV, VGL2_L_DIV (2.6MHz) */
+ 0xCC, /* VGH2_R_DIV, VGL2_R_DIV (2.6MHz) */
+ 0x77, /* VGH3_L_DIV, VGL3_L_DIV (4.5MHz) */
+ 0x77 /* VGH3_R_DIV, VGL3_R_DIV (4.5MHz) */);
/* Reference voltage. */
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETBGP,
- 0x07, /* VREF_SEL = 4.2V */
- 0x07 /* NVREF_SEL = 4.2V */);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETBGP,
+ 0x07, /* VREF_SEL = 4.2V */
+ 0x07 /* NVREF_SEL = 4.2V */);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVCOM,
- 0x2C, /* VCOMDC_F = -0.67V */
- 0x2C /* VCOMDC_B = -0.67V */);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVCOM,
+ 0x2C, /* VCOMDC_F = -0.67V */
+ 0x2C /* VCOMDC_B = -0.67V */);
/* Undocumented command. */
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
/* This command is to set forward GIP timing. */
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP1,
- 0x82, 0x10, 0x06, 0x05, 0xA2, 0x0A, 0xA5, 0x12,
- 0x31, 0x23, 0x37, 0x83, 0x04, 0xBC, 0x27, 0x38,
- 0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x75, 0x75, 0x31, 0x88,
- 0x88, 0x88, 0x88, 0x88, 0x88, 0x13, 0x88, 0x64,
- 0x64, 0x20, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
- 0x02, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP1,
+ 0x82, 0x10, 0x06, 0x05, 0xA2, 0x0A, 0xA5, 0x12,
+ 0x31, 0x23, 0x37, 0x83, 0x04, 0xBC, 0x27, 0x38,
+ 0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x75, 0x75, 0x31, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x13, 0x88, 0x64,
+ 0x64, 0x20, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x02, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
/* This command is to set backward GIP timing. */
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP2,
- 0x02, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x02, 0x46, 0x02, 0x88,
- 0x88, 0x88, 0x88, 0x88, 0x88, 0x64, 0x88, 0x13,
- 0x57, 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
- 0x75, 0x88, 0x23, 0x14, 0x00, 0x00, 0x02, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0A,
- 0xA5, 0x00, 0x00, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP2,
+ 0x02, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x46, 0x02, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x64, 0x88, 0x13,
+ 0x57, 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x75, 0x88, 0x23, 0x14, 0x00, 0x00, 0x02, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0A,
+ 0xA5, 0x00, 0x00, 0x00, 0x00);
/* Adjust the gamma characteristics of the panel. */
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGAMMA,
- 0x00, 0x09, 0x0D, 0x23, 0x27, 0x3C, 0x41, 0x35,
- 0x07, 0x0D, 0x0E, 0x12, 0x13, 0x10, 0x12, 0x12,
- 0x18, 0x00, 0x09, 0x0D, 0x23, 0x27, 0x3C, 0x41,
- 0x35, 0x07, 0x0D, 0x0E, 0x12, 0x13, 0x10, 0x12,
- 0x12, 0x18);
-
- return 0;
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGAMMA,
+ 0x00, 0x09, 0x0D, 0x23, 0x27, 0x3C, 0x41, 0x35,
+ 0x07, 0x0D, 0x0E, 0x12, 0x13, 0x10, 0x12, 0x12,
+ 0x18, 0x00, 0x09, 0x0D, 0x23, 0x27, 0x3C, 0x41,
+ 0x35, 0x07, 0x0D, 0x0E, 0x12, 0x13, 0x10, 0x12,
+ 0x12, 0x18);
}
static const struct drm_display_mode xbd599_mode = {
@@ -342,72 +333,68 @@ static const struct st7703_panel_desc xbd599_desc = {
.init_sequence = xbd599_init_sequence,
};
-static int rg353v2_init_sequence(struct st7703 *ctx)
+static void rg353v2_init_sequence(struct mipi_dsi_multi_context *dsi_ctx)
{
- struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
-
/*
* Init sequence was supplied by the panel vendor.
*/
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEXTC, 0xf1, 0x12, 0x83);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETAPID, 0x00, 0x00, 0x00,
- 0xda, 0x80);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETDISP, 0x00, 0x13, 0x70);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETRGBIF, 0x10, 0x10, 0x28,
- 0x28, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETCYC, 0x80);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETBGP, 0x0a, 0x0a);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVCOM, 0x92, 0x92);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER_EXT, 0x25, 0x22,
- 0xf0, 0x63);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETMIPI, 0x33, 0x81, 0x05,
- 0xf9, 0x0e, 0x0e, 0x20, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x44, 0x25, 0x00, 0x90, 0x0a,
- 0x00, 0x00, 0x01, 0x4f, 0x01, 0x00, 0x00, 0x37);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVDC, 0x47);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETSCR, 0x73, 0x73, 0x50, 0x50,
- 0x00, 0x00, 0x12, 0x50, 0x00);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER, 0x53, 0xc0, 0x32,
- 0x32, 0x77, 0xe1, 0xdd, 0xdd, 0x77, 0x77, 0x33,
- 0x33);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETECO, 0x82, 0x00, 0xbf, 0xff,
- 0x00, 0xff);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETIO, 0xb8, 0x00, 0x0a, 0x00,
- 0x00, 0x00);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETCABC, 0x10, 0x40, 0x1e,
- 0x02);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0b);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGAMMA, 0x00, 0x07, 0x0d,
- 0x37, 0x35, 0x3f, 0x41, 0x44, 0x06, 0x0c, 0x0d,
- 0x0f, 0x11, 0x10, 0x12, 0x14, 0x1a, 0x00, 0x07,
- 0x0d, 0x37, 0x35, 0x3f, 0x41, 0x44, 0x06, 0x0c,
- 0x0d, 0x0f, 0x11, 0x10, 0x12, 0x14, 0x1a);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEQ, 0x07, 0x07, 0x0b, 0x0b,
- 0x0b, 0x0b, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
- 0xc0, 0x10);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP1, 0xc8, 0x10, 0x02, 0x00,
- 0x00, 0xb0, 0xb1, 0x11, 0x31, 0x23, 0x28, 0x80,
- 0xb0, 0xb1, 0x27, 0x08, 0x00, 0x04, 0x02, 0x00,
- 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00,
- 0x88, 0x88, 0xba, 0x60, 0x24, 0x08, 0x88, 0x88,
- 0x88, 0x88, 0x88, 0x88, 0x88, 0xba, 0x71, 0x35,
- 0x18, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00,
- 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP2, 0x97, 0x0a, 0x82, 0x02,
- 0x03, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x81, 0x88, 0xba, 0x17, 0x53, 0x88, 0x88, 0x88,
- 0x88, 0x88, 0x88, 0x80, 0x88, 0xba, 0x06, 0x42,
- 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x23, 0x00,
- 0x00, 0x02, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_EF, 0xff, 0xff, 0x01);
-
- return 0;
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEXTC, 0xf1, 0x12, 0x83);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETAPID, 0x00, 0x00, 0x00,
+ 0xda, 0x80);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETDISP, 0x00, 0x13, 0x70);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETRGBIF, 0x10, 0x10, 0x28,
+ 0x28, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETCYC, 0x80);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETBGP, 0x0a, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVCOM, 0x92, 0x92);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER_EXT, 0x25, 0x22,
+ 0xf0, 0x63);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETMIPI, 0x33, 0x81, 0x05,
+ 0xf9, 0x0e, 0x0e, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x25, 0x00, 0x90, 0x0a,
+ 0x00, 0x00, 0x01, 0x4f, 0x01, 0x00, 0x00, 0x37);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVDC, 0x47);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETSCR, 0x73, 0x73, 0x50, 0x50,
+ 0x00, 0x00, 0x12, 0x50, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER, 0x53, 0xc0, 0x32,
+ 0x32, 0x77, 0xe1, 0xdd, 0xdd, 0x77, 0x77, 0x33,
+ 0x33);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETECO, 0x82, 0x00, 0xbf, 0xff,
+ 0x00, 0xff);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETIO, 0xb8, 0x00, 0x0a, 0x00,
+ 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETCABC, 0x10, 0x40, 0x1e,
+ 0x02);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPANEL, 0x0b);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGAMMA, 0x00, 0x07, 0x0d,
+ 0x37, 0x35, 0x3f, 0x41, 0x44, 0x06, 0x0c, 0x0d,
+ 0x0f, 0x11, 0x10, 0x12, 0x14, 0x1a, 0x00, 0x07,
+ 0x0d, 0x37, 0x35, 0x3f, 0x41, 0x44, 0x06, 0x0c,
+ 0x0d, 0x0f, 0x11, 0x10, 0x12, 0x14, 0x1a);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEQ, 0x07, 0x07, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
+ 0xc0, 0x10);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP1, 0xc8, 0x10, 0x02, 0x00,
+ 0x00, 0xb0, 0xb1, 0x11, 0x31, 0x23, 0x28, 0x80,
+ 0xb0, 0xb1, 0x27, 0x08, 0x00, 0x04, 0x02, 0x00,
+ 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00,
+ 0x88, 0x88, 0xba, 0x60, 0x24, 0x08, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0xba, 0x71, 0x35,
+ 0x18, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP2, 0x97, 0x0a, 0x82, 0x02,
+ 0x03, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x81, 0x88, 0xba, 0x17, 0x53, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x80, 0x88, 0xba, 0x06, 0x42,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x23, 0x00,
+ 0x00, 0x02, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_UNKNOWN_EF, 0xff, 0xff, 0x01);
}
static const struct drm_display_mode rg353v2_mode = {
@@ -434,68 +421,64 @@ static const struct st7703_panel_desc rg353v2_desc = {
.init_sequence = rg353v2_init_sequence,
};
-static int rgb30panel_init_sequence(struct st7703 *ctx)
+static void rgb30panel_init_sequence(struct mipi_dsi_multi_context *dsi_ctx)
{
- struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
-
/* Init sequence extracted from Powkiddy RGB30 BSP kernel. */
/*
* For some reason this specific panel must be taken out of sleep
* before the full init sequence, or else it will not display.
*/
- mipi_dsi_dcs_exit_sleep_mode(dsi);
- msleep(250);
-
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEXTC, 0xf1, 0x12, 0x83);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETMIPI, 0x33, 0x81, 0x05, 0xf9,
- 0x0e, 0x0e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x44, 0x25, 0x00, 0x90, 0x0a, 0x00,
- 0x00, 0x01, 0x4f, 0x01, 0x00, 0x00, 0x37);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER_EXT, 0x25, 0x22, 0xf0,
- 0x63);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETRGBIF, 0x10, 0x10, 0x28,
- 0x28, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETSCR, 0x73, 0x73, 0x50, 0x50,
- 0x00, 0x00, 0x12, 0x70, 0x00);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVDC, 0x46);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0b);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETCYC, 0x80);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETDISP, 0x3c, 0x12, 0x30);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEQ, 0x07, 0x07, 0x0b, 0x0b,
- 0x03, 0x0b, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
- 0xc0, 0x10);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER, 0x36, 0x00, 0x32,
- 0x32, 0x77, 0xf1, 0xcc, 0xcc, 0x77, 0x77, 0x33,
- 0x33);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETBGP, 0x0a, 0x0a);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVCOM, 0x88, 0x88);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP1, 0xc8, 0x10, 0x0a, 0x10,
- 0x0f, 0xa1, 0x80, 0x12, 0x31, 0x23, 0x47, 0x86,
- 0xa1, 0x80, 0x47, 0x08, 0x00, 0x00, 0x0d, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
- 0x48, 0x02, 0x8b, 0xaf, 0x46, 0x02, 0x88, 0x88,
- 0x88, 0x88, 0x88, 0x48, 0x13, 0x8b, 0xaf, 0x57,
- 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP2, 0x96, 0x12, 0x01, 0x01,
- 0x01, 0x78, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x4f, 0x31, 0x8b, 0xa8, 0x31, 0x75, 0x88, 0x88,
- 0x88, 0x88, 0x88, 0x4f, 0x20, 0x8b, 0xa8, 0x20,
- 0x64, 0x88, 0x88, 0x88, 0x88, 0x88, 0x23, 0x00,
- 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x40, 0xa1, 0x80, 0x00, 0x00, 0x00,
- 0x00);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGAMMA, 0x00, 0x0a, 0x0f,
- 0x29, 0x3b, 0x3f, 0x42, 0x39, 0x06, 0x0d, 0x10,
- 0x13, 0x15, 0x14, 0x15, 0x10, 0x17, 0x00, 0x0a,
- 0x0f, 0x29, 0x3b, 0x3f, 0x42, 0x39, 0x06, 0x0d,
- 0x10, 0x13, 0x15, 0x14, 0x15, 0x10, 0x17);
-
- return 0;
+ mipi_dsi_dcs_exit_sleep_mode_multi(dsi_ctx);
+ mipi_dsi_msleep(dsi_ctx, 250);
+
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEXTC, 0xf1, 0x12, 0x83);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETMIPI, 0x33, 0x81, 0x05, 0xf9,
+ 0x0e, 0x0e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x44, 0x25, 0x00, 0x90, 0x0a, 0x00,
+ 0x00, 0x01, 0x4f, 0x01, 0x00, 0x00, 0x37);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER_EXT, 0x25, 0x22, 0xf0,
+ 0x63);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETRGBIF, 0x10, 0x10, 0x28,
+ 0x28, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETSCR, 0x73, 0x73, 0x50, 0x50,
+ 0x00, 0x00, 0x12, 0x70, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVDC, 0x46);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPANEL, 0x0b);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETCYC, 0x80);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETDISP, 0x3c, 0x12, 0x30);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEQ, 0x07, 0x07, 0x0b, 0x0b,
+ 0x03, 0x0b, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
+ 0xc0, 0x10);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER, 0x36, 0x00, 0x32,
+ 0x32, 0x77, 0xf1, 0xcc, 0xcc, 0x77, 0x77, 0x33,
+ 0x33);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETBGP, 0x0a, 0x0a);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVCOM, 0x88, 0x88);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP1, 0xc8, 0x10, 0x0a, 0x10,
+ 0x0f, 0xa1, 0x80, 0x12, 0x31, 0x23, 0x47, 0x86,
+ 0xa1, 0x80, 0x47, 0x08, 0x00, 0x00, 0x0d, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
+ 0x48, 0x02, 0x8b, 0xaf, 0x46, 0x02, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x48, 0x13, 0x8b, 0xaf, 0x57,
+ 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP2, 0x96, 0x12, 0x01, 0x01,
+ 0x01, 0x78, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x4f, 0x31, 0x8b, 0xa8, 0x31, 0x75, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x4f, 0x20, 0x8b, 0xa8, 0x20,
+ 0x64, 0x88, 0x88, 0x88, 0x88, 0x88, 0x23, 0x00,
+ 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x40, 0xa1, 0x80, 0x00, 0x00, 0x00,
+ 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGAMMA, 0x00, 0x0a, 0x0f,
+ 0x29, 0x3b, 0x3f, 0x42, 0x39, 0x06, 0x0d, 0x10,
+ 0x13, 0x15, 0x14, 0x15, 0x10, 0x17, 0x00, 0x0a,
+ 0x0f, 0x29, 0x3b, 0x3f, 0x42, 0x39, 0x06, 0x0d,
+ 0x10, 0x13, 0x15, 0x14, 0x15, 0x10, 0x17);
}
static const struct drm_display_mode rgb30panel_mode = {
@@ -522,70 +505,66 @@ static const struct st7703_panel_desc rgb30panel_desc = {
.init_sequence = rgb30panel_init_sequence,
};
-static int rgb10max3_panel_init_sequence(struct st7703 *ctx)
+static void rgb10max3_panel_init_sequence(struct mipi_dsi_multi_context *dsi_ctx)
{
- struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
-
/* Init sequence extracted from Powkiddy RGB10MAX3 BSP kernel. */
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEXTC, 0xf1, 0x12, 0x83);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETAPID, 0x00, 0x00, 0x00, 0xda,
- 0x80);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETDISP, 0xc8, 0x02, 0x30);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETRGBIF, 0x10, 0x10, 0x28,
- 0x28, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETCYC, 0x80);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETBGP, 0x04, 0x04);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVCOM, 0x78, 0x78);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER_EXT, 0x25, 0x22, 0xf0,
- 0x63);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETMIPI, 0x33, 0x81, 0x05, 0xf9,
- 0x0e, 0x0e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x44, 0x25, 0x00, 0x90, 0x0a, 0x00,
- 0x00, 0x01, 0x4f, 0x01, 0x00, 0x00, 0x37);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVDC, 0x47);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETSCR, 0x73, 0x73, 0x50, 0x50,
- 0x00, 0x00, 0x12, 0x70, 0x00);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER, 0x25, 0x00, 0x32,
- 0x32, 0x77, 0xe1, 0xff, 0xff, 0xcc, 0xcc, 0x77,
- 0x77);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETECO, 0x82, 0x00, 0xbf, 0xff,
- 0x00, 0xff);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETIO, 0xb8, 0x00, 0x0a, 0x00,
- 0x00, 0x00);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETCABC, 0x10, 0x40, 0x1e,
- 0x02);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0b);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGAMMA, 0x00, 0x04, 0x07,
- 0x2a, 0x39, 0x3f, 0x36, 0x31, 0x06, 0x0b, 0x0e,
- 0x12, 0x14, 0x12, 0x13, 0x0f, 0x17, 0x00, 0x04,
- 0x07, 0x2a, 0x39, 0x3f, 0x36, 0x31, 0x06, 0x0b,
- 0x0e, 0x12, 0x14, 0x12, 0x13, 0x0f, 0x17);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEQ, 0x03, 0x03, 0x03, 0x03,
- 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0xff, 0x80,
- 0xc0, 0x10);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP1, 0xc8, 0x10, 0x08, 0x00,
- 0x00, 0x41, 0xf8, 0x12, 0x31, 0x23, 0x37, 0x86,
- 0x11, 0xc8, 0x37, 0x2a, 0x00, 0x00, 0x0c, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
- 0x88, 0x20, 0x46, 0x02, 0x88, 0x88, 0x88, 0x88,
- 0x88, 0x88, 0xff, 0x88, 0x31, 0x57, 0x13, 0x88,
- 0x88, 0x88, 0x88, 0x88, 0x88, 0xff, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP2, 0x00, 0x1a, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x8f, 0x13, 0x31, 0x75, 0x88, 0x88, 0x88, 0x88,
- 0x88, 0x88, 0xf8, 0x8f, 0x02, 0x20, 0x64, 0x88,
- 0x88, 0x88, 0x88, 0x88, 0x88, 0xf8, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_EF, 0xff, 0xff, 0x01);
-
- return 0;
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEXTC, 0xf1, 0x12, 0x83);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETAPID, 0x00, 0x00, 0x00, 0xda,
+ 0x80);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETDISP, 0xc8, 0x02, 0x30);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETRGBIF, 0x10, 0x10, 0x28,
+ 0x28, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETCYC, 0x80);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETBGP, 0x04, 0x04);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVCOM, 0x78, 0x78);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER_EXT, 0x25, 0x22, 0xf0,
+ 0x63);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETMIPI, 0x33, 0x81, 0x05, 0xf9,
+ 0x0e, 0x0e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x44, 0x25, 0x00, 0x90, 0x0a, 0x00,
+ 0x00, 0x01, 0x4f, 0x01, 0x00, 0x00, 0x37);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVDC, 0x47);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETSCR, 0x73, 0x73, 0x50, 0x50,
+ 0x00, 0x00, 0x12, 0x70, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER, 0x25, 0x00, 0x32,
+ 0x32, 0x77, 0xe1, 0xff, 0xff, 0xcc, 0xcc, 0x77,
+ 0x77);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETECO, 0x82, 0x00, 0xbf, 0xff,
+ 0x00, 0xff);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETIO, 0xb8, 0x00, 0x0a, 0x00,
+ 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETCABC, 0x10, 0x40, 0x1e,
+ 0x02);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPANEL, 0x0b);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGAMMA, 0x00, 0x04, 0x07,
+ 0x2a, 0x39, 0x3f, 0x36, 0x31, 0x06, 0x0b, 0x0e,
+ 0x12, 0x14, 0x12, 0x13, 0x0f, 0x17, 0x00, 0x04,
+ 0x07, 0x2a, 0x39, 0x3f, 0x36, 0x31, 0x06, 0x0b,
+ 0x0e, 0x12, 0x14, 0x12, 0x13, 0x0f, 0x17);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEQ, 0x03, 0x03, 0x03, 0x03,
+ 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0xff, 0x80,
+ 0xc0, 0x10);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP1, 0xc8, 0x10, 0x08, 0x00,
+ 0x00, 0x41, 0xf8, 0x12, 0x31, 0x23, 0x37, 0x86,
+ 0x11, 0xc8, 0x37, 0x2a, 0x00, 0x00, 0x0c, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x88, 0x20, 0x46, 0x02, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0xff, 0x88, 0x31, 0x57, 0x13, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0xff, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP2, 0x00, 0x1a, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x8f, 0x13, 0x31, 0x75, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0xf8, 0x8f, 0x02, 0x20, 0x64, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0xf8, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_UNKNOWN_EF, 0xff, 0xff, 0x01);
}
static const struct drm_display_mode rgb10max3_panel_mode = {
@@ -612,66 +591,62 @@ static const struct st7703_panel_desc rgb10max3_panel_desc = {
.init_sequence = rgb10max3_panel_init_sequence,
};
-static int gameforcechi_init_sequence(struct st7703 *ctx)
+static void gameforcechi_init_sequence(struct mipi_dsi_multi_context *dsi_ctx)
{
- struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
-
/*
* Init sequence was supplied by the panel vendor. Panel will not
* respond to commands until it is brought out of sleep mode first.
*/
- mipi_dsi_dcs_exit_sleep_mode(dsi);
- msleep(250);
-
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEXTC, 0xf1, 0x12, 0x83);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETMIPI, 0x31, 0x81, 0x05, 0xf9,
- 0x0e, 0x0e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x44, 0x25, 0x00, 0x91, 0x0a, 0x00,
- 0x00, 0x02, 0x4f, 0xd1, 0x00, 0x00, 0x37);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER_EXT, 0x25);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETRGBIF, 0x0c, 0x10, 0x0a,
- 0x50, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETSCR, 0x73, 0x73, 0x50, 0x50,
- 0x00, 0x00, 0x08, 0x70, 0x00);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVDC, 0x46);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0b);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETCYC, 0x80);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETDISP, 0x00, 0x13, 0xf0);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEQ, 0x07, 0x07, 0x0b, 0x0b,
- 0x03, 0x0b, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
- 0xc0, 0x10);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER, 0x53, 0x00, 0x1e,
- 0x1e, 0x77, 0xe1, 0xcc, 0xdd, 0x67, 0x77, 0x33,
- 0x33);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETBGP, 0x10, 0x10);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVCOM, 0x6c, 0x7c);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP1, 0x08, 0x00, 0x0e, 0x00,
- 0x00, 0xb0, 0xb1, 0x11, 0x31, 0x23, 0x28, 0x10,
- 0xb0, 0xb1, 0x27, 0x08, 0x00, 0x04, 0x02, 0x00,
- 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00,
- 0x88, 0x88, 0xba, 0x60, 0x24, 0x08, 0x88, 0x88,
- 0x88, 0x88, 0x88, 0x88, 0x88, 0xba, 0x71, 0x35,
- 0x18, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00,
- 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP2, 0x97, 0x0a, 0x82, 0x02,
- 0x13, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x88, 0xba, 0x17, 0x53, 0x88, 0x88, 0x88,
- 0x88, 0x88, 0x88, 0x81, 0x88, 0xba, 0x06, 0x42,
- 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x23, 0x10,
- 0x00, 0x02, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00);
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGAMMA, 0x00, 0x07, 0x0b,
- 0x27, 0x2d, 0x3f, 0x3b, 0x37, 0x05, 0x0a, 0x0b,
- 0x0f, 0x11, 0x0f, 0x12, 0x12, 0x18, 0x00, 0x07,
- 0x0b, 0x27, 0x2d, 0x3f, 0x3b, 0x37, 0x05, 0xa0,
- 0x0b, 0x0f, 0x11, 0x0f, 0x12, 0x12, 0x18);
-
- return 0;
+ mipi_dsi_dcs_exit_sleep_mode_multi(dsi_ctx);
+ mipi_dsi_msleep(dsi_ctx, 250);
+
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEXTC, 0xf1, 0x12, 0x83);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETMIPI, 0x31, 0x81, 0x05, 0xf9,
+ 0x0e, 0x0e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x44, 0x25, 0x00, 0x91, 0x0a, 0x00,
+ 0x00, 0x02, 0x4f, 0xd1, 0x00, 0x00, 0x37);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER_EXT, 0x25);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETRGBIF, 0x0c, 0x10, 0x0a,
+ 0x50, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETSCR, 0x73, 0x73, 0x50, 0x50,
+ 0x00, 0x00, 0x08, 0x70, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVDC, 0x46);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPANEL, 0x0b);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETCYC, 0x80);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETDISP, 0x00, 0x13, 0xf0);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEQ, 0x07, 0x07, 0x0b, 0x0b,
+ 0x03, 0x0b, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
+ 0xc0, 0x10);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER, 0x53, 0x00, 0x1e,
+ 0x1e, 0x77, 0xe1, 0xcc, 0xdd, 0x67, 0x77, 0x33,
+ 0x33);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETBGP, 0x10, 0x10);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVCOM, 0x6c, 0x7c);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP1, 0x08, 0x00, 0x0e, 0x00,
+ 0x00, 0xb0, 0xb1, 0x11, 0x31, 0x23, 0x28, 0x10,
+ 0xb0, 0xb1, 0x27, 0x08, 0x00, 0x04, 0x02, 0x00,
+ 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00,
+ 0x88, 0x88, 0xba, 0x60, 0x24, 0x08, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0xba, 0x71, 0x35,
+ 0x18, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP2, 0x97, 0x0a, 0x82, 0x02,
+ 0x13, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x88, 0xba, 0x17, 0x53, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x81, 0x88, 0xba, 0x06, 0x42,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x23, 0x10,
+ 0x00, 0x02, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGAMMA, 0x00, 0x07, 0x0b,
+ 0x27, 0x2d, 0x3f, 0x3b, 0x37, 0x05, 0x0a, 0x0b,
+ 0x0f, 0x11, 0x0f, 0x12, 0x12, 0x18, 0x00, 0x07,
+ 0x0b, 0x27, 0x2d, 0x3f, 0x3b, 0x37, 0x05, 0xa0,
+ 0x0b, 0x0f, 0x11, 0x0f, 0x12, 0x12, 0x18);
}
static const struct drm_display_mode gameforcechi_mode = {
@@ -702,63 +677,46 @@ static int st7703_enable(struct drm_panel *panel)
{
struct st7703 *ctx = panel_to_st7703(panel);
struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
- int ret;
+ struct mipi_dsi_multi_context dsi_ctx = {.dsi = dsi};
- ret = ctx->desc->init_sequence(ctx);
- if (ret < 0) {
- dev_err(ctx->dev, "Panel init sequence failed: %d\n", ret);
- return ret;
- }
+ ctx->desc->init_sequence(&dsi_ctx);
- ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
- if (ret < 0) {
- dev_err(ctx->dev, "Failed to exit sleep mode: %d\n", ret);
- return ret;
- }
+ mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);
/* It takes the controller 120 msec to wake up after sleep. */
- msleep(120);
+ mipi_dsi_msleep(&dsi_ctx, 120);
- ret = mipi_dsi_dcs_set_display_on(dsi);
- if (ret)
- return ret;
+ mipi_dsi_dcs_set_display_on_multi(&dsi_ctx);
- dev_dbg(ctx->dev, "Panel init sequence done\n");
+ if (!dsi_ctx.accum_err)
+ dev_dbg(ctx->dev, "Panel init sequence done\n");
- return 0;
+ return dsi_ctx.accum_err;
}
static int st7703_disable(struct drm_panel *panel)
{
struct st7703 *ctx = panel_to_st7703(panel);
struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
- int ret;
+ struct mipi_dsi_multi_context dsi_ctx = {.dsi = dsi};
- ret = mipi_dsi_dcs_set_display_off(dsi);
- if (ret < 0)
- dev_err(ctx->dev, "Failed to turn off the display: %d\n", ret);
+ mipi_dsi_dcs_set_display_off_multi(&dsi_ctx);
- ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
- if (ret < 0)
- dev_err(ctx->dev, "Failed to enter sleep mode: %d\n", ret);
+ mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx);
/* It takes the controller 120 msec to enter sleep mode. */
- msleep(120);
+ mipi_dsi_msleep(&dsi_ctx, 120);
- return 0;
+ return dsi_ctx.accum_err;
}
static int st7703_unprepare(struct drm_panel *panel)
{
struct st7703 *ctx = panel_to_st7703(panel);
- if (!ctx->prepared)
- return 0;
-
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
regulator_disable(ctx->iovcc);
regulator_disable(ctx->vcc);
- ctx->prepared = false;
return 0;
}
@@ -768,9 +726,6 @@ static int st7703_prepare(struct drm_panel *panel)
struct st7703 *ctx = panel_to_st7703(panel);
int ret;
- if (ctx->prepared)
- return 0;
-
dev_dbg(ctx->dev, "Resetting the panel\n");
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
@@ -793,8 +748,6 @@ static int st7703_prepare(struct drm_panel *panel)
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
usleep_range(15000, 20000);
- ctx->prepared = true;
-
return 0;
}
@@ -850,17 +803,24 @@ static int allpixelson_set(void *data, u64 val)
{
struct st7703 *ctx = data;
struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
+ struct mipi_dsi_multi_context dsi_ctx = {.dsi = dsi};
dev_dbg(ctx->dev, "Setting all pixels on\n");
- mipi_dsi_generic_write_seq(dsi, ST7703_CMD_ALL_PIXEL_ON);
- msleep(val * 1000);
- /* Reset the panel to get video back */
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, ST7703_CMD_ALL_PIXEL_ON);
+ mipi_dsi_msleep(&dsi_ctx, val * 1000);
+
+ /*
+ * Reset the panel to get video back. NOTE: This isn't a
+ * particularly safe thing to do in general because it assumes
+ * that the screen was on to begin with, but this is just a
+ * debugfs file so it's not a huge deal.
+ */
drm_panel_disable(&ctx->panel);
drm_panel_unprepare(&ctx->panel);
drm_panel_prepare(&ctx->panel);
drm_panel_enable(&ctx->panel);
- return 0;
+ return dsi_ctx.accum_err;
}
DEFINE_SIMPLE_ATTRIBUTE(allpixelson_fops, NULL,
@@ -941,27 +901,11 @@ static int st7703_probe(struct mipi_dsi_device *dsi)
return 0;
}
-static void st7703_shutdown(struct mipi_dsi_device *dsi)
-{
- struct st7703 *ctx = mipi_dsi_get_drvdata(dsi);
- int ret;
-
- ret = drm_panel_unprepare(&ctx->panel);
- if (ret < 0)
- dev_err(&dsi->dev, "Failed to unprepare panel: %d\n", ret);
-
- ret = drm_panel_disable(&ctx->panel);
- if (ret < 0)
- dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret);
-}
-
static void st7703_remove(struct mipi_dsi_device *dsi)
{
struct st7703 *ctx = mipi_dsi_get_drvdata(dsi);
int ret;
- st7703_shutdown(dsi);
-
ret = mipi_dsi_detach(dsi);
if (ret < 0)
dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
@@ -985,7 +929,6 @@ MODULE_DEVICE_TABLE(of, st7703_of_match);
static struct mipi_dsi_driver st7703_driver = {
.probe = st7703_probe,
.remove = st7703_remove,
- .shutdown = st7703_shutdown,
.driver = {
.name = DRV_NAME,
.of_match_table = st7703_of_match,
diff --git a/drivers/gpu/drm/panel/panel-sony-acx565akm.c b/drivers/gpu/drm/panel/panel-sony-acx565akm.c
index 3d6a286056a0..73ba93ff00fe 100644
--- a/drivers/gpu/drm/panel/panel-sony-acx565akm.c
+++ b/drivers/gpu/drm/panel/panel-sony-acx565akm.c
@@ -454,9 +454,6 @@ static int acx565akm_power_on(struct acx565akm_panel *lcd)
static void acx565akm_power_off(struct acx565akm_panel *lcd)
{
- if (!lcd->enabled)
- return;
-
acx565akm_set_display_state(lcd, 0);
acx565akm_set_sleep_mode(lcd, 1);
lcd->enabled = false;
@@ -655,9 +652,6 @@ static void acx565akm_remove(struct spi_device *spi)
if (lcd->has_bc)
acx565akm_backlight_cleanup(lcd);
-
- drm_panel_disable(&lcd->panel);
- drm_panel_unprepare(&lcd->panel);
}
static const struct of_device_id acx565akm_of_match[] = {
diff --git a/drivers/gpu/drm/panel/panel-sony-tulip-truly-nt35521.c b/drivers/gpu/drm/panel/panel-sony-tulip-truly-nt35521.c
index 6d44970dccd9..f2198fa29735 100644
--- a/drivers/gpu/drm/panel/panel-sony-tulip-truly-nt35521.c
+++ b/drivers/gpu/drm/panel/panel-sony-tulip-truly-nt35521.c
@@ -44,248 +44,229 @@ static void truly_nt35521_reset(struct truly_nt35521 *ctx)
static int truly_nt35521_on(struct truly_nt35521 *ctx)
{
struct mipi_dsi_device *dsi = ctx->dsi;
- struct device *dev = &dsi->dev;
- int ret;
+ struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
- mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xff, 0xaa, 0x55, 0xa5, 0x80);
- mipi_dsi_generic_write_seq(dsi, 0x6f, 0x11, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xf7, 0x20, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0x6f, 0x01);
- mipi_dsi_generic_write_seq(dsi, 0xb1, 0x21);
- mipi_dsi_generic_write_seq(dsi, 0xbd, 0x01, 0xa0, 0x10, 0x08, 0x01);
- mipi_dsi_generic_write_seq(dsi, 0xb8, 0x01, 0x02, 0x0c, 0x02);
- mipi_dsi_generic_write_seq(dsi, 0xbb, 0x11, 0x11);
- mipi_dsi_generic_write_seq(dsi, 0xbc, 0x00, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xb6, 0x02);
- mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x01);
- mipi_dsi_generic_write_seq(dsi, 0xb0, 0x09, 0x09);
- mipi_dsi_generic_write_seq(dsi, 0xb1, 0x09, 0x09);
- mipi_dsi_generic_write_seq(dsi, 0xbc, 0x8c, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xbd, 0x8c, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xca, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xc0, 0x04);
- mipi_dsi_generic_write_seq(dsi, 0xbe, 0xb5);
- mipi_dsi_generic_write_seq(dsi, 0xb3, 0x35, 0x35);
- mipi_dsi_generic_write_seq(dsi, 0xb4, 0x25, 0x25);
- mipi_dsi_generic_write_seq(dsi, 0xb9, 0x43, 0x43);
- mipi_dsi_generic_write_seq(dsi, 0xba, 0x24, 0x24);
- mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x02);
- mipi_dsi_generic_write_seq(dsi, 0xee, 0x03);
- mipi_dsi_generic_write_seq(dsi, 0xb0,
- 0x00, 0xb2, 0x00, 0xb3, 0x00, 0xb6, 0x00, 0xc3,
- 0x00, 0xce, 0x00, 0xe1, 0x00, 0xf3, 0x01, 0x11);
- mipi_dsi_generic_write_seq(dsi, 0xb1,
- 0x01, 0x2e, 0x01, 0x5c, 0x01, 0x82, 0x01, 0xc3,
- 0x01, 0xfe, 0x02, 0x00, 0x02, 0x37, 0x02, 0x77);
- mipi_dsi_generic_write_seq(dsi, 0xb2,
- 0x02, 0xa1, 0x02, 0xd7, 0x02, 0xfe, 0x03, 0x2c,
- 0x03, 0x4b, 0x03, 0x63, 0x03, 0x8f, 0x03, 0x90);
- mipi_dsi_generic_write_seq(dsi, 0xb3, 0x03, 0x96, 0x03, 0x98);
- mipi_dsi_generic_write_seq(dsi, 0xb4,
- 0x00, 0x81, 0x00, 0x8b, 0x00, 0x9c, 0x00, 0xa9,
- 0x00, 0xb5, 0x00, 0xcb, 0x00, 0xdf, 0x01, 0x02);
- mipi_dsi_generic_write_seq(dsi, 0xb5,
- 0x01, 0x1f, 0x01, 0x51, 0x01, 0x7a, 0x01, 0xbf,
- 0x01, 0xfa, 0x01, 0xfc, 0x02, 0x34, 0x02, 0x76);
- mipi_dsi_generic_write_seq(dsi, 0xb6,
- 0x02, 0x9f, 0x02, 0xd7, 0x02, 0xfc, 0x03, 0x2c,
- 0x03, 0x4a, 0x03, 0x63, 0x03, 0x8f, 0x03, 0xa2);
- mipi_dsi_generic_write_seq(dsi, 0xb7, 0x03, 0xb8, 0x03, 0xba);
- mipi_dsi_generic_write_seq(dsi, 0xb8,
- 0x00, 0x01, 0x00, 0x02, 0x00, 0x0e, 0x00, 0x2a,
- 0x00, 0x41, 0x00, 0x67, 0x00, 0x87, 0x00, 0xb9);
- mipi_dsi_generic_write_seq(dsi, 0xb9,
- 0x00, 0xe2, 0x01, 0x22, 0x01, 0x54, 0x01, 0xa3,
- 0x01, 0xe6, 0x01, 0xe7, 0x02, 0x24, 0x02, 0x67);
- mipi_dsi_generic_write_seq(dsi, 0xba,
- 0x02, 0x93, 0x02, 0xcd, 0x02, 0xf6, 0x03, 0x31,
- 0x03, 0x6c, 0x03, 0xe9, 0x03, 0xef, 0x03, 0xf4);
- mipi_dsi_generic_write_seq(dsi, 0xbb, 0x03, 0xf6, 0x03, 0xf7);
- mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x03);
- mipi_dsi_generic_write_seq(dsi, 0xb0, 0x22, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xb1, 0x22, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xb2, 0x05, 0x00, 0x60, 0x00, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xb3, 0x05, 0x00, 0x60, 0x00, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xb4, 0x05, 0x00, 0x60, 0x00, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xb5, 0x05, 0x00, 0x60, 0x00, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xba, 0x53, 0x00, 0x60, 0x00, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xbb, 0x53, 0x00, 0x60, 0x00, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xbc, 0x53, 0x00, 0x60, 0x00, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xbd, 0x53, 0x00, 0x60, 0x00, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xc0, 0x00, 0x34, 0x00, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xc1, 0x00, 0x00, 0x34, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xc2, 0x00, 0x00, 0x34, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xc3, 0x00, 0x00, 0x34, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xc4, 0x60);
- mipi_dsi_generic_write_seq(dsi, 0xc5, 0xc0);
- mipi_dsi_generic_write_seq(dsi, 0xc6, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xc7, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x05);
- mipi_dsi_generic_write_seq(dsi, 0xb0, 0x17, 0x06);
- mipi_dsi_generic_write_seq(dsi, 0xb1, 0x17, 0x06);
- mipi_dsi_generic_write_seq(dsi, 0xb2, 0x17, 0x06);
- mipi_dsi_generic_write_seq(dsi, 0xb3, 0x17, 0x06);
- mipi_dsi_generic_write_seq(dsi, 0xb4, 0x17, 0x06);
- mipi_dsi_generic_write_seq(dsi, 0xb5, 0x17, 0x06);
- mipi_dsi_generic_write_seq(dsi, 0xb6, 0x17, 0x06);
- mipi_dsi_generic_write_seq(dsi, 0xb7, 0x17, 0x06);
- mipi_dsi_generic_write_seq(dsi, 0xb8, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xb9, 0x00, 0x03);
- mipi_dsi_generic_write_seq(dsi, 0xba, 0x00, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xbb, 0x02, 0x03);
- mipi_dsi_generic_write_seq(dsi, 0xbc, 0x02, 0x03);
- mipi_dsi_generic_write_seq(dsi, 0xbd, 0x03, 0x03, 0x00, 0x03, 0x03);
- mipi_dsi_generic_write_seq(dsi, 0xc0, 0x0b);
- mipi_dsi_generic_write_seq(dsi, 0xc1, 0x09);
- mipi_dsi_generic_write_seq(dsi, 0xc2, 0xa6);
- mipi_dsi_generic_write_seq(dsi, 0xc3, 0x05);
- mipi_dsi_generic_write_seq(dsi, 0xc4, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xc5, 0x02);
- mipi_dsi_generic_write_seq(dsi, 0xc6, 0x22);
- mipi_dsi_generic_write_seq(dsi, 0xc7, 0x03);
- mipi_dsi_generic_write_seq(dsi, 0xc8, 0x07, 0x20);
- mipi_dsi_generic_write_seq(dsi, 0xc9, 0x03, 0x20);
- mipi_dsi_generic_write_seq(dsi, 0xca, 0x01, 0x60);
- mipi_dsi_generic_write_seq(dsi, 0xcb, 0x01, 0x60);
- mipi_dsi_generic_write_seq(dsi, 0xcc, 0x00, 0x00, 0x02);
- mipi_dsi_generic_write_seq(dsi, 0xcd, 0x00, 0x00, 0x02);
- mipi_dsi_generic_write_seq(dsi, 0xce, 0x00, 0x00, 0x02);
- mipi_dsi_generic_write_seq(dsi, 0xcf, 0x00, 0x00, 0x02);
- mipi_dsi_generic_write_seq(dsi, 0xd1, 0x00, 0x05, 0x01, 0x07, 0x10);
- mipi_dsi_generic_write_seq(dsi, 0xd2, 0x10, 0x05, 0x05, 0x03, 0x10);
- mipi_dsi_generic_write_seq(dsi, 0xd3, 0x20, 0x00, 0x43, 0x07, 0x10);
- mipi_dsi_generic_write_seq(dsi, 0xd4, 0x30, 0x00, 0x43, 0x07, 0x10);
- mipi_dsi_generic_write_seq(dsi, 0xd0,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xd5,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xd6,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xd7,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xe5, 0x06);
- mipi_dsi_generic_write_seq(dsi, 0xe6, 0x06);
- mipi_dsi_generic_write_seq(dsi, 0xe7, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xe8, 0x06);
- mipi_dsi_generic_write_seq(dsi, 0xe9, 0x06);
- mipi_dsi_generic_write_seq(dsi, 0xea, 0x06);
- mipi_dsi_generic_write_seq(dsi, 0xeb, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xec, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xed, 0x30);
- mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x06);
- mipi_dsi_generic_write_seq(dsi, 0xb0, 0x31, 0x31);
- mipi_dsi_generic_write_seq(dsi, 0xb1, 0x31, 0x31);
- mipi_dsi_generic_write_seq(dsi, 0xb2, 0x2d, 0x2e);
- mipi_dsi_generic_write_seq(dsi, 0xb3, 0x31, 0x34);
- mipi_dsi_generic_write_seq(dsi, 0xb4, 0x29, 0x2a);
- mipi_dsi_generic_write_seq(dsi, 0xb5, 0x12, 0x10);
- mipi_dsi_generic_write_seq(dsi, 0xb6, 0x18, 0x16);
- mipi_dsi_generic_write_seq(dsi, 0xb7, 0x00, 0x02);
- mipi_dsi_generic_write_seq(dsi, 0xb8, 0x08, 0x31);
- mipi_dsi_generic_write_seq(dsi, 0xb9, 0x31, 0x31);
- mipi_dsi_generic_write_seq(dsi, 0xba, 0x31, 0x31);
- mipi_dsi_generic_write_seq(dsi, 0xbb, 0x31, 0x08);
- mipi_dsi_generic_write_seq(dsi, 0xbc, 0x03, 0x01);
- mipi_dsi_generic_write_seq(dsi, 0xbd, 0x17, 0x19);
- mipi_dsi_generic_write_seq(dsi, 0xbe, 0x11, 0x13);
- mipi_dsi_generic_write_seq(dsi, 0xbf, 0x2a, 0x29);
- mipi_dsi_generic_write_seq(dsi, 0xc0, 0x34, 0x31);
- mipi_dsi_generic_write_seq(dsi, 0xc1, 0x2e, 0x2d);
- mipi_dsi_generic_write_seq(dsi, 0xc2, 0x31, 0x31);
- mipi_dsi_generic_write_seq(dsi, 0xc3, 0x31, 0x31);
- mipi_dsi_generic_write_seq(dsi, 0xc4, 0x31, 0x31);
- mipi_dsi_generic_write_seq(dsi, 0xc5, 0x31, 0x31);
- mipi_dsi_generic_write_seq(dsi, 0xc6, 0x2e, 0x2d);
- mipi_dsi_generic_write_seq(dsi, 0xc7, 0x31, 0x34);
- mipi_dsi_generic_write_seq(dsi, 0xc8, 0x29, 0x2a);
- mipi_dsi_generic_write_seq(dsi, 0xc9, 0x17, 0x19);
- mipi_dsi_generic_write_seq(dsi, 0xca, 0x11, 0x13);
- mipi_dsi_generic_write_seq(dsi, 0xcb, 0x03, 0x01);
- mipi_dsi_generic_write_seq(dsi, 0xcc, 0x08, 0x31);
- mipi_dsi_generic_write_seq(dsi, 0xcd, 0x31, 0x31);
- mipi_dsi_generic_write_seq(dsi, 0xce, 0x31, 0x31);
- mipi_dsi_generic_write_seq(dsi, 0xcf, 0x31, 0x08);
- mipi_dsi_generic_write_seq(dsi, 0xd0, 0x00, 0x02);
- mipi_dsi_generic_write_seq(dsi, 0xd1, 0x12, 0x10);
- mipi_dsi_generic_write_seq(dsi, 0xd2, 0x18, 0x16);
- mipi_dsi_generic_write_seq(dsi, 0xd3, 0x2a, 0x29);
- mipi_dsi_generic_write_seq(dsi, 0xd4, 0x34, 0x31);
- mipi_dsi_generic_write_seq(dsi, 0xd5, 0x2d, 0x2e);
- mipi_dsi_generic_write_seq(dsi, 0xd6, 0x31, 0x31);
- mipi_dsi_generic_write_seq(dsi, 0xd7, 0x31, 0x31);
- mipi_dsi_generic_write_seq(dsi, 0xe5, 0x31, 0x31);
- mipi_dsi_generic_write_seq(dsi, 0xe6, 0x31, 0x31);
- mipi_dsi_generic_write_seq(dsi, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xd9, 0x00, 0x00, 0x00, 0x00, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xe7, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0x6f, 0x02);
- mipi_dsi_generic_write_seq(dsi, 0xf7, 0x47);
- mipi_dsi_generic_write_seq(dsi, 0x6f, 0x0a);
- mipi_dsi_generic_write_seq(dsi, 0xf7, 0x02);
- mipi_dsi_generic_write_seq(dsi, 0x6f, 0x17);
- mipi_dsi_generic_write_seq(dsi, 0xf4, 0x60);
- mipi_dsi_generic_write_seq(dsi, 0x6f, 0x01);
- mipi_dsi_generic_write_seq(dsi, 0xf9, 0x46);
- mipi_dsi_generic_write_seq(dsi, 0x6f, 0x11);
- mipi_dsi_generic_write_seq(dsi, 0xf3, 0x01);
- mipi_dsi_generic_write_seq(dsi, 0x35, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xd9, 0x02, 0x03, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x00, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0xb1, 0x6c, 0x21);
- mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x00, 0x00);
- mipi_dsi_generic_write_seq(dsi, 0x35, 0x00);
-
- ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
- if (ret < 0) {
- dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
- return ret;
- }
- msleep(120);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xff, 0xaa, 0x55, 0xa5, 0x80);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x6f, 0x11, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf7, 0x20, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x6f, 0x01);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb1, 0x21);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbd, 0x01, 0xa0, 0x10, 0x08, 0x01);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb8, 0x01, 0x02, 0x0c, 0x02);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbb, 0x11, 0x11);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbc, 0x00, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb6, 0x02);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x01);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb0, 0x09, 0x09);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb1, 0x09, 0x09);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbc, 0x8c, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbd, 0x8c, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xca, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc0, 0x04);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbe, 0xb5);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb3, 0x35, 0x35);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb4, 0x25, 0x25);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb9, 0x43, 0x43);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xba, 0x24, 0x24);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x02);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xee, 0x03);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb0,
+ 0x00, 0xb2, 0x00, 0xb3, 0x00, 0xb6, 0x00, 0xc3,
+ 0x00, 0xce, 0x00, 0xe1, 0x00, 0xf3, 0x01, 0x11);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb1,
+ 0x01, 0x2e, 0x01, 0x5c, 0x01, 0x82, 0x01, 0xc3,
+ 0x01, 0xfe, 0x02, 0x00, 0x02, 0x37, 0x02, 0x77);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb2,
+ 0x02, 0xa1, 0x02, 0xd7, 0x02, 0xfe, 0x03, 0x2c,
+ 0x03, 0x4b, 0x03, 0x63, 0x03, 0x8f, 0x03, 0x90);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb3, 0x03, 0x96, 0x03, 0x98);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb4,
+ 0x00, 0x81, 0x00, 0x8b, 0x00, 0x9c, 0x00, 0xa9,
+ 0x00, 0xb5, 0x00, 0xcb, 0x00, 0xdf, 0x01, 0x02);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb5,
+ 0x01, 0x1f, 0x01, 0x51, 0x01, 0x7a, 0x01, 0xbf,
+ 0x01, 0xfa, 0x01, 0xfc, 0x02, 0x34, 0x02, 0x76);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb6,
+ 0x02, 0x9f, 0x02, 0xd7, 0x02, 0xfc, 0x03, 0x2c,
+ 0x03, 0x4a, 0x03, 0x63, 0x03, 0x8f, 0x03, 0xa2);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb7, 0x03, 0xb8, 0x03, 0xba);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb8,
+ 0x00, 0x01, 0x00, 0x02, 0x00, 0x0e, 0x00, 0x2a,
+ 0x00, 0x41, 0x00, 0x67, 0x00, 0x87, 0x00, 0xb9);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb9,
+ 0x00, 0xe2, 0x01, 0x22, 0x01, 0x54, 0x01, 0xa3,
+ 0x01, 0xe6, 0x01, 0xe7, 0x02, 0x24, 0x02, 0x67);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xba,
+ 0x02, 0x93, 0x02, 0xcd, 0x02, 0xf6, 0x03, 0x31,
+ 0x03, 0x6c, 0x03, 0xe9, 0x03, 0xef, 0x03, 0xf4);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbb, 0x03, 0xf6, 0x03, 0xf7);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x03);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb0, 0x22, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb1, 0x22, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb2, 0x05, 0x00, 0x60, 0x00, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb3, 0x05, 0x00, 0x60, 0x00, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb4, 0x05, 0x00, 0x60, 0x00, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb5, 0x05, 0x00, 0x60, 0x00, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xba, 0x53, 0x00, 0x60, 0x00, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbb, 0x53, 0x00, 0x60, 0x00, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbc, 0x53, 0x00, 0x60, 0x00, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbd, 0x53, 0x00, 0x60, 0x00, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc0, 0x00, 0x34, 0x00, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc1, 0x00, 0x00, 0x34, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc2, 0x00, 0x00, 0x34, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc3, 0x00, 0x00, 0x34, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc4, 0x60);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc5, 0xc0);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc6, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc7, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x05);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb0, 0x17, 0x06);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb1, 0x17, 0x06);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb2, 0x17, 0x06);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb3, 0x17, 0x06);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb4, 0x17, 0x06);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb5, 0x17, 0x06);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb6, 0x17, 0x06);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb7, 0x17, 0x06);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb8, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb9, 0x00, 0x03);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xba, 0x00, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbb, 0x02, 0x03);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbc, 0x02, 0x03);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbd, 0x03, 0x03, 0x00, 0x03, 0x03);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc0, 0x0b);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc1, 0x09);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc2, 0xa6);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc3, 0x05);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc4, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc5, 0x02);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc6, 0x22);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc7, 0x03);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc8, 0x07, 0x20);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc9, 0x03, 0x20);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xca, 0x01, 0x60);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcb, 0x01, 0x60);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcc, 0x00, 0x00, 0x02);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcd, 0x00, 0x00, 0x02);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xce, 0x00, 0x00, 0x02);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcf, 0x00, 0x00, 0x02);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd1, 0x00, 0x05, 0x01, 0x07, 0x10);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd2, 0x10, 0x05, 0x05, 0x03, 0x10);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd3, 0x20, 0x00, 0x43, 0x07, 0x10);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd4, 0x30, 0x00, 0x43, 0x07, 0x10);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd5,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd7,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xe5, 0x06);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xe6, 0x06);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xe7, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xe8, 0x06);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xe9, 0x06);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xea, 0x06);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xeb, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xec, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xed, 0x30);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x06);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb0, 0x31, 0x31);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb1, 0x31, 0x31);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb2, 0x2d, 0x2e);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb3, 0x31, 0x34);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb4, 0x29, 0x2a);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb5, 0x12, 0x10);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb6, 0x18, 0x16);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb7, 0x00, 0x02);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb8, 0x08, 0x31);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb9, 0x31, 0x31);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xba, 0x31, 0x31);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbb, 0x31, 0x08);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbc, 0x03, 0x01);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbd, 0x17, 0x19);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbe, 0x11, 0x13);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbf, 0x2a, 0x29);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc0, 0x34, 0x31);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc1, 0x2e, 0x2d);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc2, 0x31, 0x31);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc3, 0x31, 0x31);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc4, 0x31, 0x31);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc5, 0x31, 0x31);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc6, 0x2e, 0x2d);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc7, 0x31, 0x34);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc8, 0x29, 0x2a);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc9, 0x17, 0x19);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xca, 0x11, 0x13);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcb, 0x03, 0x01);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcc, 0x08, 0x31);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcd, 0x31, 0x31);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xce, 0x31, 0x31);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcf, 0x31, 0x08);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd0, 0x00, 0x02);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd1, 0x12, 0x10);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd2, 0x18, 0x16);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd3, 0x2a, 0x29);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd4, 0x34, 0x31);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd5, 0x2d, 0x2e);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd6, 0x31, 0x31);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd7, 0x31, 0x31);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xe5, 0x31, 0x31);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xe6, 0x31, 0x31);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd9, 0x00, 0x00, 0x00, 0x00, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xe7, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x6f, 0x02);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf7, 0x47);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x6f, 0x0a);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf7, 0x02);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x6f, 0x17);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf4, 0x60);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x6f, 0x01);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf9, 0x46);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x6f, 0x11);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf3, 0x01);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x35, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd9, 0x02, 0x03, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf0, 0x55, 0xaa, 0x52, 0x00, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb1, 0x6c, 0x21);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf0, 0x55, 0xaa, 0x52, 0x00, 0x00);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x35, 0x00);
+
+ mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);
+ mipi_dsi_msleep(&dsi_ctx, 120);
+ mipi_dsi_dcs_set_display_on_multi(&dsi_ctx);
- ret = mipi_dsi_dcs_set_display_on(dsi);
- if (ret < 0) {
- dev_err(dev, "Failed to set display on: %d\n", ret);
- return ret;
- }
usleep_range(1000, 2000);
- mipi_dsi_generic_write_seq(dsi, 0x53, 0x24);
+ mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x53, 0x24);
- return 0;
+ return dsi_ctx.accum_err;
}
static int truly_nt35521_off(struct truly_nt35521 *ctx)
{
struct mipi_dsi_device *dsi = ctx->dsi;
- struct device *dev = &dsi->dev;
- int ret;
+ struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
- ret = mipi_dsi_dcs_set_display_off(dsi);
- if (ret < 0) {
- dev_err(dev, "Failed to set display off: %d\n", ret);
- return ret;
- }
- msleep(50);
-
- ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
- if (ret < 0) {
- dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
- return ret;
- }
- msleep(150);
+ mipi_dsi_dcs_set_display_off_multi(&dsi_ctx);
+ mipi_dsi_msleep(&dsi_ctx, 50);
+ mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx);
+ mipi_dsi_msleep(&dsi_ctx, 150);
- return 0;
+ return dsi_ctx.accum_err;
}
static int truly_nt35521_prepare(struct drm_panel *panel)
diff --git a/drivers/gpu/drm/panel/panel-tdo-tl070wsh30.c b/drivers/gpu/drm/panel/panel-tdo-tl070wsh30.c
index d8487bc6d611..227f97f9b136 100644
--- a/drivers/gpu/drm/panel/panel-tdo-tl070wsh30.c
+++ b/drivers/gpu/drm/panel/panel-tdo-tl070wsh30.c
@@ -24,8 +24,6 @@ struct tdo_tl070wsh30_panel {
struct regulator *supply;
struct gpio_desc *reset_gpio;
-
- bool prepared;
};
static inline
@@ -39,9 +37,6 @@ static int tdo_tl070wsh30_panel_prepare(struct drm_panel *panel)
struct tdo_tl070wsh30_panel *tdo_tl070wsh30 = to_tdo_tl070wsh30_panel(panel);
int err;
- if (tdo_tl070wsh30->prepared)
- return 0;
-
err = regulator_enable(tdo_tl070wsh30->supply);
if (err < 0)
return err;
@@ -74,8 +69,6 @@ static int tdo_tl070wsh30_panel_prepare(struct drm_panel *panel)
msleep(20);
- tdo_tl070wsh30->prepared = true;
-
return 0;
}
@@ -84,9 +77,6 @@ static int tdo_tl070wsh30_panel_unprepare(struct drm_panel *panel)
struct tdo_tl070wsh30_panel *tdo_tl070wsh30 = to_tdo_tl070wsh30_panel(panel);
int err;
- if (!tdo_tl070wsh30->prepared)
- return 0;
-
err = mipi_dsi_dcs_set_display_off(tdo_tl070wsh30->link);
if (err < 0)
dev_err(panel->dev, "failed to set display off: %d\n", err);
@@ -103,8 +93,6 @@ static int tdo_tl070wsh30_panel_unprepare(struct drm_panel *panel)
regulator_disable(tdo_tl070wsh30->supply);
- tdo_tl070wsh30->prepared = false;
-
return 0;
}
@@ -220,16 +208,6 @@ static void tdo_tl070wsh30_panel_remove(struct mipi_dsi_device *dsi)
dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err);
drm_panel_remove(&tdo_tl070wsh30->base);
- drm_panel_disable(&tdo_tl070wsh30->base);
- drm_panel_unprepare(&tdo_tl070wsh30->base);
-}
-
-static void tdo_tl070wsh30_panel_shutdown(struct mipi_dsi_device *dsi)
-{
- struct tdo_tl070wsh30_panel *tdo_tl070wsh30 = mipi_dsi_get_drvdata(dsi);
-
- drm_panel_disable(&tdo_tl070wsh30->base);
- drm_panel_unprepare(&tdo_tl070wsh30->base);
}
static struct mipi_dsi_driver tdo_tl070wsh30_panel_driver = {
@@ -239,7 +217,6 @@ static struct mipi_dsi_driver tdo_tl070wsh30_panel_driver = {
},
.probe = tdo_tl070wsh30_panel_probe,
.remove = tdo_tl070wsh30_panel_remove,
- .shutdown = tdo_tl070wsh30_panel_shutdown,
};
module_mipi_dsi_driver(tdo_tl070wsh30_panel_driver);
diff --git a/drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c b/drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c
index 8670386498a4..22a14006765e 100644
--- a/drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c
+++ b/drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c
@@ -52,7 +52,6 @@ struct xpp055c272 {
struct gpio_desc *reset_gpio;
struct regulator *vci;
struct regulator *iovcc;
- bool prepared;
};
static inline struct xpp055c272 *panel_to_xpp055c272(struct drm_panel *panel)
@@ -136,9 +135,6 @@ static int xpp055c272_unprepare(struct drm_panel *panel)
struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
int ret;
- if (!ctx->prepared)
- return 0;
-
ret = mipi_dsi_dcs_set_display_off(dsi);
if (ret < 0)
dev_err(ctx->dev, "failed to set display off: %d\n", ret);
@@ -152,8 +148,6 @@ static int xpp055c272_unprepare(struct drm_panel *panel)
regulator_disable(ctx->iovcc);
regulator_disable(ctx->vci);
- ctx->prepared = false;
-
return 0;
}
@@ -163,9 +157,6 @@ static int xpp055c272_prepare(struct drm_panel *panel)
struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
int ret;
- if (ctx->prepared)
- return 0;
-
dev_dbg(ctx->dev, "Resetting the panel\n");
ret = regulator_enable(ctx->vci);
if (ret < 0) {
@@ -209,8 +200,6 @@ static int xpp055c272_prepare(struct drm_panel *panel)
msleep(50);
- ctx->prepared = true;
-
return 0;
disable_iovcc:
@@ -317,27 +306,11 @@ static int xpp055c272_probe(struct mipi_dsi_device *dsi)
return 0;
}
-static void xpp055c272_shutdown(struct mipi_dsi_device *dsi)
-{
- struct xpp055c272 *ctx = mipi_dsi_get_drvdata(dsi);
- int ret;
-
- ret = drm_panel_unprepare(&ctx->panel);
- if (ret < 0)
- dev_err(&dsi->dev, "Failed to unprepare panel: %d\n", ret);
-
- ret = drm_panel_disable(&ctx->panel);
- if (ret < 0)
- dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret);
-}
-
static void xpp055c272_remove(struct mipi_dsi_device *dsi)
{
struct xpp055c272 *ctx = mipi_dsi_get_drvdata(dsi);
int ret;
- xpp055c272_shutdown(dsi);
-
ret = mipi_dsi_detach(dsi);
if (ret < 0)
dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
@@ -358,7 +331,6 @@ static struct mipi_dsi_driver xpp055c272_driver = {
},
.probe = xpp055c272_probe,
.remove = xpp055c272_remove,
- .shutdown = xpp055c272_shutdown,
};
module_mipi_dsi_driver(xpp055c272_driver);
diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c
index ef9f6c0716d5..671eed4ad890 100644
--- a/drivers/gpu/drm/panfrost/panfrost_drv.c
+++ b/drivers/gpu/drm/panfrost/panfrost_drv.c
@@ -777,6 +777,15 @@ static const struct panfrost_compatible mediatek_mt8186_data = {
.pm_features = BIT(GPU_PM_CLK_DIS) | BIT(GPU_PM_VREG_OFF),
};
+/* MT8188 uses the same power domains and power supplies as MT8183 */
+static const struct panfrost_compatible mediatek_mt8188_data = {
+ .num_supplies = ARRAY_SIZE(mediatek_mt8183_b_supplies) - 1,
+ .supply_names = mediatek_mt8183_b_supplies,
+ .num_pm_domains = ARRAY_SIZE(mediatek_mt8183_pm_domains),
+ .pm_domain_names = mediatek_mt8183_pm_domains,
+ .pm_features = BIT(GPU_PM_CLK_DIS) | BIT(GPU_PM_VREG_OFF),
+};
+
static const char * const mediatek_mt8192_supplies[] = { "mali", NULL };
static const char * const mediatek_mt8192_pm_domains[] = { "core0", "core1", "core2",
"core3", "core4" };
@@ -808,6 +817,7 @@ static const struct of_device_id dt_match[] = {
{ .compatible = "mediatek,mt8183-mali", .data = &mediatek_mt8183_data },
{ .compatible = "mediatek,mt8183b-mali", .data = &mediatek_mt8183_b_data },
{ .compatible = "mediatek,mt8186-mali", .data = &mediatek_mt8186_data },
+ { .compatible = "mediatek,mt8188-mali", .data = &mediatek_mt8188_data },
{ .compatible = "mediatek,mt8192-mali", .data = &mediatek_mt8192_data },
{}
};
@@ -828,3 +838,4 @@ module_platform_driver(panfrost_driver);
MODULE_AUTHOR("Panfrost Project Developers");
MODULE_DESCRIPTION("Panfrost DRM Driver");
MODULE_LICENSE("GPL v2");
+MODULE_SOFTDEP("pre: governor_simpleondemand");
diff --git a/drivers/gpu/drm/panthor/panthor_drv.c b/drivers/gpu/drm/panthor/panthor_drv.c
index b8a84f26b3ef..b5e7b919f241 100644
--- a/drivers/gpu/drm/panthor/panthor_drv.c
+++ b/drivers/gpu/drm/panthor/panthor_drv.c
@@ -86,15 +86,15 @@ panthor_get_uobj_array(const struct drm_panthor_obj_array *in, u32 min_stride,
int ret = 0;
void *out_alloc;
+ if (!in->count)
+ return NULL;
+
/* User stride must be at least the minimum object size, otherwise it might
* lack useful information.
*/
if (in->stride < min_stride)
return ERR_PTR(-EINVAL);
- if (!in->count)
- return NULL;
-
out_alloc = kvmalloc_array(in->count, obj_size, GFP_KERNEL);
if (!out_alloc)
return ERR_PTR(-ENOMEM);
diff --git a/drivers/gpu/drm/panthor/panthor_sched.c b/drivers/gpu/drm/panthor/panthor_sched.c
index 79ffcbc41d78..463bcd3cf00f 100644
--- a/drivers/gpu/drm/panthor/panthor_sched.c
+++ b/drivers/gpu/drm/panthor/panthor_sched.c
@@ -459,6 +459,16 @@ struct panthor_queue {
atomic64_t seqno;
/**
+ * @last_fence: Fence of the last submitted job.
+ *
+ * We return this fence when we get an empty command stream.
+ * This way, we are guaranteed that all earlier jobs have completed
+ * when drm_sched_job::s_fence::finished without having to feed
+ * the CS ring buffer with a dummy job that only signals the fence.
+ */
+ struct dma_fence *last_fence;
+
+ /**
* @in_flight_jobs: List containing all in-flight jobs.
*
* Used to keep track and signal panthor_job::done_fence when the
@@ -829,6 +839,9 @@ static void group_free_queue(struct panthor_group *group, struct panthor_queue *
panthor_kernel_bo_destroy(queue->ringbuf);
panthor_kernel_bo_destroy(queue->iface.mem);
+ /* Release the last_fence we were holding, if any. */
+ dma_fence_put(queue->fence_ctx.last_fence);
+
kfree(queue);
}
@@ -2784,9 +2797,6 @@ static void group_sync_upd_work(struct work_struct *work)
spin_lock(&queue->fence_ctx.lock);
list_for_each_entry_safe(job, job_tmp, &queue->fence_ctx.in_flight_jobs, node) {
- if (!job->call_info.size)
- continue;
-
if (syncobj->seqno < job->done_fence->seqno)
break;
@@ -2865,11 +2875,14 @@ queue_run_job(struct drm_sched_job *sched_job)
static_assert(sizeof(call_instrs) % 64 == 0,
"call_instrs is not aligned on a cacheline");
- /* Stream size is zero, nothing to do => return a NULL fence and let
- * drm_sched signal the parent.
+ /* Stream size is zero, nothing to do except making sure all previously
+ * submitted jobs are done before we signal the
+ * drm_sched_job::s_fence::finished fence.
*/
- if (!job->call_info.size)
- return NULL;
+ if (!job->call_info.size) {
+ job->done_fence = dma_fence_get(queue->fence_ctx.last_fence);
+ return dma_fence_get(job->done_fence);
+ }
ret = pm_runtime_resume_and_get(ptdev->base.dev);
if (drm_WARN_ON(&ptdev->base, ret))
@@ -2926,8 +2939,13 @@ queue_run_job(struct drm_sched_job *sched_job)
pm_runtime_get(ptdev->base.dev);
sched->pm.has_ref = true;
}
+ panthor_devfreq_record_busy(sched->ptdev);
}
+ /* Update the last fence. */
+ dma_fence_put(queue->fence_ctx.last_fence);
+ queue->fence_ctx.last_fence = dma_fence_get(job->done_fence);
+
done_fence = dma_fence_get(job->done_fence);
out_unlock:
@@ -3378,10 +3396,15 @@ panthor_job_create(struct panthor_file *pfile,
goto err_put_job;
}
- job->done_fence = kzalloc(sizeof(*job->done_fence), GFP_KERNEL);
- if (!job->done_fence) {
- ret = -ENOMEM;
- goto err_put_job;
+ /* Empty command streams don't need a fence, they'll pick the one from
+ * the previously submitted job.
+ */
+ if (job->call_info.size) {
+ job->done_fence = kzalloc(sizeof(*job->done_fence), GFP_KERNEL);
+ if (!job->done_fence) {
+ ret = -ENOMEM;
+ goto err_put_job;
+ }
}
ret = drm_sched_job_init(&job->base,
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index c6d35c33d5d6..bc24af08dfcd 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -236,6 +236,9 @@ static int qxl_add_mode(struct drm_connector *connector,
return 0;
mode = drm_cvt_mode(dev, width, height, 60, false, false, false);
+ if (!mode)
+ return 0;
+
if (preferred)
mode->type |= DRM_MODE_TYPE_PREFERRED;
mode->hdisplay = width;
@@ -581,11 +584,11 @@ static struct qxl_bo *qxl_create_cursor(struct qxl_device *qdev,
if (ret)
goto err;
- ret = qxl_bo_vmap(cursor_bo, &cursor_map);
+ ret = qxl_bo_pin_and_vmap(cursor_bo, &cursor_map);
if (ret)
goto err_unref;
- ret = qxl_bo_vmap(user_bo, &user_map);
+ ret = qxl_bo_pin_and_vmap(user_bo, &user_map);
if (ret)
goto err_unmap;
@@ -611,12 +614,12 @@ static struct qxl_bo *qxl_create_cursor(struct qxl_device *qdev,
user_map.vaddr, size);
}
- qxl_bo_vunmap(user_bo);
- qxl_bo_vunmap(cursor_bo);
+ qxl_bo_vunmap_and_unpin(user_bo);
+ qxl_bo_vunmap_and_unpin(cursor_bo);
return cursor_bo;
err_unmap:
- qxl_bo_vunmap(cursor_bo);
+ qxl_bo_vunmap_and_unpin(cursor_bo);
err_unref:
qxl_bo_unpin(cursor_bo);
qxl_bo_unref(&cursor_bo);
@@ -1202,7 +1205,7 @@ int qxl_create_monitors_object(struct qxl_device *qdev)
}
qdev->monitors_config_bo = gem_to_qxl_bo(gobj);
- ret = qxl_bo_vmap(qdev->monitors_config_bo, &map);
+ ret = qxl_bo_pin_and_vmap(qdev->monitors_config_bo, &map);
if (ret)
return ret;
@@ -1233,7 +1236,7 @@ int qxl_destroy_monitors_object(struct qxl_device *qdev)
qdev->monitors_config = NULL;
qdev->ram_header->monitors_config = 0;
- ret = qxl_bo_vunmap(qdev->monitors_config_bo);
+ ret = qxl_bo_vunmap_and_unpin(qdev->monitors_config_bo);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c
index beee5563031a..5eb3f5719fdf 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.c
+++ b/drivers/gpu/drm/qxl/qxl_drv.c
@@ -37,7 +37,7 @@
#include <drm/drm_aperture.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_ttm.h>
#include <drm/drm_file.h>
#include <drm/drm_gem_ttm_helper.h>
#include <drm/drm_module.h>
@@ -118,7 +118,7 @@ qxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (ret)
goto modeset_cleanup;
- drm_fbdev_generic_setup(&qdev->ddev, 32);
+ drm_fbdev_ttm_setup(&qdev->ddev, 32);
return 0;
modeset_cleanup:
diff --git a/drivers/gpu/drm/qxl/qxl_object.c b/drivers/gpu/drm/qxl/qxl_object.c
index 5893e27a7ae5..66635c55cf85 100644
--- a/drivers/gpu/drm/qxl/qxl_object.c
+++ b/drivers/gpu/drm/qxl/qxl_object.c
@@ -182,7 +182,7 @@ out:
return 0;
}
-int qxl_bo_vmap(struct qxl_bo *bo, struct iosys_map *map)
+int qxl_bo_pin_and_vmap(struct qxl_bo *bo, struct iosys_map *map)
{
int r;
@@ -190,7 +190,15 @@ int qxl_bo_vmap(struct qxl_bo *bo, struct iosys_map *map)
if (r)
return r;
+ r = qxl_bo_pin_locked(bo);
+ if (r) {
+ qxl_bo_unreserve(bo);
+ return r;
+ }
+
r = qxl_bo_vmap_locked(bo, map);
+ if (r)
+ qxl_bo_unpin_locked(bo);
qxl_bo_unreserve(bo);
return r;
}
@@ -241,7 +249,7 @@ void qxl_bo_vunmap_locked(struct qxl_bo *bo)
ttm_bo_vunmap(&bo->tbo, &bo->map);
}
-int qxl_bo_vunmap(struct qxl_bo *bo)
+int qxl_bo_vunmap_and_unpin(struct qxl_bo *bo)
{
int r;
@@ -250,6 +258,7 @@ int qxl_bo_vunmap(struct qxl_bo *bo)
return r;
qxl_bo_vunmap_locked(bo);
+ qxl_bo_unpin_locked(bo);
qxl_bo_unreserve(bo);
return 0;
}
diff --git a/drivers/gpu/drm/qxl/qxl_object.h b/drivers/gpu/drm/qxl/qxl_object.h
index 1cf5bc759101..875f63221074 100644
--- a/drivers/gpu/drm/qxl/qxl_object.h
+++ b/drivers/gpu/drm/qxl/qxl_object.h
@@ -59,9 +59,9 @@ extern int qxl_bo_create(struct qxl_device *qdev,
u32 priority,
struct qxl_surface *surf,
struct qxl_bo **bo_ptr);
-int qxl_bo_vmap(struct qxl_bo *bo, struct iosys_map *map);
+int qxl_bo_pin_and_vmap(struct qxl_bo *bo, struct iosys_map *map);
int qxl_bo_vmap_locked(struct qxl_bo *bo, struct iosys_map *map);
-int qxl_bo_vunmap(struct qxl_bo *bo);
+int qxl_bo_vunmap_and_unpin(struct qxl_bo *bo);
void qxl_bo_vunmap_locked(struct qxl_bo *bo);
void *qxl_bo_kmap_atomic_page(struct qxl_device *qdev, struct qxl_bo *bo, int page_offset);
void qxl_bo_kunmap_atomic_page(struct qxl_device *qdev, struct qxl_bo *bo, void *map);
diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c
index 7b11674f5d45..03e6871b3065 100644
--- a/drivers/gpu/drm/radeon/atombios_encoders.c
+++ b/drivers/gpu/drm/radeon/atombios_encoders.c
@@ -701,7 +701,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
if (radeon_connector->use_digital &&
(radeon_connector->audio == RADEON_AUDIO_ENABLE))
return ATOM_ENCODER_MODE_HDMI;
- else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) &&
+ else if (connector->display_info.is_hdmi &&
(radeon_connector->audio == RADEON_AUDIO_AUTO))
return ATOM_ENCODER_MODE_HDMI;
else if (radeon_connector->use_digital)
@@ -720,7 +720,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
if (radeon_audio != 0) {
if (radeon_connector->audio == RADEON_AUDIO_ENABLE)
return ATOM_ENCODER_MODE_HDMI;
- else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) &&
+ else if (connector->display_info.is_hdmi &&
(radeon_connector->audio == RADEON_AUDIO_AUTO))
return ATOM_ENCODER_MODE_HDMI;
else
@@ -737,14 +737,14 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
(dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) {
if (radeon_audio != 0 &&
- drm_detect_monitor_audio(radeon_connector_edid(connector)) &&
+ connector->display_info.has_audio &&
ASIC_IS_DCE4(rdev) && !ASIC_IS_DCE5(rdev))
return ATOM_ENCODER_MODE_DP_AUDIO;
return ATOM_ENCODER_MODE_DP;
} else if (radeon_audio != 0) {
if (radeon_connector->audio == RADEON_AUDIO_ENABLE)
return ATOM_ENCODER_MODE_HDMI;
- else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) &&
+ else if (connector->display_info.is_hdmi &&
(radeon_connector->audio == RADEON_AUDIO_AUTO))
return ATOM_ENCODER_MODE_HDMI;
else
@@ -755,7 +755,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
break;
case DRM_MODE_CONNECTOR_eDP:
if (radeon_audio != 0 &&
- drm_detect_monitor_audio(radeon_connector_edid(connector)) &&
+ connector->display_info.has_audio &&
ASIC_IS_DCE4(rdev) && !ASIC_IS_DCE5(rdev))
return ATOM_ENCODER_MODE_DP_AUDIO;
return ATOM_ENCODER_MODE_DP;
diff --git a/drivers/gpu/drm/radeon/evergreen_hdmi.c b/drivers/gpu/drm/radeon/evergreen_hdmi.c
index 681119c91d94..09dda114e218 100644
--- a/drivers/gpu/drm/radeon/evergreen_hdmi.c
+++ b/drivers/gpu/drm/radeon/evergreen_hdmi.c
@@ -412,7 +412,7 @@ void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable)
if (enable) {
struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
- if (connector && drm_detect_monitor_audio(radeon_connector_edid(connector))) {
+ if (connector && connector->display_info.has_audio) {
WREG32(HDMI_INFOFRAME_CONTROL0 + dig->afmt->offset,
HDMI_AVI_INFO_SEND | /* enable AVI info frames */
HDMI_AVI_INFO_CONT | /* required for audio info values to be updated */
@@ -450,8 +450,7 @@ void evergreen_dp_enable(struct drm_encoder *encoder, bool enable)
if (!dig || !dig->afmt)
return;
- if (enable && connector &&
- drm_detect_monitor_audio(radeon_connector_edid(connector))) {
+ if (enable && connector && connector->display_info.has_audio) {
struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
struct radeon_connector_atom_dig *dig_connector;
diff --git a/drivers/gpu/drm/radeon/radeon_audio.c b/drivers/gpu/drm/radeon/radeon_audio.c
index 74753bb26d33..0bcd767b9f47 100644
--- a/drivers/gpu/drm/radeon/radeon_audio.c
+++ b/drivers/gpu/drm/radeon/radeon_audio.c
@@ -303,6 +303,7 @@ void radeon_audio_endpoint_wreg(struct radeon_device *rdev, u32 offset,
static void radeon_audio_write_sad_regs(struct drm_encoder *encoder)
{
struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
+ struct radeon_connector *radeon_connector = to_radeon_connector(connector);
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct cea_sad *sads;
int sad_count;
@@ -310,7 +311,7 @@ static void radeon_audio_write_sad_regs(struct drm_encoder *encoder)
if (!connector)
return;
- sad_count = drm_edid_to_sad(radeon_connector_edid(connector), &sads);
+ sad_count = drm_edid_to_sad(radeon_connector->edid, &sads);
if (sad_count < 0)
DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
if (sad_count <= 0)
@@ -326,6 +327,7 @@ static void radeon_audio_write_sad_regs(struct drm_encoder *encoder)
static void radeon_audio_write_speaker_allocation(struct drm_encoder *encoder)
{
struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
+ struct radeon_connector *radeon_connector = to_radeon_connector(connector);
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
u8 *sadb = NULL;
int sad_count;
@@ -333,8 +335,7 @@ static void radeon_audio_write_speaker_allocation(struct drm_encoder *encoder)
if (!connector)
return;
- sad_count = drm_edid_to_speaker_allocation(radeon_connector_edid(connector),
- &sadb);
+ sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb);
if (sad_count < 0) {
DRM_DEBUG("Couldn't read Speaker Allocation Data Block: %d\n",
sad_count);
@@ -409,7 +410,7 @@ void radeon_audio_detect(struct drm_connector *connector,
radeon_encoder->audio = rdev->audio.hdmi_funcs;
}
- if (drm_detect_monitor_audio(radeon_connector_edid(connector))) {
+ if (connector->display_info.has_audio) {
if (!dig->pin)
dig->pin = radeon_audio_get_pin(encoder);
radeon_audio_enable(rdev, dig->pin, 0xf);
@@ -646,7 +647,7 @@ static void radeon_audio_hdmi_mode_set(struct drm_encoder *encoder,
if (!connector)
return;
- if (drm_detect_monitor_audio(radeon_connector_edid(connector))) {
+ if (connector->display_info.has_audio) {
radeon_audio_set_mute(encoder, true);
radeon_audio_write_speaker_allocation(encoder);
@@ -686,7 +687,7 @@ static void radeon_audio_dp_mode_set(struct drm_encoder *encoder,
if (!connector)
return;
- if (drm_detect_monitor_audio(radeon_connector_edid(connector))) {
+ if (connector->display_info.has_audio) {
radeon_audio_write_speaker_allocation(encoder);
radeon_audio_write_sad_regs(encoder);
radeon_audio_write_latency_fields(encoder, mode);
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index cf0114ca59a4..69693ba5949e 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -109,7 +109,7 @@ int radeon_get_monitor_bpc(struct drm_connector *connector)
case DRM_MODE_CONNECTOR_DVII:
case DRM_MODE_CONNECTOR_HDMIB:
if (radeon_connector->use_digital) {
- if (drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
+ if (connector->display_info.is_hdmi) {
if (connector->display_info.bpc)
bpc = connector->display_info.bpc;
}
@@ -117,7 +117,7 @@ int radeon_get_monitor_bpc(struct drm_connector *connector)
break;
case DRM_MODE_CONNECTOR_DVID:
case DRM_MODE_CONNECTOR_HDMIA:
- if (drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
+ if (connector->display_info.is_hdmi) {
if (connector->display_info.bpc)
bpc = connector->display_info.bpc;
}
@@ -126,7 +126,7 @@ int radeon_get_monitor_bpc(struct drm_connector *connector)
dig_connector = radeon_connector->con_priv;
if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
(dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) ||
- drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
+ connector->display_info.is_hdmi) {
if (connector->display_info.bpc)
bpc = connector->display_info.bpc;
}
@@ -150,7 +150,7 @@ int radeon_get_monitor_bpc(struct drm_connector *connector)
break;
}
- if (drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
+ if (connector->display_info.is_hdmi) {
/* hdmi deep color only implemented on DCE4+ */
if ((bpc > 8) && !ASIC_IS_DCE4(rdev)) {
DRM_DEBUG("%s: HDMI deep color %d bpc unsupported. Using 8 bpc.\n",
@@ -255,21 +255,6 @@ static struct drm_encoder *radeon_find_encoder(struct drm_connector *connector,
return NULL;
}
-struct edid *radeon_connector_edid(struct drm_connector *connector)
-{
- struct radeon_connector *radeon_connector = to_radeon_connector(connector);
- struct drm_property_blob *edid_blob = connector->edid_blob_ptr;
-
- if (radeon_connector->edid) {
- return radeon_connector->edid;
- } else if (edid_blob) {
- struct edid *edid = kmemdup(edid_blob->data, edid_blob->length, GFP_KERNEL);
- if (edid)
- radeon_connector->edid = edid;
- }
- return radeon_connector->edid;
-}
-
static void radeon_connector_get_edid(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
@@ -1488,7 +1473,7 @@ static enum drm_mode_status radeon_dvi_mode_valid(struct drm_connector *connecto
(radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D) ||
(radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_HDMI_TYPE_B))
return MODE_OK;
- else if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
+ else if (ASIC_IS_DCE6(rdev) && connector->display_info.is_hdmi) {
/* HDMI 1.3+ supports max clock of 340 Mhz */
if (mode->clock > 340000)
return MODE_CLOCK_HIGH;
@@ -1784,7 +1769,7 @@ static enum drm_mode_status radeon_dp_mode_valid(struct drm_connector *connector
(radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) {
return radeon_dp_mode_valid_helper(connector, mode);
} else {
- if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
+ if (ASIC_IS_DCE6(rdev) && connector->display_info.is_hdmi) {
/* HDMI 1.3+ supports max clock of 340 Mhz */
if (mode->clock > 340000)
return MODE_CLOCK_HIGH;
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 5f1d24d3120c..843383f7237f 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -1722,7 +1722,7 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
(!(mode->flags & DRM_MODE_FLAG_INTERLACE)) &&
((radeon_encoder->underscan_type == UNDERSCAN_ON) ||
((radeon_encoder->underscan_type == UNDERSCAN_AUTO) &&
- drm_detect_hdmi_monitor(radeon_connector_edid(connector)) &&
+ connector->display_info.is_hdmi &&
is_hdtv_mode(mode)))) {
if (radeon_encoder->underscan_hborder != 0)
radeon_crtc->h_border = radeon_encoder->underscan_hborder;
diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c
index 3de3dce9e89d..0f723292409e 100644
--- a/drivers/gpu/drm/radeon/radeon_encoders.c
+++ b/drivers/gpu/drm/radeon/radeon_encoders.c
@@ -386,7 +386,7 @@ bool radeon_dig_monitor_is_duallink(struct drm_encoder *encoder,
case DRM_MODE_CONNECTOR_HDMIB:
if (radeon_connector->use_digital) {
/* HDMI 1.3 supports up to 340 Mhz over single link */
- if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
+ if (ASIC_IS_DCE6(rdev) && connector->display_info.is_hdmi) {
if (pixel_clock > 340000)
return true;
else
@@ -408,7 +408,7 @@ bool radeon_dig_monitor_is_duallink(struct drm_encoder *encoder,
return false;
else {
/* HDMI 1.3 supports up to 340 Mhz over single link */
- if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
+ if (ASIC_IS_DCE6(rdev) && connector->display_info.is_hdmi) {
if (pixel_clock > 340000)
return true;
else
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c
index 2ef201a072f1..e66a230331ee 100644
--- a/drivers/gpu/drm/radeon/radeon_gem.c
+++ b/drivers/gpu/drm/radeon/radeon_gem.c
@@ -642,7 +642,7 @@ static void radeon_gem_va_update_vm(struct radeon_device *rdev,
if (r)
goto error_unlock;
- if (bo_va->it.start)
+ if (bo_va->it.start && bo_va->bo)
r = radeon_vm_bo_update(rdev, bo_va, bo_va->bo->tbo.resource);
error_unlock:
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 546381a5c918..e0a5af180801 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -701,8 +701,6 @@ extern u16 radeon_connector_encoder_get_dp_bridge_encoder_id(struct drm_connecto
extern bool radeon_connector_is_dp12_capable(struct drm_connector *connector);
extern int radeon_get_monitor_bpc(struct drm_connector *connector);
-extern struct edid *radeon_connector_edid(struct drm_connector *connector);
-
extern void radeon_connector_hotplug(struct drm_connector *connector);
extern int radeon_dp_mode_valid_helper(struct drm_connector *connector,
struct drm_display_mode *mode);
diff --git a/drivers/gpu/drm/radeon/sumo_dpm.c b/drivers/gpu/drm/radeon/sumo_dpm.c
index 21d27e6235f3..b11f7c5bbcbe 100644
--- a/drivers/gpu/drm/radeon/sumo_dpm.c
+++ b/drivers/gpu/drm/radeon/sumo_dpm.c
@@ -1619,6 +1619,8 @@ void sumo_construct_vid_mapping_table(struct radeon_device *rdev,
for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++) {
if (table[i].ulSupportedSCLK != 0) {
+ if (table[i].usVoltageIndex >= SUMO_MAX_NUMBER_VOLTAGES)
+ continue;
vid_mapping_table->entries[table[i].usVoltageIndex].vid_7bit =
table[i].usVoltageID;
vid_mapping_table->entries[table[i].usVoltageIndex].vid_2bit =
diff --git a/drivers/gpu/drm/renesas/rcar-du/Kconfig b/drivers/gpu/drm/renesas/rcar-du/Kconfig
index 53c356aed5d5..c17e7c50492c 100644
--- a/drivers/gpu/drm/renesas/rcar-du/Kconfig
+++ b/drivers/gpu/drm/renesas/rcar-du/Kconfig
@@ -2,7 +2,7 @@
config DRM_RCAR_DU
tristate "DRM Support for R-Car Display Unit"
depends on DRM && OF
- depends on ARM || ARM64
+ depends on ARM || ARM64 || COMPILE_TEST
depends on ARCH_RENESAS || COMPILE_TEST
select DRM_KMS_HELPER
select DRM_GEM_DMA_HELPER
diff --git a/drivers/gpu/drm/renesas/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/renesas/rcar-du/rcar_du_drv.c
index dee530e4c8b2..fb719d9aff10 100644
--- a/drivers/gpu/drm/renesas/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_du_drv.c
@@ -20,7 +20,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_dma.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_managed.h>
#include <drm/drm_probe_helper.h>
@@ -716,7 +716,7 @@ static int rcar_du_probe(struct platform_device *pdev)
drm_info(&rcdu->ddev, "Device %s probed\n", dev_name(&pdev->dev));
- drm_fbdev_generic_setup(&rcdu->ddev, 32);
+ drm_fbdev_dma_setup(&rcdu->ddev, 32);
return 0;
diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_du_drv.c b/drivers/gpu/drm/renesas/rz-du/rzg2l_du_drv.c
index 470d34da1d6c..e5eca8691a33 100644
--- a/drivers/gpu/drm/renesas/rz-du/rzg2l_du_drv.c
+++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_du_drv.c
@@ -14,7 +14,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_dma.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_probe_helper.h>
@@ -149,7 +149,7 @@ static int rzg2l_du_probe(struct platform_device *pdev)
drm_info(&rcdu->ddev, "Device %s probed\n", dev_name(&pdev->dev));
- drm_fbdev_generic_setup(&rcdu->ddev, 32);
+ drm_fbdev_dma_setup(&rcdu->ddev, 32);
return 0;
diff --git a/drivers/gpu/drm/renesas/shmobile/shmob_drm_drv.c b/drivers/gpu/drm/renesas/shmobile/shmob_drm_drv.c
index e83c3e52251d..ff2883c7fd46 100644
--- a/drivers/gpu/drm/renesas/shmobile/shmob_drm_drv.c
+++ b/drivers/gpu/drm/renesas/shmobile/shmob_drm_drv.c
@@ -19,7 +19,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_dma.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_modeset_helper.h>
#include <drm/drm_module.h>
@@ -171,6 +171,13 @@ static void shmob_drm_remove(struct platform_device *pdev)
drm_kms_helper_poll_fini(ddev);
}
+static void shmob_drm_shutdown(struct platform_device *pdev)
+{
+ struct shmob_drm_device *sdev = platform_get_drvdata(pdev);
+
+ drm_atomic_helper_shutdown(&sdev->ddev);
+}
+
static int shmob_drm_probe(struct platform_device *pdev)
{
struct shmob_drm_platform_data *pdata = pdev->dev.platform_data;
@@ -250,7 +257,7 @@ static int shmob_drm_probe(struct platform_device *pdev)
if (ret < 0)
goto err_modeset_cleanup;
- drm_fbdev_generic_setup(ddev, 16);
+ drm_fbdev_dma_setup(ddev, 16);
return 0;
@@ -273,6 +280,7 @@ static const struct of_device_id shmob_drm_of_table[] __maybe_unused = {
static struct platform_driver shmob_drm_platform_driver = {
.probe = shmob_drm_probe,
.remove_new = shmob_drm_remove,
+ .shutdown = shmob_drm_shutdown,
.driver = {
.name = "shmob-drm",
.of_match_table = of_match_ptr(shmob_drm_of_table),
diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
index 1bf3e2829cd0..7df875e38517 100644
--- a/drivers/gpu/drm/rockchip/Kconfig
+++ b/drivers/gpu/drm/rockchip/Kconfig
@@ -74,6 +74,9 @@ config ROCKCHIP_DW_MIPI_DSI
config ROCKCHIP_INNO_HDMI
bool "Rockchip specific extensions for Innosilicon HDMI"
+ select DRM_DISPLAY_HDMI_HELPER
+ select DRM_DISPLAY_HDMI_STATE_HELPER
+ select DRM_DISPLAY_HELPER
help
This selects support for Rockchip SoC specific extensions
for the Innosilicon HDMI driver. If you want to enable
diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index 7069a3d4d581..362c7951ca4a 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -13,6 +13,7 @@
#include <linux/of.h>
#include <linux/of_graph.h>
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/reset.h>
#include <linux/clk.h>
@@ -92,7 +93,7 @@ static int rockchip_dp_pre_init(struct rockchip_dp_device *dp)
return 0;
}
-static int rockchip_dp_poweron_start(struct analogix_dp_plat_data *plat_data)
+static int rockchip_dp_poweron(struct analogix_dp_plat_data *plat_data)
{
struct rockchip_dp_device *dp = pdata_encoder_to_dp(plat_data);
int ret;
@@ -397,7 +398,7 @@ static int rockchip_dp_probe(struct platform_device *pdev)
dp->data = dp_data;
dp->plat_data.panel = panel;
dp->plat_data.dev_type = dp->data->chip_type;
- dp->plat_data.power_on_start = rockchip_dp_poweron_start;
+ dp->plat_data.power_on = rockchip_dp_poweron;
dp->plat_data.power_off = rockchip_dp_powerdown;
dp->plat_data.get_modes = rockchip_dp_get_modes;
@@ -413,24 +414,16 @@ static int rockchip_dp_probe(struct platform_device *pdev)
ret = component_add(dev, &rockchip_dp_component_ops);
if (ret)
- goto err_dp_remove;
+ return ret;
return 0;
-
-err_dp_remove:
- analogix_dp_remove(dp->adp);
- return ret;
}
static void rockchip_dp_remove(struct platform_device *pdev)
{
- struct rockchip_dp_device *dp = platform_get_drvdata(pdev);
-
component_del(&pdev->dev, &rockchip_dp_component_ops);
- analogix_dp_remove(dp->adp);
}
-#ifdef CONFIG_PM_SLEEP
static int rockchip_dp_suspend(struct device *dev)
{
struct rockchip_dp_device *dp = dev_get_drvdata(dev);
@@ -450,14 +443,9 @@ static int rockchip_dp_resume(struct device *dev)
return analogix_dp_resume(dp->adp);
}
-#endif
-static const struct dev_pm_ops rockchip_dp_pm_ops = {
-#ifdef CONFIG_PM_SLEEP
- .suspend_late = rockchip_dp_suspend,
- .resume_early = rockchip_dp_resume,
-#endif
-};
+static DEFINE_RUNTIME_DEV_PM_OPS(rockchip_dp_pm_ops, rockchip_dp_suspend,
+ rockchip_dp_resume, NULL);
static const struct rockchip_dp_chip_data rk3399_edp = {
.lcdsel_grf_reg = RK3399_GRF_SOC_CON20,
@@ -485,7 +473,7 @@ struct platform_driver rockchip_dp_driver = {
.remove_new = rockchip_dp_remove,
.driver = {
.name = "rockchip-dp",
- .pm = &rockchip_dp_pm_ops,
+ .pm = pm_ptr(&rockchip_dp_pm_ops),
.of_match_table = rockchip_dp_dt_ids,
},
};
diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c
index 4cc8ed8f4fbd..58a44af0e9ad 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c
@@ -153,6 +153,11 @@
#define PX30_DSI_TURNDISABLE BIT(5)
#define PX30_DSI_LCDC_SEL BIT(0)
+#define RK3128_GRF_LVDS_CON0 0x0150
+#define RK3128_DSI_FORCETXSTOPMODE GENMASK(13, 10)
+#define RK3128_DSI_FORCERXMODE BIT(9)
+#define RK3128_DSI_TURNDISABLE BIT(8)
+
#define RK3288_GRF_SOC_CON6 0x025c
#define RK3288_DSI0_LCDC_SEL BIT(6)
#define RK3288_DSI1_LCDC_SEL BIT(9)
@@ -1493,6 +1498,18 @@ static const struct rockchip_dw_dsi_chip_data px30_chip_data[] = {
{ /* sentinel */ }
};
+static const struct rockchip_dw_dsi_chip_data rk3128_chip_data[] = {
+ {
+ .reg = 0x10110000,
+ .lanecfg1_grf_reg = RK3128_GRF_LVDS_CON0,
+ .lanecfg1 = HIWORD_UPDATE(0, RK3128_DSI_TURNDISABLE |
+ RK3128_DSI_FORCERXMODE |
+ RK3128_DSI_FORCETXSTOPMODE),
+ .max_data_lanes = 4,
+ },
+ { /* sentinel */ }
+};
+
static const struct rockchip_dw_dsi_chip_data rk3288_chip_data[] = {
{
.reg = 0xff960000,
@@ -1671,6 +1688,9 @@ static const struct of_device_id dw_mipi_dsi_rockchip_dt_ids[] = {
.compatible = "rockchip,px30-mipi-dsi",
.data = &px30_chip_data,
}, {
+ .compatible = "rockchip,rk3128-mipi-dsi",
+ .data = &rk3128_chip_data,
+ }, {
.compatible = "rockchip,rk3288-mipi-dsi",
.data = &rk3288_chip_data,
}, {
diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c
index 3df2cfcf9998..2241e53a2946 100644
--- a/drivers/gpu/drm/rockchip/inno_hdmi.c
+++ b/drivers/gpu/drm/rockchip/inno_hdmi.c
@@ -22,6 +22,9 @@
#include <drm/drm_probe_helper.h>
#include <drm/drm_simple_kms_helper.h>
+#include <drm/display/drm_hdmi_helper.h>
+#include <drm/display/drm_hdmi_state_helper.h>
+
#include "rockchip_drm_drv.h"
#include "inno_hdmi.h"
@@ -67,9 +70,7 @@ struct inno_hdmi {
struct inno_hdmi_connector_state {
struct drm_connector_state base;
- unsigned int enc_out_format;
unsigned int colorimetry;
- bool rgb_limited_range;
};
static struct inno_hdmi *encoder_to_inno_hdmi(struct drm_encoder *encoder)
@@ -257,26 +258,29 @@ static void inno_hdmi_reset(struct inno_hdmi *hdmi)
inno_hdmi_standby(hdmi);
}
-static void inno_hdmi_disable_frame(struct inno_hdmi *hdmi,
- enum hdmi_infoframe_type type)
+static int inno_hdmi_disable_frame(struct drm_connector *connector,
+ enum hdmi_infoframe_type type)
{
- struct drm_connector *connector = &hdmi->connector;
+ struct inno_hdmi *hdmi = connector_to_inno_hdmi(connector);
if (type != HDMI_INFOFRAME_TYPE_AVI) {
drm_err(connector->dev,
"Unsupported infoframe type: %u\n", type);
- return;
+ return 0;
}
hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_BUF_INDEX, INFOFRAME_AVI);
+
+ return 0;
}
-static int inno_hdmi_upload_frame(struct inno_hdmi *hdmi,
- union hdmi_infoframe *frame, enum hdmi_infoframe_type type)
+static int inno_hdmi_upload_frame(struct drm_connector *connector,
+ enum hdmi_infoframe_type type,
+ const u8 *buffer, size_t len)
{
- struct drm_connector *connector = &hdmi->connector;
+ struct inno_hdmi *hdmi = connector_to_inno_hdmi(connector);
u8 packed_frame[HDMI_MAXIMUM_INFO_FRAME_SIZE];
- ssize_t rc, i;
+ ssize_t i;
if (type != HDMI_INFOFRAME_TYPE_AVI) {
drm_err(connector->dev,
@@ -284,59 +288,19 @@ static int inno_hdmi_upload_frame(struct inno_hdmi *hdmi,
return 0;
}
- inno_hdmi_disable_frame(hdmi, type);
-
- rc = hdmi_infoframe_pack(frame, packed_frame,
- sizeof(packed_frame));
- if (rc < 0)
- return rc;
+ inno_hdmi_disable_frame(connector, type);
- for (i = 0; i < rc; i++)
+ for (i = 0; i < len; i++)
hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_ADDR + i,
packed_frame[i]);
return 0;
}
-static int inno_hdmi_config_video_avi(struct inno_hdmi *hdmi,
- struct drm_display_mode *mode)
-{
- struct drm_connector *connector = &hdmi->connector;
- struct drm_connector_state *conn_state = connector->state;
- struct inno_hdmi_connector_state *inno_conn_state =
- to_inno_hdmi_conn_state(conn_state);
- union hdmi_infoframe frame;
- int rc;
-
- rc = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
- &hdmi->connector,
- mode);
- if (rc) {
- inno_hdmi_disable_frame(hdmi, HDMI_INFOFRAME_TYPE_AVI);
- return rc;
- }
-
- if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_YUV444)
- frame.avi.colorspace = HDMI_COLORSPACE_YUV444;
- else if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_YUV422)
- frame.avi.colorspace = HDMI_COLORSPACE_YUV422;
- else
- frame.avi.colorspace = HDMI_COLORSPACE_RGB;
-
- if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_RGB) {
- drm_hdmi_avi_infoframe_quant_range(&frame.avi,
- connector, mode,
- inno_conn_state->rgb_limited_range ?
- HDMI_QUANTIZATION_RANGE_LIMITED :
- HDMI_QUANTIZATION_RANGE_FULL);
- } else {
- frame.avi.quantization_range = HDMI_QUANTIZATION_RANGE_DEFAULT;
- frame.avi.ycc_quantization_range =
- HDMI_YCC_QUANTIZATION_RANGE_LIMITED;
- }
-
- return inno_hdmi_upload_frame(hdmi, &frame, HDMI_INFOFRAME_TYPE_AVI);
-}
+static const struct drm_connector_hdmi_funcs inno_hdmi_hdmi_connector_funcs = {
+ .clear_infoframe = inno_hdmi_disable_frame,
+ .write_infoframe = inno_hdmi_upload_frame,
+};
static int inno_hdmi_config_video_csc(struct inno_hdmi *hdmi)
{
@@ -361,8 +325,8 @@ static int inno_hdmi_config_video_csc(struct inno_hdmi *hdmi)
v_VIDEO_INPUT_CSP(0);
hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL2, value);
- if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_RGB) {
- if (inno_conn_state->rgb_limited_range) {
+ if (conn_state->hdmi.output_format == HDMI_COLORSPACE_RGB) {
+ if (conn_state->hdmi.is_limited_range) {
csc_mode = CSC_RGB_0_255_TO_RGB_16_235_8BIT;
auto_csc = AUTO_CSC_DISABLE;
c0_c2_change = C0_C2_CHANGE_DISABLE;
@@ -380,14 +344,14 @@ static int inno_hdmi_config_video_csc(struct inno_hdmi *hdmi)
}
} else {
if (inno_conn_state->colorimetry == HDMI_COLORIMETRY_ITU_601) {
- if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_YUV444) {
+ if (conn_state->hdmi.output_format == HDMI_COLORSPACE_YUV444) {
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 (inno_conn_state->enc_out_format == HDMI_COLORSPACE_YUV444) {
+ if (conn_state->hdmi.output_format == HDMI_COLORSPACE_YUV444) {
csc_mode = CSC_RGB_0_255_TO_ITU709_16_235_8BIT;
auto_csc = AUTO_CSC_DISABLE;
c0_c2_change = C0_C2_CHANGE_DISABLE;
@@ -462,10 +426,20 @@ static int inno_hdmi_config_video_timing(struct inno_hdmi *hdmi,
}
static int inno_hdmi_setup(struct inno_hdmi *hdmi,
- struct drm_display_mode *mode)
+ struct drm_atomic_state *state)
{
- struct drm_display_info *display = &hdmi->connector.display_info;
- unsigned long mpixelclock = mode->clock * 1000;
+ struct drm_connector *connector = &hdmi->connector;
+ struct drm_display_info *display = &connector->display_info;
+ struct drm_connector_state *new_conn_state;
+ struct drm_crtc_state *new_crtc_state;
+
+ new_conn_state = drm_atomic_get_new_connector_state(state, connector);
+ if (WARN_ON(!new_conn_state))
+ return -EINVAL;
+
+ new_crtc_state = drm_atomic_get_new_crtc_state(state, new_conn_state->crtc);
+ if (WARN_ON(!new_crtc_state))
+ return -EINVAL;
/* Mute video and audio output */
hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_VIDEO_BLACK,
@@ -475,12 +449,11 @@ static int inno_hdmi_setup(struct inno_hdmi *hdmi,
hdmi_writeb(hdmi, HDMI_HDCP_CTRL,
v_HDMI_DVI(display->is_hdmi));
- inno_hdmi_config_video_timing(hdmi, mode);
+ inno_hdmi_config_video_timing(hdmi, &new_crtc_state->adjusted_mode);
inno_hdmi_config_video_csc(hdmi);
- if (display->is_hdmi)
- inno_hdmi_config_video_avi(hdmi, mode);
+ drm_atomic_helper_connector_hdmi_update_infoframes(connector, state);
/*
* When IP controller have configured to an accurate video
@@ -488,13 +461,13 @@ static int inno_hdmi_setup(struct inno_hdmi *hdmi,
* DCLK_LCDC, so we need to init the TMDS rate to mode pixel
* clock rate, and reconfigure the DDC clock.
*/
- inno_hdmi_i2c_init(hdmi, mpixelclock);
+ inno_hdmi_i2c_init(hdmi, new_conn_state->hdmi.tmds_char_rate);
/* Unmute video and audio output */
hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_VIDEO_BLACK,
v_AUDIO_MUTE(0) | v_VIDEO_MUTE(0));
- inno_hdmi_power_up(hdmi, mpixelclock);
+ inno_hdmi_power_up(hdmi, new_conn_state->hdmi.tmds_char_rate);
return 0;
}
@@ -535,18 +508,8 @@ static void inno_hdmi_encoder_enable(struct drm_encoder *encoder,
struct drm_atomic_state *state)
{
struct inno_hdmi *hdmi = encoder_to_inno_hdmi(encoder);
- struct drm_connector_state *conn_state;
- struct drm_crtc_state *crtc_state;
- conn_state = drm_atomic_get_new_connector_state(state, &hdmi->connector);
- if (WARN_ON(!conn_state))
- return;
-
- crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc);
- if (WARN_ON(!crtc_state))
- return;
-
- inno_hdmi_setup(hdmi, &crtc_state->adjusted_mode);
+ inno_hdmi_setup(hdmi, state);
}
static void inno_hdmi_encoder_disable(struct drm_encoder *encoder,
@@ -563,7 +526,6 @@ inno_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
struct drm_connector_state *conn_state)
{
struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
- struct inno_hdmi *hdmi = encoder_to_inno_hdmi(encoder);
struct drm_display_mode *mode = &crtc_state->adjusted_mode;
u8 vic = drm_match_cea_mode(mode);
struct inno_hdmi_connector_state *inno_conn_state =
@@ -580,12 +542,7 @@ inno_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
else
inno_conn_state->colorimetry = HDMI_COLORIMETRY_ITU_709;
- inno_conn_state->enc_out_format = HDMI_COLORSPACE_RGB;
- inno_conn_state->rgb_limited_range =
- drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_LIMITED;
-
- return inno_hdmi_display_mode_valid(hdmi,
- &crtc_state->adjusted_mode) == MODE_OK ? 0 : -EINVAL;
+ return 0;
}
static struct drm_encoder_helper_funcs inno_hdmi_encoder_helper_funcs = {
@@ -629,12 +586,6 @@ inno_hdmi_connector_mode_valid(struct drm_connector *connector,
return inno_hdmi_display_mode_valid(hdmi, mode);
}
-static void inno_hdmi_connector_destroy(struct drm_connector *connector)
-{
- drm_connector_unregister(connector);
- drm_connector_cleanup(connector);
-}
-
static void
inno_hdmi_connector_destroy_state(struct drm_connector *connector,
struct drm_connector_state *state)
@@ -660,10 +611,9 @@ static void inno_hdmi_connector_reset(struct drm_connector *connector)
return;
__drm_atomic_helper_connector_reset(connector, &inno_conn_state->base);
+ __drm_atomic_helper_connector_hdmi_reset(connector, connector->state);
inno_conn_state->colorimetry = HDMI_COLORIMETRY_ITU_709;
- inno_conn_state->enc_out_format = HDMI_COLORSPACE_RGB;
- inno_conn_state->rgb_limited_range = false;
}
static struct drm_connector_state *
@@ -689,13 +639,13 @@ inno_hdmi_connector_duplicate_state(struct drm_connector *connector)
static const struct drm_connector_funcs inno_hdmi_connector_funcs = {
.fill_modes = drm_helper_probe_single_connector_modes,
.detect = inno_hdmi_connector_detect,
- .destroy = inno_hdmi_connector_destroy,
.reset = inno_hdmi_connector_reset,
.atomic_duplicate_state = inno_hdmi_connector_duplicate_state,
.atomic_destroy_state = inno_hdmi_connector_destroy_state,
};
static struct drm_connector_helper_funcs inno_hdmi_connector_helper_funcs = {
+ .atomic_check = drm_atomic_helper_connector_hdmi_check,
.get_modes = inno_hdmi_connector_get_modes,
.mode_valid = inno_hdmi_connector_mode_valid,
};
@@ -723,10 +673,14 @@ static int inno_hdmi_register(struct drm_device *drm, struct inno_hdmi *hdmi)
drm_connector_helper_add(&hdmi->connector,
&inno_hdmi_connector_helper_funcs);
- drm_connector_init_with_ddc(drm, &hdmi->connector,
- &inno_hdmi_connector_funcs,
- DRM_MODE_CONNECTOR_HDMIA,
- hdmi->ddc);
+ drmm_connector_hdmi_init(drm, &hdmi->connector,
+ "Rockchip", "Inno HDMI",
+ &inno_hdmi_connector_funcs,
+ &inno_hdmi_hdmi_connector_funcs,
+ DRM_MODE_CONNECTOR_HDMIA,
+ hdmi->ddc,
+ BIT(HDMI_COLORSPACE_RGB),
+ 8);
drm_connector_attach_encoder(&hdmi->connector, encoder);
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index ab55d7132550..44d769d9234d 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -18,7 +18,7 @@
#include <drm/drm_aperture.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_dma.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_of.h>
#include <drm/drm_probe_helper.h>
@@ -191,7 +191,7 @@ static int rockchip_drm_bind(struct device *dev)
if (ret)
goto err_kms_helper_poll_fini;
- drm_fbdev_generic_setup(drm_dev, 0);
+ drm_fbdev_dma_setup(drm_dev, 0);
return 0;
err_kms_helper_poll_fini:
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
index 62ebbdb16253..9873172e3fd3 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
@@ -2344,7 +2344,7 @@ static void vop2_setup_layer_mixer(struct vop2_video_port *vp)
port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT2_MUX,
(vp2->nlayers + vp1->nlayers + vp0->nlayers - 1));
else
- port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT1_MUX, 8);
+ port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT2_MUX, 8);
layer_sel = vop2_readl(vop2, RK3568_OVL_LAYER_SEL);
diff --git a/drivers/gpu/drm/solomon/ssd130x.c b/drivers/gpu/drm/solomon/ssd130x.c
index ebd943b9e357..6f51bcf774e2 100644
--- a/drivers/gpu/drm/solomon/ssd130x.c
+++ b/drivers/gpu/drm/solomon/ssd130x.c
@@ -23,7 +23,7 @@
#include <drm/drm_crtc_helper.h>
#include <drm/drm_damage_helper.h>
#include <drm/drm_edid.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_shmem.h>
#include <drm/drm_format_helper.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_atomic_helper.h>
@@ -2029,7 +2029,7 @@ struct ssd130x_device *ssd130x_probe(struct device *dev, struct regmap *regmap)
if (ret)
return ERR_PTR(dev_err_probe(dev, ret, "DRM device register failed\n"));
- drm_fbdev_generic_setup(drm, 32);
+ drm_fbdev_shmem_setup(drm, 32);
return ssd130x;
}
diff --git a/drivers/gpu/drm/sti/Kconfig b/drivers/gpu/drm/sti/Kconfig
index 3c7a5feff8de..75c301aadcbc 100644
--- a/drivers/gpu/drm/sti/Kconfig
+++ b/drivers/gpu/drm/sti/Kconfig
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
config DRM_STI
tristate "DRM Support for STMicroelectronics SoC stiH4xx Series"
- depends on OF && DRM && ARCH_STI
+ depends on OF && DRM && (ARCH_STI || COMPILE_TEST)
select RESET_CONTROLLER
select DRM_KMS_HELPER
select DRM_GEM_DMA_HELPER
diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c
index fd1df4ce3852..48a5d49fc131 100644
--- a/drivers/gpu/drm/sti/sti_dvo.c
+++ b/drivers/gpu/drm/sti/sti_dvo.c
@@ -7,6 +7,7 @@
#include <linux/clk.h>
#include <linux/component.h>
#include <linux/debugfs.h>
+#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
diff --git a/drivers/gpu/drm/stm/Kconfig b/drivers/gpu/drm/stm/Kconfig
index fa49cde43bb2..1cc6b6cbdfa9 100644
--- a/drivers/gpu/drm/stm/Kconfig
+++ b/drivers/gpu/drm/stm/Kconfig
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
config DRM_STM
tristate "DRM Support for STMicroelectronics SoC Series"
- depends on DRM && ARCH_STM32
+ depends on DRM && (ARCH_STM32 || COMPILE_TEST)
select DRM_KMS_HELPER
select DRM_GEM_DMA_HELPER
select DRM_PANEL_BRIDGE
@@ -20,3 +20,14 @@ config DRM_STM_DSI
select DRM_DW_MIPI_DSI
help
Choose this option for MIPI DSI support on STMicroelectronics SoC.
+
+config DRM_STM_LVDS
+ tristate "STMicroelectronics LVDS Display Interface Transmitter DRM driver"
+ depends on DRM_STM
+ help
+ Enable support for LVDS encoders on STMicroelectronics SoC.
+ The STM LVDS is a bridge which serialize pixel stream onto
+ a LVDS protocol.
+
+ To compile this driver as a module, choose M here: the module will be
+ called lvds.
diff --git a/drivers/gpu/drm/stm/Makefile b/drivers/gpu/drm/stm/Makefile
index 4df5caf01f35..ad740d6175a6 100644
--- a/drivers/gpu/drm/stm/Makefile
+++ b/drivers/gpu/drm/stm/Makefile
@@ -5,4 +5,6 @@ stm-drm-y := \
obj-$(CONFIG_DRM_STM_DSI) += dw_mipi_dsi-stm.o
+obj-$(CONFIG_DRM_STM_LVDS) += lvds.o
+
obj-$(CONFIG_DRM_STM) += stm-drm.o
diff --git a/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c b/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c
index d5f8c923d7bc..b20123854c4a 100644
--- a/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c
+++ b/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c
@@ -7,10 +7,13 @@
*/
#include <linux/clk.h>
+#include <linux/clk-provider.h>
#include <linux/iopoll.h>
+#include <linux/kernel.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
#include <video/mipi_display.h>
@@ -76,8 +79,12 @@ enum dsi_color {
struct dw_mipi_dsi_stm {
void __iomem *base;
+ struct device *dev;
struct clk *pllref_clk;
+ struct clk *pclk;
+ struct clk_hw txbyte_clk;
struct dw_mipi_dsi *dsi;
+ struct dw_mipi_dsi_plat_data pdata;
u32 hw_version;
int lane_min_kbps;
int lane_max_kbps;
@@ -194,29 +201,198 @@ static int dsi_pll_get_params(struct dw_mipi_dsi_stm *dsi,
return 0;
}
-static int dw_mipi_dsi_phy_init(void *priv_data)
+#define clk_to_dw_mipi_dsi_stm(clk) \
+ container_of(clk, struct dw_mipi_dsi_stm, txbyte_clk)
+
+static void dw_mipi_dsi_clk_disable(struct clk_hw *clk)
{
- struct dw_mipi_dsi_stm *dsi = priv_data;
+ struct dw_mipi_dsi_stm *dsi = clk_to_dw_mipi_dsi_stm(clk);
+
+ DRM_DEBUG_DRIVER("\n");
+
+ /* Disable the DSI PLL */
+ dsi_clear(dsi, DSI_WRPCR, WRPCR_PLLEN);
+
+ /* Disable the regulator */
+ dsi_clear(dsi, DSI_WRPCR, WRPCR_REGEN | WRPCR_BGREN);
+}
+
+static int dw_mipi_dsi_clk_enable(struct clk_hw *clk)
+{
+ struct dw_mipi_dsi_stm *dsi = clk_to_dw_mipi_dsi_stm(clk);
u32 val;
int ret;
+ DRM_DEBUG_DRIVER("\n");
+
/* Enable the regulator */
dsi_set(dsi, DSI_WRPCR, WRPCR_REGEN | WRPCR_BGREN);
- ret = readl_poll_timeout(dsi->base + DSI_WISR, val, val & WISR_RRS,
- SLEEP_US, TIMEOUT_US);
+ ret = readl_poll_timeout_atomic(dsi->base + DSI_WISR, val, val & WISR_RRS,
+ SLEEP_US, TIMEOUT_US);
if (ret)
DRM_DEBUG_DRIVER("!TIMEOUT! waiting REGU, let's continue\n");
/* Enable the DSI PLL & wait for its lock */
dsi_set(dsi, DSI_WRPCR, WRPCR_PLLEN);
- ret = readl_poll_timeout(dsi->base + DSI_WISR, val, val & WISR_PLLLS,
- SLEEP_US, TIMEOUT_US);
+ ret = readl_poll_timeout_atomic(dsi->base + DSI_WISR, val, val & WISR_PLLLS,
+ SLEEP_US, TIMEOUT_US);
if (ret)
DRM_DEBUG_DRIVER("!TIMEOUT! waiting PLL, let's continue\n");
return 0;
}
+static int dw_mipi_dsi_clk_is_enabled(struct clk_hw *hw)
+{
+ struct dw_mipi_dsi_stm *dsi = clk_to_dw_mipi_dsi_stm(hw);
+
+ return dsi_read(dsi, DSI_WRPCR) & WRPCR_PLLEN;
+}
+
+static unsigned long dw_mipi_dsi_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct dw_mipi_dsi_stm *dsi = clk_to_dw_mipi_dsi_stm(hw);
+ unsigned int idf, ndiv, odf, pll_in_khz, pll_out_khz;
+ u32 val;
+
+ DRM_DEBUG_DRIVER("\n");
+
+ pll_in_khz = (unsigned int)(parent_rate / 1000);
+
+ val = dsi_read(dsi, DSI_WRPCR);
+
+ idf = (val & WRPCR_IDF) >> 11;
+ if (!idf)
+ idf = 1;
+ ndiv = (val & WRPCR_NDIV) >> 2;
+ odf = int_pow(2, (val & WRPCR_ODF) >> 16);
+
+ /* Get the adjusted pll out value */
+ pll_out_khz = dsi_pll_get_clkout_khz(pll_in_khz, idf, ndiv, odf);
+
+ return (unsigned long)pll_out_khz * 1000;
+}
+
+static long dw_mipi_dsi_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ struct dw_mipi_dsi_stm *dsi = clk_to_dw_mipi_dsi_stm(hw);
+ unsigned int idf, ndiv, odf, pll_in_khz, pll_out_khz;
+ int ret;
+
+ DRM_DEBUG_DRIVER("\n");
+
+ pll_in_khz = (unsigned int)(*parent_rate / 1000);
+
+ /* Compute best pll parameters */
+ idf = 0;
+ ndiv = 0;
+ odf = 0;
+
+ ret = dsi_pll_get_params(dsi, pll_in_khz, rate / 1000,
+ &idf, &ndiv, &odf);
+ if (ret)
+ DRM_WARN("Warning dsi_pll_get_params(): bad params\n");
+
+ /* Get the adjusted pll out value */
+ pll_out_khz = dsi_pll_get_clkout_khz(pll_in_khz, idf, ndiv, odf);
+
+ return pll_out_khz * 1000;
+}
+
+static int dw_mipi_dsi_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct dw_mipi_dsi_stm *dsi = clk_to_dw_mipi_dsi_stm(hw);
+ unsigned int idf, ndiv, odf, pll_in_khz, pll_out_khz;
+ int ret;
+ u32 val;
+
+ DRM_DEBUG_DRIVER("\n");
+
+ pll_in_khz = (unsigned int)(parent_rate / 1000);
+
+ /* Compute best pll parameters */
+ idf = 0;
+ ndiv = 0;
+ odf = 0;
+
+ ret = dsi_pll_get_params(dsi, pll_in_khz, rate / 1000, &idf, &ndiv, &odf);
+ if (ret)
+ DRM_WARN("Warning dsi_pll_get_params(): bad params\n");
+
+ /* Get the adjusted pll out value */
+ pll_out_khz = dsi_pll_get_clkout_khz(pll_in_khz, idf, ndiv, odf);
+
+ /* Set the PLL division factors */
+ dsi_update_bits(dsi, DSI_WRPCR, WRPCR_NDIV | WRPCR_IDF | WRPCR_ODF,
+ (ndiv << 2) | (idf << 11) | ((ffs(odf) - 1) << 16));
+
+ /* Compute uix4 & set the bit period in high-speed mode */
+ val = 4000000 / pll_out_khz;
+ dsi_update_bits(dsi, DSI_WPCR0, WPCR0_UIX4, val);
+
+ return 0;
+}
+
+static void dw_mipi_dsi_clk_unregister(void *data)
+{
+ struct dw_mipi_dsi_stm *dsi = data;
+
+ DRM_DEBUG_DRIVER("\n");
+
+ of_clk_del_provider(dsi->dev->of_node);
+ clk_hw_unregister(&dsi->txbyte_clk);
+}
+
+static const struct clk_ops dw_mipi_dsi_stm_clk_ops = {
+ .enable = dw_mipi_dsi_clk_enable,
+ .disable = dw_mipi_dsi_clk_disable,
+ .is_enabled = dw_mipi_dsi_clk_is_enabled,
+ .recalc_rate = dw_mipi_dsi_clk_recalc_rate,
+ .round_rate = dw_mipi_dsi_clk_round_rate,
+ .set_rate = dw_mipi_dsi_clk_set_rate,
+};
+
+static struct clk_init_data cdata_init = {
+ .name = "ck_dsi_phy",
+ .ops = &dw_mipi_dsi_stm_clk_ops,
+ .parent_names = (const char * []) {"ck_hse"},
+ .num_parents = 1,
+};
+
+static int dw_mipi_dsi_clk_register(struct dw_mipi_dsi_stm *dsi,
+ struct device *dev)
+{
+ struct device_node *node = dev->of_node;
+ int ret;
+
+ DRM_DEBUG_DRIVER("Registering clk\n");
+
+ dsi->txbyte_clk.init = &cdata_init;
+
+ ret = clk_hw_register(dev, &dsi->txbyte_clk);
+ if (ret)
+ return ret;
+
+ ret = of_clk_add_hw_provider(node, of_clk_hw_simple_get,
+ &dsi->txbyte_clk);
+ if (ret)
+ clk_hw_unregister(&dsi->txbyte_clk);
+
+ return ret;
+}
+
+static int dw_mipi_dsi_phy_init(void *priv_data)
+{
+ struct dw_mipi_dsi_stm *dsi = priv_data;
+ int ret;
+
+ ret = clk_prepare_enable(dsi->txbyte_clk.clk);
+ return ret;
+}
+
static void dw_mipi_dsi_phy_power_on(void *priv_data)
{
struct dw_mipi_dsi_stm *dsi = priv_data;
@@ -233,6 +409,8 @@ static void dw_mipi_dsi_phy_power_off(void *priv_data)
DRM_DEBUG_DRIVER("\n");
+ clk_disable_unprepare(dsi->txbyte_clk.clk);
+
/* Disable the DSI wrapper */
dsi_clear(dsi, DSI_WCR, WCR_DSIEN);
}
@@ -243,9 +421,8 @@ dw_mipi_dsi_get_lane_mbps(void *priv_data, const struct drm_display_mode *mode,
unsigned int *lane_mbps)
{
struct dw_mipi_dsi_stm *dsi = priv_data;
- unsigned int idf, ndiv, odf, pll_in_khz, pll_out_khz;
+ unsigned int pll_in_khz, pll_out_khz;
int ret, bpp;
- u32 val;
pll_in_khz = (unsigned int)(clk_get_rate(dsi->pllref_clk) / 1000);
@@ -266,25 +443,10 @@ dw_mipi_dsi_get_lane_mbps(void *priv_data, const struct drm_display_mode *mode,
DRM_WARN("Warning min phy mbps is used\n");
}
- /* Compute best pll parameters */
- idf = 0;
- ndiv = 0;
- odf = 0;
- ret = dsi_pll_get_params(dsi, pll_in_khz, pll_out_khz,
- &idf, &ndiv, &odf);
+ ret = clk_set_rate((dsi->txbyte_clk.clk), pll_out_khz * 1000);
if (ret)
- DRM_WARN("Warning dsi_pll_get_params(): bad params\n");
-
- /* Get the adjusted pll out value */
- pll_out_khz = dsi_pll_get_clkout_khz(pll_in_khz, idf, ndiv, odf);
-
- /* Set the PLL division factors */
- dsi_update_bits(dsi, DSI_WRPCR, WRPCR_NDIV | WRPCR_IDF | WRPCR_ODF,
- (ndiv << 2) | (idf << 11) | ((ffs(odf) - 1) << 16));
-
- /* Compute uix4 & set the bit period in high-speed mode */
- val = 4000000 / pll_out_khz;
- dsi_update_bits(dsi, DSI_WPCR0, WPCR0_UIX4, val);
+ DRM_DEBUG_DRIVER("ERROR Could not set rate of %d to %s clk->name",
+ pll_out_khz, clk_hw_get_name(&dsi->txbyte_clk));
/* Select video mode by resetting DSIM bit */
dsi_clear(dsi, DSI_WCFGR, WCFGR_DSIM);
@@ -443,7 +605,7 @@ static int dw_mipi_dsi_stm_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct dw_mipi_dsi_stm *dsi;
- struct clk *pclk;
+ const struct dw_mipi_dsi_plat_data *pdata = of_device_get_match_data(dev);
int ret;
dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL);
@@ -483,21 +645,21 @@ static int dw_mipi_dsi_stm_probe(struct platform_device *pdev)
goto err_clk_get;
}
- pclk = devm_clk_get(dev, "pclk");
- if (IS_ERR(pclk)) {
- ret = PTR_ERR(pclk);
+ dsi->pclk = devm_clk_get(dev, "pclk");
+ if (IS_ERR(dsi->pclk)) {
+ ret = PTR_ERR(dsi->pclk);
DRM_ERROR("Unable to get peripheral clock: %d\n", ret);
goto err_dsi_probe;
}
- ret = clk_prepare_enable(pclk);
+ ret = clk_prepare_enable(dsi->pclk);
if (ret) {
DRM_ERROR("%s: Failed to enable peripheral clk\n", __func__);
goto err_dsi_probe;
}
dsi->hw_version = dsi_read(dsi, DSI_VERSION) & VERSION;
- clk_disable_unprepare(pclk);
+ clk_disable_unprepare(dsi->pclk);
if (dsi->hw_version != HWVER_130 && dsi->hw_version != HWVER_131) {
ret = -ENODEV;
@@ -513,18 +675,41 @@ static int dw_mipi_dsi_stm_probe(struct platform_device *pdev)
dsi->lane_max_kbps *= 2;
}
- dw_mipi_dsi_stm_plat_data.base = dsi->base;
- dw_mipi_dsi_stm_plat_data.priv_data = dsi;
+ dsi->pdata = *pdata;
+ dsi->pdata.base = dsi->base;
+ dsi->pdata.priv_data = dsi;
+
+ dsi->pdata.max_data_lanes = 2;
+ dsi->pdata.phy_ops = &dw_mipi_dsi_stm_phy_ops;
platform_set_drvdata(pdev, dsi);
- dsi->dsi = dw_mipi_dsi_probe(pdev, &dw_mipi_dsi_stm_plat_data);
+ dsi->dsi = dw_mipi_dsi_probe(pdev, &dsi->pdata);
if (IS_ERR(dsi->dsi)) {
ret = PTR_ERR(dsi->dsi);
dev_err_probe(dev, ret, "Failed to initialize mipi dsi host\n");
goto err_dsi_probe;
}
+ /*
+ * We need to wait for the generic bridge to probe before enabling and
+ * register the internal pixel clock.
+ */
+ ret = clk_prepare_enable(dsi->pclk);
+ if (ret) {
+ DRM_ERROR("%s: Failed to enable peripheral clk\n", __func__);
+ goto err_dsi_probe;
+ }
+
+ ret = dw_mipi_dsi_clk_register(dsi, dev);
+ if (ret) {
+ DRM_ERROR("Failed to register DSI pixel clock: %d\n", ret);
+ clk_disable_unprepare(dsi->pclk);
+ goto err_dsi_probe;
+ }
+
+ clk_disable_unprepare(dsi->pclk);
+
return 0;
err_dsi_probe:
@@ -541,24 +726,26 @@ static void dw_mipi_dsi_stm_remove(struct platform_device *pdev)
dw_mipi_dsi_remove(dsi->dsi);
clk_disable_unprepare(dsi->pllref_clk);
+ dw_mipi_dsi_clk_unregister(dsi);
regulator_disable(dsi->vdd_supply);
}
-static int __maybe_unused dw_mipi_dsi_stm_suspend(struct device *dev)
+static int dw_mipi_dsi_stm_suspend(struct device *dev)
{
- struct dw_mipi_dsi_stm *dsi = dw_mipi_dsi_stm_plat_data.priv_data;
+ struct dw_mipi_dsi_stm *dsi = dev_get_drvdata(dev);
DRM_DEBUG_DRIVER("\n");
clk_disable_unprepare(dsi->pllref_clk);
+ clk_disable_unprepare(dsi->pclk);
regulator_disable(dsi->vdd_supply);
return 0;
}
-static int __maybe_unused dw_mipi_dsi_stm_resume(struct device *dev)
+static int dw_mipi_dsi_stm_resume(struct device *dev)
{
- struct dw_mipi_dsi_stm *dsi = dw_mipi_dsi_stm_plat_data.priv_data;
+ struct dw_mipi_dsi_stm *dsi = dev_get_drvdata(dev);
int ret;
DRM_DEBUG_DRIVER("\n");
@@ -569,8 +756,16 @@ static int __maybe_unused dw_mipi_dsi_stm_resume(struct device *dev)
return ret;
}
+ ret = clk_prepare_enable(dsi->pclk);
+ if (ret) {
+ regulator_disable(dsi->vdd_supply);
+ DRM_ERROR("Failed to enable pclk: %d\n", ret);
+ return ret;
+ }
+
ret = clk_prepare_enable(dsi->pllref_clk);
if (ret) {
+ clk_disable_unprepare(dsi->pclk);
regulator_disable(dsi->vdd_supply);
DRM_ERROR("Failed to enable pllref_clk: %d\n", ret);
return ret;
@@ -580,8 +775,10 @@ static int __maybe_unused dw_mipi_dsi_stm_resume(struct device *dev)
}
static const struct dev_pm_ops dw_mipi_dsi_stm_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(dw_mipi_dsi_stm_suspend,
- dw_mipi_dsi_stm_resume)
+ SYSTEM_SLEEP_PM_OPS(dw_mipi_dsi_stm_suspend,
+ dw_mipi_dsi_stm_resume)
+ RUNTIME_PM_OPS(dw_mipi_dsi_stm_suspend,
+ dw_mipi_dsi_stm_resume, NULL)
};
static struct platform_driver dw_mipi_dsi_stm_driver = {
diff --git a/drivers/gpu/drm/stm/lvds.c b/drivers/gpu/drm/stm/lvds.c
new file mode 100644
index 000000000000..2fa2c81784e9
--- /dev/null
+++ b/drivers/gpu/drm/stm/lvds.c
@@ -0,0 +1,1224 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2023, STMicroelectronics - All Rights Reserved
+ * Author(s): Raphaël GALLAIS-POU <raphael.gallais-pou@foss.st.com> for STMicroelectronics.
+ */
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
+#include <drm/drm_device.h>
+#include <drm/drm_of.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_print.h>
+#include <drm/drm_probe_helper.h>
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/media-bus-format.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+/* LVDS Host registers */
+#define LVDS_CR 0x0000 /* configuration register */
+#define LVDS_DMLCR0 0x0004 /* data mapping lsb configuration register 0 */
+#define LVDS_DMMCR0 0x0008 /* data mapping msb configuration register 0 */
+#define LVDS_DMLCR1 0x000C /* data mapping lsb configuration register 1 */
+#define LVDS_DMMCR1 0x0010 /* data mapping msb configuration register 1 */
+#define LVDS_DMLCR2 0x0014 /* data mapping lsb configuration register 2 */
+#define LVDS_DMMCR2 0x0018 /* data mapping msb configuration register 2 */
+#define LVDS_DMLCR3 0x001C /* data mapping lsb configuration register 3 */
+#define LVDS_DMMCR3 0x0020 /* data mapping msb configuration register 3 */
+#define LVDS_DMLCR4 0x0024 /* data mapping lsb configuration register 4 */
+#define LVDS_DMMCR4 0x0028 /* data mapping msb configuration register 4 */
+#define LVDS_CDL1CR 0x002C /* channel distrib link 1 configuration register */
+#define LVDS_CDL2CR 0x0030 /* channel distrib link 2 configuration register */
+
+#define CDL1CR_DEFAULT 0x04321 /* Default value for CDL1CR */
+#define CDL2CR_DEFAULT 0x59876 /* Default value for CDL2CR */
+
+#define LVDS_DMLCR(bit) (LVDS_DMLCR0 + 0x8 * (bit))
+#define LVDS_DMMCR(bit) (LVDS_DMMCR0 + 0x8 * (bit))
+
+/* LVDS Wrapper registers */
+#define LVDS_WCLKCR 0x11B0 /* Wrapper clock control register */
+
+#define LVDS_HWCFGR 0x1FF0 /* HW configuration register */
+#define LVDS_VERR 0x1FF4 /* Version register */
+#define LVDS_IPIDR 0x1FF8 /* Identification register */
+#define LVDS_SIDR 0x1FFC /* Size Identification register */
+
+/* Bitfield description */
+#define CR_LVDSEN BIT(0) /* LVDS PHY Enable */
+#define CR_HSPOL BIT(1) /* Horizontal Synchronization Polarity */
+#define CR_VSPOL BIT(2) /* Vertical Synchronization Polarity */
+#define CR_DEPOL BIT(3) /* Data Enable Polarity */
+#define CR_CI BIT(4) /* Control Internal (software controlled bit) */
+#define CR_LKMOD BIT(5) /* Link Mode, for both Links */
+#define CR_LKPHA BIT(6) /* Link Phase, for both Links */
+#define CR_LK1POL GENMASK(20, 16) /* Link-1 output Polarity */
+#define CR_LK2POL GENMASK(25, 21) /* Link-2 output Polarity */
+
+#define DMMCR_MAP0 GENMASK(4, 0) /* Mapping for bit 0 of datalane x */
+#define DMMCR_MAP1 GENMASK(9, 5) /* Mapping for bit 1 of datalane x */
+#define DMMCR_MAP2 GENMASK(14, 10) /* Mapping for bit 2 of datalane x */
+#define DMMCR_MAP3 GENMASK(19, 15) /* Mapping for bit 3 of datalane x */
+#define DMLCR_MAP4 GENMASK(4, 0) /* Mapping for bit 4 of datalane x */
+#define DMLCR_MAP5 GENMASK(9, 5) /* Mapping for bit 5 of datalane x */
+#define DMLCR_MAP6 GENMASK(14, 10) /* Mapping for bit 6 of datalane x */
+
+#define CDLCR_DISTR0 GENMASK(3, 0) /* Channel distribution for lane 0 */
+#define CDLCR_DISTR1 GENMASK(7, 4) /* Channel distribution for lane 1 */
+#define CDLCR_DISTR2 GENMASK(11, 8) /* Channel distribution for lane 2 */
+#define CDLCR_DISTR3 GENMASK(15, 12) /* Channel distribution for lane 3 */
+#define CDLCR_DISTR4 GENMASK(19, 16) /* Channel distribution for lane 4 */
+
+#define PHY_GCR_BIT_CLK_OUT BIT(0) /* BIT clock enable */
+#define PHY_GCR_LS_CLK_OUT BIT(4) /* LS clock enable */
+#define PHY_GCR_DP_CLK_OUT BIT(8) /* DP clock enable */
+#define PHY_GCR_RSTZ BIT(24) /* LVDS PHY digital reset */
+#define PHY_GCR_DIV_RSTN BIT(25) /* Output divider reset */
+#define PHY_SCR_TX_EN BIT(16) /* Transmission mode enable */
+/* Current mode driver enable */
+#define PHY_CMCR_CM_EN_DL (BIT(28) | BIT(20) | BIT(12) | BIT(4))
+#define PHY_CMCR_CM_EN_DL4 BIT(4)
+/* Bias enable */
+#define PHY_BCR1_EN_BIAS_DL (BIT(16) | BIT(12) | BIT(8) | BIT(4) | BIT(0))
+#define PHY_BCR2_BIAS_EN BIT(28)
+/* Voltage mode driver enable */
+#define PHY_BCR3_VM_EN_DL (BIT(16) | BIT(12) | BIT(8) | BIT(4) | BIT(0))
+#define PHY_DCR_POWER_OK BIT(12)
+#define PHY_CFGCR_EN_DIG_DL GENMASK(4, 0) /* LVDS PHY digital lane enable */
+#define PHY_PLLCR1_PLL_EN BIT(0) /* LVDS PHY PLL enable */
+#define PHY_PLLCR1_EN_SD BIT(1) /* LVDS PHY PLL sigma-delta signal enable */
+#define PHY_PLLCR1_EN_TWG BIT(2) /* LVDS PHY PLL triangular wave generator enable */
+#define PHY_PLLCR1_DIV_EN BIT(8) /* LVDS PHY PLL dividers enable */
+#define PHY_PLLCR2_NDIV GENMASK(25, 16) /* NDIV mask value */
+#define PHY_PLLCR2_BDIV GENMASK(9, 0) /* BDIV mask value */
+#define PHY_PLLSR_PLL_LOCK BIT(0) /* LVDS PHY PLL lock status */
+#define PHY_PLLSDCR1_MDIV GENMASK(9, 0) /* MDIV mask value */
+#define PHY_PLLTESTCR_TDIV GENMASK(25, 16) /* TDIV mask value */
+#define PHY_PLLTESTCR_CLK_EN BIT(0) /* Test clock enable */
+#define PHY_PLLTESTCR_EN BIT(8) /* Test divider output enable */
+
+#define WCLKCR_SECND_CLKPIX_SEL BIT(0) /* Pixel clock selection */
+#define WCLKCR_SRCSEL BIT(8) /* Source selection for the pixel clock */
+
+/* Sleep & timeout for pll lock/unlock */
+#define SLEEP_US 1000
+#define TIMEOUT_US 200000
+
+/*
+ * The link phase defines whether an ODD pixel is carried over together with
+ * the next EVEN pixel or together with the previous EVEN pixel.
+ *
+ * LVDS_DUAL_LINK_EVEN_ODD_PIXELS (LKPHA = 0)
+ *
+ * ,--------. ,--------. ,--------. ,--------. ,---------.
+ * | ODD LK \/ PIXEL 3 \/ PIXEL 1 \/ PIXEL' 1 \/ PIXEL' 3 |
+ * | EVEN LK /\ PIXEL 2 /\ PIXEL' 0 /\ PIXEL' 2 /\ PIXEL' 4 |
+ * `--------' `--------' `--------' `--------' `---------'
+ *
+ * LVDS_DUAL_LINK_ODD_EVEN_PIXELS (LKPHA = 1)
+ *
+ * ,--------. ,--------. ,--------. ,--------. ,---------.
+ * | ODD LK \/ PIXEL 3 \/ PIXEL 1 \/ PIXEL' 1 \/ PIXEL' 3 |
+ * | EVEN LK /\ PIXEL 4 /\ PIXEL 2 /\ PIXEL' 0 /\ PIXEL' 2 |
+ * `--------' `--------' `--------' `--------' `---------'
+ *
+ */
+enum lvds_link_type {
+ LVDS_SINGLE_LINK_PRIMARY = 0,
+ LVDS_SINGLE_LINK_SECONDARY,
+ LVDS_DUAL_LINK_EVEN_ODD_PIXELS,
+ LVDS_DUAL_LINK_ODD_EVEN_PIXELS,
+};
+
+enum lvds_pixel {
+ PIX_R_0 = 0,
+ PIX_R_1,
+ PIX_R_2,
+ PIX_R_3,
+ PIX_R_4,
+ PIX_R_5,
+ PIX_R_6,
+ PIX_R_7,
+ PIX_G_0,
+ PIX_G_1,
+ PIX_G_2,
+ PIX_G_3,
+ PIX_G_4,
+ PIX_G_5,
+ PIX_G_6,
+ PIX_G_7,
+ PIX_B_0,
+ PIX_B_1,
+ PIX_B_2,
+ PIX_B_3,
+ PIX_B_4,
+ PIX_B_5,
+ PIX_B_6,
+ PIX_B_7,
+ PIX_H_S,
+ PIX_V_S,
+ PIX_D_E,
+ PIX_C_E,
+ PIX_C_I,
+ PIX_TOG,
+ PIX_ONE,
+ PIX_ZER,
+};
+
+struct phy_reg_offsets {
+ u32 GCR; /* Global Control Register */
+ u32 CMCR1; /* Current Mode Control Register 1 */
+ u32 CMCR2; /* Current Mode Control Register 2 */
+ u32 SCR; /* Serial Control Register */
+ u32 BCR1; /* Bias Control Register 1 */
+ u32 BCR2; /* Bias Control Register 2 */
+ u32 BCR3; /* Bias Control Register 3 */
+ u32 MPLCR; /* Monitor PLL Lock Control Register */
+ u32 DCR; /* Debug Control Register */
+ u32 SSR1; /* Spare Status Register 1 */
+ u32 CFGCR; /* Configuration Control Register */
+ u32 PLLCR1; /* PLL_MODE 1 Control Register */
+ u32 PLLCR2; /* PLL_MODE 2 Control Register */
+ u32 PLLSR; /* PLL Status Register */
+ u32 PLLSDCR1; /* PLL_SD_1 Control Register */
+ u32 PLLSDCR2; /* PLL_SD_2 Control Register */
+ u32 PLLTWGCR1;/* PLL_TWG_1 Control Register */
+ u32 PLLTWGCR2;/* PLL_TWG_2 Control Register */
+ u32 PLLCPCR; /* PLL_CP Control Register */
+ u32 PLLTESTCR;/* PLL_TEST Control Register */
+};
+
+struct lvds_phy_info {
+ u32 base;
+ struct phy_reg_offsets ofs;
+};
+
+static struct lvds_phy_info lvds_phy_16ff_primary = {
+ .base = 0x1000,
+ .ofs = {
+ .GCR = 0x0,
+ .CMCR1 = 0xC,
+ .CMCR2 = 0x10,
+ .SCR = 0x20,
+ .BCR1 = 0x2C,
+ .BCR2 = 0x30,
+ .BCR3 = 0x34,
+ .MPLCR = 0x64,
+ .DCR = 0x84,
+ .SSR1 = 0x88,
+ .CFGCR = 0xA0,
+ .PLLCR1 = 0xC0,
+ .PLLCR2 = 0xC4,
+ .PLLSR = 0xC8,
+ .PLLSDCR1 = 0xCC,
+ .PLLSDCR2 = 0xD0,
+ .PLLTWGCR1 = 0xD4,
+ .PLLTWGCR2 = 0xD8,
+ .PLLCPCR = 0xE0,
+ .PLLTESTCR = 0xE8,
+ }
+};
+
+static struct lvds_phy_info lvds_phy_16ff_secondary = {
+ .base = 0x1100,
+ .ofs = {
+ .GCR = 0x0,
+ .CMCR1 = 0xC,
+ .CMCR2 = 0x10,
+ .SCR = 0x20,
+ .BCR1 = 0x2C,
+ .BCR2 = 0x30,
+ .BCR3 = 0x34,
+ .MPLCR = 0x64,
+ .DCR = 0x84,
+ .SSR1 = 0x88,
+ .CFGCR = 0xA0,
+ .PLLCR1 = 0xC0,
+ .PLLCR2 = 0xC4,
+ .PLLSR = 0xC8,
+ .PLLSDCR1 = 0xCC,
+ .PLLSDCR2 = 0xD0,
+ .PLLTWGCR1 = 0xD4,
+ .PLLTWGCR2 = 0xD8,
+ .PLLCPCR = 0xE0,
+ .PLLTESTCR = 0xE8,
+ }
+};
+
+struct stm_lvds {
+ void __iomem *base;
+ struct device *dev;
+ struct clk *pclk; /* APB peripheral clock */
+ struct clk *pllref_clk; /* Reference clock for the internal PLL */
+ struct clk_hw lvds_ck_px; /* Pixel clock */
+ u32 pixel_clock_rate; /* Pixel clock rate */
+
+ struct lvds_phy_info *primary;
+ struct lvds_phy_info *secondary;
+
+ struct drm_bridge lvds_bridge;
+ struct drm_bridge *next_bridge;
+ struct drm_connector connector;
+ struct drm_encoder *encoder;
+ struct drm_panel *panel;
+
+ u32 hw_version;
+ u32 link_type;
+};
+
+#define bridge_to_stm_lvds(b) \
+ container_of(b, struct stm_lvds, lvds_bridge)
+
+#define connector_to_stm_lvds(c) \
+ container_of(c, struct stm_lvds, connector)
+
+#define lvds_is_dual_link(lvds) \
+ ({ \
+ typeof(lvds) __lvds = (lvds); \
+ __lvds == LVDS_DUAL_LINK_EVEN_ODD_PIXELS || \
+ __lvds == LVDS_DUAL_LINK_ODD_EVEN_PIXELS; \
+ })
+
+static inline void lvds_write(struct stm_lvds *lvds, u32 reg, u32 val)
+{
+ writel(val, lvds->base + reg);
+}
+
+static inline u32 lvds_read(struct stm_lvds *lvds, u32 reg)
+{
+ return readl(lvds->base + reg);
+}
+
+static inline void lvds_set(struct stm_lvds *lvds, u32 reg, u32 mask)
+{
+ lvds_write(lvds, reg, lvds_read(lvds, reg) | mask);
+}
+
+static inline void lvds_clear(struct stm_lvds *lvds, u32 reg, u32 mask)
+{
+ lvds_write(lvds, reg, lvds_read(lvds, reg) & ~mask);
+}
+
+/*
+ * Expected JEIDA-RGB888 data to be sent in LSB format
+ * bit6 ............................bit0
+ * CHAN0 {ONE, ONE, ZERO, ZERO, ZERO, ONE, ONE}
+ * CHAN1 {G2, R7, R6, R5, R4, R3, R2}
+ * CHAN2 {B3, B2, G7, G6, G5, G4, G3}
+ * CHAN3 {DE, VS, HS, B7, B6, B5, B4}
+ * CHAN4 {CE, B1, B0, G1, G0, R1, R0}
+ */
+static enum lvds_pixel lvds_bitmap_jeida_rgb888[5][7] = {
+ { PIX_ONE, PIX_ONE, PIX_ZER, PIX_ZER, PIX_ZER, PIX_ONE, PIX_ONE },
+ { PIX_G_2, PIX_R_7, PIX_R_6, PIX_R_5, PIX_R_4, PIX_R_3, PIX_R_2 },
+ { PIX_B_3, PIX_B_2, PIX_G_7, PIX_G_6, PIX_G_5, PIX_G_4, PIX_G_3 },
+ { PIX_D_E, PIX_V_S, PIX_H_S, PIX_B_7, PIX_B_6, PIX_B_5, PIX_B_4 },
+ { PIX_C_E, PIX_B_1, PIX_B_0, PIX_G_1, PIX_G_0, PIX_R_1, PIX_R_0 }
+};
+
+/*
+ * Expected VESA-RGB888 data to be sent in LSB format
+ * bit6 ............................bit0
+ * CHAN0 {ONE, ONE, ZERO, ZERO, ZERO, ONE, ONE}
+ * CHAN1 {G0, R5, R4, R3, R2, R1, R0}
+ * CHAN2 {B1, B0, G5, G4, G3, G2, G1}
+ * CHAN3 {DE, VS, HS, B5, B4, B3, B2}
+ * CHAN4 {CE, B7, B6, G7, G6, R7, R6}
+ */
+static enum lvds_pixel lvds_bitmap_vesa_rgb888[5][7] = {
+ { PIX_ONE, PIX_ONE, PIX_ZER, PIX_ZER, PIX_ZER, PIX_ONE, PIX_ONE },
+ { PIX_G_0, PIX_R_5, PIX_R_4, PIX_R_3, PIX_R_2, PIX_R_1, PIX_R_0 },
+ { PIX_B_1, PIX_B_0, PIX_G_5, PIX_G_4, PIX_G_3, PIX_G_2, PIX_G_1 },
+ { PIX_D_E, PIX_V_S, PIX_H_S, PIX_B_5, PIX_B_4, PIX_B_3, PIX_B_2 },
+ { PIX_C_E, PIX_B_7, PIX_B_6, PIX_G_7, PIX_G_6, PIX_R_7, PIX_R_6 }
+};
+
+/*
+ * Clocks and PHY related functions
+ */
+static int lvds_pll_enable(struct stm_lvds *lvds, struct lvds_phy_info *phy)
+{
+ struct drm_device *drm = lvds->lvds_bridge.dev;
+ u32 lvds_gcr;
+ int val, ret;
+
+ /*
+ * PLL lock timing control for the monitor unmask after startup (pll_en)
+ * Adjusted value so that the masking window is opened at start-up
+ */
+ lvds_write(lvds, phy->base + phy->ofs.MPLCR, (0x200 - 0x160) << 16);
+
+ /* Enable bias */
+ lvds_write(lvds, phy->base + phy->ofs.BCR2, PHY_BCR2_BIAS_EN);
+
+ /* Enable DP, LS, BIT clock output */
+ lvds_gcr = PHY_GCR_DP_CLK_OUT | PHY_GCR_LS_CLK_OUT | PHY_GCR_BIT_CLK_OUT;
+ lvds_set(lvds, phy->base + phy->ofs.GCR, lvds_gcr);
+
+ /* Power up all output dividers */
+ lvds_set(lvds, phy->base + phy->ofs.PLLTESTCR, PHY_PLLTESTCR_EN);
+ lvds_set(lvds, phy->base + phy->ofs.PLLCR1, PHY_PLLCR1_DIV_EN);
+
+ /* Set PHY in serial transmission mode */
+ lvds_set(lvds, phy->base + phy->ofs.SCR, PHY_SCR_TX_EN);
+
+ /* Enable the LVDS PLL & wait for its lock */
+ lvds_set(lvds, phy->base + phy->ofs.PLLCR1, PHY_PLLCR1_PLL_EN);
+ ret = readl_poll_timeout_atomic(lvds->base + phy->base + phy->ofs.PLLSR,
+ val, val & PHY_PLLSR_PLL_LOCK,
+ SLEEP_US, TIMEOUT_US);
+ if (ret)
+ drm_err(drm, "!TIMEOUT! waiting PLL, let's continue\n");
+
+ /* WCLKCR_SECND_CLKPIX_SEL is for dual link */
+ lvds_write(lvds, LVDS_WCLKCR, WCLKCR_SECND_CLKPIX_SEL);
+
+ lvds_set(lvds, phy->ofs.PLLTESTCR, PHY_PLLTESTCR_CLK_EN);
+
+ return ret;
+}
+
+static int pll_get_clkout_khz(int clkin_khz, int bdiv, int mdiv, int ndiv)
+{
+ int divisor = ndiv * bdiv;
+
+ /* Prevents from division by 0 */
+ if (!divisor)
+ return 0;
+
+ return clkin_khz * mdiv / divisor;
+}
+
+#define TDIV 70
+#define NDIV_MIN 2
+#define NDIV_MAX 6
+#define BDIV_MIN 2
+#define BDIV_MAX 6
+#define MDIV_MIN 1
+#define MDIV_MAX 1023
+
+static int lvds_pll_get_params(struct stm_lvds *lvds,
+ unsigned int clkin_khz, unsigned int clkout_khz,
+ unsigned int *bdiv, unsigned int *mdiv, unsigned int *ndiv)
+{
+ int delta, best_delta; /* all in khz */
+ int i, o, n;
+
+ /* Early checks preventing division by 0 & odd results */
+ if (clkin_khz <= 0 || clkout_khz <= 0)
+ return -EINVAL;
+
+ best_delta = 1000000; /* big started value (1000000khz) */
+
+ for (i = NDIV_MIN; i <= NDIV_MAX; i++) {
+ for (o = BDIV_MIN; o <= BDIV_MAX; o++) {
+ n = DIV_ROUND_CLOSEST(i * o * clkout_khz, clkin_khz);
+ /* Check ndiv according to vco range */
+ if (n < MDIV_MIN || n > MDIV_MAX)
+ continue;
+ /* Check if new delta is better & saves parameters */
+ delta = pll_get_clkout_khz(clkin_khz, i, n, o) - clkout_khz;
+ if (delta < 0)
+ delta = -delta;
+ if (delta < best_delta) {
+ *ndiv = i;
+ *mdiv = n;
+ *bdiv = o;
+ best_delta = delta;
+ }
+ /* fast return in case of "perfect result" */
+ if (!delta)
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+static void lvds_pll_config(struct stm_lvds *lvds, struct lvds_phy_info *phy)
+{
+ unsigned int pll_in_khz, bdiv = 0, mdiv = 0, ndiv = 0;
+ struct clk_hw *hwclk;
+ int multiplier;
+
+ /*
+ * The LVDS PHY includes a low power low jitter high performance and
+ * highly configuration Phase Locked Loop supporting integer and
+ * fractional multiplication ratios and Spread Spectrum Clocking. In
+ * integer mode, the only software supported feature for now, the PLL is
+ * made of a pre-divider NDIV, a feedback multiplier MDIV, followed by
+ * several post-dividers, each one with a specific application.
+ *
+ * ,------. ,-----. ,-----.
+ * Fref --> | NDIV | -Fpdf-> | PFD | --> | VCO | --------> Fvco
+ * `------' ,-> | | `-----' |
+ * | `-----' |
+ * | ,------. |
+ * `-------- | MDIV | <-----'
+ * `------'
+ *
+ * From the output of the VCO, the clock can be optionally extracted on
+ * the RCC clock observer, with a divider TDIV, for testing purpose, or
+ * is passed through a programmable post-divider BDIV. Finally, the
+ * frequency can be divided further with two fixed dividers.
+ *
+ * ,--------.
+ * ,-----> | DP div | ----------------> Fdp
+ * ,------. | `--------'
+ * Fvco --> | BDIV | ------------------------------------> Fbit
+ * | `------' ,------. |
+ * `-------------> | TDIV | --.---------------------> ClkObs
+ * '------' | ,--------.
+ * `--> | LS div | ------> Fls
+ * '--------'
+ *
+ * The LS and DP clock dividers operate at a fixed ratio of 7 and 3.5
+ * respectively with regards to fbit. LS divider converts the bit clock
+ * to a pixel clock per lane per clock sample (Fls). This is useful
+ * when used to generate a dot clock for the display unit RGB output,
+ * and DP divider is.
+ */
+
+ hwclk = __clk_get_hw(lvds->pllref_clk);
+ if (!hwclk)
+ return;
+
+ pll_in_khz = clk_hw_get_rate(hwclk) / 1000;
+
+ if (lvds_is_dual_link(lvds->link_type))
+ multiplier = 2;
+ else
+ multiplier = 1;
+
+ lvds_pll_get_params(lvds, pll_in_khz,
+ lvds->pixel_clock_rate * 7 / 1000 / multiplier,
+ &bdiv, &mdiv, &ndiv);
+
+ /* Set BDIV, MDIV and NDIV */
+ lvds_write(lvds, phy->base + phy->ofs.PLLCR2, ndiv << 16);
+ lvds_set(lvds, phy->base + phy->ofs.PLLCR2, bdiv);
+ lvds_write(lvds, phy->base + phy->ofs.PLLSDCR1, mdiv);
+
+ /* Hardcode TDIV as dynamic values are not yet implemented */
+ lvds_write(lvds, phy->base + phy->ofs.PLLTESTCR, TDIV << 16);
+
+ /*
+ * For now, PLL just needs to be in integer mode
+ * Fractional and spread spectrum clocking are not yet implemented
+ *
+ * PLL integer mode:
+ * - PMRY_PLL_TWG_STEP = PMRY_PLL_SD_INT_RATIO
+ * - EN_TWG = 0
+ * - EN_SD = 0
+ * - DOWN_SPREAD = 0
+ *
+ * PLL fractional mode:
+ * - EN_TWG = 0
+ * - EN_SD = 1
+ * - DOWN_SPREAD = 0
+ *
+ * Spread Spectrum Clocking
+ * - EN_TWG = 1
+ * - EN_SD = 1
+ */
+
+ /* Disable TWG and SD */
+ lvds_clear(lvds, phy->base + phy->ofs.PLLCR1, PHY_PLLCR1_EN_TWG | PHY_PLLCR1_EN_SD);
+
+ /* Power up bias and PLL dividers */
+ lvds_set(lvds, phy->base + phy->ofs.DCR, PHY_DCR_POWER_OK);
+ lvds_set(lvds, phy->base + phy->ofs.CMCR1, PHY_CMCR_CM_EN_DL);
+ lvds_set(lvds, phy->base + phy->ofs.CMCR2, PHY_CMCR_CM_EN_DL4);
+
+ /* Set up voltage mode */
+ lvds_set(lvds, phy->base + phy->ofs.PLLCPCR, 0x1);
+ lvds_set(lvds, phy->base + phy->ofs.BCR3, PHY_BCR3_VM_EN_DL);
+ lvds_set(lvds, phy->base + phy->ofs.BCR1, PHY_BCR1_EN_BIAS_DL);
+ /* Enable digital datalanes */
+ lvds_set(lvds, phy->base + phy->ofs.CFGCR, PHY_CFGCR_EN_DIG_DL);
+}
+
+static int lvds_pixel_clk_enable(struct clk_hw *hw)
+{
+ struct stm_lvds *lvds = container_of(hw, struct stm_lvds, lvds_ck_px);
+ struct drm_device *drm = lvds->lvds_bridge.dev;
+ struct lvds_phy_info *phy;
+ int ret;
+
+ ret = clk_prepare_enable(lvds->pclk);
+ if (ret) {
+ drm_err(drm, "Failed to enable lvds peripheral clk\n");
+ return ret;
+ }
+
+ ret = clk_prepare_enable(lvds->pllref_clk);
+ if (ret) {
+ drm_err(drm, "Failed to enable lvds reference clk\n");
+ clk_disable_unprepare(lvds->pclk);
+ return ret;
+ }
+
+ /* In case we are operating in dual link the second PHY is set before the primary PHY. */
+ if (lvds->secondary) {
+ phy = lvds->secondary;
+
+ /* Release LVDS PHY from reset mode */
+ lvds_set(lvds, phy->base + phy->ofs.GCR, PHY_GCR_DIV_RSTN | PHY_GCR_RSTZ);
+ lvds_pll_config(lvds, phy);
+
+ ret = lvds_pll_enable(lvds, phy);
+ if (ret) {
+ drm_err(drm, "Failed to enable secondary PHY PLL: %d\n", ret);
+ return ret;
+ }
+ }
+
+ if (lvds->primary) {
+ phy = lvds->primary;
+
+ /* Release LVDS PHY from reset mode */
+ lvds_set(lvds, phy->base + phy->ofs.GCR, PHY_GCR_DIV_RSTN | PHY_GCR_RSTZ);
+ lvds_pll_config(lvds, phy);
+
+ ret = lvds_pll_enable(lvds, phy);
+ if (ret) {
+ drm_err(drm, "Failed to enable primary PHY PLL: %d\n", ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static void lvds_pixel_clk_disable(struct clk_hw *hw)
+{
+ struct stm_lvds *lvds = container_of(hw, struct stm_lvds, lvds_ck_px);
+
+ /*
+ * For each PHY:
+ * Disable DP, LS, BIT clock outputs
+ * Shutdown the PLL
+ * Assert LVDS PHY in reset mode
+ */
+
+ if (lvds->primary) {
+ lvds_clear(lvds, lvds->primary->base + lvds->primary->ofs.GCR,
+ (PHY_GCR_DP_CLK_OUT | PHY_GCR_LS_CLK_OUT | PHY_GCR_BIT_CLK_OUT));
+ lvds_clear(lvds, lvds->primary->base + lvds->primary->ofs.PLLCR1,
+ PHY_PLLCR1_PLL_EN);
+ lvds_clear(lvds, lvds->primary->base + lvds->primary->ofs.GCR,
+ PHY_GCR_DIV_RSTN | PHY_GCR_RSTZ);
+ }
+
+ if (lvds->secondary) {
+ lvds_clear(lvds, lvds->secondary->base + lvds->secondary->ofs.GCR,
+ (PHY_GCR_DP_CLK_OUT | PHY_GCR_LS_CLK_OUT | PHY_GCR_BIT_CLK_OUT));
+ lvds_clear(lvds, lvds->secondary->base + lvds->secondary->ofs.PLLCR1,
+ PHY_PLLCR1_PLL_EN);
+ lvds_clear(lvds, lvds->secondary->base + lvds->secondary->ofs.GCR,
+ PHY_GCR_DIV_RSTN | PHY_GCR_RSTZ);
+ }
+
+ clk_disable_unprepare(lvds->pllref_clk);
+ clk_disable_unprepare(lvds->pclk);
+}
+
+static unsigned long lvds_pixel_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct stm_lvds *lvds = container_of(hw, struct stm_lvds, lvds_ck_px);
+ struct drm_device *drm = lvds->lvds_bridge.dev;
+ unsigned int pll_in_khz, bdiv, mdiv, ndiv;
+ int ret, multiplier, pll_out_khz;
+ u32 val;
+
+ ret = clk_prepare_enable(lvds->pclk);
+ if (ret) {
+ drm_err(drm, "Failed to enable lvds peripheral clk\n");
+ return 0;
+ }
+
+ if (lvds_is_dual_link(lvds->link_type))
+ multiplier = 2;
+ else
+ multiplier = 1;
+
+ val = lvds_read(lvds, lvds->primary->base + lvds->primary->ofs.PLLCR2);
+
+ ndiv = (val & PHY_PLLCR2_NDIV) >> 16;
+ bdiv = (val & PHY_PLLCR2_BDIV) >> 0;
+
+ mdiv = (unsigned int)lvds_read(lvds,
+ lvds->primary->base + lvds->primary->ofs.PLLSDCR1);
+
+ pll_in_khz = (unsigned int)(parent_rate / 1000);
+
+ /* Compute values if not yet accessible */
+ if (val == 0 || mdiv == 0) {
+ lvds_pll_get_params(lvds, pll_in_khz,
+ lvds->pixel_clock_rate * 7 / 1000 / multiplier,
+ &bdiv, &mdiv, &ndiv);
+ }
+
+ pll_out_khz = pll_get_clkout_khz(pll_in_khz, bdiv, mdiv, ndiv);
+ drm_dbg(drm, "ndiv %d , bdiv %d, mdiv %d, pll_out_khz %d\n",
+ ndiv, bdiv, mdiv, pll_out_khz);
+
+ /*
+ * 1/7 because for each pixel in 1 lane there is 7 bits
+ * We want pixclk, not bitclk
+ */
+ lvds->pixel_clock_rate = pll_out_khz * 1000 * multiplier / 7;
+
+ clk_disable_unprepare(lvds->pclk);
+
+ return (unsigned long)lvds->pixel_clock_rate;
+}
+
+static long lvds_pixel_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ struct stm_lvds *lvds = container_of(hw, struct stm_lvds, lvds_ck_px);
+ unsigned int pll_in_khz, bdiv = 0, mdiv = 0, ndiv = 0;
+ const struct drm_connector *connector;
+ const struct drm_display_mode *mode;
+ int multiplier;
+
+ connector = &lvds->connector;
+ if (!connector)
+ return -EINVAL;
+
+ if (list_empty(&connector->modes)) {
+ drm_dbg(connector->dev, "connector: empty modes list\n");
+ return -EINVAL;
+ }
+
+ mode = list_first_entry(&connector->modes,
+ struct drm_display_mode, head);
+
+ pll_in_khz = (unsigned int)(*parent_rate / 1000);
+
+ if (lvds_is_dual_link(lvds->link_type))
+ multiplier = 2;
+ else
+ multiplier = 1;
+
+ lvds_pll_get_params(lvds, pll_in_khz, mode->clock * 7 / multiplier, &bdiv, &mdiv, &ndiv);
+
+ /*
+ * 1/7 because for each pixel in 1 lane there is 7 bits
+ * We want pixclk, not bitclk
+ */
+ lvds->pixel_clock_rate = (unsigned long)pll_get_clkout_khz(pll_in_khz, bdiv, mdiv, ndiv)
+ * 1000 * multiplier / 7;
+
+ return lvds->pixel_clock_rate;
+}
+
+static const struct clk_ops lvds_pixel_clk_ops = {
+ .enable = lvds_pixel_clk_enable,
+ .disable = lvds_pixel_clk_disable,
+ .recalc_rate = lvds_pixel_clk_recalc_rate,
+ .round_rate = lvds_pixel_clk_round_rate,
+};
+
+static const struct clk_init_data clk_data = {
+ .name = "clk_pix_lvds",
+ .ops = &lvds_pixel_clk_ops,
+ .parent_names = (const char * []) {"ck_ker_lvdsphy"},
+ .num_parents = 1,
+ .flags = CLK_IGNORE_UNUSED,
+};
+
+static void lvds_pixel_clk_unregister(void *data)
+{
+ struct stm_lvds *lvds = data;
+
+ of_clk_del_provider(lvds->dev->of_node);
+ clk_hw_unregister(&lvds->lvds_ck_px);
+}
+
+static int lvds_pixel_clk_register(struct stm_lvds *lvds)
+{
+ struct device_node *node = lvds->dev->of_node;
+ int ret;
+
+ lvds->lvds_ck_px.init = &clk_data;
+
+ /* set the rate by default at 148500000 */
+ lvds->pixel_clock_rate = 148500000;
+
+ ret = clk_hw_register(lvds->dev, &lvds->lvds_ck_px);
+ if (ret)
+ return ret;
+
+ ret = of_clk_add_hw_provider(node, of_clk_hw_simple_get,
+ &lvds->lvds_ck_px);
+ if (ret)
+ clk_hw_unregister(&lvds->lvds_ck_px);
+
+ return ret;
+}
+
+/*
+ * Host configuration related
+ */
+static void lvds_config_data_mapping(struct stm_lvds *lvds)
+{
+ struct drm_device *drm = lvds->lvds_bridge.dev;
+ const struct drm_display_info *info;
+ enum lvds_pixel (*bitmap)[7];
+ u32 lvds_dmlcr, lvds_dmmcr;
+ int i;
+
+ info = &(&lvds->connector)->display_info;
+ if (!info->num_bus_formats || !info->bus_formats) {
+ drm_warn(drm, "No LVDS bus format reported\n");
+ return;
+ }
+
+ switch (info->bus_formats[0]) {
+ case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: /* VESA-RGB666 */
+ drm_warn(drm, "Pixel format with data mapping not yet supported.\n");
+ return;
+ case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG: /* VESA-RGB888 */
+ bitmap = lvds_bitmap_vesa_rgb888;
+ break;
+ case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA: /* JEIDA-RGB888 */
+ bitmap = lvds_bitmap_jeida_rgb888;
+ break;
+ default:
+ drm_warn(drm, "Unsupported LVDS bus format 0x%04x\n", info->bus_formats[0]);
+ return;
+ }
+
+ /* Set bitmap for each lane */
+ for (i = 0; i < 5; i++) {
+ lvds_dmlcr = ((bitmap[i][0])
+ + (bitmap[i][1] << 5)
+ + (bitmap[i][2] << 10)
+ + (bitmap[i][3] << 15));
+ lvds_dmmcr = ((bitmap[i][4])
+ + (bitmap[i][5] << 5)
+ + (bitmap[i][6] << 10));
+
+ lvds_write(lvds, LVDS_DMLCR(i), lvds_dmlcr);
+ lvds_write(lvds, LVDS_DMMCR(i), lvds_dmmcr);
+ }
+}
+
+static void lvds_config_mode(struct stm_lvds *lvds)
+{
+ u32 bus_flags, lvds_cr = 0, lvds_cdl1cr = 0, lvds_cdl2cr = 0;
+ const struct drm_display_mode *mode;
+ const struct drm_connector *connector;
+
+ connector = &lvds->connector;
+ if (!connector)
+ return;
+
+ if (list_empty(&connector->modes)) {
+ drm_dbg(connector->dev, "connector: empty modes list\n");
+ return;
+ }
+
+ bus_flags = connector->display_info.bus_flags;
+ mode = list_first_entry(&connector->modes,
+ struct drm_display_mode, head);
+
+ lvds_clear(lvds, LVDS_CR, CR_LKMOD);
+ lvds_clear(lvds, LVDS_CDL1CR, CDLCR_DISTR0 | CDLCR_DISTR1 | CDLCR_DISTR2 |
+ CDLCR_DISTR3 | CDLCR_DISTR4);
+ lvds_clear(lvds, LVDS_CDL2CR, CDLCR_DISTR0 | CDLCR_DISTR1 | CDLCR_DISTR2 |
+ CDLCR_DISTR3 | CDLCR_DISTR4);
+
+ /* Set channel distribution */
+ if (lvds->primary)
+ lvds_cdl1cr = CDL1CR_DEFAULT;
+
+ if (lvds->secondary) {
+ lvds_cr |= CR_LKMOD;
+ lvds_cdl2cr = CDL2CR_DEFAULT;
+ }
+
+ /* Set signal polarity */
+ if (bus_flags & DRM_BUS_FLAG_DE_LOW)
+ lvds_cr |= CR_DEPOL;
+
+ if (mode->flags & DRM_MODE_FLAG_NHSYNC)
+ lvds_cr |= CR_HSPOL;
+
+ if (mode->flags & DRM_MODE_FLAG_NVSYNC)
+ lvds_cr |= CR_VSPOL;
+
+ switch (lvds->link_type) {
+ case LVDS_DUAL_LINK_EVEN_ODD_PIXELS: /* LKPHA = 0 */
+ lvds_cr &= ~CR_LKPHA;
+ break;
+ case LVDS_DUAL_LINK_ODD_EVEN_PIXELS: /* LKPHA = 1 */
+ lvds_cr |= CR_LKPHA;
+ break;
+ default:
+ drm_notice(lvds->lvds_bridge.dev, "No phase precised, setting default\n");
+ lvds_cr &= ~CR_LKPHA;
+ break;
+ }
+
+ /* Write config to registers */
+ lvds_set(lvds, LVDS_CR, lvds_cr);
+ lvds_write(lvds, LVDS_CDL1CR, lvds_cdl1cr);
+ lvds_write(lvds, LVDS_CDL2CR, lvds_cdl2cr);
+}
+
+static int lvds_connector_get_modes(struct drm_connector *connector)
+{
+ struct stm_lvds *lvds = connector_to_stm_lvds(connector);
+
+ return drm_panel_get_modes(lvds->panel, connector);
+}
+
+static int lvds_connector_atomic_check(struct drm_connector *connector,
+ struct drm_atomic_state *state)
+{
+ const struct drm_display_mode *panel_mode;
+ struct drm_connector_state *conn_state;
+ struct drm_crtc_state *crtc_state;
+
+ conn_state = drm_atomic_get_new_connector_state(state, connector);
+ if (!conn_state)
+ return -EINVAL;
+
+ if (list_empty(&connector->modes)) {
+ drm_dbg(connector->dev, "connector: empty modes list\n");
+ return -EINVAL;
+ }
+
+ if (!conn_state->crtc)
+ return -EINVAL;
+
+ panel_mode = list_first_entry(&connector->modes,
+ struct drm_display_mode, head);
+
+ /* We're not allowed to modify the resolution. */
+ crtc_state = drm_atomic_get_crtc_state(state, conn_state->crtc);
+ if (IS_ERR(crtc_state))
+ return PTR_ERR(crtc_state);
+
+ if (crtc_state->mode.hdisplay != panel_mode->hdisplay ||
+ crtc_state->mode.vdisplay != panel_mode->vdisplay)
+ return -EINVAL;
+
+ /* The flat panel mode is fixed, just copy it to the adjusted mode. */
+ drm_mode_copy(&crtc_state->adjusted_mode, panel_mode);
+
+ return 0;
+}
+
+static const struct drm_connector_helper_funcs lvds_conn_helper_funcs = {
+ .get_modes = lvds_connector_get_modes,
+ .atomic_check = lvds_connector_atomic_check,
+};
+
+static const struct drm_connector_funcs lvds_conn_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,
+};
+
+static int lvds_attach(struct drm_bridge *bridge,
+ enum drm_bridge_attach_flags flags)
+{
+ struct stm_lvds *lvds = bridge_to_stm_lvds(bridge);
+ struct drm_connector *connector = &lvds->connector;
+ struct drm_encoder *encoder = bridge->encoder;
+ int ret;
+
+ if (!bridge->encoder) {
+ drm_err(bridge->dev, "Parent encoder object not found\n");
+ return -ENODEV;
+ }
+
+ /* Set the encoder type as caller does not know it */
+ bridge->encoder->encoder_type = DRM_MODE_ENCODER_LVDS;
+
+ /* No cloning support */
+ bridge->encoder->possible_clones = 0;
+
+ /* If we have a next bridge just attach it. */
+ if (lvds->next_bridge)
+ return drm_bridge_attach(bridge->encoder, lvds->next_bridge,
+ bridge, flags);
+
+ if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) {
+ drm_err(bridge->dev, "Fix bridge driver to make connector optional!");
+ return -EINVAL;
+ }
+
+ /* Otherwise if we have a panel, create a connector. */
+ if (!lvds->panel)
+ return 0;
+
+ ret = drm_connector_init(bridge->dev, connector,
+ &lvds_conn_funcs, DRM_MODE_CONNECTOR_LVDS);
+ if (ret < 0)
+ return ret;
+
+ drm_connector_helper_add(connector, &lvds_conn_helper_funcs);
+
+ ret = drm_connector_attach_encoder(connector, encoder);
+
+ return ret;
+}
+
+static void lvds_atomic_enable(struct drm_bridge *bridge,
+ struct drm_bridge_state *old_bridge_state)
+{
+ struct drm_atomic_state *state = old_bridge_state->base.state;
+ struct stm_lvds *lvds = bridge_to_stm_lvds(bridge);
+ struct drm_connector_state *conn_state;
+ struct drm_connector *connector;
+ int ret;
+
+ ret = clk_prepare_enable(lvds->pclk);
+ if (ret) {
+ drm_err(bridge->dev, "Failed to enable lvds peripheral clk\n");
+ return;
+ }
+
+ connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder);
+ if (!connector)
+ return;
+
+ conn_state = drm_atomic_get_new_connector_state(state, connector);
+ if (!conn_state)
+ return;
+
+ lvds_config_mode(lvds);
+
+ /* Set Data Mapping */
+ lvds_config_data_mapping(lvds);
+
+ /* Turn the output on. */
+ lvds_set(lvds, LVDS_CR, CR_LVDSEN);
+
+ if (lvds->panel) {
+ drm_panel_prepare(lvds->panel);
+ drm_panel_enable(lvds->panel);
+ }
+}
+
+static void lvds_atomic_disable(struct drm_bridge *bridge,
+ struct drm_bridge_state *old_bridge_state)
+{
+ struct stm_lvds *lvds = bridge_to_stm_lvds(bridge);
+
+ if (lvds->panel) {
+ drm_panel_disable(lvds->panel);
+ drm_panel_unprepare(lvds->panel);
+ }
+
+ /* Disable LVDS module */
+ lvds_clear(lvds, LVDS_CR, CR_LVDSEN);
+
+ clk_disable_unprepare(lvds->pclk);
+}
+
+static const struct drm_bridge_funcs lvds_bridge_funcs = {
+ .attach = lvds_attach,
+ .atomic_enable = lvds_atomic_enable,
+ .atomic_disable = lvds_atomic_disable,
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_reset = drm_atomic_helper_bridge_reset,
+};
+
+static int lvds_probe(struct platform_device *pdev)
+{
+ struct device_node *port1, *port2, *remote;
+ struct device *dev = &pdev->dev;
+ struct reset_control *rstc;
+ struct stm_lvds *lvds;
+ int ret, dual_link;
+
+ dev_dbg(dev, "Probing LVDS driver...\n");
+
+ lvds = devm_kzalloc(dev, sizeof(*lvds), GFP_KERNEL);
+ if (!lvds)
+ return -ENOMEM;
+
+ lvds->dev = dev;
+
+ ret = drm_of_find_panel_or_bridge(dev->of_node, 1, 0,
+ &lvds->panel, &lvds->next_bridge);
+ if (ret) {
+ dev_err_probe(dev, ret, "Panel not found\n");
+ return ret;
+ }
+
+ lvds->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(lvds->base)) {
+ ret = PTR_ERR(lvds->base);
+ dev_err(dev, "Unable to get regs %d\n", ret);
+ return ret;
+ }
+
+ lvds->pclk = devm_clk_get(dev, "pclk");
+ if (IS_ERR(lvds->pclk)) {
+ ret = PTR_ERR(lvds->pclk);
+ dev_err(dev, "Unable to get peripheral clock: %d\n", ret);
+ return ret;
+ }
+
+ ret = clk_prepare_enable(lvds->pclk);
+ if (ret) {
+ dev_err(dev, "%s: Failed to enable peripheral clk\n", __func__);
+ return ret;
+ }
+
+ rstc = devm_reset_control_get_exclusive(dev, NULL);
+
+ if (IS_ERR(rstc)) {
+ ret = PTR_ERR(rstc);
+ goto err_lvds_probe;
+ }
+
+ reset_control_assert(rstc);
+ usleep_range(10, 20);
+ reset_control_deassert(rstc);
+
+ port1 = of_graph_get_port_by_id(dev->of_node, 1);
+ port2 = of_graph_get_port_by_id(dev->of_node, 2);
+ dual_link = drm_of_lvds_get_dual_link_pixel_order(port1, port2);
+
+ switch (dual_link) {
+ case DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS:
+ lvds->link_type = LVDS_DUAL_LINK_ODD_EVEN_PIXELS;
+ lvds->primary = &lvds_phy_16ff_primary;
+ lvds->secondary = &lvds_phy_16ff_secondary;
+ break;
+ case DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS:
+ lvds->link_type = LVDS_DUAL_LINK_EVEN_ODD_PIXELS;
+ lvds->primary = &lvds_phy_16ff_primary;
+ lvds->secondary = &lvds_phy_16ff_secondary;
+ break;
+ case -EINVAL:
+ /*
+ * drm_of_lvds_get_dual_pixel_order returns 4 possible values.
+ * In the case where the returned value is an error, it can be
+ * either ENODEV or EINVAL. Seeing the structure of this
+ * function, EINVAL means that either port1 or port2 is not
+ * present in the device tree.
+ * In that case, the lvds panel can be a single link panel, or
+ * there is a semantical error in the device tree code.
+ */
+ remote = of_get_next_available_child(port1, NULL);
+ if (remote) {
+ if (of_graph_get_remote_endpoint(remote)) {
+ lvds->link_type = LVDS_SINGLE_LINK_PRIMARY;
+ lvds->primary = &lvds_phy_16ff_primary;
+ lvds->secondary = NULL;
+ } else {
+ ret = -EINVAL;
+ }
+
+ of_node_put(remote);
+ }
+
+ remote = of_get_next_available_child(port2, NULL);
+ if (remote) {
+ if (of_graph_get_remote_endpoint(remote)) {
+ lvds->link_type = LVDS_SINGLE_LINK_SECONDARY;
+ lvds->primary = NULL;
+ lvds->secondary = &lvds_phy_16ff_secondary;
+ } else {
+ ret = (ret == -EINVAL) ? -EINVAL : 0;
+ }
+
+ of_node_put(remote);
+ }
+ break;
+ default:
+ ret = -EINVAL;
+ goto err_lvds_probe;
+ }
+ of_node_put(port1);
+ of_node_put(port2);
+
+ lvds->pllref_clk = devm_clk_get(dev, "ref");
+ if (IS_ERR(lvds->pllref_clk)) {
+ ret = PTR_ERR(lvds->pllref_clk);
+ dev_err(dev, "Unable to get reference clock: %d\n", ret);
+ goto err_lvds_probe;
+ }
+
+ ret = lvds_pixel_clk_register(lvds);
+ if (ret) {
+ dev_err(dev, "Failed to register LVDS pixel clock: %d\n", ret);
+ goto err_lvds_probe;
+ }
+
+ lvds->lvds_bridge.funcs = &lvds_bridge_funcs;
+ lvds->lvds_bridge.of_node = dev->of_node;
+ lvds->hw_version = lvds_read(lvds, LVDS_VERR);
+
+ dev_info(dev, "version 0x%02x initialized\n", lvds->hw_version);
+
+ drm_bridge_add(&lvds->lvds_bridge);
+
+ platform_set_drvdata(pdev, lvds);
+
+ clk_disable_unprepare(lvds->pclk);
+
+ return 0;
+
+err_lvds_probe:
+ clk_disable_unprepare(lvds->pclk);
+
+ return ret;
+}
+
+static void lvds_remove(struct platform_device *pdev)
+{
+ struct stm_lvds *lvds = platform_get_drvdata(pdev);
+
+ lvds_pixel_clk_unregister(lvds);
+
+ drm_bridge_remove(&lvds->lvds_bridge);
+}
+
+static const struct of_device_id lvds_dt_ids[] = {
+ {
+ .compatible = "st,stm32mp25-lvds",
+ .data = NULL
+ },
+ { /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, lvds_dt_ids);
+
+static struct platform_driver lvds_platform_driver = {
+ .probe = lvds_probe,
+ .remove = lvds_remove,
+ .driver = {
+ .name = "stm32-display-lvds",
+ .owner = THIS_MODULE,
+ .of_match_table = lvds_dt_ids,
+ },
+};
+
+module_platform_driver(lvds_platform_driver);
+
+MODULE_AUTHOR("Raphaël Gallais-Pou <raphael.gallais-pou@foss.st.com>");
+MODULE_AUTHOR("Philippe Cornu <philippe.cornu@foss.st.com>");
+MODULE_AUTHOR("Yannick Fertre <yannick.fertre@foss.st.com>");
+MODULE_DESCRIPTION("STMicroelectronics LVDS Display Interface Transmitter DRM driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig
index 4741d9f6544c..4037e085430e 100644
--- a/drivers/gpu/drm/sun4i/Kconfig
+++ b/drivers/gpu/drm/sun4i/Kconfig
@@ -18,6 +18,9 @@ if DRM_SUN4I
config DRM_SUN4I_HDMI
tristate "Allwinner A10/A10s/A20/A31 HDMI Controller Support"
depends on ARM || COMPILE_TEST
+ select DRM_DISPLAY_HDMI_HELPER
+ select DRM_DISPLAY_HDMI_STATE_HELPER
+ select DRM_DISPLAY_HELPER
default DRM_SUN4I
help
Choose this option if you have an Allwinner A10/A10s/A20/A31
diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c
index 335fd0edb904..e89eb96d3131 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.c
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.c
@@ -69,7 +69,9 @@ static void sun4i_backend_disable_color_correction(struct sunxi_engine *engine)
SUN4I_BACKEND_OCCTL_ENABLE, 0);
}
-static void sun4i_backend_commit(struct sunxi_engine *engine)
+static void sun4i_backend_commit(struct sunxi_engine *engine,
+ struct drm_crtc *crtc,
+ struct drm_atomic_state *state)
{
DRM_DEBUG_DRIVER("Committing changes\n");
diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
index c06d7cd45388..18e74047b0f5 100644
--- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
@@ -91,7 +91,7 @@ static void sun4i_crtc_atomic_flush(struct drm_crtc *crtc,
DRM_DEBUG_DRIVER("Committing plane changes\n");
- sunxi_engine_commit(scrtc->engine);
+ sunxi_engine_commit(scrtc->engine, crtc, state);
if (event) {
crtc->state->event = NULL;
diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
index 245b34adca5a..b3649449de30 100644
--- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
@@ -26,6 +26,9 @@
#include <drm/drm_probe_helper.h>
#include <drm/drm_simple_kms_helper.h>
+#include <drm/display/drm_hdmi_helper.h>
+#include <drm/display/drm_hdmi_state_helper.h>
+
#include "sun4i_backend.h"
#include "sun4i_crtc.h"
#include "sun4i_drv.h"
@@ -37,30 +40,24 @@
#define drm_connector_to_sun4i_hdmi(c) \
container_of_const(c, struct sun4i_hdmi, connector)
-static int sun4i_hdmi_setup_avi_infoframes(struct sun4i_hdmi *hdmi,
- struct drm_display_mode *mode)
+static int sun4i_hdmi_write_infoframe(struct drm_connector *connector,
+ enum hdmi_infoframe_type type,
+ const u8 *buffer, size_t len)
{
- struct hdmi_avi_infoframe frame;
- u8 buffer[17];
- int i, ret;
-
- ret = drm_hdmi_avi_infoframe_from_display_mode(&frame,
- &hdmi->connector, mode);
- if (ret < 0) {
- DRM_ERROR("Failed to get infoframes from mode\n");
- return ret;
- }
+ struct sun4i_hdmi *hdmi = drm_connector_to_sun4i_hdmi(connector);
+ int i;
- ret = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer));
- if (ret < 0) {
- DRM_ERROR("Failed to pack infoframes\n");
- return ret;
+ if (type != HDMI_INFOFRAME_TYPE_AVI) {
+ drm_err(connector->dev,
+ "Unsupported infoframe type: %u\n", type);
+ return 0;
}
- for (i = 0; i < sizeof(buffer); i++)
+ for (i = 0; i < len; i++)
writeb(buffer[i], hdmi->base + SUN4I_HDMI_AVI_INFOFRAME_REG(i));
return 0;
+
}
static void sun4i_hdmi_disable(struct drm_encoder *encoder,
@@ -83,14 +80,18 @@ static void sun4i_hdmi_enable(struct drm_encoder *encoder,
{
struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
- struct drm_display_info *display = &hdmi->connector.display_info;
+ struct drm_connector *connector = &hdmi->connector;
+ struct drm_display_info *display = &connector->display_info;
+ struct drm_connector_state *conn_state =
+ drm_atomic_get_new_connector_state(state, connector);
+ unsigned long long tmds_rate = conn_state->hdmi.tmds_char_rate;
unsigned int x, y;
u32 val = 0;
DRM_DEBUG_DRIVER("Enabling the HDMI Output\n");
- clk_set_rate(hdmi->mod_clk, mode->crtc_clock * 1000);
- clk_set_rate(hdmi->tmds_clk, mode->crtc_clock * 1000);
+ clk_set_rate(hdmi->mod_clk, tmds_rate);
+ clk_set_rate(hdmi->tmds_clk, tmds_rate);
/* Set input sync enable */
writel(SUN4I_HDMI_UNKNOWN_INPUT_SYNC,
@@ -143,7 +144,8 @@ static void sun4i_hdmi_enable(struct drm_encoder *encoder,
clk_prepare_enable(hdmi->tmds_clk);
- sun4i_hdmi_setup_avi_infoframes(hdmi, mode);
+ drm_atomic_helper_connector_hdmi_update_infoframes(connector, state);
+
val |= SUN4I_HDMI_PKT_CTRL_TYPE(0, SUN4I_HDMI_PKT_AVI);
val |= SUN4I_HDMI_PKT_CTRL_TYPE(1, SUN4I_HDMI_PKT_END);
writel(val, hdmi->base + SUN4I_HDMI_PKT_CTRL_REG(0));
@@ -196,7 +198,7 @@ static int sun4i_hdmi_connector_atomic_check(struct drm_connector *connector,
enum drm_mode_status status;
status = sun4i_hdmi_connector_clock_valid(connector, mode,
- mode->clock * 1000);
+ conn_state->hdmi.tmds_char_rate);
if (status != MODE_OK)
return -EINVAL;
@@ -207,8 +209,10 @@ static enum drm_mode_status
sun4i_hdmi_connector_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
- return sun4i_hdmi_connector_clock_valid(connector, mode,
- mode->clock * 1000);
+ unsigned long long rate = drm_hdmi_compute_mode_clock(mode, 8,
+ HDMI_COLORSPACE_RGB);
+
+ return sun4i_hdmi_connector_clock_valid(connector, mode, rate);
}
static int sun4i_hdmi_get_modes(struct drm_connector *connector)
@@ -258,6 +262,11 @@ static struct i2c_adapter *sun4i_hdmi_get_ddc(struct device *dev)
return ddc;
}
+static const struct drm_connector_hdmi_funcs sun4i_hdmi_hdmi_connector_funcs = {
+ .tmds_char_rate_valid = sun4i_hdmi_connector_clock_valid,
+ .write_infoframe = sun4i_hdmi_write_infoframe,
+};
+
static const struct drm_connector_helper_funcs sun4i_hdmi_connector_helper_funcs = {
.atomic_check = sun4i_hdmi_connector_atomic_check,
.mode_valid = sun4i_hdmi_connector_mode_valid,
@@ -279,11 +288,16 @@ sun4i_hdmi_connector_detect(struct drm_connector *connector, bool force)
return connector_status_connected;
}
+static void sun4i_hdmi_connector_reset(struct drm_connector *connector)
+{
+ drm_atomic_helper_connector_reset(connector);
+ __drm_atomic_helper_connector_hdmi_reset(connector, connector->state);
+}
+
static const struct drm_connector_funcs sun4i_hdmi_connector_funcs = {
.detect = sun4i_hdmi_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
- .destroy = drm_connector_cleanup,
- .reset = drm_atomic_helper_connector_reset,
+ .reset = sun4i_hdmi_connector_reset,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};
@@ -642,10 +656,19 @@ static int sun4i_hdmi_bind(struct device *dev, struct device *master,
drm_connector_helper_add(&hdmi->connector,
&sun4i_hdmi_connector_helper_funcs);
- ret = drm_connector_init_with_ddc(drm, &hdmi->connector,
- &sun4i_hdmi_connector_funcs,
- DRM_MODE_CONNECTOR_HDMIA,
- hdmi->ddc_i2c);
+ ret = drmm_connector_hdmi_init(drm, &hdmi->connector,
+ /*
+ * NOTE: Those are likely to be
+ * wrong, but I couldn't find the
+ * actual ones in the BSP.
+ */
+ "AW", "HDMI",
+ &sun4i_hdmi_connector_funcs,
+ &sun4i_hdmi_hdmi_connector_funcs,
+ DRM_MODE_CONNECTOR_HDMIA,
+ hdmi->ddc_i2c,
+ BIT(HDMI_COLORSPACE_RGB),
+ 8);
if (ret) {
dev_err(dev,
"Couldn't initialise the HDMI connector\n");
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 01382860aaee..bd0fe2c6624e 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -16,6 +16,7 @@
#include <linux/platform_device.h>
#include <linux/reset.h>
+#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
#include <drm/drm_framebuffer.h>
@@ -249,10 +250,73 @@ int sun8i_mixer_drm_format_to_hw(u32 format, u32 *hw_format)
return -EINVAL;
}
-static void sun8i_mixer_commit(struct sunxi_engine *engine)
+static void sun8i_layer_enable(struct sun8i_layer *layer, bool enable)
{
+ u32 ch_base = sun8i_channel_base(layer->mixer, layer->channel);
+ u32 val, reg, mask;
+
+ if (layer->type == SUN8I_LAYER_TYPE_UI) {
+ val = enable ? SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN : 0;
+ mask = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN;
+ reg = SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ch_base, layer->overlay);
+ } else {
+ val = enable ? SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN : 0;
+ mask = SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN;
+ reg = SUN8I_MIXER_CHAN_VI_LAYER_ATTR(ch_base, layer->overlay);
+ }
+
+ regmap_update_bits(layer->mixer->engine.regs, reg, mask, val);
+}
+
+static void sun8i_mixer_commit(struct sunxi_engine *engine,
+ struct drm_crtc *crtc,
+ struct drm_atomic_state *state)
+{
+ struct sun8i_mixer *mixer = engine_to_sun8i_mixer(engine);
+ u32 bld_base = sun8i_blender_base(mixer);
+ struct drm_plane_state *plane_state;
+ struct drm_plane *plane;
+ u32 route = 0, pipe_en = 0;
+
DRM_DEBUG_DRIVER("Committing changes\n");
+ drm_for_each_plane(plane, state->dev) {
+ struct sun8i_layer *layer = plane_to_sun8i_layer(plane);
+ bool enable;
+ int zpos;
+
+ if (!(plane->possible_crtcs & drm_crtc_mask(crtc)) || layer->mixer != mixer)
+ continue;
+
+ plane_state = drm_atomic_get_new_plane_state(state, plane);
+ if (!plane_state)
+ plane_state = plane->state;
+
+ enable = plane_state->crtc && plane_state->visible;
+ zpos = plane_state->normalized_zpos;
+
+ DRM_DEBUG_DRIVER(" plane %d: chan=%d ovl=%d en=%d zpos=%d\n",
+ plane->base.id, layer->channel, layer->overlay,
+ enable, zpos);
+
+ /*
+ * We always update the layer enable bit, because it can clear
+ * spontaneously for unknown reasons.
+ */
+ sun8i_layer_enable(layer, enable);
+
+ if (!enable)
+ continue;
+
+ /* Route layer to pipe based on zpos */
+ route |= layer->channel << SUN8I_MIXER_BLEND_ROUTE_PIPE_SHIFT(zpos);
+ pipe_en |= SUN8I_MIXER_BLEND_PIPE_CTL_EN(zpos);
+ }
+
+ regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ROUTE(bld_base), route);
+ regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(bld_base),
+ pipe_en | SUN8I_MIXER_BLEND_PIPE_CTL_FC_EN(0));
+
regmap_write(engine->regs, SUN8I_MIXER_GLOBAL_DBUFF,
SUN8I_MIXER_GLOBAL_DBUFF_ENABLE);
}
@@ -271,7 +335,7 @@ static struct drm_plane **sun8i_layers_init(struct drm_device *drm,
return ERR_PTR(-ENOMEM);
for (i = 0; i < mixer->cfg->vi_num; i++) {
- struct sun8i_vi_layer *layer;
+ struct sun8i_layer *layer;
layer = sun8i_vi_layer_init_one(drm, mixer, i);
if (IS_ERR(layer)) {
@@ -284,7 +348,7 @@ static struct drm_plane **sun8i_layers_init(struct drm_device *drm,
}
for (i = 0; i < mixer->cfg->ui_num; i++) {
- struct sun8i_ui_layer *layer;
+ struct sun8i_layer *layer;
layer = sun8i_ui_layer_init_one(drm, mixer, i);
if (IS_ERR(layer)) {
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
index 85c94884fb9a..d7898c9c9cc0 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -9,6 +9,7 @@
#include <linux/clk.h>
#include <linux/regmap.h>
#include <linux/reset.h>
+#include <drm/drm_plane.h>
#include "sunxi_engine.h"
@@ -185,6 +186,25 @@ struct sun8i_mixer {
struct clk *mod_clk;
};
+enum {
+ SUN8I_LAYER_TYPE_UI,
+ SUN8I_LAYER_TYPE_VI,
+};
+
+struct sun8i_layer {
+ struct drm_plane plane;
+ struct sun8i_mixer *mixer;
+ int type;
+ int channel;
+ int overlay;
+};
+
+static inline struct sun8i_layer *
+plane_to_sun8i_layer(struct drm_plane *plane)
+{
+ return container_of(plane, struct sun8i_layer, plane);
+}
+
static inline struct sun8i_mixer *
engine_to_sun8i_mixer(struct sunxi_engine *engine)
{
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
index ca75ca0835a6..b90e5edef4e8 100644
--- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
@@ -24,55 +24,6 @@
#include "sun8i_ui_layer.h"
#include "sun8i_ui_scaler.h"
-static void sun8i_ui_layer_enable(struct sun8i_mixer *mixer, int channel,
- int overlay, bool enable, unsigned int zpos,
- unsigned int old_zpos)
-{
- u32 val, bld_base, ch_base;
-
- bld_base = sun8i_blender_base(mixer);
- ch_base = sun8i_channel_base(mixer, channel);
-
- DRM_DEBUG_DRIVER("%sabling channel %d overlay %d\n",
- enable ? "En" : "Dis", channel, overlay);
-
- if (enable)
- val = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN;
- else
- val = 0;
-
- regmap_update_bits(mixer->engine.regs,
- SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ch_base, overlay),
- SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN, val);
-
- if (!enable || zpos != old_zpos) {
- regmap_update_bits(mixer->engine.regs,
- SUN8I_MIXER_BLEND_PIPE_CTL(bld_base),
- SUN8I_MIXER_BLEND_PIPE_CTL_EN(old_zpos),
- 0);
-
- regmap_update_bits(mixer->engine.regs,
- SUN8I_MIXER_BLEND_ROUTE(bld_base),
- SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(old_zpos),
- 0);
- }
-
- if (enable) {
- val = SUN8I_MIXER_BLEND_PIPE_CTL_EN(zpos);
-
- regmap_update_bits(mixer->engine.regs,
- SUN8I_MIXER_BLEND_PIPE_CTL(bld_base),
- val, val);
-
- val = channel << SUN8I_MIXER_BLEND_ROUTE_PIPE_SHIFT(zpos);
-
- regmap_update_bits(mixer->engine.regs,
- SUN8I_MIXER_BLEND_ROUTE(bld_base),
- SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(zpos),
- val);
- }
-}
-
static void sun8i_ui_layer_update_alpha(struct sun8i_mixer *mixer, int channel,
int overlay, struct drm_plane *plane)
{
@@ -232,7 +183,7 @@ static int sun8i_ui_layer_atomic_check(struct drm_plane *plane,
{
struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
plane);
- struct sun8i_ui_layer *layer = plane_to_sun8i_ui_layer(plane);
+ struct sun8i_layer *layer = plane_to_sun8i_layer(plane);
struct drm_crtc *crtc = new_plane_state->crtc;
struct drm_crtc_state *crtc_state;
int min_scale, max_scale;
@@ -259,36 +210,18 @@ static int sun8i_ui_layer_atomic_check(struct drm_plane *plane,
true, true);
}
-static void sun8i_ui_layer_atomic_disable(struct drm_plane *plane,
- struct drm_atomic_state *state)
-{
- struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state,
- plane);
- struct sun8i_ui_layer *layer = plane_to_sun8i_ui_layer(plane);
- unsigned int old_zpos = old_state->normalized_zpos;
- struct sun8i_mixer *mixer = layer->mixer;
-
- sun8i_ui_layer_enable(mixer, layer->channel, layer->overlay, false, 0,
- old_zpos);
-}
static void sun8i_ui_layer_atomic_update(struct drm_plane *plane,
struct drm_atomic_state *state)
{
- struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state,
- plane);
struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
plane);
- struct sun8i_ui_layer *layer = plane_to_sun8i_ui_layer(plane);
+ struct sun8i_layer *layer = plane_to_sun8i_layer(plane);
unsigned int zpos = new_state->normalized_zpos;
- unsigned int old_zpos = old_state->normalized_zpos;
struct sun8i_mixer *mixer = layer->mixer;
- if (!new_state->visible) {
- sun8i_ui_layer_enable(mixer, layer->channel,
- layer->overlay, false, 0, old_zpos);
+ if (!new_state->crtc || !new_state->visible)
return;
- }
sun8i_ui_layer_update_coord(mixer, layer->channel,
layer->overlay, plane, zpos);
@@ -298,13 +231,10 @@ static void sun8i_ui_layer_atomic_update(struct drm_plane *plane,
layer->overlay, plane);
sun8i_ui_layer_update_buffer(mixer, layer->channel,
layer->overlay, plane);
- sun8i_ui_layer_enable(mixer, layer->channel, layer->overlay,
- true, zpos, old_zpos);
}
static const struct drm_plane_helper_funcs sun8i_ui_layer_helper_funcs = {
.atomic_check = sun8i_ui_layer_atomic_check,
- .atomic_disable = sun8i_ui_layer_atomic_disable,
.atomic_update = sun8i_ui_layer_atomic_update,
};
@@ -345,13 +275,13 @@ static const uint64_t sun8i_layer_modifiers[] = {
DRM_FORMAT_MOD_INVALID
};
-struct sun8i_ui_layer *sun8i_ui_layer_init_one(struct drm_device *drm,
- struct sun8i_mixer *mixer,
- int index)
+struct sun8i_layer *sun8i_ui_layer_init_one(struct drm_device *drm,
+ struct sun8i_mixer *mixer,
+ int index)
{
enum drm_plane_type type = DRM_PLANE_TYPE_OVERLAY;
int channel = mixer->cfg->vi_num + index;
- struct sun8i_ui_layer *layer;
+ struct sun8i_layer *layer;
unsigned int plane_cnt;
int ret;
@@ -390,6 +320,7 @@ struct sun8i_ui_layer *sun8i_ui_layer_init_one(struct drm_device *drm,
drm_plane_helper_add(&layer->plane, &sun8i_ui_layer_helper_funcs);
layer->mixer = mixer;
+ layer->type = SUN8I_LAYER_TYPE_UI;
layer->channel = channel;
layer->overlay = 0;
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.h b/drivers/gpu/drm/sun4i/sun8i_ui_layer.h
index e3e32ee1178d..83892f6ff211 100644
--- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.h
@@ -47,21 +47,9 @@
#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_COMBINED ((2) << 1)
struct sun8i_mixer;
+struct sun8i_layer;
-struct sun8i_ui_layer {
- struct drm_plane plane;
- struct sun8i_mixer *mixer;
- int channel;
- int overlay;
-};
-
-static inline struct sun8i_ui_layer *
-plane_to_sun8i_ui_layer(struct drm_plane *plane)
-{
- return container_of(plane, struct sun8i_ui_layer, plane);
-}
-
-struct sun8i_ui_layer *sun8i_ui_layer_init_one(struct drm_device *drm,
- struct sun8i_mixer *mixer,
- int index);
+struct sun8i_layer *sun8i_ui_layer_init_one(struct drm_device *drm,
+ struct sun8i_mixer *mixer,
+ int index);
#endif /* _SUN8I_UI_LAYER_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
index f9c0a56d3a14..9c09d9c08496 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
@@ -18,55 +18,6 @@
#include "sun8i_vi_layer.h"
#include "sun8i_vi_scaler.h"
-static void sun8i_vi_layer_enable(struct sun8i_mixer *mixer, int channel,
- int overlay, bool enable, unsigned int zpos,
- unsigned int old_zpos)
-{
- u32 val, bld_base, ch_base;
-
- bld_base = sun8i_blender_base(mixer);
- ch_base = sun8i_channel_base(mixer, channel);
-
- DRM_DEBUG_DRIVER("%sabling VI channel %d overlay %d\n",
- enable ? "En" : "Dis", channel, overlay);
-
- if (enable)
- val = SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN;
- else
- val = 0;
-
- regmap_update_bits(mixer->engine.regs,
- SUN8I_MIXER_CHAN_VI_LAYER_ATTR(ch_base, overlay),
- SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN, val);
-
- if (!enable || zpos != old_zpos) {
- regmap_update_bits(mixer->engine.regs,
- SUN8I_MIXER_BLEND_PIPE_CTL(bld_base),
- SUN8I_MIXER_BLEND_PIPE_CTL_EN(old_zpos),
- 0);
-
- regmap_update_bits(mixer->engine.regs,
- SUN8I_MIXER_BLEND_ROUTE(bld_base),
- SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(old_zpos),
- 0);
- }
-
- if (enable) {
- val = SUN8I_MIXER_BLEND_PIPE_CTL_EN(zpos);
-
- regmap_update_bits(mixer->engine.regs,
- SUN8I_MIXER_BLEND_PIPE_CTL(bld_base),
- val, val);
-
- val = channel << SUN8I_MIXER_BLEND_ROUTE_PIPE_SHIFT(zpos);
-
- regmap_update_bits(mixer->engine.regs,
- SUN8I_MIXER_BLEND_ROUTE(bld_base),
- SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(zpos),
- val);
- }
-}
-
static void sun8i_vi_layer_update_alpha(struct sun8i_mixer *mixer, int channel,
int overlay, struct drm_plane *plane)
{
@@ -366,7 +317,7 @@ static int sun8i_vi_layer_atomic_check(struct drm_plane *plane,
{
struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
plane);
- struct sun8i_vi_layer *layer = plane_to_sun8i_vi_layer(plane);
+ struct sun8i_layer *layer = plane_to_sun8i_layer(plane);
struct drm_crtc *crtc = new_plane_state->crtc;
struct drm_crtc_state *crtc_state;
int min_scale, max_scale;
@@ -393,36 +344,17 @@ static int sun8i_vi_layer_atomic_check(struct drm_plane *plane,
true, true);
}
-static void sun8i_vi_layer_atomic_disable(struct drm_plane *plane,
- struct drm_atomic_state *state)
-{
- struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state,
- plane);
- struct sun8i_vi_layer *layer = plane_to_sun8i_vi_layer(plane);
- unsigned int old_zpos = old_state->normalized_zpos;
- struct sun8i_mixer *mixer = layer->mixer;
-
- sun8i_vi_layer_enable(mixer, layer->channel, layer->overlay, false, 0,
- old_zpos);
-}
-
static void sun8i_vi_layer_atomic_update(struct drm_plane *plane,
struct drm_atomic_state *state)
{
- struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state,
- plane);
struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
plane);
- struct sun8i_vi_layer *layer = plane_to_sun8i_vi_layer(plane);
+ struct sun8i_layer *layer = plane_to_sun8i_layer(plane);
unsigned int zpos = new_state->normalized_zpos;
- unsigned int old_zpos = old_state->normalized_zpos;
struct sun8i_mixer *mixer = layer->mixer;
- if (!new_state->visible) {
- sun8i_vi_layer_enable(mixer, layer->channel,
- layer->overlay, false, 0, old_zpos);
+ if (!new_state->crtc || !new_state->visible)
return;
- }
sun8i_vi_layer_update_coord(mixer, layer->channel,
layer->overlay, plane, zpos);
@@ -432,13 +364,10 @@ static void sun8i_vi_layer_atomic_update(struct drm_plane *plane,
layer->overlay, plane);
sun8i_vi_layer_update_buffer(mixer, layer->channel,
layer->overlay, plane);
- sun8i_vi_layer_enable(mixer, layer->channel, layer->overlay,
- true, zpos, old_zpos);
}
static const struct drm_plane_helper_funcs sun8i_vi_layer_helper_funcs = {
.atomic_check = sun8i_vi_layer_atomic_check,
- .atomic_disable = sun8i_vi_layer_atomic_disable,
.atomic_update = sun8i_vi_layer_atomic_update,
};
@@ -539,14 +468,14 @@ static const uint64_t sun8i_layer_modifiers[] = {
DRM_FORMAT_MOD_INVALID
};
-struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
- struct sun8i_mixer *mixer,
- int index)
+struct sun8i_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
+ struct sun8i_mixer *mixer,
+ int index)
{
enum drm_plane_type type = DRM_PLANE_TYPE_OVERLAY;
u32 supported_encodings, supported_ranges;
unsigned int plane_cnt, format_count;
- struct sun8i_vi_layer *layer;
+ struct sun8i_layer *layer;
const u32 *formats;
int ret;
@@ -613,6 +542,7 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
drm_plane_helper_add(&layer->plane, &sun8i_vi_layer_helper_funcs);
layer->mixer = mixer;
+ layer->type = SUN8I_LAYER_TYPE_VI;
layer->channel = index;
layer->overlay = 0;
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.h b/drivers/gpu/drm/sun4i/sun8i_vi_layer.h
index 48c399e1c86d..655440cdc78f 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.h
@@ -52,21 +52,9 @@
#define SUN8I_MIXER_CHAN_VI_DS_M(x) ((x) << 0)
struct sun8i_mixer;
+struct sun8i_layer;
-struct sun8i_vi_layer {
- struct drm_plane plane;
- struct sun8i_mixer *mixer;
- int channel;
- int overlay;
-};
-
-static inline struct sun8i_vi_layer *
-plane_to_sun8i_vi_layer(struct drm_plane *plane)
-{
- return container_of(plane, struct sun8i_vi_layer, plane);
-}
-
-struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
- struct sun8i_mixer *mixer,
- int index);
+struct sun8i_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
+ struct sun8i_mixer *mixer,
+ int index);
#endif /* _SUN8I_VI_LAYER_H_ */
diff --git a/drivers/gpu/drm/sun4i/sunxi_engine.h b/drivers/gpu/drm/sun4i/sunxi_engine.h
index ec8cf9b2bda4..ec0c4932f15c 100644
--- a/drivers/gpu/drm/sun4i/sunxi_engine.h
+++ b/drivers/gpu/drm/sun4i/sunxi_engine.h
@@ -7,6 +7,7 @@
#define _SUNXI_ENGINE_H_
struct drm_plane;
+struct drm_crtc;
struct drm_device;
struct drm_crtc_state;
struct drm_display_mode;
@@ -59,7 +60,9 @@ struct sunxi_engine_ops {
*
* This function is optional.
*/
- void (*commit)(struct sunxi_engine *engine);
+ void (*commit)(struct sunxi_engine *engine,
+ struct drm_crtc *crtc,
+ struct drm_atomic_state *state);
/**
* @layers_init:
@@ -144,12 +147,16 @@ struct sunxi_engine {
/**
* sunxi_engine_commit() - commit all changes of the engine
* @engine: pointer to the engine
+ * @crtc: pointer to crtc the engine is associated with
+ * @state: atomic state
*/
static inline void
-sunxi_engine_commit(struct sunxi_engine *engine)
+sunxi_engine_commit(struct sunxi_engine *engine,
+ struct drm_crtc *crtc,
+ struct drm_atomic_state *state)
{
if (engine->ops && engine->ops->commit)
- engine->ops->commit(engine);
+ engine->ops->commit(engine, crtc, state);
}
/**
diff --git a/drivers/gpu/drm/tests/Makefile b/drivers/gpu/drm/tests/Makefile
index d6183b3d7688..56dab563abd7 100644
--- a/drivers/gpu/drm/tests/Makefile
+++ b/drivers/gpu/drm/tests/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_DRM_KUNIT_TEST) += \
drm_format_test.o \
drm_framebuffer_test.o \
drm_gem_shmem_test.o \
+ drm_hdmi_state_helper_test.o \
drm_managed_test.o \
drm_mm_test.o \
drm_modes_test.o \
diff --git a/drivers/gpu/drm/tests/drm_buddy_test.c b/drivers/gpu/drm/tests/drm_buddy_test.c
index dd8fb9f8341a..9662c949d0e3 100644
--- a/drivers/gpu/drm/tests/drm_buddy_test.c
+++ b/drivers/gpu/drm/tests/drm_buddy_test.c
@@ -774,4 +774,5 @@ static struct kunit_suite drm_buddy_test_suite = {
kunit_test_suite(drm_buddy_test_suite);
MODULE_AUTHOR("Intel Corporation");
+MODULE_DESCRIPTION("Kunit test for drm_buddy functions");
MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tests/drm_cmdline_parser_test.c b/drivers/gpu/drm/tests/drm_cmdline_parser_test.c
index 88f7f518ffb3..59c8408c453c 100644
--- a/drivers/gpu/drm/tests/drm_cmdline_parser_test.c
+++ b/drivers/gpu/drm/tests/drm_cmdline_parser_test.c
@@ -992,6 +992,17 @@ static const struct drm_cmdline_tv_option_test drm_cmdline_tv_option_tests[] = {
TV_OPT_TEST(PAL_M, "720x480i,tv_mode=PAL-M", drm_mode_analog_ntsc_480i),
TV_OPT_TEST(PAL_N, "720x576i,tv_mode=PAL-N", drm_mode_analog_pal_576i),
TV_OPT_TEST(SECAM, "720x576i,tv_mode=SECAM", drm_mode_analog_pal_576i),
+ {
+ .name = "MONO_525",
+ .cmdline = "720x480i,tv_mode=Mono",
+ .mode_fn = drm_mode_analog_ntsc_480i,
+ .tv_mode = DRM_MODE_TV_MODE_MONOCHROME,
+ }, {
+ .name = "MONO_625",
+ .cmdline = "720x576i,tv_mode=Mono",
+ .mode_fn = drm_mode_analog_pal_576i,
+ .tv_mode = DRM_MODE_TV_MODE_MONOCHROME,
+ },
};
static void drm_cmdline_tv_option_desc(const struct drm_cmdline_tv_option_test *t,
@@ -1056,4 +1067,5 @@ static struct kunit_suite drm_cmdline_parser_test_suite = {
kunit_test_suite(drm_cmdline_parser_test_suite);
MODULE_AUTHOR("Maxime Ripard <maxime.ripard@bootlin.com>");
+MODULE_DESCRIPTION("Kunit test for drm_cmdline_parser functions");
MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tests/drm_connector_test.c b/drivers/gpu/drm/tests/drm_connector_test.c
index 44f82ed2a958..15e36a8db685 100644
--- a/drivers/gpu/drm/tests/drm_connector_test.c
+++ b/drivers/gpu/drm/tests/drm_connector_test.c
@@ -8,16 +8,25 @@
#include <drm/drm_atomic_state_helper.h>
#include <drm/drm_connector.h>
#include <drm/drm_drv.h>
+#include <drm/drm_edid.h>
#include <drm/drm_kunit_helpers.h>
+#include <drm/drm_modes.h>
+
+#include <drm/display/drm_hdmi_helper.h>
#include <kunit/test.h>
+#include "../drm_crtc_internal.h"
+
struct drm_connector_init_priv {
struct drm_device drm;
struct drm_connector connector;
struct i2c_adapter ddc;
};
+static const struct drm_connector_hdmi_funcs dummy_hdmi_funcs = {
+};
+
static const struct drm_connector_funcs dummy_funcs = {
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
@@ -172,6 +181,573 @@ static struct kunit_suite drmm_connector_init_test_suite = {
.test_cases = drmm_connector_init_tests,
};
+/*
+ * Test that the registration of a bog standard connector works as
+ * expected and doesn't report any error.
+ */
+static void drm_test_connector_hdmi_init_valid(struct kunit *test)
+{
+ struct drm_connector_init_priv *priv = test->priv;
+ int ret;
+
+ ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
+ "Vendor", "Product",
+ &dummy_funcs,
+ &dummy_hdmi_funcs,
+ DRM_MODE_CONNECTOR_HDMIA,
+ &priv->ddc,
+ BIT(HDMI_COLORSPACE_RGB),
+ 8);
+ KUNIT_EXPECT_EQ(test, ret, 0);
+}
+
+/*
+ * Test that the registration of a connector without a DDC adapter
+ * doesn't report any error.
+ */
+static void drm_test_connector_hdmi_init_null_ddc(struct kunit *test)
+{
+ struct drm_connector_init_priv *priv = test->priv;
+ int ret;
+
+ ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
+ "Vendor", "Product",
+ &dummy_funcs,
+ &dummy_hdmi_funcs,
+ DRM_MODE_CONNECTOR_HDMIA,
+ NULL,
+ BIT(HDMI_COLORSPACE_RGB),
+ 8);
+ KUNIT_EXPECT_EQ(test, ret, 0);
+}
+
+/*
+ * Test that the registration of an HDMI connector with a NULL vendor
+ * fails.
+ */
+static void drm_test_connector_hdmi_init_null_vendor(struct kunit *test)
+{
+ struct drm_connector_init_priv *priv = test->priv;
+ int ret;
+
+ ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
+ NULL, "Product",
+ &dummy_funcs,
+ &dummy_hdmi_funcs,
+ DRM_MODE_CONNECTOR_HDMIA,
+ &priv->ddc,
+ BIT(HDMI_COLORSPACE_RGB),
+ 8);
+ KUNIT_EXPECT_LT(test, ret, 0);
+}
+
+/*
+ * Test that the registration of an HDMI connector with a NULL product
+ * fails.
+ */
+static void drm_test_connector_hdmi_init_null_product(struct kunit *test)
+{
+ struct drm_connector_init_priv *priv = test->priv;
+ int ret;
+
+ ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
+ "Vendor", NULL,
+ &dummy_funcs,
+ &dummy_hdmi_funcs,
+ DRM_MODE_CONNECTOR_HDMIA,
+ &priv->ddc,
+ BIT(HDMI_COLORSPACE_RGB),
+ 8);
+ KUNIT_EXPECT_LT(test, ret, 0);
+}
+
+/*
+ * Test that the registration of a connector with a valid, shorter than
+ * the max length, product name succeeds, and is stored padded with 0.
+ */
+static void drm_test_connector_hdmi_init_product_valid(struct kunit *test)
+{
+ struct drm_connector_init_priv *priv = test->priv;
+ const unsigned char expected_product[DRM_CONNECTOR_HDMI_PRODUCT_LEN] = {
+ 'P', 'r', 'o', 'd',
+ };
+ const char *product_name = "Prod";
+ int ret;
+
+ KUNIT_ASSERT_LT(test, strlen(product_name), DRM_CONNECTOR_HDMI_PRODUCT_LEN);
+
+ ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
+ "Vendor", product_name,
+ &dummy_funcs,
+ &dummy_hdmi_funcs,
+ DRM_MODE_CONNECTOR_HDMIA,
+ &priv->ddc,
+ BIT(HDMI_COLORSPACE_RGB),
+ 8);
+ KUNIT_EXPECT_EQ(test, ret, 0);
+ KUNIT_EXPECT_MEMEQ(test,
+ priv->connector.hdmi.product,
+ expected_product,
+ sizeof(priv->connector.hdmi.product));
+}
+
+/*
+ * Test that the registration of a connector with a valid, at max
+ * length, product name succeeds, and is stored padded without any
+ * trailing \0.
+ */
+static void drm_test_connector_hdmi_init_product_length_exact(struct kunit *test)
+{
+ struct drm_connector_init_priv *priv = test->priv;
+ const unsigned char expected_product[DRM_CONNECTOR_HDMI_PRODUCT_LEN] = {
+ 'P', 'r', 'o', 'd', 'u', 'c', 't',
+ 'P', 'r', 'o', 'd', 'u', 'c', 't',
+ 'P', 'r',
+ };
+ const char *product_name = "ProductProductPr";
+ int ret;
+
+ KUNIT_ASSERT_EQ(test, strlen(product_name), DRM_CONNECTOR_HDMI_PRODUCT_LEN);
+
+ ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
+ "Vendor", product_name,
+ &dummy_funcs,
+ &dummy_hdmi_funcs,
+ DRM_MODE_CONNECTOR_HDMIA,
+ &priv->ddc,
+ BIT(HDMI_COLORSPACE_RGB),
+ 8);
+ KUNIT_EXPECT_EQ(test, ret, 0);
+ KUNIT_EXPECT_MEMEQ(test,
+ priv->connector.hdmi.product,
+ expected_product,
+ sizeof(priv->connector.hdmi.product));
+}
+
+/*
+ * Test that the registration of a connector with a product name larger
+ * than the maximum length fails.
+ */
+static void drm_test_connector_hdmi_init_product_length_too_long(struct kunit *test)
+{
+ struct drm_connector_init_priv *priv = test->priv;
+ const char *product_name = "ProductProductProduct";
+ int ret;
+
+ KUNIT_ASSERT_GT(test, strlen(product_name), DRM_CONNECTOR_HDMI_PRODUCT_LEN);
+
+ ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
+ "Vendor", product_name,
+ &dummy_funcs,
+ &dummy_hdmi_funcs,
+ DRM_MODE_CONNECTOR_HDMIA,
+ &priv->ddc,
+ BIT(HDMI_COLORSPACE_RGB),
+ 8);
+ KUNIT_EXPECT_LT(test, ret, 0);
+}
+
+/*
+ * Test that the registration of a connector with a vendor name smaller
+ * than the maximum length succeeds, and is stored padded with zeros.
+ */
+static void drm_test_connector_hdmi_init_vendor_valid(struct kunit *test)
+{
+ struct drm_connector_init_priv *priv = test->priv;
+ const char expected_vendor[DRM_CONNECTOR_HDMI_VENDOR_LEN] = {
+ 'V', 'e', 'n', 'd',
+ };
+ const char *vendor_name = "Vend";
+ int ret;
+
+ KUNIT_ASSERT_LT(test, strlen(vendor_name), DRM_CONNECTOR_HDMI_VENDOR_LEN);
+
+ ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
+ vendor_name, "Product",
+ &dummy_funcs,
+ &dummy_hdmi_funcs,
+ DRM_MODE_CONNECTOR_HDMIA,
+ &priv->ddc,
+ BIT(HDMI_COLORSPACE_RGB),
+ 8);
+ KUNIT_EXPECT_EQ(test, ret, 0);
+ KUNIT_EXPECT_MEMEQ(test,
+ priv->connector.hdmi.vendor,
+ expected_vendor,
+ sizeof(priv->connector.hdmi.vendor));
+}
+
+/*
+ * Test that the registration of a connector with a vendor name at the
+ * maximum length succeeds, and is stored padded without the trailing
+ * zero.
+ */
+static void drm_test_connector_hdmi_init_vendor_length_exact(struct kunit *test)
+{
+ struct drm_connector_init_priv *priv = test->priv;
+ const char expected_vendor[DRM_CONNECTOR_HDMI_VENDOR_LEN] = {
+ 'V', 'e', 'n', 'd', 'o', 'r',
+ 'V', 'e',
+ };
+ const char *vendor_name = "VendorVe";
+ int ret;
+
+ KUNIT_ASSERT_EQ(test, strlen(vendor_name), DRM_CONNECTOR_HDMI_VENDOR_LEN);
+
+ ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
+ vendor_name, "Product",
+ &dummy_funcs,
+ &dummy_hdmi_funcs,
+ DRM_MODE_CONNECTOR_HDMIA,
+ &priv->ddc,
+ BIT(HDMI_COLORSPACE_RGB),
+ 8);
+ KUNIT_EXPECT_EQ(test, ret, 0);
+ KUNIT_EXPECT_MEMEQ(test,
+ priv->connector.hdmi.vendor,
+ expected_vendor,
+ sizeof(priv->connector.hdmi.vendor));
+}
+
+/*
+ * Test that the registration of a connector with a vendor name larger
+ * than the maximum length fails.
+ */
+static void drm_test_connector_hdmi_init_vendor_length_too_long(struct kunit *test)
+{
+ struct drm_connector_init_priv *priv = test->priv;
+ const char *vendor_name = "VendorVendor";
+ int ret;
+
+ KUNIT_ASSERT_GT(test, strlen(vendor_name), DRM_CONNECTOR_HDMI_VENDOR_LEN);
+
+ ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
+ vendor_name, "Product",
+ &dummy_funcs,
+ &dummy_hdmi_funcs,
+ DRM_MODE_CONNECTOR_HDMIA,
+ &priv->ddc,
+ BIT(HDMI_COLORSPACE_RGB),
+ 8);
+ KUNIT_EXPECT_LT(test, ret, 0);
+}
+
+/*
+ * Test that the registration of a connector with an invalid maximum bpc
+ * count fails.
+ */
+static void drm_test_connector_hdmi_init_bpc_invalid(struct kunit *test)
+{
+ struct drm_connector_init_priv *priv = test->priv;
+ int ret;
+
+ ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
+ "Vendor", "Product",
+ &dummy_funcs,
+ &dummy_hdmi_funcs,
+ DRM_MODE_CONNECTOR_HDMIA,
+ &priv->ddc,
+ BIT(HDMI_COLORSPACE_RGB),
+ 9);
+ KUNIT_EXPECT_LT(test, ret, 0);
+}
+
+/*
+ * Test that the registration of a connector with a null maximum bpc
+ * count fails.
+ */
+static void drm_test_connector_hdmi_init_bpc_null(struct kunit *test)
+{
+ struct drm_connector_init_priv *priv = test->priv;
+ int ret;
+
+ ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
+ "Vendor", "Product",
+ &dummy_funcs,
+ &dummy_hdmi_funcs,
+ DRM_MODE_CONNECTOR_HDMIA,
+ &priv->ddc,
+ BIT(HDMI_COLORSPACE_RGB),
+ 0);
+ KUNIT_EXPECT_LT(test, ret, 0);
+}
+
+/*
+ * Test that the registration of a connector with a maximum bpc count of
+ * 8 succeeds, registers the max bpc property, but doesn't register the
+ * HDR output metadata one.
+ */
+static void drm_test_connector_hdmi_init_bpc_8(struct kunit *test)
+{
+ struct drm_connector_init_priv *priv = test->priv;
+ struct drm_connector_state *state;
+ struct drm_connector *connector = &priv->connector;
+ struct drm_property *prop;
+ uint64_t val;
+ int ret;
+
+ ret = drmm_connector_hdmi_init(&priv->drm, connector,
+ "Vendor", "Product",
+ &dummy_funcs,
+ &dummy_hdmi_funcs,
+ DRM_MODE_CONNECTOR_HDMIA,
+ &priv->ddc,
+ BIT(HDMI_COLORSPACE_RGB),
+ 8);
+ KUNIT_EXPECT_EQ(test, ret, 0);
+
+ prop = connector->max_bpc_property;
+ KUNIT_ASSERT_NOT_NULL(test, prop);
+ KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id));
+
+ ret = drm_object_property_get_default_value(&connector->base, prop, &val);
+ KUNIT_EXPECT_EQ(test, ret, 0);
+ KUNIT_EXPECT_EQ(test, val, 8);
+
+ state = connector->state;
+ KUNIT_EXPECT_EQ(test, state->max_bpc, 8);
+ KUNIT_EXPECT_EQ(test, state->max_requested_bpc, 8);
+
+ prop = priv->drm.mode_config.hdr_output_metadata_property;
+ KUNIT_ASSERT_NOT_NULL(test, prop);
+ KUNIT_EXPECT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id));
+}
+
+/*
+ * Test that the registration of a connector with a maximum bpc count of
+ * 10 succeeds and registers the max bpc and HDR output metadata
+ * properties.
+ */
+static void drm_test_connector_hdmi_init_bpc_10(struct kunit *test)
+{
+ struct drm_connector_init_priv *priv = test->priv;
+ struct drm_connector_state *state;
+ struct drm_connector *connector = &priv->connector;
+ struct drm_property *prop;
+ uint64_t val;
+ int ret;
+
+ ret = drmm_connector_hdmi_init(&priv->drm, connector,
+ "Vendor", "Product",
+ &dummy_funcs,
+ &dummy_hdmi_funcs,
+ DRM_MODE_CONNECTOR_HDMIA,
+ &priv->ddc,
+ BIT(HDMI_COLORSPACE_RGB),
+ 10);
+ KUNIT_EXPECT_EQ(test, ret, 0);
+
+ prop = connector->max_bpc_property;
+ KUNIT_ASSERT_NOT_NULL(test, prop);
+ KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id));
+
+ ret = drm_object_property_get_default_value(&connector->base, prop, &val);
+ KUNIT_EXPECT_EQ(test, ret, 0);
+ KUNIT_EXPECT_EQ(test, val, 10);
+
+ state = connector->state;
+ KUNIT_EXPECT_EQ(test, state->max_bpc, 10);
+ KUNIT_EXPECT_EQ(test, state->max_requested_bpc, 10);
+
+ prop = priv->drm.mode_config.hdr_output_metadata_property;
+ KUNIT_ASSERT_NOT_NULL(test, prop);
+ KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id));
+}
+
+/*
+ * Test that the registration of a connector with a maximum bpc count of
+ * 12 succeeds and registers the max bpc and HDR output metadata
+ * properties.
+ */
+static void drm_test_connector_hdmi_init_bpc_12(struct kunit *test)
+{
+ struct drm_connector_init_priv *priv = test->priv;
+ struct drm_connector_state *state;
+ struct drm_connector *connector = &priv->connector;
+ struct drm_property *prop;
+ uint64_t val;
+ int ret;
+
+ ret = drmm_connector_hdmi_init(&priv->drm, connector,
+ "Vendor", "Product",
+ &dummy_funcs,
+ &dummy_hdmi_funcs,
+ DRM_MODE_CONNECTOR_HDMIA,
+ &priv->ddc,
+ BIT(HDMI_COLORSPACE_RGB),
+ 12);
+ KUNIT_EXPECT_EQ(test, ret, 0);
+
+ prop = connector->max_bpc_property;
+ KUNIT_ASSERT_NOT_NULL(test, prop);
+ KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id));
+
+ ret = drm_object_property_get_default_value(&connector->base, prop, &val);
+ KUNIT_EXPECT_EQ(test, ret, 0);
+ KUNIT_EXPECT_EQ(test, val, 12);
+
+ state = connector->state;
+ KUNIT_EXPECT_EQ(test, state->max_bpc, 12);
+ KUNIT_EXPECT_EQ(test, state->max_requested_bpc, 12);
+
+ prop = priv->drm.mode_config.hdr_output_metadata_property;
+ KUNIT_ASSERT_NOT_NULL(test, prop);
+ KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id));
+}
+
+/*
+ * Test that the registration of an HDMI connector with no supported
+ * format fails.
+ */
+static void drm_test_connector_hdmi_init_formats_empty(struct kunit *test)
+{
+ struct drm_connector_init_priv *priv = test->priv;
+ int ret;
+
+ ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
+ "Vendor", "Product",
+ &dummy_funcs,
+ &dummy_hdmi_funcs,
+ DRM_MODE_CONNECTOR_HDMIA,
+ &priv->ddc,
+ 0,
+ 8);
+ KUNIT_EXPECT_LT(test, ret, 0);
+}
+
+/*
+ * Test that the registration of an HDMI connector not listing RGB as a
+ * supported format fails.
+ */
+static void drm_test_connector_hdmi_init_formats_no_rgb(struct kunit *test)
+{
+ struct drm_connector_init_priv *priv = test->priv;
+ int ret;
+
+ ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
+ "Vendor", "Product",
+ &dummy_funcs,
+ &dummy_hdmi_funcs,
+ DRM_MODE_CONNECTOR_HDMIA,
+ &priv->ddc,
+ BIT(HDMI_COLORSPACE_YUV422),
+ 8);
+ KUNIT_EXPECT_LT(test, ret, 0);
+}
+
+/*
+ * Test that the registration of an HDMI connector with an HDMI
+ * connector type succeeds.
+ */
+static void drm_test_connector_hdmi_init_type_valid(struct kunit *test)
+{
+ struct drm_connector_init_priv *priv = test->priv;
+ unsigned int connector_type = *(unsigned int *)test->param_value;
+ int ret;
+
+ ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
+ "Vendor", "Product",
+ &dummy_funcs,
+ &dummy_hdmi_funcs,
+ connector_type,
+ &priv->ddc,
+ BIT(HDMI_COLORSPACE_RGB),
+ 8);
+ KUNIT_EXPECT_EQ(test, ret, 0);
+}
+
+static const unsigned int drm_connector_hdmi_init_type_valid_tests[] = {
+ DRM_MODE_CONNECTOR_HDMIA,
+ DRM_MODE_CONNECTOR_HDMIB,
+};
+
+static void drm_connector_hdmi_init_type_desc(const unsigned int *type, char *desc)
+{
+ sprintf(desc, "%s", drm_get_connector_type_name(*type));
+}
+
+KUNIT_ARRAY_PARAM(drm_connector_hdmi_init_type_valid,
+ drm_connector_hdmi_init_type_valid_tests,
+ drm_connector_hdmi_init_type_desc);
+
+/*
+ * Test that the registration of an HDMI connector with an !HDMI
+ * connector type fails.
+ */
+static void drm_test_connector_hdmi_init_type_invalid(struct kunit *test)
+{
+ struct drm_connector_init_priv *priv = test->priv;
+ unsigned int connector_type = *(unsigned int *)test->param_value;
+ int ret;
+
+ ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
+ "Vendor", "Product",
+ &dummy_funcs,
+ &dummy_hdmi_funcs,
+ connector_type,
+ &priv->ddc,
+ BIT(HDMI_COLORSPACE_RGB),
+ 8);
+ KUNIT_EXPECT_LT(test, ret, 0);
+}
+
+static const unsigned int drm_connector_hdmi_init_type_invalid_tests[] = {
+ DRM_MODE_CONNECTOR_Unknown,
+ DRM_MODE_CONNECTOR_VGA,
+ DRM_MODE_CONNECTOR_DVII,
+ DRM_MODE_CONNECTOR_DVID,
+ DRM_MODE_CONNECTOR_DVIA,
+ DRM_MODE_CONNECTOR_Composite,
+ DRM_MODE_CONNECTOR_SVIDEO,
+ DRM_MODE_CONNECTOR_LVDS,
+ DRM_MODE_CONNECTOR_Component,
+ DRM_MODE_CONNECTOR_9PinDIN,
+ DRM_MODE_CONNECTOR_DisplayPort,
+ DRM_MODE_CONNECTOR_TV,
+ DRM_MODE_CONNECTOR_eDP,
+ DRM_MODE_CONNECTOR_VIRTUAL,
+ DRM_MODE_CONNECTOR_DSI,
+ DRM_MODE_CONNECTOR_DPI,
+ DRM_MODE_CONNECTOR_WRITEBACK,
+ DRM_MODE_CONNECTOR_SPI,
+ DRM_MODE_CONNECTOR_USB,
+};
+
+KUNIT_ARRAY_PARAM(drm_connector_hdmi_init_type_invalid,
+ drm_connector_hdmi_init_type_invalid_tests,
+ drm_connector_hdmi_init_type_desc);
+
+static struct kunit_case drmm_connector_hdmi_init_tests[] = {
+ KUNIT_CASE(drm_test_connector_hdmi_init_valid),
+ KUNIT_CASE(drm_test_connector_hdmi_init_bpc_8),
+ KUNIT_CASE(drm_test_connector_hdmi_init_bpc_10),
+ KUNIT_CASE(drm_test_connector_hdmi_init_bpc_12),
+ KUNIT_CASE(drm_test_connector_hdmi_init_bpc_invalid),
+ KUNIT_CASE(drm_test_connector_hdmi_init_bpc_null),
+ KUNIT_CASE(drm_test_connector_hdmi_init_formats_empty),
+ KUNIT_CASE(drm_test_connector_hdmi_init_formats_no_rgb),
+ KUNIT_CASE(drm_test_connector_hdmi_init_null_ddc),
+ KUNIT_CASE(drm_test_connector_hdmi_init_null_product),
+ KUNIT_CASE(drm_test_connector_hdmi_init_null_vendor),
+ KUNIT_CASE(drm_test_connector_hdmi_init_product_length_exact),
+ KUNIT_CASE(drm_test_connector_hdmi_init_product_length_too_long),
+ KUNIT_CASE(drm_test_connector_hdmi_init_product_valid),
+ KUNIT_CASE(drm_test_connector_hdmi_init_vendor_length_exact),
+ KUNIT_CASE(drm_test_connector_hdmi_init_vendor_length_too_long),
+ KUNIT_CASE(drm_test_connector_hdmi_init_vendor_valid),
+ KUNIT_CASE_PARAM(drm_test_connector_hdmi_init_type_valid,
+ drm_connector_hdmi_init_type_valid_gen_params),
+ KUNIT_CASE_PARAM(drm_test_connector_hdmi_init_type_invalid,
+ drm_connector_hdmi_init_type_invalid_gen_params),
+ { }
+};
+
+static struct kunit_suite drmm_connector_hdmi_init_test_suite = {
+ .name = "drmm_connector_hdmi_init",
+ .init = drm_test_connector_init,
+ .test_cases = drmm_connector_hdmi_init_tests,
+};
+
struct drm_get_tv_mode_from_name_test {
const char *name;
enum drm_connector_tv_mode expected_mode;
@@ -201,6 +777,7 @@ struct drm_get_tv_mode_from_name_test drm_get_tv_mode_from_name_valid_tests[] =
TV_MODE_NAME("PAL-M", DRM_MODE_TV_MODE_PAL_M),
TV_MODE_NAME("PAL-N", DRM_MODE_TV_MODE_PAL_N),
TV_MODE_NAME("SECAM", DRM_MODE_TV_MODE_SECAM),
+ TV_MODE_NAME("Mono", DRM_MODE_TV_MODE_MONOCHROME),
};
static void
@@ -235,10 +812,484 @@ static struct kunit_suite drm_get_tv_mode_from_name_test_suite = {
.test_cases = drm_get_tv_mode_from_name_tests,
};
+struct drm_hdmi_connector_get_broadcast_rgb_name_test {
+ unsigned int kind;
+ const char *expected_name;
+};
+
+#define BROADCAST_RGB_TEST(_kind, _name) \
+ { \
+ .kind = _kind, \
+ .expected_name = _name, \
+ }
+
+static void drm_test_drm_hdmi_connector_get_broadcast_rgb_name(struct kunit *test)
+{
+ const struct drm_hdmi_connector_get_broadcast_rgb_name_test *params =
+ test->param_value;
+
+ KUNIT_EXPECT_STREQ(test,
+ drm_hdmi_connector_get_broadcast_rgb_name(params->kind),
+ params->expected_name);
+}
+
+static const
+struct drm_hdmi_connector_get_broadcast_rgb_name_test
+drm_hdmi_connector_get_broadcast_rgb_name_valid_tests[] = {
+ BROADCAST_RGB_TEST(DRM_HDMI_BROADCAST_RGB_AUTO, "Automatic"),
+ BROADCAST_RGB_TEST(DRM_HDMI_BROADCAST_RGB_FULL, "Full"),
+ BROADCAST_RGB_TEST(DRM_HDMI_BROADCAST_RGB_LIMITED, "Limited 16:235"),
+};
+
+static void
+drm_hdmi_connector_get_broadcast_rgb_name_valid_desc(const struct drm_hdmi_connector_get_broadcast_rgb_name_test *t,
+ char *desc)
+{
+ sprintf(desc, "%s", t->expected_name);
+}
+
+KUNIT_ARRAY_PARAM(drm_hdmi_connector_get_broadcast_rgb_name_valid,
+ drm_hdmi_connector_get_broadcast_rgb_name_valid_tests,
+ drm_hdmi_connector_get_broadcast_rgb_name_valid_desc);
+
+static void drm_test_drm_hdmi_connector_get_broadcast_rgb_name_invalid(struct kunit *test)
+{
+ KUNIT_EXPECT_NULL(test, drm_hdmi_connector_get_broadcast_rgb_name(3));
+};
+
+static struct kunit_case drm_hdmi_connector_get_broadcast_rgb_name_tests[] = {
+ KUNIT_CASE_PARAM(drm_test_drm_hdmi_connector_get_broadcast_rgb_name,
+ drm_hdmi_connector_get_broadcast_rgb_name_valid_gen_params),
+ KUNIT_CASE(drm_test_drm_hdmi_connector_get_broadcast_rgb_name_invalid),
+ { }
+};
+
+static struct kunit_suite drm_hdmi_connector_get_broadcast_rgb_name_test_suite = {
+ .name = "drm_hdmi_connector_get_broadcast_rgb_name",
+ .test_cases = drm_hdmi_connector_get_broadcast_rgb_name_tests,
+};
+
+struct drm_hdmi_connector_get_output_format_name_test {
+ unsigned int kind;
+ const char *expected_name;
+};
+
+#define OUTPUT_FORMAT_TEST(_kind, _name) \
+ { \
+ .kind = _kind, \
+ .expected_name = _name, \
+ }
+
+static void drm_test_drm_hdmi_connector_get_output_format_name(struct kunit *test)
+{
+ const struct drm_hdmi_connector_get_output_format_name_test *params =
+ test->param_value;
+
+ KUNIT_EXPECT_STREQ(test,
+ drm_hdmi_connector_get_output_format_name(params->kind),
+ params->expected_name);
+}
+
+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"),
+};
+
+static void
+drm_hdmi_connector_get_output_format_name_valid_desc(const struct drm_hdmi_connector_get_output_format_name_test *t,
+ char *desc)
+{
+ sprintf(desc, "%s", t->expected_name);
+}
+
+KUNIT_ARRAY_PARAM(drm_hdmi_connector_get_output_format_name_valid,
+ drm_hdmi_connector_get_output_format_name_valid_tests,
+ drm_hdmi_connector_get_output_format_name_valid_desc);
+
+static void drm_test_drm_hdmi_connector_get_output_format_name_invalid(struct kunit *test)
+{
+ KUNIT_EXPECT_NULL(test, drm_hdmi_connector_get_output_format_name(4));
+};
+
+static struct kunit_case drm_hdmi_connector_get_output_format_name_tests[] = {
+ KUNIT_CASE_PARAM(drm_test_drm_hdmi_connector_get_output_format_name,
+ drm_hdmi_connector_get_output_format_name_valid_gen_params),
+ KUNIT_CASE(drm_test_drm_hdmi_connector_get_output_format_name_invalid),
+ { }
+};
+
+static struct kunit_suite drm_hdmi_connector_get_output_format_name_test_suite = {
+ .name = "drm_hdmi_connector_get_output_format_name",
+ .test_cases = drm_hdmi_connector_get_output_format_name_tests,
+};
+
+static void drm_test_drm_connector_attach_broadcast_rgb_property(struct kunit *test)
+{
+ struct drm_connector_init_priv *priv = test->priv;
+ struct drm_connector *connector = &priv->connector;
+ struct drm_property *prop;
+ int ret;
+
+ ret = drmm_connector_init(&priv->drm, connector,
+ &dummy_funcs,
+ DRM_MODE_CONNECTOR_HDMIA,
+ &priv->ddc);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ ret = drm_connector_attach_broadcast_rgb_property(connector);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ prop = connector->broadcast_rgb_property;
+ KUNIT_ASSERT_NOT_NULL(test, prop);
+ KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id));
+}
+
+static void drm_test_drm_connector_attach_broadcast_rgb_property_hdmi_connector(struct kunit *test)
+{
+ struct drm_connector_init_priv *priv = test->priv;
+ struct drm_connector *connector = &priv->connector;
+ struct drm_property *prop;
+ int ret;
+
+ ret = drmm_connector_hdmi_init(&priv->drm, connector,
+ "Vendor", "Product",
+ &dummy_funcs,
+ &dummy_hdmi_funcs,
+ DRM_MODE_CONNECTOR_HDMIA,
+ &priv->ddc,
+ BIT(HDMI_COLORSPACE_RGB),
+ 8);
+ KUNIT_EXPECT_EQ(test, ret, 0);
+
+ ret = drm_connector_attach_broadcast_rgb_property(connector);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ prop = connector->broadcast_rgb_property;
+ KUNIT_ASSERT_NOT_NULL(test, prop);
+ KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id));
+}
+
+static struct kunit_case drm_connector_attach_broadcast_rgb_property_tests[] = {
+ KUNIT_CASE(drm_test_drm_connector_attach_broadcast_rgb_property),
+ KUNIT_CASE(drm_test_drm_connector_attach_broadcast_rgb_property_hdmi_connector),
+ { }
+};
+
+static struct kunit_suite drm_connector_attach_broadcast_rgb_property_test_suite = {
+ .name = "drm_connector_attach_broadcast_rgb_property",
+ .init = drm_test_connector_init,
+ .test_cases = drm_connector_attach_broadcast_rgb_property_tests,
+};
+
+/*
+ * Test that for a given mode, with 8bpc and an RGB output the TMDS
+ * character rate is equal to the mode pixel clock.
+ */
+static void drm_test_drm_hdmi_compute_mode_clock_rgb(struct kunit *test)
+{
+ struct drm_connector_init_priv *priv = test->priv;
+ const struct drm_display_mode *mode;
+ unsigned long long rate;
+ struct drm_device *drm = &priv->drm;
+
+ mode = drm_display_mode_from_cea_vic(drm, 16);
+ KUNIT_ASSERT_NOT_NULL(test, mode);
+
+ KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
+
+ rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_RGB);
+ KUNIT_ASSERT_GT(test, rate, 0);
+ KUNIT_EXPECT_EQ(test, mode->clock * 1000ULL, rate);
+}
+
+/*
+ * Test that for a given mode, with 10bpc and an RGB output the TMDS
+ * character rate is equal to 1.25 times the mode pixel clock.
+ */
+static void drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc(struct kunit *test)
+{
+ struct drm_connector_init_priv *priv = test->priv;
+ const struct drm_display_mode *mode;
+ unsigned long long rate;
+ struct drm_device *drm = &priv->drm;
+
+ mode = drm_display_mode_from_cea_vic(drm, 16);
+ KUNIT_ASSERT_NOT_NULL(test, mode);
+
+ KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
+
+ rate = drm_hdmi_compute_mode_clock(mode, 10, HDMI_COLORSPACE_RGB);
+ KUNIT_ASSERT_GT(test, rate, 0);
+ KUNIT_EXPECT_EQ(test, mode->clock * 1250, rate);
+}
+
+/*
+ * Test that for the VIC-1 mode, with 10bpc and an RGB output the TMDS
+ * character rate computation fails.
+ */
+static void drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc_vic_1(struct kunit *test)
+{
+ struct drm_connector_init_priv *priv = test->priv;
+ const struct drm_display_mode *mode;
+ unsigned long long rate;
+ struct drm_device *drm = &priv->drm;
+
+ mode = drm_display_mode_from_cea_vic(drm, 1);
+ KUNIT_ASSERT_NOT_NULL(test, mode);
+
+ rate = drm_hdmi_compute_mode_clock(mode, 10, HDMI_COLORSPACE_RGB);
+ KUNIT_EXPECT_EQ(test, rate, 0);
+}
+
+/*
+ * Test that for a given mode, with 12bpc and an RGB output the TMDS
+ * character rate is equal to 1.5 times the mode pixel clock.
+ */
+static void drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc(struct kunit *test)
+{
+ struct drm_connector_init_priv *priv = test->priv;
+ const struct drm_display_mode *mode;
+ unsigned long long rate;
+ struct drm_device *drm = &priv->drm;
+
+ mode = drm_display_mode_from_cea_vic(drm, 16);
+ KUNIT_ASSERT_NOT_NULL(test, mode);
+
+ KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
+
+ rate = drm_hdmi_compute_mode_clock(mode, 12, HDMI_COLORSPACE_RGB);
+ KUNIT_ASSERT_GT(test, rate, 0);
+ KUNIT_EXPECT_EQ(test, mode->clock * 1500, rate);
+}
+
+/*
+ * Test that for the VIC-1 mode, with 12bpc and an RGB output the TMDS
+ * character rate computation fails.
+ */
+static void drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc_vic_1(struct kunit *test)
+{
+ struct drm_connector_init_priv *priv = test->priv;
+ const struct drm_display_mode *mode;
+ unsigned long long rate;
+ struct drm_device *drm = &priv->drm;
+
+ mode = drm_display_mode_from_cea_vic(drm, 1);
+ KUNIT_ASSERT_NOT_NULL(test, mode);
+
+ rate = drm_hdmi_compute_mode_clock(mode, 12, HDMI_COLORSPACE_RGB);
+ KUNIT_EXPECT_EQ(test, rate, 0);
+}
+
+/*
+ * Test that for a mode with the pixel repetition flag, the TMDS
+ * character rate is indeed double the mode pixel clock.
+ */
+static void drm_test_drm_hdmi_compute_mode_clock_rgb_double(struct kunit *test)
+{
+ struct drm_connector_init_priv *priv = test->priv;
+ const struct drm_display_mode *mode;
+ unsigned long long rate;
+ struct drm_device *drm = &priv->drm;
+
+ mode = drm_display_mode_from_cea_vic(drm, 6);
+ KUNIT_ASSERT_NOT_NULL(test, mode);
+
+ KUNIT_ASSERT_TRUE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
+
+ rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_RGB);
+ KUNIT_ASSERT_GT(test, rate, 0);
+ KUNIT_EXPECT_EQ(test, (mode->clock * 1000ULL) * 2, rate);
+}
+
+/*
+ * Test that the TMDS character rate computation for the VIC modes
+ * explicitly listed in the spec as supporting YUV420 succeed and return
+ * half the mode pixel clock.
+ */
+static void drm_test_connector_hdmi_compute_mode_clock_yuv420_valid(struct kunit *test)
+{
+ struct drm_connector_init_priv *priv = test->priv;
+ const struct drm_display_mode *mode;
+ struct drm_device *drm = &priv->drm;
+ unsigned long long rate;
+ unsigned int vic = *(unsigned int *)test->param_value;
+
+ mode = drm_display_mode_from_cea_vic(drm, vic);
+ KUNIT_ASSERT_NOT_NULL(test, mode);
+
+ KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
+
+ rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_YUV420);
+ KUNIT_ASSERT_GT(test, rate, 0);
+ KUNIT_EXPECT_EQ(test, (mode->clock * 1000ULL) / 2, rate);
+}
+
+static const unsigned int drm_hdmi_compute_mode_clock_yuv420_vic_valid_tests[] = {
+ 96, 97, 101, 102, 106, 107,
+};
+
+static void drm_hdmi_compute_mode_clock_yuv420_vic_desc(const unsigned int *vic, char *desc)
+{
+ sprintf(desc, "VIC %u", *vic);
+}
+
+KUNIT_ARRAY_PARAM(drm_hdmi_compute_mode_clock_yuv420_valid,
+ drm_hdmi_compute_mode_clock_yuv420_vic_valid_tests,
+ drm_hdmi_compute_mode_clock_yuv420_vic_desc);
+
+/*
+ * Test that for a given mode listed supporting it and an YUV420 output
+ * with 10bpc, the TMDS character rate is equal to 0.625 times the mode
+ * pixel clock.
+ */
+static void drm_test_connector_hdmi_compute_mode_clock_yuv420_10_bpc(struct kunit *test)
+{
+ struct drm_connector_init_priv *priv = test->priv;
+ const struct drm_display_mode *mode;
+ struct drm_device *drm = &priv->drm;
+ unsigned int vic =
+ drm_hdmi_compute_mode_clock_yuv420_vic_valid_tests[0];
+ unsigned long long rate;
+
+ mode = drm_display_mode_from_cea_vic(drm, vic);
+ KUNIT_ASSERT_NOT_NULL(test, mode);
+
+ KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
+
+ rate = drm_hdmi_compute_mode_clock(mode, 10, HDMI_COLORSPACE_YUV420);
+ KUNIT_ASSERT_GT(test, rate, 0);
+
+ KUNIT_EXPECT_EQ(test, mode->clock * 625, rate);
+}
+
+/*
+ * Test that for a given mode listed supporting it and an YUV420 output
+ * with 12bpc, the TMDS character rate is equal to 0.75 times the mode
+ * pixel clock.
+ */
+static void drm_test_connector_hdmi_compute_mode_clock_yuv420_12_bpc(struct kunit *test)
+{
+ struct drm_connector_init_priv *priv = test->priv;
+ const struct drm_display_mode *mode;
+ struct drm_device *drm = &priv->drm;
+ unsigned int vic =
+ drm_hdmi_compute_mode_clock_yuv420_vic_valid_tests[0];
+ unsigned long long rate;
+
+ mode = drm_display_mode_from_cea_vic(drm, vic);
+ KUNIT_ASSERT_NOT_NULL(test, mode);
+
+ KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
+
+ rate = drm_hdmi_compute_mode_clock(mode, 12, HDMI_COLORSPACE_YUV420);
+ KUNIT_ASSERT_GT(test, rate, 0);
+
+ KUNIT_EXPECT_EQ(test, mode->clock * 750, rate);
+}
+
+/*
+ * Test that for a given mode, the computation of the TMDS character
+ * rate with 8bpc and a YUV422 output succeeds and returns a rate equal
+ * to the mode pixel clock.
+ */
+static void drm_test_connector_hdmi_compute_mode_clock_yuv422_8_bpc(struct kunit *test)
+{
+ struct drm_connector_init_priv *priv = test->priv;
+ const struct drm_display_mode *mode;
+ struct drm_device *drm = &priv->drm;
+ unsigned long long rate;
+
+ mode = drm_display_mode_from_cea_vic(drm, 16);
+ KUNIT_ASSERT_NOT_NULL(test, mode);
+
+ KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
+
+ rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_YUV422);
+ KUNIT_ASSERT_GT(test, rate, 0);
+ KUNIT_EXPECT_EQ(test, mode->clock * 1000, rate);
+}
+
+/*
+ * Test that for a given mode, the computation of the TMDS character
+ * rate with 10bpc and a YUV422 output succeeds and returns a rate equal
+ * to the mode pixel clock.
+ */
+static void drm_test_connector_hdmi_compute_mode_clock_yuv422_10_bpc(struct kunit *test)
+{
+ struct drm_connector_init_priv *priv = test->priv;
+ const struct drm_display_mode *mode;
+ struct drm_device *drm = &priv->drm;
+ unsigned long long rate;
+
+ mode = drm_display_mode_from_cea_vic(drm, 16);
+ KUNIT_ASSERT_NOT_NULL(test, mode);
+
+ KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
+
+ rate = drm_hdmi_compute_mode_clock(mode, 10, HDMI_COLORSPACE_YUV422);
+ KUNIT_ASSERT_GT(test, rate, 0);
+ KUNIT_EXPECT_EQ(test, mode->clock * 1000, rate);
+}
+
+/*
+ * Test that for a given mode, the computation of the TMDS character
+ * rate with 12bpc and a YUV422 output succeeds and returns a rate equal
+ * to the mode pixel clock.
+ */
+static void drm_test_connector_hdmi_compute_mode_clock_yuv422_12_bpc(struct kunit *test)
+{
+ struct drm_connector_init_priv *priv = test->priv;
+ const struct drm_display_mode *mode;
+ struct drm_device *drm = &priv->drm;
+ unsigned long long rate;
+
+ mode = drm_display_mode_from_cea_vic(drm, 16);
+ KUNIT_ASSERT_NOT_NULL(test, mode);
+
+ KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
+
+ rate = drm_hdmi_compute_mode_clock(mode, 12, HDMI_COLORSPACE_YUV422);
+ KUNIT_ASSERT_GT(test, rate, 0);
+ KUNIT_EXPECT_EQ(test, mode->clock * 1000, rate);
+}
+
+static struct kunit_case drm_hdmi_compute_mode_clock_tests[] = {
+ KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb),
+ KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc),
+ KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc_vic_1),
+ KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc),
+ KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc_vic_1),
+ KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb_double),
+ KUNIT_CASE_PARAM(drm_test_connector_hdmi_compute_mode_clock_yuv420_valid,
+ drm_hdmi_compute_mode_clock_yuv420_valid_gen_params),
+ KUNIT_CASE(drm_test_connector_hdmi_compute_mode_clock_yuv420_10_bpc),
+ KUNIT_CASE(drm_test_connector_hdmi_compute_mode_clock_yuv420_12_bpc),
+ KUNIT_CASE(drm_test_connector_hdmi_compute_mode_clock_yuv422_8_bpc),
+ KUNIT_CASE(drm_test_connector_hdmi_compute_mode_clock_yuv422_10_bpc),
+ KUNIT_CASE(drm_test_connector_hdmi_compute_mode_clock_yuv422_12_bpc),
+ { }
+};
+
+static struct kunit_suite drm_hdmi_compute_mode_clock_test_suite = {
+ .name = "drm_test_connector_hdmi_compute_mode_clock",
+ .init = drm_test_connector_init,
+ .test_cases = drm_hdmi_compute_mode_clock_tests,
+};
+
kunit_test_suites(
+ &drmm_connector_hdmi_init_test_suite,
&drmm_connector_init_test_suite,
- &drm_get_tv_mode_from_name_test_suite
+ &drm_connector_attach_broadcast_rgb_property_test_suite,
+ &drm_get_tv_mode_from_name_test_suite,
+ &drm_hdmi_compute_mode_clock_test_suite,
+ &drm_hdmi_connector_get_broadcast_rgb_name_test_suite,
+ &drm_hdmi_connector_get_output_format_name_test_suite
);
MODULE_AUTHOR("Maxime Ripard <maxime@cerno.tech>");
+MODULE_DESCRIPTION("Kunit test for drm_modes functions");
MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tests/drm_damage_helper_test.c b/drivers/gpu/drm/tests/drm_damage_helper_test.c
index 115034fc3421..0df2e1a54b0d 100644
--- a/drivers/gpu/drm/tests/drm_damage_helper_test.c
+++ b/drivers/gpu/drm/tests/drm_damage_helper_test.c
@@ -636,4 +636,5 @@ static struct kunit_suite drm_damage_helper_test_suite = {
kunit_test_suite(drm_damage_helper_test_suite);
+MODULE_DESCRIPTION("Test case for drm_damage_helper functions");
MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tests/drm_dp_mst_helper_test.c b/drivers/gpu/drm/tests/drm_dp_mst_helper_test.c
index d916e548fcb1..89cd9e4f4d32 100644
--- a/drivers/gpu/drm/tests/drm_dp_mst_helper_test.c
+++ b/drivers/gpu/drm/tests/drm_dp_mst_helper_test.c
@@ -588,4 +588,5 @@ static struct kunit_suite drm_dp_mst_helper_test_suite = {
kunit_test_suite(drm_dp_mst_helper_test_suite);
+MODULE_DESCRIPTION("Test cases for the DRM DP MST helpers");
MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tests/drm_exec_test.c b/drivers/gpu/drm/tests/drm_exec_test.c
index 81f928a429ba..d6c4dd1194a0 100644
--- a/drivers/gpu/drm/tests/drm_exec_test.c
+++ b/drivers/gpu/drm/tests/drm_exec_test.c
@@ -210,4 +210,5 @@ static struct kunit_suite drm_exec_test_suite = {
kunit_test_suite(drm_exec_test_suite);
MODULE_AUTHOR("AMD");
+MODULE_DESCRIPTION("Kunit test for drm_exec functions");
MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/gpu/drm/tests/drm_format_test.c b/drivers/gpu/drm/tests/drm_format_test.c
index ec6996ce819a..22e2371fd66a 100644
--- a/drivers/gpu/drm/tests/drm_format_test.c
+++ b/drivers/gpu/drm/tests/drm_format_test.c
@@ -356,4 +356,5 @@ static struct kunit_suite drm_format_test_suite = {
kunit_test_suite(drm_format_test_suite);
+MODULE_DESCRIPTION("Test cases for the drm_format functions");
MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tests/drm_framebuffer_test.c b/drivers/gpu/drm/tests/drm_framebuffer_test.c
index f759d9f3b76e..06f03b78c9c4 100644
--- a/drivers/gpu/drm/tests/drm_framebuffer_test.c
+++ b/drivers/gpu/drm/tests/drm_framebuffer_test.c
@@ -379,4 +379,5 @@ static struct kunit_suite drm_framebuffer_test_suite = {
kunit_test_suite(drm_framebuffer_test_suite);
+MODULE_DESCRIPTION("Test cases for the drm_framebuffer functions");
MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tests/drm_gem_shmem_test.c b/drivers/gpu/drm/tests/drm_gem_shmem_test.c
index 91202e40cde9..c3758faa1b83 100644
--- a/drivers/gpu/drm/tests/drm_gem_shmem_test.c
+++ b/drivers/gpu/drm/tests/drm_gem_shmem_test.c
@@ -380,4 +380,5 @@ static struct kunit_suite drm_gem_shmem_suite = {
kunit_test_suite(drm_gem_shmem_suite);
+MODULE_DESCRIPTION("KUnit test suite for GEM objects backed by shmem buffers");
MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c
new file mode 100644
index 000000000000..34ee95d41f29
--- /dev/null
+++ b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c
@@ -0,0 +1,1744 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Kunit test for drm_hdmi_state_helper functions
+ */
+
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_state_helper.h>
+#include <drm/drm_atomic_uapi.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_connector.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_kunit_helpers.h>
+#include <drm/drm_managed.h>
+#include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_print.h>
+#include <drm/drm_probe_helper.h>
+
+#include <drm/display/drm_hdmi_helper.h>
+#include <drm/display/drm_hdmi_state_helper.h>
+
+#include "../drm_crtc_internal.h"
+
+#include <kunit/test.h>
+
+#include "drm_kunit_edid.h"
+
+struct drm_atomic_helper_connector_hdmi_priv {
+ struct drm_device drm;
+ struct drm_plane *plane;
+ struct drm_crtc *crtc;
+ struct drm_encoder encoder;
+ struct drm_connector connector;
+
+ const char *current_edid;
+ size_t current_edid_len;
+};
+
+#define connector_to_priv(c) \
+ container_of_const(c, struct drm_atomic_helper_connector_hdmi_priv, connector)
+
+static struct drm_display_mode *find_preferred_mode(struct drm_connector *connector)
+{
+ struct drm_device *drm = connector->dev;
+ struct drm_display_mode *mode, *preferred;
+
+ mutex_lock(&drm->mode_config.mutex);
+ preferred = list_first_entry(&connector->modes, struct drm_display_mode, head);
+ list_for_each_entry(mode, &connector->modes, head)
+ if (mode->type & DRM_MODE_TYPE_PREFERRED)
+ preferred = mode;
+ mutex_unlock(&drm->mode_config.mutex);
+
+ return preferred;
+}
+
+static int light_up_connector(struct kunit *test,
+ struct drm_device *drm,
+ struct drm_crtc *crtc,
+ struct drm_connector *connector,
+ struct drm_display_mode *mode,
+ struct drm_modeset_acquire_ctx *ctx)
+{
+ struct drm_atomic_state *state;
+ struct drm_connector_state *conn_state;
+ struct drm_crtc_state *crtc_state;
+ int ret;
+
+ state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
+
+ conn_state = drm_atomic_get_connector_state(state, connector);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
+
+ ret = drm_atomic_set_crtc_for_connector(conn_state, crtc);
+ KUNIT_EXPECT_EQ(test, ret, 0);
+
+ crtc_state = drm_atomic_get_crtc_state(state, crtc);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
+
+ ret = drm_atomic_set_mode_for_crtc(crtc_state, mode);
+ KUNIT_EXPECT_EQ(test, ret, 0);
+
+ crtc_state->enable = true;
+ crtc_state->active = true;
+
+ ret = drm_atomic_commit(state);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ return 0;
+}
+
+static int set_connector_edid(struct kunit *test, struct drm_connector *connector,
+ const char *edid, size_t edid_len)
+{
+ struct drm_atomic_helper_connector_hdmi_priv *priv =
+ connector_to_priv(connector);
+ struct drm_device *drm = connector->dev;
+ int ret;
+
+ priv->current_edid = edid;
+ priv->current_edid_len = edid_len;
+
+ mutex_lock(&drm->mode_config.mutex);
+ ret = connector->funcs->fill_modes(connector, 4096, 4096);
+ mutex_unlock(&drm->mode_config.mutex);
+ KUNIT_ASSERT_GT(test, ret, 0);
+
+ return 0;
+}
+
+static const struct drm_connector_hdmi_funcs dummy_connector_hdmi_funcs = {
+};
+
+static enum drm_mode_status
+reject_connector_tmds_char_rate_valid(const struct drm_connector *connector,
+ const struct drm_display_mode *mode,
+ unsigned long long tmds_rate)
+{
+ return MODE_BAD;
+}
+
+static const struct drm_connector_hdmi_funcs reject_connector_hdmi_funcs = {
+ .tmds_char_rate_valid = reject_connector_tmds_char_rate_valid,
+};
+
+static int dummy_connector_get_modes(struct drm_connector *connector)
+{
+ struct drm_atomic_helper_connector_hdmi_priv *priv =
+ connector_to_priv(connector);
+ const struct drm_edid *edid;
+ unsigned int num_modes;
+
+ edid = drm_edid_alloc(priv->current_edid, priv->current_edid_len);
+ if (!edid)
+ return -EINVAL;
+
+ drm_edid_connector_update(connector, edid);
+ num_modes = drm_edid_connector_add_modes(connector);
+
+ drm_edid_free(edid);
+
+ return num_modes;
+}
+
+static const struct drm_connector_helper_funcs dummy_connector_helper_funcs = {
+ .atomic_check = drm_atomic_helper_connector_hdmi_check,
+ .get_modes = dummy_connector_get_modes,
+};
+
+static void dummy_hdmi_connector_reset(struct drm_connector *connector)
+{
+ drm_atomic_helper_connector_reset(connector);
+ __drm_atomic_helper_connector_hdmi_reset(connector, connector->state);
+}
+
+static const struct drm_connector_funcs dummy_connector_funcs = {
+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .reset = dummy_hdmi_connector_reset,
+};
+
+static
+struct drm_atomic_helper_connector_hdmi_priv *
+drm_atomic_helper_connector_hdmi_init(struct kunit *test,
+ unsigned int formats,
+ unsigned int max_bpc)
+{
+ struct drm_atomic_helper_connector_hdmi_priv *priv;
+ struct drm_connector *conn;
+ struct drm_encoder *enc;
+ struct drm_device *drm;
+ struct device *dev;
+ int ret;
+
+ dev = drm_kunit_helper_alloc_device(test);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
+
+ priv = drm_kunit_helper_alloc_drm_device(test, dev,
+ struct drm_atomic_helper_connector_hdmi_priv, drm,
+ DRIVER_MODESET | DRIVER_ATOMIC);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv);
+ test->priv = priv;
+
+ drm = &priv->drm;
+ priv->plane = drm_kunit_helper_create_primary_plane(test, drm,
+ NULL,
+ NULL,
+ NULL, 0,
+ NULL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->plane);
+
+ priv->crtc = drm_kunit_helper_create_crtc(test, drm,
+ priv->plane, NULL,
+ NULL,
+ NULL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->crtc);
+
+ enc = &priv->encoder;
+ ret = drmm_encoder_init(drm, enc, NULL, DRM_MODE_ENCODER_TMDS, NULL);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ enc->possible_crtcs = drm_crtc_mask(priv->crtc);
+
+ conn = &priv->connector;
+ ret = drmm_connector_hdmi_init(drm, conn,
+ "Vendor", "Product",
+ &dummy_connector_funcs,
+ &dummy_connector_hdmi_funcs,
+ DRM_MODE_CONNECTOR_HDMIA,
+ NULL,
+ formats,
+ max_bpc);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ drm_connector_helper_add(conn, &dummy_connector_helper_funcs);
+ drm_connector_attach_encoder(conn, enc);
+
+ drm_mode_config_reset(drm);
+
+ ret = set_connector_edid(test, conn,
+ test_edid_hdmi_1080p_rgb_max_200mhz,
+ ARRAY_SIZE(test_edid_hdmi_1080p_rgb_max_200mhz));
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ return priv;
+}
+
+/*
+ * Test that if we change the RGB quantization property to a different
+ * value, we trigger a mode change on the connector's CRTC, which will
+ * in turn disable/enable the connector.
+ */
+static void drm_test_check_broadcast_rgb_crtc_mode_changed(struct kunit *test)
+{
+ struct drm_atomic_helper_connector_hdmi_priv *priv;
+ struct drm_modeset_acquire_ctx *ctx;
+ struct drm_connector_state *old_conn_state;
+ struct drm_connector_state *new_conn_state;
+ struct drm_crtc_state *crtc_state;
+ struct drm_atomic_state *state;
+ struct drm_display_mode *preferred;
+ struct drm_connector *conn;
+ struct drm_device *drm;
+ struct drm_crtc *crtc;
+ int ret;
+
+ priv = drm_atomic_helper_connector_hdmi_init(test,
+ BIT(HDMI_COLORSPACE_RGB),
+ 8);
+ KUNIT_ASSERT_NOT_NULL(test, priv);
+
+ ctx = drm_kunit_helper_acquire_ctx_alloc(test);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
+
+ conn = &priv->connector;
+ preferred = find_preferred_mode(conn);
+ KUNIT_ASSERT_NOT_NULL(test, preferred);
+
+ drm = &priv->drm;
+ crtc = priv->crtc;
+ ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
+
+ new_conn_state = drm_atomic_get_connector_state(state, conn);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
+
+ old_conn_state = drm_atomic_get_old_connector_state(state, conn);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state);
+
+ new_conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_FULL;
+
+ KUNIT_ASSERT_NE(test,
+ old_conn_state->hdmi.broadcast_rgb,
+ new_conn_state->hdmi.broadcast_rgb);
+
+ ret = drm_atomic_check_only(state);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ new_conn_state = drm_atomic_get_new_connector_state(state, conn);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
+ KUNIT_EXPECT_EQ(test, new_conn_state->hdmi.broadcast_rgb, DRM_HDMI_BROADCAST_RGB_FULL);
+
+ crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
+ KUNIT_EXPECT_TRUE(test, crtc_state->mode_changed);
+}
+
+/*
+ * Test that if we set the RGB quantization property to the same value,
+ * we don't trigger a mode change on the connector's CRTC and leave the
+ * connector unaffected.
+ */
+static void drm_test_check_broadcast_rgb_crtc_mode_not_changed(struct kunit *test)
+{
+ struct drm_atomic_helper_connector_hdmi_priv *priv;
+ struct drm_modeset_acquire_ctx *ctx;
+ struct drm_connector_state *old_conn_state;
+ struct drm_connector_state *new_conn_state;
+ struct drm_crtc_state *crtc_state;
+ struct drm_atomic_state *state;
+ struct drm_display_mode *preferred;
+ struct drm_connector *conn;
+ struct drm_device *drm;
+ struct drm_crtc *crtc;
+ int ret;
+
+ priv = drm_atomic_helper_connector_hdmi_init(test,
+ BIT(HDMI_COLORSPACE_RGB),
+ 8);
+ KUNIT_ASSERT_NOT_NULL(test, priv);
+
+ ctx = drm_kunit_helper_acquire_ctx_alloc(test);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
+
+ conn = &priv->connector;
+ preferred = find_preferred_mode(conn);
+ KUNIT_ASSERT_NOT_NULL(test, preferred);
+
+ drm = &priv->drm;
+ crtc = priv->crtc;
+ ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
+
+ new_conn_state = drm_atomic_get_connector_state(state, conn);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
+
+ old_conn_state = drm_atomic_get_old_connector_state(state, conn);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state);
+
+ new_conn_state->hdmi.broadcast_rgb = old_conn_state->hdmi.broadcast_rgb;
+
+ ret = drm_atomic_check_only(state);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ old_conn_state = drm_atomic_get_old_connector_state(state, conn);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state);
+
+ new_conn_state = drm_atomic_get_new_connector_state(state, conn);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
+
+ KUNIT_EXPECT_EQ(test,
+ old_conn_state->hdmi.broadcast_rgb,
+ new_conn_state->hdmi.broadcast_rgb);
+
+ crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
+ KUNIT_EXPECT_FALSE(test, crtc_state->mode_changed);
+}
+
+/*
+ * Test that for an HDMI connector, with an HDMI monitor, if the
+ * Broadcast RGB property is set to auto with a mode that isn't the
+ * VIC-1 mode, we will get a limited RGB Quantization Range.
+ */
+static void drm_test_check_broadcast_rgb_auto_cea_mode(struct kunit *test)
+{
+ struct drm_atomic_helper_connector_hdmi_priv *priv;
+ struct drm_modeset_acquire_ctx *ctx;
+ struct drm_connector_state *conn_state;
+ struct drm_atomic_state *state;
+ struct drm_display_mode *preferred;
+ struct drm_connector *conn;
+ struct drm_device *drm;
+ struct drm_crtc *crtc;
+ int ret;
+
+ priv = drm_atomic_helper_connector_hdmi_init(test,
+ BIT(HDMI_COLORSPACE_RGB),
+ 8);
+ KUNIT_ASSERT_NOT_NULL(test, priv);
+
+ conn = &priv->connector;
+ KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi);
+
+ ctx = drm_kunit_helper_acquire_ctx_alloc(test);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
+
+ preferred = find_preferred_mode(conn);
+ KUNIT_ASSERT_NOT_NULL(test, preferred);
+ KUNIT_ASSERT_NE(test, drm_match_cea_mode(preferred), 1);
+
+ drm = &priv->drm;
+ crtc = priv->crtc;
+ ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
+
+ conn_state = drm_atomic_get_connector_state(state, conn);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
+
+ KUNIT_ASSERT_EQ(test,
+ conn_state->hdmi.broadcast_rgb,
+ DRM_HDMI_BROADCAST_RGB_AUTO);
+
+ ret = drm_atomic_check_only(state);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ conn_state = drm_atomic_get_connector_state(state, conn);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
+
+ KUNIT_EXPECT_TRUE(test, conn_state->hdmi.is_limited_range);
+}
+
+/*
+ * Test that for an HDMI connector, with an HDMI monitor, if the
+ * Broadcast RGB property is set to auto with a VIC-1 mode, we will get
+ * a full RGB Quantization Range.
+ */
+static void drm_test_check_broadcast_rgb_auto_cea_mode_vic_1(struct kunit *test)
+{
+ struct drm_atomic_helper_connector_hdmi_priv *priv;
+ struct drm_modeset_acquire_ctx *ctx;
+ struct drm_connector_state *conn_state;
+ struct drm_atomic_state *state;
+ struct drm_display_mode *mode;
+ struct drm_connector *conn;
+ struct drm_device *drm;
+ struct drm_crtc *crtc;
+ int ret;
+
+ priv = drm_atomic_helper_connector_hdmi_init(test,
+ BIT(HDMI_COLORSPACE_RGB),
+ 8);
+ KUNIT_ASSERT_NOT_NULL(test, priv);
+
+ drm = &priv->drm;
+ conn = &priv->connector;
+ KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi);
+
+ ctx = drm_kunit_helper_acquire_ctx_alloc(test);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
+
+ mode = drm_display_mode_from_cea_vic(drm, 1);
+ KUNIT_ASSERT_NOT_NULL(test, mode);
+
+ drm = &priv->drm;
+ crtc = priv->crtc;
+ ret = light_up_connector(test, drm, crtc, conn, mode, ctx);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
+
+ conn_state = drm_atomic_get_connector_state(state, conn);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
+
+ KUNIT_ASSERT_EQ(test,
+ conn_state->hdmi.broadcast_rgb,
+ DRM_HDMI_BROADCAST_RGB_AUTO);
+
+ ret = drm_atomic_check_only(state);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ conn_state = drm_atomic_get_connector_state(state, conn);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
+
+ KUNIT_EXPECT_FALSE(test, conn_state->hdmi.is_limited_range);
+}
+
+/*
+ * Test that for an HDMI connector, with an HDMI monitor, if the
+ * Broadcast RGB property is set to full with a mode that isn't the
+ * VIC-1 mode, we will get a full RGB Quantization Range.
+ */
+static void drm_test_check_broadcast_rgb_full_cea_mode(struct kunit *test)
+{
+ struct drm_atomic_helper_connector_hdmi_priv *priv;
+ struct drm_modeset_acquire_ctx *ctx;
+ struct drm_connector_state *conn_state;
+ struct drm_atomic_state *state;
+ struct drm_display_mode *preferred;
+ struct drm_connector *conn;
+ struct drm_device *drm;
+ struct drm_crtc *crtc;
+ int ret;
+
+ priv = drm_atomic_helper_connector_hdmi_init(test,
+ BIT(HDMI_COLORSPACE_RGB),
+ 8);
+ KUNIT_ASSERT_NOT_NULL(test, priv);
+
+ conn = &priv->connector;
+ KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi);
+
+ ctx = drm_kunit_helper_acquire_ctx_alloc(test);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
+
+ preferred = find_preferred_mode(conn);
+ KUNIT_ASSERT_NOT_NULL(test, preferred);
+ KUNIT_ASSERT_NE(test, drm_match_cea_mode(preferred), 1);
+
+ drm = &priv->drm;
+ crtc = priv->crtc;
+ ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
+
+ conn_state = drm_atomic_get_connector_state(state, conn);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
+
+ conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_FULL;
+
+ ret = drm_atomic_check_only(state);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ conn_state = drm_atomic_get_connector_state(state, conn);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
+
+ KUNIT_ASSERT_EQ(test,
+ conn_state->hdmi.broadcast_rgb,
+ DRM_HDMI_BROADCAST_RGB_FULL);
+
+ KUNIT_EXPECT_FALSE(test, conn_state->hdmi.is_limited_range);
+}
+
+/*
+ * Test that for an HDMI connector, with an HDMI monitor, if the
+ * Broadcast RGB property is set to full with a VIC-1 mode, we will get
+ * a full RGB Quantization Range.
+ */
+static void drm_test_check_broadcast_rgb_full_cea_mode_vic_1(struct kunit *test)
+{
+ struct drm_atomic_helper_connector_hdmi_priv *priv;
+ struct drm_modeset_acquire_ctx *ctx;
+ struct drm_connector_state *conn_state;
+ struct drm_atomic_state *state;
+ struct drm_display_mode *mode;
+ struct drm_connector *conn;
+ struct drm_device *drm;
+ struct drm_crtc *crtc;
+ int ret;
+
+ priv = drm_atomic_helper_connector_hdmi_init(test,
+ BIT(HDMI_COLORSPACE_RGB),
+ 8);
+ KUNIT_ASSERT_NOT_NULL(test, priv);
+
+ drm = &priv->drm;
+ conn = &priv->connector;
+ KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi);
+
+ ctx = drm_kunit_helper_acquire_ctx_alloc(test);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
+
+ mode = drm_display_mode_from_cea_vic(drm, 1);
+ KUNIT_ASSERT_NOT_NULL(test, mode);
+
+ drm = &priv->drm;
+ crtc = priv->crtc;
+ ret = light_up_connector(test, drm, crtc, conn, mode, ctx);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
+
+ conn_state = drm_atomic_get_connector_state(state, conn);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
+
+ conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_FULL;
+
+ ret = drm_atomic_check_only(state);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ conn_state = drm_atomic_get_connector_state(state, conn);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
+
+ KUNIT_ASSERT_EQ(test,
+ conn_state->hdmi.broadcast_rgb,
+ DRM_HDMI_BROADCAST_RGB_FULL);
+
+ KUNIT_EXPECT_FALSE(test, conn_state->hdmi.is_limited_range);
+}
+
+/*
+ * Test that for an HDMI connector, with an HDMI monitor, if the
+ * Broadcast RGB property is set to limited with a mode that isn't the
+ * VIC-1 mode, we will get a limited RGB Quantization Range.
+ */
+static void drm_test_check_broadcast_rgb_limited_cea_mode(struct kunit *test)
+{
+ struct drm_atomic_helper_connector_hdmi_priv *priv;
+ struct drm_modeset_acquire_ctx *ctx;
+ struct drm_connector_state *conn_state;
+ struct drm_atomic_state *state;
+ struct drm_display_mode *preferred;
+ struct drm_connector *conn;
+ struct drm_device *drm;
+ struct drm_crtc *crtc;
+ int ret;
+
+ priv = drm_atomic_helper_connector_hdmi_init(test,
+ BIT(HDMI_COLORSPACE_RGB),
+ 8);
+ KUNIT_ASSERT_NOT_NULL(test, priv);
+
+ conn = &priv->connector;
+ KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi);
+
+ ctx = drm_kunit_helper_acquire_ctx_alloc(test);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
+
+ preferred = find_preferred_mode(conn);
+ KUNIT_ASSERT_NOT_NULL(test, preferred);
+ KUNIT_ASSERT_NE(test, drm_match_cea_mode(preferred), 1);
+
+ drm = &priv->drm;
+ crtc = priv->crtc;
+ ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
+
+ conn_state = drm_atomic_get_connector_state(state, conn);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
+
+ conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_LIMITED;
+
+ ret = drm_atomic_check_only(state);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ conn_state = drm_atomic_get_connector_state(state, conn);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
+
+ KUNIT_ASSERT_EQ(test,
+ conn_state->hdmi.broadcast_rgb,
+ DRM_HDMI_BROADCAST_RGB_LIMITED);
+
+ KUNIT_EXPECT_TRUE(test, conn_state->hdmi.is_limited_range);
+}
+
+/*
+ * Test that for an HDMI connector, with an HDMI monitor, if the
+ * Broadcast RGB property is set to limited with a VIC-1 mode, we will
+ * get a limited RGB Quantization Range.
+ */
+static void drm_test_check_broadcast_rgb_limited_cea_mode_vic_1(struct kunit *test)
+{
+ struct drm_atomic_helper_connector_hdmi_priv *priv;
+ struct drm_modeset_acquire_ctx *ctx;
+ struct drm_connector_state *conn_state;
+ struct drm_atomic_state *state;
+ struct drm_display_mode *mode;
+ struct drm_connector *conn;
+ struct drm_device *drm;
+ struct drm_crtc *crtc;
+ int ret;
+
+ priv = drm_atomic_helper_connector_hdmi_init(test,
+ BIT(HDMI_COLORSPACE_RGB),
+ 8);
+ KUNIT_ASSERT_NOT_NULL(test, priv);
+
+ drm = &priv->drm;
+ conn = &priv->connector;
+ KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi);
+
+ ctx = drm_kunit_helper_acquire_ctx_alloc(test);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
+
+ mode = drm_display_mode_from_cea_vic(drm, 1);
+ KUNIT_ASSERT_NOT_NULL(test, mode);
+
+ drm = &priv->drm;
+ crtc = priv->crtc;
+ ret = light_up_connector(test, drm, crtc, conn, mode, ctx);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
+
+ conn_state = drm_atomic_get_connector_state(state, conn);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
+
+ conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_LIMITED;
+
+ ret = drm_atomic_check_only(state);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ conn_state = drm_atomic_get_connector_state(state, conn);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
+
+ KUNIT_ASSERT_EQ(test,
+ conn_state->hdmi.broadcast_rgb,
+ DRM_HDMI_BROADCAST_RGB_LIMITED);
+
+ KUNIT_EXPECT_TRUE(test, conn_state->hdmi.is_limited_range);
+}
+
+/*
+ * Test that if we change the maximum bpc property to a different value,
+ * we trigger a mode change on the connector's CRTC, which will in turn
+ * disable/enable the connector.
+ */
+static void drm_test_check_output_bpc_crtc_mode_changed(struct kunit *test)
+{
+ struct drm_atomic_helper_connector_hdmi_priv *priv;
+ struct drm_modeset_acquire_ctx *ctx;
+ struct drm_connector_state *old_conn_state;
+ struct drm_connector_state *new_conn_state;
+ struct drm_crtc_state *crtc_state;
+ struct drm_atomic_state *state;
+ struct drm_display_mode *preferred;
+ struct drm_connector *conn;
+ struct drm_device *drm;
+ struct drm_crtc *crtc;
+ int ret;
+
+ priv = drm_atomic_helper_connector_hdmi_init(test,
+ BIT(HDMI_COLORSPACE_RGB),
+ 10);
+ KUNIT_ASSERT_NOT_NULL(test, priv);
+
+ conn = &priv->connector;
+ ret = set_connector_edid(test, conn,
+ test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz,
+ ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz));
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ ctx = drm_kunit_helper_acquire_ctx_alloc(test);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
+
+ preferred = find_preferred_mode(conn);
+ KUNIT_ASSERT_NOT_NULL(test, preferred);
+
+ drm = &priv->drm;
+ crtc = priv->crtc;
+ ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
+
+ new_conn_state = drm_atomic_get_connector_state(state, conn);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
+
+ old_conn_state = drm_atomic_get_old_connector_state(state, conn);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state);
+
+ new_conn_state->max_requested_bpc = 8;
+
+ KUNIT_ASSERT_NE(test,
+ old_conn_state->max_requested_bpc,
+ new_conn_state->max_requested_bpc);
+
+ ret = drm_atomic_check_only(state);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ old_conn_state = drm_atomic_get_old_connector_state(state, conn);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state);
+
+ new_conn_state = drm_atomic_get_new_connector_state(state, conn);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
+
+ KUNIT_ASSERT_NE(test,
+ old_conn_state->hdmi.output_bpc,
+ new_conn_state->hdmi.output_bpc);
+
+ crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
+ KUNIT_EXPECT_TRUE(test, crtc_state->mode_changed);
+}
+
+/*
+ * Test that if we set the output bpc property to the same value, we
+ * don't trigger a mode change on the connector's CRTC and leave the
+ * connector unaffected.
+ */
+static void drm_test_check_output_bpc_crtc_mode_not_changed(struct kunit *test)
+{
+ struct drm_atomic_helper_connector_hdmi_priv *priv;
+ struct drm_modeset_acquire_ctx *ctx;
+ struct drm_connector_state *old_conn_state;
+ struct drm_connector_state *new_conn_state;
+ struct drm_crtc_state *crtc_state;
+ struct drm_atomic_state *state;
+ struct drm_display_mode *preferred;
+ struct drm_connector *conn;
+ struct drm_device *drm;
+ struct drm_crtc *crtc;
+ int ret;
+
+ priv = drm_atomic_helper_connector_hdmi_init(test,
+ BIT(HDMI_COLORSPACE_RGB),
+ 10);
+ KUNIT_ASSERT_NOT_NULL(test, priv);
+
+ conn = &priv->connector;
+ ret = set_connector_edid(test, conn,
+ test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz,
+ ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz));
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ ctx = drm_kunit_helper_acquire_ctx_alloc(test);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
+
+ preferred = find_preferred_mode(conn);
+ KUNIT_ASSERT_NOT_NULL(test, preferred);
+
+ drm = &priv->drm;
+ crtc = priv->crtc;
+ ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
+
+ new_conn_state = drm_atomic_get_connector_state(state, conn);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
+
+ old_conn_state = drm_atomic_get_old_connector_state(state, conn);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state);
+
+ KUNIT_ASSERT_EQ(test,
+ new_conn_state->hdmi.output_bpc,
+ old_conn_state->hdmi.output_bpc);
+
+ ret = drm_atomic_check_only(state);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ old_conn_state = drm_atomic_get_old_connector_state(state, conn);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state);
+
+ new_conn_state = drm_atomic_get_new_connector_state(state, conn);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
+
+ KUNIT_EXPECT_EQ(test,
+ old_conn_state->hdmi.output_bpc,
+ new_conn_state->hdmi.output_bpc);
+
+ crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
+ KUNIT_EXPECT_FALSE(test, crtc_state->mode_changed);
+}
+
+/*
+ * Test that if we have an HDMI connector but a !HDMI display, we always
+ * output RGB with 8 bpc.
+ */
+static void drm_test_check_output_bpc_dvi(struct kunit *test)
+{
+ struct drm_atomic_helper_connector_hdmi_priv *priv;
+ struct drm_modeset_acquire_ctx *ctx;
+ struct drm_connector_state *conn_state;
+ struct drm_display_info *info;
+ struct drm_display_mode *preferred;
+ struct drm_connector *conn;
+ struct drm_device *drm;
+ struct drm_crtc *crtc;
+ int ret;
+
+ priv = drm_atomic_helper_connector_hdmi_init(test,
+ BIT(HDMI_COLORSPACE_RGB) |
+ BIT(HDMI_COLORSPACE_YUV422) |
+ BIT(HDMI_COLORSPACE_YUV444),
+ 12);
+ KUNIT_ASSERT_NOT_NULL(test, priv);
+
+ conn = &priv->connector;
+ ret = set_connector_edid(test, conn,
+ test_edid_dvi_1080p,
+ ARRAY_SIZE(test_edid_dvi_1080p));
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ info = &conn->display_info;
+ KUNIT_ASSERT_FALSE(test, info->is_hdmi);
+
+ ctx = drm_kunit_helper_acquire_ctx_alloc(test);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
+
+ preferred = find_preferred_mode(conn);
+ KUNIT_ASSERT_NOT_NULL(test, preferred);
+
+ drm = &priv->drm;
+ crtc = priv->crtc;
+ ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ conn_state = conn->state;
+ 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);
+}
+
+/*
+ * Test that when doing a commit which would use RGB 8bpc, the TMDS
+ * clock rate stored in the connector state is equal to the mode clock
+ */
+static void drm_test_check_tmds_char_rate_rgb_8bpc(struct kunit *test)
+{
+ struct drm_atomic_helper_connector_hdmi_priv *priv;
+ struct drm_modeset_acquire_ctx *ctx;
+ struct drm_connector_state *conn_state;
+ struct drm_display_mode *preferred;
+ struct drm_connector *conn;
+ struct drm_device *drm;
+ struct drm_crtc *crtc;
+ int ret;
+
+ priv = drm_atomic_helper_connector_hdmi_init(test,
+ BIT(HDMI_COLORSPACE_RGB),
+ 8);
+ KUNIT_ASSERT_NOT_NULL(test, priv);
+
+ conn = &priv->connector;
+ ret = set_connector_edid(test, conn,
+ test_edid_hdmi_1080p_rgb_max_200mhz,
+ ARRAY_SIZE(test_edid_hdmi_1080p_rgb_max_200mhz));
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ ctx = drm_kunit_helper_acquire_ctx_alloc(test);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
+
+ preferred = find_preferred_mode(conn);
+ KUNIT_ASSERT_NOT_NULL(test, preferred);
+ KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK);
+
+ drm = &priv->drm;
+ crtc = priv->crtc;
+ ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ conn_state = conn->state;
+ 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_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, preferred->clock * 1000);
+}
+
+/*
+ * Test that when doing a commit which would use RGB 10bpc, the TMDS
+ * clock rate stored in the connector state is equal to 1.25 times the
+ * mode pixel clock
+ */
+static void drm_test_check_tmds_char_rate_rgb_10bpc(struct kunit *test)
+{
+ struct drm_atomic_helper_connector_hdmi_priv *priv;
+ struct drm_modeset_acquire_ctx *ctx;
+ struct drm_connector_state *conn_state;
+ struct drm_display_mode *preferred;
+ struct drm_connector *conn;
+ struct drm_device *drm;
+ struct drm_crtc *crtc;
+ int ret;
+
+ priv = drm_atomic_helper_connector_hdmi_init(test,
+ BIT(HDMI_COLORSPACE_RGB),
+ 10);
+ KUNIT_ASSERT_NOT_NULL(test, priv);
+
+ conn = &priv->connector;
+ ret = set_connector_edid(test, conn,
+ test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz,
+ ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz));
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ ctx = drm_kunit_helper_acquire_ctx_alloc(test);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
+
+ preferred = find_preferred_mode(conn);
+ KUNIT_ASSERT_NOT_NULL(test, preferred);
+ KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK);
+
+ drm = &priv->drm;
+ crtc = priv->crtc;
+ ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ conn_state = conn->state;
+ 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_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, preferred->clock * 1250);
+}
+
+/*
+ * Test that when doing a commit which would use RGB 12bpc, the TMDS
+ * clock rate stored in the connector state is equal to 1.5 times the
+ * mode pixel clock
+ */
+static void drm_test_check_tmds_char_rate_rgb_12bpc(struct kunit *test)
+{
+ struct drm_atomic_helper_connector_hdmi_priv *priv;
+ struct drm_modeset_acquire_ctx *ctx;
+ struct drm_connector_state *conn_state;
+ struct drm_display_mode *preferred;
+ struct drm_connector *conn;
+ struct drm_device *drm;
+ struct drm_crtc *crtc;
+ int ret;
+
+ priv = drm_atomic_helper_connector_hdmi_init(test,
+ BIT(HDMI_COLORSPACE_RGB),
+ 12);
+ KUNIT_ASSERT_NOT_NULL(test, priv);
+
+ conn = &priv->connector;
+ ret = set_connector_edid(test, conn,
+ test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz,
+ ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz));
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ ctx = drm_kunit_helper_acquire_ctx_alloc(test);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
+
+ preferred = find_preferred_mode(conn);
+ KUNIT_ASSERT_NOT_NULL(test, preferred);
+ KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK);
+
+ drm = &priv->drm;
+ crtc = priv->crtc;
+ ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ conn_state = conn->state;
+ 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_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, preferred->clock * 1500);
+}
+
+/*
+ * Test that if we filter a rate through our hook, it's indeed rejected
+ * by the whole atomic_check logic.
+ *
+ * We do so by first doing a commit on the pipeline to make sure that it
+ * works, change the HDMI helpers pointer, and then try the same commit
+ * again to see if it fails as it should.
+ */
+static void drm_test_check_hdmi_funcs_reject_rate(struct kunit *test)
+{
+ struct drm_atomic_helper_connector_hdmi_priv *priv;
+ struct drm_modeset_acquire_ctx *ctx;
+ struct drm_atomic_state *state;
+ struct drm_display_mode *preferred;
+ struct drm_crtc_state *crtc_state;
+ struct drm_connector *conn;
+ struct drm_device *drm;
+ struct drm_crtc *crtc;
+ int ret;
+
+ priv = drm_atomic_helper_connector_hdmi_init(test,
+ BIT(HDMI_COLORSPACE_RGB),
+ 8);
+ KUNIT_ASSERT_NOT_NULL(test, priv);
+
+ ctx = drm_kunit_helper_acquire_ctx_alloc(test);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
+
+ conn = &priv->connector;
+ preferred = find_preferred_mode(conn);
+ KUNIT_ASSERT_NOT_NULL(test, preferred);
+
+ drm = &priv->drm;
+ crtc = priv->crtc;
+ ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ /* You shouldn't be doing that at home. */
+ conn->hdmi.funcs = &reject_connector_hdmi_funcs;
+
+ state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
+
+ crtc_state = drm_atomic_get_crtc_state(state, crtc);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
+
+ crtc_state->connectors_changed = true;
+
+ ret = drm_atomic_check_only(state);
+ KUNIT_EXPECT_LT(test, ret, 0);
+}
+
+/*
+ * Test that if:
+ * - We have an HDMI connector supporting RGB only
+ * - The chosen mode has a TMDS character rate higher than the display
+ * supports in RGB/12bpc
+ * - The chosen mode has a TMDS character rate lower than the display
+ * supports in RGB/10bpc.
+ *
+ * Then we will pick the latter, and the computed TMDS character rate
+ * will be equal to 1.25 times the mode pixel clock.
+ */
+static void drm_test_check_max_tmds_rate_bpc_fallback(struct kunit *test)
+{
+ struct drm_atomic_helper_connector_hdmi_priv *priv;
+ struct drm_modeset_acquire_ctx *ctx;
+ struct drm_connector_state *conn_state;
+ struct drm_display_info *info;
+ struct drm_display_mode *preferred;
+ unsigned long long rate;
+ struct drm_connector *conn;
+ struct drm_device *drm;
+ struct drm_crtc *crtc;
+ int ret;
+
+ priv = drm_atomic_helper_connector_hdmi_init(test,
+ BIT(HDMI_COLORSPACE_RGB),
+ 12);
+ KUNIT_ASSERT_NOT_NULL(test, priv);
+
+ conn = &priv->connector;
+ ret = set_connector_edid(test, conn,
+ test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz,
+ ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz));
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ info = &conn->display_info;
+ KUNIT_ASSERT_TRUE(test, info->is_hdmi);
+ KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0);
+
+ ctx = drm_kunit_helper_acquire_ctx_alloc(test);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
+
+ preferred = find_preferred_mode(conn);
+ 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);
+ KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000);
+
+ rate = drm_hdmi_compute_mode_clock(preferred, 10, HDMI_COLORSPACE_RGB);
+ KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
+
+ drm = &priv->drm;
+ crtc = priv->crtc;
+ ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
+ KUNIT_EXPECT_EQ(test, ret, 0);
+
+ conn_state = conn->state;
+ 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.tmds_char_rate, preferred->clock * 1250);
+}
+
+/*
+ * Test that if:
+ * - We have an HDMI connector supporting both RGB and YUV422 and up to
+ * 12 bpc
+ * - The chosen mode has a TMDS character rate higher than the display
+ * supports in RGB/12bpc but lower than the display supports in
+ * RGB/10bpc
+ * - The chosen mode has a TMDS character rate lower than the display
+ * supports in YUV422/12bpc.
+ *
+ * Then we will prefer to keep the RGB format with a lower bpc over
+ * picking YUV422.
+ */
+static void drm_test_check_max_tmds_rate_format_fallback(struct kunit *test)
+{
+ struct drm_atomic_helper_connector_hdmi_priv *priv;
+ struct drm_modeset_acquire_ctx *ctx;
+ struct drm_connector_state *conn_state;
+ struct drm_display_info *info;
+ struct drm_display_mode *preferred;
+ unsigned long long rate;
+ struct drm_connector *conn;
+ struct drm_device *drm;
+ struct drm_crtc *crtc;
+ int ret;
+
+ priv = drm_atomic_helper_connector_hdmi_init(test,
+ BIT(HDMI_COLORSPACE_RGB) |
+ BIT(HDMI_COLORSPACE_YUV422) |
+ BIT(HDMI_COLORSPACE_YUV444),
+ 12);
+ KUNIT_ASSERT_NOT_NULL(test, priv);
+
+ conn = &priv->connector;
+ ret = set_connector_edid(test, conn,
+ test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz,
+ ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz));
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ info = &conn->display_info;
+ KUNIT_ASSERT_TRUE(test, info->is_hdmi);
+ KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0);
+
+ ctx = drm_kunit_helper_acquire_ctx_alloc(test);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
+
+ preferred = find_preferred_mode(conn);
+ 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);
+ KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
+
+ rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB);
+ KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000);
+
+ rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_YUV422);
+ KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
+
+ drm = &priv->drm;
+ crtc = priv->crtc;
+ ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
+ KUNIT_EXPECT_EQ(test, ret, 0);
+
+ conn_state = conn->state;
+ 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);
+}
+
+/*
+ * Test that if a driver and screen supports RGB and YUV formats, and we
+ * try to set the VIC 1 mode, we end up with 8bpc RGB even if we could
+ * have had a higher bpc.
+ */
+static void drm_test_check_output_bpc_format_vic_1(struct kunit *test)
+{
+ struct drm_atomic_helper_connector_hdmi_priv *priv;
+ struct drm_modeset_acquire_ctx *ctx;
+ struct drm_connector_state *conn_state;
+ struct drm_display_info *info;
+ struct drm_display_mode *mode;
+ unsigned long long rate;
+ struct drm_connector *conn;
+ struct drm_device *drm;
+ struct drm_crtc *crtc;
+ int ret;
+
+ priv = drm_atomic_helper_connector_hdmi_init(test,
+ BIT(HDMI_COLORSPACE_RGB) |
+ BIT(HDMI_COLORSPACE_YUV422) |
+ BIT(HDMI_COLORSPACE_YUV444),
+ 12);
+ KUNIT_ASSERT_NOT_NULL(test, priv);
+
+ drm = &priv->drm;
+ conn = &priv->connector;
+ ret = set_connector_edid(test, conn,
+ test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz,
+ ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz));
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ info = &conn->display_info;
+ KUNIT_ASSERT_TRUE(test, info->is_hdmi);
+ KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0);
+
+ ctx = drm_kunit_helper_acquire_ctx_alloc(test);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
+
+ mode = drm_display_mode_from_cea_vic(drm, 1);
+ KUNIT_ASSERT_NOT_NULL(test, mode);
+
+ /*
+ * NOTE: We can't use drm_hdmi_compute_mode_clock()
+ * here because we're trying to get the rate of an invalid
+ * configuration.
+ *
+ * Thus, we have to calculate the rate by hand.
+ */
+ rate = mode->clock * 1500;
+ KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
+
+ drm = &priv->drm;
+ crtc = priv->crtc;
+ ret = light_up_connector(test, drm, crtc, conn, mode, ctx);
+ KUNIT_EXPECT_EQ(test, ret, 0);
+
+ conn_state = conn->state;
+ 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);
+}
+
+/*
+ * Test that if a driver supports only RGB but the screen also supports
+ * YUV formats, we only end up with an RGB format.
+ */
+static void drm_test_check_output_bpc_format_driver_rgb_only(struct kunit *test)
+{
+ struct drm_atomic_helper_connector_hdmi_priv *priv;
+ struct drm_modeset_acquire_ctx *ctx;
+ struct drm_connector_state *conn_state;
+ struct drm_display_info *info;
+ struct drm_display_mode *preferred;
+ unsigned long long rate;
+ struct drm_connector *conn;
+ struct drm_device *drm;
+ struct drm_crtc *crtc;
+ int ret;
+
+ priv = drm_atomic_helper_connector_hdmi_init(test,
+ BIT(HDMI_COLORSPACE_RGB),
+ 12);
+ KUNIT_ASSERT_NOT_NULL(test, priv);
+
+ conn = &priv->connector;
+ ret = set_connector_edid(test, conn,
+ test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz,
+ ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz));
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ info = &conn->display_info;
+ KUNIT_ASSERT_TRUE(test, info->is_hdmi);
+ KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0);
+
+ ctx = drm_kunit_helper_acquire_ctx_alloc(test);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
+
+ preferred = find_preferred_mode(conn);
+ KUNIT_ASSERT_NOT_NULL(test, preferred);
+
+ /*
+ * We're making sure that YUV422 would be the preferred option
+ * here: we're always favouring higher bpc, we can't have RGB
+ * because the TMDS character rate exceeds the maximum supported
+ * by the display, and YUV422 works for that display.
+ *
+ * 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);
+ KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000);
+
+ rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_YUV422);
+ KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
+
+ drm = &priv->drm;
+ crtc = priv->crtc;
+ ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
+ KUNIT_EXPECT_EQ(test, ret, 0);
+
+ conn_state = conn->state;
+ 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);
+}
+
+/*
+ * Test that if a screen supports only RGB but the driver also supports
+ * YUV formats, we only end up with an RGB format.
+ */
+static void drm_test_check_output_bpc_format_display_rgb_only(struct kunit *test)
+{
+ struct drm_atomic_helper_connector_hdmi_priv *priv;
+ struct drm_modeset_acquire_ctx *ctx;
+ struct drm_connector_state *conn_state;
+ struct drm_display_info *info;
+ struct drm_display_mode *preferred;
+ unsigned long long rate;
+ struct drm_connector *conn;
+ struct drm_device *drm;
+ struct drm_crtc *crtc;
+ int ret;
+
+ priv = drm_atomic_helper_connector_hdmi_init(test,
+ BIT(HDMI_COLORSPACE_RGB) |
+ BIT(HDMI_COLORSPACE_YUV422) |
+ BIT(HDMI_COLORSPACE_YUV444),
+ 12);
+ KUNIT_ASSERT_NOT_NULL(test, priv);
+
+ conn = &priv->connector;
+ ret = set_connector_edid(test, conn,
+ test_edid_hdmi_1080p_rgb_max_200mhz,
+ ARRAY_SIZE(test_edid_hdmi_1080p_rgb_max_200mhz));
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ info = &conn->display_info;
+ KUNIT_ASSERT_TRUE(test, info->is_hdmi);
+ KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0);
+
+ ctx = drm_kunit_helper_acquire_ctx_alloc(test);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
+
+ preferred = find_preferred_mode(conn);
+ KUNIT_ASSERT_NOT_NULL(test, preferred);
+
+ /*
+ * We're making sure that YUV422 would be the preferred option
+ * here: we're always favouring higher bpc, we can't have RGB
+ * because the TMDS character rate exceeds the maximum supported
+ * by the display, and YUV422 works for that display.
+ *
+ * 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);
+ KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000);
+
+ rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_YUV422);
+ KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
+
+ drm = &priv->drm;
+ crtc = priv->crtc;
+ ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
+ KUNIT_EXPECT_EQ(test, ret, 0);
+
+ conn_state = conn->state;
+ 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);
+}
+
+/*
+ * Test that if a display supports higher bpc but the driver only
+ * supports 8 bpc, we only end up with 8 bpc even if we could have had a
+ * higher bpc.
+ */
+static void drm_test_check_output_bpc_format_driver_8bpc_only(struct kunit *test)
+{
+ struct drm_atomic_helper_connector_hdmi_priv *priv;
+ struct drm_modeset_acquire_ctx *ctx;
+ struct drm_connector_state *conn_state;
+ struct drm_display_info *info;
+ struct drm_display_mode *preferred;
+ unsigned long long rate;
+ struct drm_connector *conn;
+ struct drm_device *drm;
+ struct drm_crtc *crtc;
+ int ret;
+
+ priv = drm_atomic_helper_connector_hdmi_init(test,
+ BIT(HDMI_COLORSPACE_RGB),
+ 8);
+ KUNIT_ASSERT_NOT_NULL(test, priv);
+
+ conn = &priv->connector;
+ ret = set_connector_edid(test, conn,
+ test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz,
+ ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz));
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ info = &conn->display_info;
+ KUNIT_ASSERT_TRUE(test, info->is_hdmi);
+ KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0);
+
+ ctx = drm_kunit_helper_acquire_ctx_alloc(test);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
+
+ preferred = find_preferred_mode(conn);
+ KUNIT_ASSERT_NOT_NULL(test, preferred);
+
+ /*
+ * 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);
+ KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
+
+ drm = &priv->drm;
+ crtc = priv->crtc;
+ ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
+ KUNIT_EXPECT_EQ(test, ret, 0);
+
+ conn_state = conn->state;
+ 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);
+}
+
+/*
+ * Test that if a driver supports higher bpc but the display only
+ * supports 8 bpc, we only end up with 8 bpc even if we could have had a
+ * higher bpc.
+ */
+static void drm_test_check_output_bpc_format_display_8bpc_only(struct kunit *test)
+{
+ struct drm_atomic_helper_connector_hdmi_priv *priv;
+ struct drm_modeset_acquire_ctx *ctx;
+ struct drm_connector_state *conn_state;
+ struct drm_display_info *info;
+ struct drm_display_mode *preferred;
+ unsigned long long rate;
+ struct drm_connector *conn;
+ struct drm_device *drm;
+ struct drm_crtc *crtc;
+ int ret;
+
+ priv = drm_atomic_helper_connector_hdmi_init(test,
+ BIT(HDMI_COLORSPACE_RGB) |
+ BIT(HDMI_COLORSPACE_YUV422) |
+ BIT(HDMI_COLORSPACE_YUV444),
+ 12);
+ KUNIT_ASSERT_NOT_NULL(test, priv);
+
+ conn = &priv->connector;
+ ret = set_connector_edid(test, conn,
+ test_edid_hdmi_1080p_rgb_max_340mhz,
+ ARRAY_SIZE(test_edid_hdmi_1080p_rgb_max_340mhz));
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ info = &conn->display_info;
+ KUNIT_ASSERT_TRUE(test, info->is_hdmi);
+ KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0);
+
+ ctx = drm_kunit_helper_acquire_ctx_alloc(test);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
+
+ preferred = find_preferred_mode(conn);
+ KUNIT_ASSERT_NOT_NULL(test, preferred);
+
+ /*
+ * 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);
+ KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
+
+ drm = &priv->drm;
+ crtc = priv->crtc;
+ ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
+ KUNIT_EXPECT_EQ(test, ret, 0);
+
+ conn_state = conn->state;
+ 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);
+}
+
+static struct kunit_case drm_atomic_helper_connector_hdmi_check_tests[] = {
+ KUNIT_CASE(drm_test_check_broadcast_rgb_auto_cea_mode),
+ KUNIT_CASE(drm_test_check_broadcast_rgb_auto_cea_mode_vic_1),
+ KUNIT_CASE(drm_test_check_broadcast_rgb_full_cea_mode),
+ KUNIT_CASE(drm_test_check_broadcast_rgb_full_cea_mode_vic_1),
+ KUNIT_CASE(drm_test_check_broadcast_rgb_limited_cea_mode),
+ KUNIT_CASE(drm_test_check_broadcast_rgb_limited_cea_mode_vic_1),
+ /*
+ * TODO: When we'll have YUV output support, we need to check
+ * that the limited range is always set to limited no matter
+ * what the value of Broadcast RGB is.
+ */
+ KUNIT_CASE(drm_test_check_broadcast_rgb_crtc_mode_changed),
+ KUNIT_CASE(drm_test_check_broadcast_rgb_crtc_mode_not_changed),
+ KUNIT_CASE(drm_test_check_hdmi_funcs_reject_rate),
+ KUNIT_CASE(drm_test_check_max_tmds_rate_bpc_fallback),
+ KUNIT_CASE(drm_test_check_max_tmds_rate_format_fallback),
+ KUNIT_CASE(drm_test_check_output_bpc_crtc_mode_changed),
+ KUNIT_CASE(drm_test_check_output_bpc_crtc_mode_not_changed),
+ KUNIT_CASE(drm_test_check_output_bpc_dvi),
+ KUNIT_CASE(drm_test_check_output_bpc_format_vic_1),
+ KUNIT_CASE(drm_test_check_output_bpc_format_display_8bpc_only),
+ KUNIT_CASE(drm_test_check_output_bpc_format_display_rgb_only),
+ KUNIT_CASE(drm_test_check_output_bpc_format_driver_8bpc_only),
+ KUNIT_CASE(drm_test_check_output_bpc_format_driver_rgb_only),
+ KUNIT_CASE(drm_test_check_tmds_char_rate_rgb_8bpc),
+ KUNIT_CASE(drm_test_check_tmds_char_rate_rgb_10bpc),
+ KUNIT_CASE(drm_test_check_tmds_char_rate_rgb_12bpc),
+ /*
+ * TODO: We should have tests to check that a change in the
+ * format triggers a CRTC mode change just like we do for the
+ * RGB Quantization and BPC.
+ *
+ * However, we don't have any way to control which format gets
+ * picked up aside from changing the BPC or mode which would
+ * already trigger a mode change.
+ */
+ { }
+};
+
+static struct kunit_suite drm_atomic_helper_connector_hdmi_check_test_suite = {
+ .name = "drm_atomic_helper_connector_hdmi_check",
+ .test_cases = drm_atomic_helper_connector_hdmi_check_tests,
+};
+
+/*
+ * Test that the value of the Broadcast RGB property out of reset is set
+ * to auto.
+ */
+static void drm_test_check_broadcast_rgb_value(struct kunit *test)
+{
+ struct drm_atomic_helper_connector_hdmi_priv *priv;
+ struct drm_connector_state *conn_state;
+ struct drm_connector *conn;
+
+ priv = drm_atomic_helper_connector_hdmi_init(test,
+ BIT(HDMI_COLORSPACE_RGB),
+ 8);
+ KUNIT_ASSERT_NOT_NULL(test, priv);
+
+ conn = &priv->connector;
+ conn_state = conn->state;
+ KUNIT_EXPECT_EQ(test, conn_state->hdmi.broadcast_rgb, DRM_HDMI_BROADCAST_RGB_AUTO);
+}
+
+/*
+ * Test that if the connector was initialised with a maximum bpc of 8,
+ * the value of the max_bpc and max_requested_bpc properties out of
+ * reset are also set to 8, and output_bpc is set to 0 and will be
+ * filled at atomic_check time.
+ */
+static void drm_test_check_bpc_8_value(struct kunit *test)
+{
+ struct drm_atomic_helper_connector_hdmi_priv *priv;
+ struct drm_connector_state *conn_state;
+ struct drm_connector *conn;
+
+ priv = drm_atomic_helper_connector_hdmi_init(test,
+ BIT(HDMI_COLORSPACE_RGB),
+ 8);
+ KUNIT_ASSERT_NOT_NULL(test, priv);
+
+ conn = &priv->connector;
+ conn_state = conn->state;
+ KUNIT_EXPECT_EQ(test, conn_state->max_bpc, 8);
+ KUNIT_EXPECT_EQ(test, conn_state->max_requested_bpc, 8);
+ KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 0);
+}
+
+/*
+ * Test that if the connector was initialised with a maximum bpc of 10,
+ * the value of the max_bpc and max_requested_bpc properties out of
+ * reset are also set to 10, and output_bpc is set to 0 and will be
+ * filled at atomic_check time.
+ */
+static void drm_test_check_bpc_10_value(struct kunit *test)
+{
+ struct drm_atomic_helper_connector_hdmi_priv *priv;
+ struct drm_connector_state *conn_state;
+ struct drm_connector *conn;
+
+ priv = drm_atomic_helper_connector_hdmi_init(test,
+ BIT(HDMI_COLORSPACE_RGB),
+ 10);
+ KUNIT_ASSERT_NOT_NULL(test, priv);
+
+ conn = &priv->connector;
+ conn_state = conn->state;
+ KUNIT_EXPECT_EQ(test, conn_state->max_bpc, 10);
+ KUNIT_EXPECT_EQ(test, conn_state->max_requested_bpc, 10);
+ KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 0);
+}
+
+/*
+ * Test that if the connector was initialised with a maximum bpc of 12,
+ * the value of the max_bpc and max_requested_bpc properties out of
+ * reset are also set to 12, and output_bpc is set to 0 and will be
+ * filled at atomic_check time.
+ */
+static void drm_test_check_bpc_12_value(struct kunit *test)
+{
+ struct drm_atomic_helper_connector_hdmi_priv *priv;
+ struct drm_connector_state *conn_state;
+ struct drm_connector *conn;
+
+ priv = drm_atomic_helper_connector_hdmi_init(test,
+ BIT(HDMI_COLORSPACE_RGB),
+ 12);
+ KUNIT_ASSERT_NOT_NULL(test, priv);
+
+ conn = &priv->connector;
+ conn_state = conn->state;
+ KUNIT_EXPECT_EQ(test, conn_state->max_bpc, 12);
+ KUNIT_EXPECT_EQ(test, conn_state->max_requested_bpc, 12);
+ KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 0);
+}
+
+/*
+ * Test that the value of the output format property out of reset is set
+ * to RGB, even if the driver supports more than that.
+ */
+static void drm_test_check_format_value(struct kunit *test)
+{
+ struct drm_atomic_helper_connector_hdmi_priv *priv;
+ struct drm_connector_state *conn_state;
+ struct drm_connector *conn;
+
+ priv = drm_atomic_helper_connector_hdmi_init(test,
+ BIT(HDMI_COLORSPACE_RGB) |
+ BIT(HDMI_COLORSPACE_YUV422) |
+ BIT(HDMI_COLORSPACE_YUV444),
+ 8);
+ KUNIT_ASSERT_NOT_NULL(test, priv);
+
+ conn = &priv->connector;
+ conn_state = conn->state;
+ KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, 0);
+}
+
+/*
+ * Test that the value of the output format property out of reset is set
+ * to 0, and will be computed at atomic_check time.
+ */
+static void drm_test_check_tmds_char_value(struct kunit *test)
+{
+ struct drm_atomic_helper_connector_hdmi_priv *priv;
+ struct drm_connector_state *conn_state;
+ struct drm_connector *conn;
+
+ priv = drm_atomic_helper_connector_hdmi_init(test,
+ BIT(HDMI_COLORSPACE_RGB) |
+ BIT(HDMI_COLORSPACE_YUV422) |
+ BIT(HDMI_COLORSPACE_YUV444),
+ 12);
+ KUNIT_ASSERT_NOT_NULL(test, priv);
+
+ conn = &priv->connector;
+ conn_state = conn->state;
+ KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, 0);
+}
+
+static struct kunit_case drm_atomic_helper_connector_hdmi_reset_tests[] = {
+ KUNIT_CASE(drm_test_check_broadcast_rgb_value),
+ KUNIT_CASE(drm_test_check_bpc_8_value),
+ KUNIT_CASE(drm_test_check_bpc_10_value),
+ KUNIT_CASE(drm_test_check_bpc_12_value),
+ KUNIT_CASE(drm_test_check_format_value),
+ KUNIT_CASE(drm_test_check_tmds_char_value),
+ { }
+};
+
+static struct kunit_suite drm_atomic_helper_connector_hdmi_reset_test_suite = {
+ .name = "drm_atomic_helper_connector_hdmi_reset",
+ .test_cases = drm_atomic_helper_connector_hdmi_reset_tests,
+};
+
+kunit_test_suites(
+ &drm_atomic_helper_connector_hdmi_check_test_suite,
+ &drm_atomic_helper_connector_hdmi_reset_test_suite,
+);
+
+MODULE_AUTHOR("Maxime Ripard <mripard@kernel.org>");
+MODULE_DESCRIPTION("Kunit test for drm_hdmi_state_helper functions");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tests/drm_kunit_edid.h b/drivers/gpu/drm/tests/drm_kunit_edid.h
new file mode 100644
index 000000000000..107559900e97
--- /dev/null
+++ b/drivers/gpu/drm/tests/drm_kunit_edid.h
@@ -0,0 +1,484 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef DRM_KUNIT_EDID_H_
+#define DRM_KUNIT_EDID_H_
+
+/*
+ * edid-decode (hex):
+ *
+ * 00 ff ff ff ff ff ff 00 31 d8 2a 00 00 00 00 00
+ * 00 21 01 03 81 a0 5a 78 0a 00 00 00 00 00 00 00
+ * 00 00 00 00 00 00 01 01 01 01 01 01 01 01 01 01
+ * 01 01 01 01 01 01 02 3a 80 18 71 38 2d 40 58 2c
+ * 45 00 40 84 63 00 00 1e 00 00 00 fc 00 54 65 73
+ * 74 20 45 44 49 44 0a 20 20 20 00 00 00 fd 00 32
+ * 46 1e 46 0f 00 0a 20 20 20 20 20 20 00 00 00 10
+ * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ab
+ *
+ * ----------------
+ *
+ * Block 0, Base EDID:
+ * EDID Structure Version & Revision: 1.3
+ * Vendor & Product Identification:
+ * Manufacturer: LNX
+ * Model: 42
+ * Made in: 2023
+ * Basic Display Parameters & Features:
+ * Digital display
+ * DFP 1.x compatible TMDS
+ * Maximum image size: 160 cm x 90 cm
+ * Gamma: 2.20
+ * RGB color display
+ * First detailed timing is the preferred timing
+ * Color Characteristics:
+ * Red : 0.0000, 0.0000
+ * Green: 0.0000, 0.0000
+ * Blue : 0.0000, 0.0000
+ * White: 0.0000, 0.0000
+ * Established Timings I & II: none
+ * Standard Timings: none
+ * Detailed Timing Descriptors:
+ * DTD 1: 1920x1080 60.000000 Hz 16:9 67.500 kHz 148.500000 MHz (1600 mm x 900 mm)
+ * Hfront 88 Hsync 44 Hback 148 Hpol P
+ * Vfront 4 Vsync 5 Vback 36 Vpol P
+ * Display Product Name: 'Test EDID'
+ * Display Range Limits:
+ * Monitor ranges (GTF): 50-70 Hz V, 30-70 kHz H, max dotclock 150 MHz
+ * Dummy Descriptor:
+ * Checksum: 0xab
+ */
+static const unsigned char test_edid_dvi_1080p[] = {
+ 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x31, 0xd8, 0x2a, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x01, 0x03, 0x81, 0xa0, 0x5a, 0x78,
+ 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38,
+ 0x2d, 0x40, 0x58, 0x2c, 0x45, 0x00, 0x40, 0x84, 0x63, 0x00, 0x00, 0x1e,
+ 0x00, 0x00, 0x00, 0xfc, 0x00, 0x54, 0x65, 0x73, 0x74, 0x20, 0x45, 0x44,
+ 0x49, 0x44, 0x0a, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x32,
+ 0x46, 0x1e, 0x46, 0x0f, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xab
+};
+
+/*
+ * edid-decode (hex):
+ *
+ * 00 ff ff ff ff ff ff 00 31 d8 2a 00 00 00 00 00
+ * 00 21 01 03 81 a0 5a 78 02 00 00 00 00 00 00 00
+ * 00 00 00 20 00 00 01 01 01 01 01 01 01 01 01 01
+ * 01 01 01 01 01 01 02 3a 80 18 71 38 2d 40 58 2c
+ * 45 00 40 84 63 00 00 1e 00 00 00 fc 00 54 65 73
+ * 74 20 45 44 49 44 0a 20 20 20 00 00 00 fd 00 32
+ * 46 1e 46 0f 00 0a 20 20 20 20 20 20 00 00 00 10
+ * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 92
+ *
+ * 02 03 1b 81 e3 05 00 20 41 10 e2 00 4a 6d 03 0c
+ * 00 12 34 00 28 20 00 00 00 00 00 00 00 00 00 00
+ * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 d0
+ *
+ * ----------------
+ *
+ * Block 0, Base EDID:
+ * EDID Structure Version & Revision: 1.3
+ * Vendor & Product Identification:
+ * Manufacturer: LNX
+ * Model: 42
+ * Made in: 2023
+ * Basic Display Parameters & Features:
+ * Digital display
+ * DFP 1.x compatible TMDS
+ * Maximum image size: 160 cm x 90 cm
+ * Gamma: 2.20
+ * Monochrome or grayscale display
+ * First detailed timing is the preferred timing
+ * Color Characteristics:
+ * Red : 0.0000, 0.0000
+ * Green: 0.0000, 0.0000
+ * Blue : 0.0000, 0.0000
+ * White: 0.0000, 0.0000
+ * Established Timings I & II:
+ * DMT 0x04: 640x480 59.940476 Hz 4:3 31.469 kHz 25.175000 MHz
+ * Standard Timings: none
+ * Detailed Timing Descriptors:
+ * DTD 1: 1920x1080 60.000000 Hz 16:9 67.500 kHz 148.500000 MHz (1600 mm x 900 mm)
+ * Hfront 88 Hsync 44 Hback 148 Hpol P
+ * Vfront 4 Vsync 5 Vback 36 Vpol P
+ * Display Product Name: 'Test EDID'
+ * Display Range Limits:
+ * Monitor ranges (GTF): 50-70 Hz V, 30-70 kHz H, max dotclock 150 MHz
+ * Dummy Descriptor:
+ * Extension blocks: 1
+ * Checksum: 0x92
+ *
+ * ----------------
+ *
+ * Block 1, CTA-861 Extension Block:
+ * Revision: 3
+ * Underscans IT Video Formats by default
+ * Native detailed modes: 1
+ * Colorimetry Data Block:
+ * sRGB
+ * Video Data Block:
+ * VIC 16: 1920x1080 60.000000 Hz 16:9 67.500 kHz 148.500000 MHz
+ * Video Capability Data Block:
+ * YCbCr quantization: No Data
+ * RGB quantization: Selectable (via AVI Q)
+ * PT scan behavior: No Data
+ * IT scan behavior: Always Underscanned
+ * CE scan behavior: Always Underscanned
+ * Vendor-Specific Data Block (HDMI), OUI 00-0C-03:
+ * Source physical address: 1.2.3.4
+ * Maximum TMDS clock: 200 MHz
+ * Extended HDMI video details:
+ * Checksum: 0xd0 Unused space in Extension Block: 100 bytes
+ */
+static const unsigned char test_edid_hdmi_1080p_rgb_max_200mhz[] = {
+ 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x31, 0xd8, 0x2a, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x01, 0x03, 0x81, 0xa0, 0x5a, 0x78,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38,
+ 0x2d, 0x40, 0x58, 0x2c, 0x45, 0x00, 0x40, 0x84, 0x63, 0x00, 0x00, 0x1e,
+ 0x00, 0x00, 0x00, 0xfc, 0x00, 0x54, 0x65, 0x73, 0x74, 0x20, 0x45, 0x44,
+ 0x49, 0x44, 0x0a, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x32,
+ 0x46, 0x00, 0x00, 0xc4, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x41, 0x02, 0x03, 0x1b, 0x81,
+ 0xe3, 0x05, 0x00, 0x20, 0x41, 0x10, 0xe2, 0x00, 0x4a, 0x6d, 0x03, 0x0c,
+ 0x00, 0x12, 0x34, 0x00, 0x28, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xd0
+};
+
+/*
+ * edid-decode (hex):
+ *
+ * 00 ff ff ff ff ff ff 00 31 d8 2a 00 00 00 00 00
+ * 00 21 01 03 81 a0 5a 78 02 00 00 00 00 00 00 00
+ * 00 00 00 20 00 00 01 01 01 01 01 01 01 01 01 01
+ * 01 01 01 01 01 01 02 3a 80 18 71 38 2d 40 58 2c
+ * 45 00 40 84 63 00 00 1e 00 00 00 fc 00 54 65 73
+ * 74 20 45 44 49 44 0a 20 20 20 00 00 00 fd 00 32
+ * 46 1e 46 0f 00 0a 20 20 20 20 20 20 00 00 00 10
+ * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 92
+ *
+ * 02 03 1b 81 e3 05 00 20 41 10 e2 00 4a 6d 03 0c
+ * 00 12 34 00 28 20 00 00 00 00 00 00 00 00 00 00
+ * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 d0
+ *
+ * ----------------
+ *
+ * Block 0, Base EDID:
+ * EDID Structure Version & Revision: 1.3
+ * Vendor & Product Identification:
+ * Manufacturer: LNX
+ * Model: 42
+ * Made in: 2023
+ * Basic Display Parameters & Features:
+ * Digital display
+ * DFP 1.x compatible TMDS
+ * Maximum image size: 160 cm x 90 cm
+ * Gamma: 2.20
+ * Monochrome or grayscale display
+ * First detailed timing is the preferred timing
+ * Color Characteristics:
+ * Red : 0.0000, 0.0000
+ * Green: 0.0000, 0.0000
+ * Blue : 0.0000, 0.0000
+ * White: 0.0000, 0.0000
+ * Established Timings I & II:
+ * DMT 0x04: 640x480 59.940476 Hz 4:3 31.469 kHz 25.175000 MHz
+ * Standard Timings: none
+ * Detailed Timing Descriptors:
+ * DTD 1: 1920x1080 60.000000 Hz 16:9 67.500 kHz 148.500000 MHz (1600 mm x 900 mm)
+ * Hfront 88 Hsync 44 Hback 148 Hpol P
+ * Vfront 4 Vsync 5 Vback 36 Vpol P
+ * Display Product Name: 'Test EDID'
+ * Display Range Limits:
+ * Monitor ranges (GTF): 50-70 Hz V, 30-70 kHz H, max dotclock 150 MHz
+ * Dummy Descriptor:
+ * Extension blocks: 1
+ * Checksum: 0x92
+ *
+ * ----------------
+ *
+ * Block 1, CTA-861 Extension Block:
+ * Revision: 3
+ * Underscans IT Video Formats by default
+ * Native detailed modes: 1
+ * Colorimetry Data Block:
+ * sRGB
+ * Video Data Block:
+ * VIC 16: 1920x1080 60.000000 Hz 16:9 67.500 kHz 148.500000 MHz
+ * Video Capability Data Block:
+ * YCbCr quantization: No Data
+ * RGB quantization: Selectable (via AVI Q)
+ * PT scan behavior: No Data
+ * IT scan behavior: Always Underscanned
+ * CE scan behavior: Always Underscanned
+ * Vendor-Specific Data Block (HDMI), OUI 00-0C-03:
+ * Source physical address: 1.2.3.4
+ * Maximum TMDS clock: 340 MHz
+ * Extended HDMI video details:
+ * Checksum: 0xd0 Unused space in Extension Block: 100 bytes
+ */
+static const unsigned char test_edid_hdmi_1080p_rgb_max_340mhz[] = {
+ 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x31, 0xd8, 0x2a, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x01, 0x03, 0x81, 0xa0, 0x5a, 0x78,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38,
+ 0x2d, 0x40, 0x58, 0x2c, 0x45, 0x00, 0x40, 0x84, 0x63, 0x00, 0x00, 0x1e,
+ 0x00, 0x00, 0x00, 0xfc, 0x00, 0x54, 0x65, 0x73, 0x74, 0x20, 0x45, 0x44,
+ 0x49, 0x44, 0x0a, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x32,
+ 0x46, 0x00, 0x00, 0xc4, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x41, 0x02, 0x03, 0x1b, 0x81,
+ 0xe3, 0x05, 0x00, 0x20, 0x41, 0x10, 0xe2, 0x00, 0x4a, 0x6d, 0x03, 0x0c,
+ 0x00, 0x12, 0x34, 0x00, 0x44, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xd0
+};
+
+/*
+ * edid-decode (hex):
+ *
+ * 00 ff ff ff ff ff ff 00 31 d8 2a 00 00 00 00 00
+ * 00 21 01 03 81 a0 5a 78 1a 00 00 00 00 00 00 00
+ * 00 00 00 20 00 00 01 01 01 01 01 01 01 01 01 01
+ * 01 01 01 01 01 01 02 3a 80 18 71 38 2d 40 58 2c
+ * 45 00 40 84 63 00 00 1e 00 00 00 fc 00 54 65 73
+ * 74 20 45 44 49 44 0a 20 20 20 00 00 00 fd 00 32
+ * 46 1e 46 0f 00 0a 20 20 20 20 20 20 00 00 00 10
+ * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 7a
+ *
+ * 02 03 1b b1 e3 05 00 20 41 10 e2 00 ca 6d 03 0c
+ * 00 12 34 78 28 20 00 00 00 00 00 00 00 00 00 00
+ * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 a8
+ *
+ * ----------------
+ *
+ * Block 0, Base EDID:
+ * EDID Structure Version & Revision: 1.3
+ * Vendor & Product Identification:
+ * Manufacturer: LNX
+ * Model: 42
+ * Made in: 2023
+ * Basic Display Parameters & Features:
+ * Digital display
+ * DFP 1.x compatible TMDS
+ * Maximum image size: 160 cm x 90 cm
+ * Gamma: 2.20
+ * Undefined display color type
+ * First detailed timing is the preferred timing
+ * Color Characteristics:
+ * Red : 0.0000, 0.0000
+ * Green: 0.0000, 0.0000
+ * Blue : 0.0000, 0.0000
+ * White: 0.0000, 0.0000
+ * Established Timings I & II:
+ * DMT 0x04: 640x480 59.940476 Hz 4:3 31.469 kHz 25.175000 MHz
+ * Standard Timings: none
+ * Detailed Timing Descriptors:
+ * DTD 1: 1920x1080 60.000000 Hz 16:9 67.500 kHz 148.500000 MHz (1600 mm x 900 mm)
+ * Hfront 88 Hsync 44 Hback 148 Hpol P
+ * Vfront 4 Vsync 5 Vback 36 Vpol P
+ * Display Product Name: 'Test EDID'
+ * Display Range Limits:
+ * Monitor ranges (GTF): 50-70 Hz V, 30-70 kHz H, max dotclock 150 MHz
+ * Dummy Descriptor:
+ * Extension blocks: 1
+ * Checksum: 0x7a
+ *
+ * ----------------
+ *
+ * Block 1, CTA-861 Extension Block:
+ * Revision: 3
+ * Underscans IT Video Formats by default
+ * Supports YCbCr 4:4:4
+ * Supports YCbCr 4:2:2
+ * Native detailed modes: 1
+ * Colorimetry Data Block:
+ * sRGB
+ * Video Data Block:
+ * VIC 16: 1920x1080 60.000000 Hz 16:9 67.500 kHz 148.500000 MHz
+ * Video Capability Data Block:
+ * YCbCr quantization: Selectable (via AVI YQ)
+ * RGB quantization: Selectable (via AVI Q)
+ * PT scan behavior: No Data
+ * IT scan behavior: Always Underscanned
+ * CE scan behavior: Always Underscanned
+ * Vendor-Specific Data Block (HDMI), OUI 00-0C-03:
+ * Source physical address: 1.2.3.4
+ * DC_48bit
+ * DC_36bit
+ * DC_30bit
+ * DC_Y444
+ * Maximum TMDS clock: 200 MHz
+ * Extended HDMI video details:
+ * Checksum: 0xa8 Unused space in Extension Block: 100 bytes
+ */
+static const unsigned char test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz[] = {
+ 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x31, 0xd8, 0x2a, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x01, 0x03, 0x81, 0xa0, 0x5a, 0x78,
+ 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38,
+ 0x2d, 0x40, 0x58, 0x2c, 0x45, 0x00, 0x40, 0x84, 0x63, 0x00, 0x00, 0x1e,
+ 0x00, 0x00, 0x00, 0xfc, 0x00, 0x54, 0x65, 0x73, 0x74, 0x20, 0x45, 0x44,
+ 0x49, 0x44, 0x0a, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x32,
+ 0x46, 0x1e, 0x46, 0x0f, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x7a, 0x02, 0x03, 0x1b, 0xb1,
+ 0xe3, 0x05, 0x00, 0x20, 0x41, 0x10, 0xe2, 0x00, 0xca, 0x6d, 0x03, 0x0c,
+ 0x00, 0x12, 0x34, 0x78, 0x28, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xa8
+};
+
+/*
+ * edid-decode (hex):
+ *
+ * 00 ff ff ff ff ff ff 00 31 d8 2a 00 00 00 00 00
+ * 00 21 01 03 81 a0 5a 78 0a 00 00 00 00 00 00 00
+ * 00 00 00 20 00 00 01 01 01 01 01 01 01 01 01 01
+ * 01 01 01 01 01 01 02 3a 80 18 71 38 2d 40 58 2c
+ * 45 00 40 84 63 00 00 1e 00 00 00 fc 00 54 65 73
+ * 74 20 45 44 49 44 0a 20 20 20 00 00 00 fd 00 32
+ * 46 1e 46 0f 00 0a 20 20 20 20 20 20 00 00 00 10
+ * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 8a
+ *
+ * 02 03 1b b1 e3 05 00 20 41 10 e2 00 ca 6d 03 0c
+ * 00 12 34 78 44 20 00 00 00 00 00 00 00 00 00 00
+ * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 8c
+ *
+ * ----------------
+ *
+ * Block 0, Base EDID:
+ * EDID Structure Version & Revision: 1.3
+ * Vendor & Product Identification:
+ * Manufacturer: LNX
+ * Model: 42
+ * Made in: 2023
+ * Basic Display Parameters & Features:
+ * Digital display
+ * DFP 1.x compatible TMDS
+ * Maximum image size: 160 cm x 90 cm
+ * Gamma: 2.20
+ * RGB color display
+ * First detailed timing is the preferred timing
+ * Color Characteristics:
+ * Red : 0.0000, 0.0000
+ * Green: 0.0000, 0.0000
+ * Blue : 0.0000, 0.0000
+ * White: 0.0000, 0.0000
+ * Established Timings I & II:
+ * DMT 0x04: 640x480 59.940476 Hz 4:3 31.469 kHz 25.175000 MHz
+ * Standard Timings: none
+ * Detailed Timing Descriptors:
+ * DTD 1: 1920x1080 60.000000 Hz 16:9 67.500 kHz 148.500000 MHz (1600 mm x 900 mm)
+ * Hfront 88 Hsync 44 Hback 148 Hpol P
+ * Vfront 4 Vsync 5 Vback 36 Vpol P
+ * Display Product Name: 'Test EDID'
+ * Display Range Limits:
+ * Monitor ranges (GTF): 50-70 Hz V, 30-70 kHz H, max dotclock 150 MHz
+ * Dummy Descriptor:
+ * Extension blocks: 1
+ * Checksum: 0x8a
+ *
+ * ----------------
+ *
+ * Block 1, CTA-861 Extension Block:
+ * Revision: 3
+ * Underscans IT Video Formats by default
+ * Supports YCbCr 4:4:4
+ * Supports YCbCr 4:2:2
+ * Native detailed modes: 1
+ * Colorimetry Data Block:
+ * sRGB
+ * Video Data Block:
+ * VIC 16: 1920x1080 60.000000 Hz 16:9 67.500 kHz 148.500000 MHz
+ * Video Capability Data Block:
+ * YCbCr quantization: Selectable (via AVI YQ)
+ * RGB quantization: Selectable (via AVI Q)
+ * PT scan behavior: No Data
+ * IT scan behavior: Always Underscanned
+ * CE scan behavior: Always Underscanned
+ * Vendor-Specific Data Block (HDMI), OUI 00-0C-03:
+ * Source physical address: 1.2.3.4
+ * DC_48bit
+ * DC_36bit
+ * DC_30bit
+ * DC_Y444
+ * Maximum TMDS clock: 340 MHz
+ * Extended HDMI video details:
+ * Checksum: 0x8c Unused space in Extension Block: 100 bytes
+ */
+static const unsigned char test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz[] = {
+ 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x31, 0xd8, 0x2a, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x01, 0x03, 0x81, 0xa0, 0x5a, 0x78,
+ 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38,
+ 0x2d, 0x40, 0x58, 0x2c, 0x45, 0x00, 0x40, 0x84, 0x63, 0x00, 0x00, 0x1e,
+ 0x00, 0x00, 0x00, 0xfc, 0x00, 0x54, 0x65, 0x73, 0x74, 0x20, 0x45, 0x44,
+ 0x49, 0x44, 0x0a, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x32,
+ 0x46, 0x1e, 0x46, 0x0f, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x8a, 0x02, 0x03, 0x1b, 0xb1,
+ 0xe3, 0x05, 0x00, 0x20, 0x41, 0x10, 0xe2, 0x00, 0xca, 0x6d, 0x03, 0x0c,
+ 0x00, 0x12, 0x34, 0x78, 0x44, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x8c
+};
+
+#endif // DRM_KUNIT_EDID_H_
diff --git a/drivers/gpu/drm/tests/drm_kunit_helpers.c b/drivers/gpu/drm/tests/drm_kunit_helpers.c
index d5317d13d3fc..aa62719dab0e 100644
--- a/drivers/gpu/drm/tests/drm_kunit_helpers.c
+++ b/drivers/gpu/drm/tests/drm_kunit_helpers.c
@@ -312,4 +312,5 @@ drm_kunit_helper_create_crtc(struct kunit *test,
EXPORT_SYMBOL_GPL(drm_kunit_helper_create_crtc);
MODULE_AUTHOR("Maxime Ripard <maxime@cerno.tech>");
+MODULE_DESCRIPTION("KUnit test suite helper functions");
MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tests/drm_managed_test.c b/drivers/gpu/drm/tests/drm_managed_test.c
index 76eb273c9b36..d40c7ef7f9e1 100644
--- a/drivers/gpu/drm/tests/drm_managed_test.c
+++ b/drivers/gpu/drm/tests/drm_managed_test.c
@@ -113,4 +113,5 @@ static struct kunit_suite drm_managed_test_suite = {
kunit_test_suite(drm_managed_test_suite);
MODULE_AUTHOR("Maxime Ripard <maxime@cerno.tech>");
+MODULE_DESCRIPTION("KUnit DRM managed test suite");
MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tests/drm_mm_test.c b/drivers/gpu/drm/tests/drm_mm_test.c
index 8497d9990b96..6174d0929020 100644
--- a/drivers/gpu/drm/tests/drm_mm_test.c
+++ b/drivers/gpu/drm/tests/drm_mm_test.c
@@ -356,4 +356,5 @@ static struct kunit_suite drm_mm_test_suite = {
kunit_test_suite(drm_mm_test_suite);
MODULE_AUTHOR("Intel Corporation");
+MODULE_DESCRIPTION("Test cases for the drm_mm range manager");
MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tests/drm_modes_test.c b/drivers/gpu/drm/tests/drm_modes_test.c
index 1e9f63fbfead..6ed51f99e133 100644
--- a/drivers/gpu/drm/tests/drm_modes_test.c
+++ b/drivers/gpu/drm/tests/drm_modes_test.c
@@ -130,7 +130,38 @@ static void drm_test_modes_analog_tv_pal_576i_inlined(struct kunit *test)
KUNIT_EXPECT_TRUE(test, drm_mode_equal(expected, mode));
}
+static void drm_test_modes_analog_tv_mono_576i(struct kunit *test)
+{
+ struct drm_test_modes_priv *priv = test->priv;
+ struct drm_display_mode *mode;
+
+ mode = drm_analog_tv_mode(priv->drm,
+ DRM_MODE_TV_MODE_MONOCHROME,
+ 13500 * HZ_PER_KHZ, 720, 576,
+ true);
+ KUNIT_ASSERT_NOT_NULL(test, mode);
+
+ KUNIT_EXPECT_EQ(test, drm_mode_vrefresh(mode), 50);
+ KUNIT_EXPECT_EQ(test, mode->hdisplay, 720);
+
+ /* BT.601 defines hsync_start at 732 for 576i */
+ KUNIT_EXPECT_EQ(test, mode->hsync_start, 732);
+
+ /*
+ * The PAL standard expects a line to take 64us. With a pixel
+ * clock of 13.5 MHz, a pixel takes around 74ns, so we need to
+ * have 64000ns / 74ns = 864.
+ *
+ * This is also mandated by BT.601.
+ */
+ KUNIT_EXPECT_EQ(test, mode->htotal, 864);
+
+ KUNIT_EXPECT_EQ(test, mode->vdisplay, 576);
+ KUNIT_EXPECT_EQ(test, mode->vtotal, 625);
+}
+
static struct kunit_case drm_modes_analog_tv_tests[] = {
+ KUNIT_CASE(drm_test_modes_analog_tv_mono_576i),
KUNIT_CASE(drm_test_modes_analog_tv_ntsc_480i),
KUNIT_CASE(drm_test_modes_analog_tv_ntsc_480i_inlined),
KUNIT_CASE(drm_test_modes_analog_tv_pal_576i),
@@ -147,4 +178,5 @@ static struct kunit_suite drm_modes_analog_tv_test_suite = {
kunit_test_suite(drm_modes_analog_tv_test_suite);
MODULE_AUTHOR("Maxime Ripard <maxime@cerno.tech>");
+MODULE_DESCRIPTION("Kunit test for drm_modes functions");
MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tests/drm_plane_helper_test.c b/drivers/gpu/drm/tests/drm_plane_helper_test.c
index 0f392146b233..7e975a3f4a71 100644
--- a/drivers/gpu/drm/tests/drm_plane_helper_test.c
+++ b/drivers/gpu/drm/tests/drm_plane_helper_test.c
@@ -315,4 +315,5 @@ static struct kunit_suite drm_plane_helper_test_suite = {
kunit_test_suite(drm_plane_helper_test_suite);
+MODULE_DESCRIPTION("Test cases for the drm_plane_helper functions");
MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tests/drm_probe_helper_test.c b/drivers/gpu/drm/tests/drm_probe_helper_test.c
index 1a2044070a6c..bc09ff38aca1 100644
--- a/drivers/gpu/drm/tests/drm_probe_helper_test.c
+++ b/drivers/gpu/drm/tests/drm_probe_helper_test.c
@@ -207,4 +207,5 @@ static struct kunit_suite drm_test_connector_helper_tv_get_modes_suite = {
kunit_test_suite(drm_test_connector_helper_tv_get_modes_suite);
MODULE_AUTHOR("Maxime Ripard <maxime@cerno.tech>");
+MODULE_DESCRIPTION("Kunit test for drm_probe_helper functions");
MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tests/drm_rect_test.c b/drivers/gpu/drm/tests/drm_rect_test.c
index 76332cd2ead8..17e1f34b7610 100644
--- a/drivers/gpu/drm/tests/drm_rect_test.c
+++ b/drivers/gpu/drm/tests/drm_rect_test.c
@@ -526,4 +526,5 @@ static struct kunit_suite drm_rect_test_suite = {
kunit_test_suite(drm_rect_test_suite);
+MODULE_DESCRIPTION("Test cases for the drm_rect functions");
MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tidss/tidss_plane.c b/drivers/gpu/drm/tidss/tidss_plane.c
index 68fed531f6a7..a5d86822c9e3 100644
--- a/drivers/gpu/drm/tidss/tidss_plane.c
+++ b/drivers/gpu/drm/tidss/tidss_plane.c
@@ -8,6 +8,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_blend.h>
#include <drm/drm_crtc.h>
+#include <drm/drm_fb_dma_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_atomic_helper.h>
@@ -166,6 +167,14 @@ static const struct drm_plane_helper_funcs tidss_plane_helper_funcs = {
.atomic_disable = tidss_plane_atomic_disable,
};
+static const struct drm_plane_helper_funcs tidss_primary_plane_helper_funcs = {
+ .atomic_check = tidss_plane_atomic_check,
+ .atomic_update = tidss_plane_atomic_update,
+ .atomic_enable = tidss_plane_atomic_enable,
+ .atomic_disable = tidss_plane_atomic_disable,
+ .get_scanout_buffer = drm_fb_dma_get_scanout_buffer,
+};
+
static const struct drm_plane_funcs tidss_plane_funcs = {
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
@@ -211,7 +220,10 @@ struct tidss_plane *tidss_plane_create(struct tidss_device *tidss,
if (ret < 0)
goto err;
- drm_plane_helper_add(&tplane->plane, &tidss_plane_helper_funcs);
+ if (type == DRM_PLANE_TYPE_PRIMARY)
+ drm_plane_helper_add(&tplane->plane, &tidss_primary_plane_helper_funcs);
+ else
+ drm_plane_helper_add(&tplane->plane, &tidss_plane_helper_funcs);
drm_plane_create_zpos_property(&tplane->plane, tidss->num_planes, 0,
num_planes - 1);
diff --git a/drivers/gpu/drm/tiny/bochs.c b/drivers/gpu/drm/tiny/bochs.c
index c23c9f0cf49c..31fc5d839e10 100644
--- a/drivers/gpu/drm/tiny/bochs.c
+++ b/drivers/gpu/drm/tiny/bochs.c
@@ -7,7 +7,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
#include <drm/drm_edid.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_ttm.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_framebuffer_helper.h>
@@ -85,7 +85,7 @@ struct bochs_device {
u16 yres_virtual;
u32 stride;
u32 bpp;
- struct edid *edid;
+ const struct drm_edid *drm_edid;
/* drm */
struct drm_device *dev;
@@ -199,10 +199,10 @@ static int bochs_hw_load_edid(struct bochs_device *bochs)
if (drm_edid_header_is_valid(header) != 8)
return -1;
- kfree(bochs->edid);
- bochs->edid = drm_do_get_edid(&bochs->connector,
- bochs_get_edid_block, bochs);
- if (bochs->edid == NULL)
+ drm_edid_free(bochs->drm_edid);
+ bochs->drm_edid = drm_edid_read_custom(&bochs->connector,
+ bochs_get_edid_block, bochs);
+ if (!bochs->drm_edid)
return -1;
return 0;
@@ -303,7 +303,7 @@ static void bochs_hw_fini(struct drm_device *dev)
if (bochs->fb_map)
iounmap(bochs->fb_map);
pci_release_regions(to_pci_dev(dev->dev));
- kfree(bochs->edid);
+ drm_edid_free(bochs->drm_edid);
}
static void bochs_hw_blank(struct bochs_device *bochs, bool blank)
@@ -471,12 +471,9 @@ static const struct drm_simple_display_pipe_funcs bochs_pipe_funcs = {
static int bochs_connector_get_modes(struct drm_connector *connector)
{
- struct bochs_device *bochs =
- container_of(connector, struct bochs_device, connector);
- int count = 0;
+ int count;
- if (bochs->edid)
- count = drm_add_edid_modes(connector, bochs->edid);
+ count = drm_edid_connector_add_modes(connector);
if (!count) {
count = drm_add_modes_noedid(connector, 8192, 8192);
@@ -507,10 +504,10 @@ static void bochs_connector_init(struct drm_device *dev)
drm_connector_helper_add(connector, &bochs_connector_connector_helper_funcs);
bochs_hw_load_edid(bochs);
- if (bochs->edid) {
+ if (bochs->drm_edid) {
DRM_INFO("Found EDID data blob.\n");
drm_connector_attach_edid_property(connector);
- drm_connector_update_edid_property(connector, bochs->edid);
+ drm_edid_connector_update(&bochs->connector, bochs->drm_edid);
}
}
@@ -670,7 +667,7 @@ static int bochs_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent
if (ret)
goto err_hw_fini;
- drm_fbdev_generic_setup(dev, 32);
+ drm_fbdev_ttm_setup(dev, 32);
return ret;
err_hw_fini:
@@ -736,4 +733,5 @@ drm_module_pci_driver_if_modeset(bochs_pci_driver, bochs_modeset);
MODULE_DEVICE_TABLE(pci, bochs_pci_tbl);
MODULE_AUTHOR("Gerd Hoffmann <kraxel@redhat.com>");
+MODULE_DESCRIPTION("DRM Support for bochs dispi vga interface (qemu stdvga)");
MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tiny/cirrus.c b/drivers/gpu/drm/tiny/cirrus.c
index 4e3a152f897a..751326e3d9c3 100644
--- a/drivers/gpu/drm/tiny/cirrus.c
+++ b/drivers/gpu/drm/tiny/cirrus.c
@@ -31,7 +31,7 @@
#include <drm/drm_damage_helper.h>
#include <drm/drm_drv.h>
#include <drm/drm_edid.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_shmem.h>
#include <drm/drm_file.h>
#include <drm/drm_format_helper.h>
#include <drm/drm_fourcc.h>
@@ -716,7 +716,7 @@ static int cirrus_pci_probe(struct pci_dev *pdev,
if (ret)
return ret;
- drm_fbdev_generic_setup(dev, 16);
+ drm_fbdev_shmem_setup(dev, 16);
return 0;
}
@@ -760,4 +760,5 @@ static struct pci_driver cirrus_pci_driver = {
drm_module_pci_driver(cirrus_pci_driver)
MODULE_DEVICE_TABLE(pci, pciidlist);
+MODULE_DESCRIPTION("Cirrus driver for QEMU emulated device");
MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tiny/gm12u320.c b/drivers/gpu/drm/tiny/gm12u320.c
index 0187539ff5ea..e0defb1d134f 100644
--- a/drivers/gpu/drm/tiny/gm12u320.c
+++ b/drivers/gpu/drm/tiny/gm12u320.c
@@ -13,7 +13,7 @@
#include <drm/drm_damage_helper.h>
#include <drm/drm_drv.h>
#include <drm/drm_edid.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_shmem.h>
#include <drm/drm_file.h>
#include <drm/drm_format_helper.h>
#include <drm/drm_fourcc.h>
@@ -699,7 +699,7 @@ static int gm12u320_usb_probe(struct usb_interface *interface,
if (ret)
goto err_put_device;
- drm_fbdev_generic_setup(dev, 0);
+ drm_fbdev_shmem_setup(dev, 0);
return 0;
@@ -755,4 +755,5 @@ static struct usb_driver gm12u320_usb_driver = {
module_usb_driver(gm12u320_usb_driver);
MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
+MODULE_DESCRIPTION("GM12U320 driver for USB projectors");
MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tiny/hx8357d.c b/drivers/gpu/drm/tiny/hx8357d.c
index cdc4486e059b..2e631282edeb 100644
--- a/drivers/gpu/drm/tiny/hx8357d.c
+++ b/drivers/gpu/drm/tiny/hx8357d.c
@@ -18,7 +18,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_dma.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_managed.h>
@@ -256,7 +256,7 @@ static int hx8357d_probe(struct spi_device *spi)
spi_set_drvdata(spi, drm);
- drm_fbdev_generic_setup(drm, 0);
+ drm_fbdev_dma_setup(drm, 0);
return 0;
}
diff --git a/drivers/gpu/drm/tiny/ili9163.c b/drivers/gpu/drm/tiny/ili9163.c
index bc4384d410fc..86f9d8834901 100644
--- a/drivers/gpu/drm/tiny/ili9163.c
+++ b/drivers/gpu/drm/tiny/ili9163.c
@@ -9,7 +9,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_dma.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_mipi_dbi.h>
@@ -185,7 +185,7 @@ static int ili9163_probe(struct spi_device *spi)
if (ret)
return ret;
- drm_fbdev_generic_setup(drm, 0);
+ drm_fbdev_dma_setup(drm, 0);
return 0;
}
diff --git a/drivers/gpu/drm/tiny/ili9225.c b/drivers/gpu/drm/tiny/ili9225.c
index dd8b0a181be9..b6b7a49147bf 100644
--- a/drivers/gpu/drm/tiny/ili9225.c
+++ b/drivers/gpu/drm/tiny/ili9225.c
@@ -20,7 +20,7 @@
#include <drm/drm_damage_helper.h>
#include <drm/drm_drv.h>
#include <drm/drm_fb_dma_helper.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_dma.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_atomic_helper.h>
@@ -426,7 +426,7 @@ static int ili9225_probe(struct spi_device *spi)
spi_set_drvdata(spi, drm);
- drm_fbdev_generic_setup(drm, 0);
+ drm_fbdev_dma_setup(drm, 0);
return 0;
}
@@ -447,7 +447,6 @@ static void ili9225_shutdown(struct spi_device *spi)
static struct spi_driver ili9225_spi_driver = {
.driver = {
.name = "ili9225",
- .owner = THIS_MODULE,
.of_match_table = ili9225_of_match,
},
.id_table = ili9225_id,
diff --git a/drivers/gpu/drm/tiny/ili9341.c b/drivers/gpu/drm/tiny/ili9341.c
index 47b61c3bf145..8bcada30af71 100644
--- a/drivers/gpu/drm/tiny/ili9341.c
+++ b/drivers/gpu/drm/tiny/ili9341.c
@@ -17,7 +17,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_dma.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_managed.h>
@@ -218,7 +218,7 @@ static int ili9341_probe(struct spi_device *spi)
spi_set_drvdata(spi, drm);
- drm_fbdev_generic_setup(drm, 0);
+ drm_fbdev_dma_setup(drm, 0);
return 0;
}
diff --git a/drivers/gpu/drm/tiny/ili9486.c b/drivers/gpu/drm/tiny/ili9486.c
index 938bceed5999..70d366260041 100644
--- a/drivers/gpu/drm/tiny/ili9486.c
+++ b/drivers/gpu/drm/tiny/ili9486.c
@@ -16,7 +16,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_dma.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_managed.h>
@@ -247,7 +247,7 @@ static int ili9486_probe(struct spi_device *spi)
spi_set_drvdata(spi, drm);
- drm_fbdev_generic_setup(drm, 0);
+ drm_fbdev_dma_setup(drm, 0);
return 0;
}
diff --git a/drivers/gpu/drm/tiny/mi0283qt.c b/drivers/gpu/drm/tiny/mi0283qt.c
index 01ff43c8ac3f..cdc5423990ca 100644
--- a/drivers/gpu/drm/tiny/mi0283qt.c
+++ b/drivers/gpu/drm/tiny/mi0283qt.c
@@ -15,7 +15,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_dma.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_managed.h>
@@ -226,7 +226,7 @@ static int mi0283qt_probe(struct spi_device *spi)
spi_set_drvdata(spi, drm);
- drm_fbdev_generic_setup(drm, 0);
+ drm_fbdev_dma_setup(drm, 0);
return 0;
}
@@ -263,7 +263,6 @@ static const struct dev_pm_ops mi0283qt_pm_ops = {
static struct spi_driver mi0283qt_spi_driver = {
.driver = {
.name = "mi0283qt",
- .owner = THIS_MODULE,
.of_match_table = mi0283qt_of_match,
.pm = &mi0283qt_pm_ops,
},
diff --git a/drivers/gpu/drm/tiny/ofdrm.c b/drivers/gpu/drm/tiny/ofdrm.c
index ab89b7fc7bf6..35996f7eedac 100644
--- a/drivers/gpu/drm/tiny/ofdrm.c
+++ b/drivers/gpu/drm/tiny/ofdrm.c
@@ -11,7 +11,7 @@
#include <drm/drm_damage_helper.h>
#include <drm/drm_device.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_shmem.h>
#include <drm/drm_format_helper.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_atomic_helper.h>
@@ -1377,7 +1377,7 @@ static int ofdrm_probe(struct platform_device *pdev)
if (color_mode == 16)
color_mode = odev->format->depth; // can be 15 or 16
- drm_fbdev_generic_setup(dev, color_mode);
+ drm_fbdev_shmem_setup(dev, color_mode);
return 0;
}
diff --git a/drivers/gpu/drm/tiny/panel-mipi-dbi.c b/drivers/gpu/drm/tiny/panel-mipi-dbi.c
index f80a141fcf36..f753cdffe6f8 100644
--- a/drivers/gpu/drm/tiny/panel-mipi-dbi.c
+++ b/drivers/gpu/drm/tiny/panel-mipi-dbi.c
@@ -16,7 +16,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_dma.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_managed.h>
@@ -26,6 +26,49 @@
#include <video/mipi_display.h>
+struct panel_mipi_dbi_format {
+ const char *name;
+ u32 fourcc;
+ unsigned int bpp;
+};
+
+static const struct panel_mipi_dbi_format panel_mipi_dbi_formats[] = {
+ { "r5g6b5", DRM_FORMAT_RGB565, 16 },
+ { "b6x2g6x2r6x2", DRM_FORMAT_RGB888, 24 },
+};
+
+static int panel_mipi_dbi_get_format(struct device *dev, u32 *formats, unsigned int *bpp)
+{
+ const char *format_name;
+ unsigned int i;
+ int ret;
+
+ formats[1] = DRM_FORMAT_XRGB8888;
+
+ ret = device_property_read_string(dev, "format", &format_name);
+ if (ret) {
+ /* Old Device Trees don't have this property */
+ formats[0] = DRM_FORMAT_RGB565;
+ *bpp = 16;
+ return 0;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(panel_mipi_dbi_formats); i++) {
+ const struct panel_mipi_dbi_format *format = &panel_mipi_dbi_formats[i];
+
+ if (strcmp(format_name, format->name))
+ continue;
+
+ formats[0] = format->fourcc;
+ *bpp = format->bpp;
+ return 0;
+ }
+
+ dev_err(dev, "Pixel format is not supported: '%s'\n", format_name);
+
+ return -EINVAL;
+}
+
static const u8 panel_mipi_dbi_magic[15] = { 'M', 'I', 'P', 'I', ' ', 'D', 'B', 'I',
0, 0, 0, 0, 0, 0, 0 };
@@ -276,6 +319,9 @@ static int panel_mipi_dbi_spi_probe(struct spi_device *spi)
struct drm_device *drm;
struct mipi_dbi *dbi;
struct gpio_desc *dc;
+ unsigned int bpp;
+ size_t buf_size;
+ u32 formats[2];
int ret;
dbidev = devm_drm_dev_alloc(dev, &panel_mipi_dbi_driver, struct mipi_dbi_dev, drm);
@@ -323,7 +369,14 @@ static int panel_mipi_dbi_spi_probe(struct spi_device *spi)
if (IS_ERR(dbidev->driver_private))
return PTR_ERR(dbidev->driver_private);
- ret = mipi_dbi_dev_init(dbidev, &panel_mipi_dbi_pipe_funcs, &mode, 0);
+ ret = panel_mipi_dbi_get_format(dev, formats, &bpp);
+ if (ret)
+ 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);
if (ret)
return ret;
@@ -335,7 +388,7 @@ static int panel_mipi_dbi_spi_probe(struct spi_device *spi)
spi_set_drvdata(spi, drm);
- drm_fbdev_generic_setup(drm, 0);
+ drm_fbdev_dma_setup(drm, 0);
return 0;
}
@@ -384,7 +437,6 @@ MODULE_DEVICE_TABLE(spi, panel_mipi_dbi_spi_id);
static struct spi_driver panel_mipi_dbi_spi_driver = {
.driver = {
.name = "panel-mipi-dbi-spi",
- .owner = THIS_MODULE,
.of_match_table = panel_mipi_dbi_spi_of_match,
.pm = &panel_mipi_dbi_pm_ops,
},
diff --git a/drivers/gpu/drm/tiny/repaper.c b/drivers/gpu/drm/tiny/repaper.c
index 8fd6758f5725..1f78aa3d26bb 100644
--- a/drivers/gpu/drm/tiny/repaper.c
+++ b/drivers/gpu/drm/tiny/repaper.c
@@ -26,7 +26,7 @@
#include <drm/drm_damage_helper.h>
#include <drm/drm_drv.h>
#include <drm/drm_fb_dma_helper.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_dma.h>
#include <drm/drm_format_helper.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_atomic_helper.h>
@@ -1118,7 +1118,7 @@ static int repaper_probe(struct spi_device *spi)
DRM_DEBUG_DRIVER("SPI speed: %uMHz\n", spi->max_speed_hz / 1000000);
- drm_fbdev_generic_setup(drm, 0);
+ drm_fbdev_dma_setup(drm, 0);
return 0;
}
diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c
index 1d8fa07572c5..d19e10289428 100644
--- a/drivers/gpu/drm/tiny/simpledrm.c
+++ b/drivers/gpu/drm/tiny/simpledrm.c
@@ -17,7 +17,7 @@
#include <drm/drm_damage_helper.h>
#include <drm/drm_device.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_shmem.h>
#include <drm/drm_format_helper.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_atomic_helper.h>
@@ -1042,7 +1042,7 @@ static int simpledrm_probe(struct platform_device *pdev)
if (color_mode == 16)
color_mode = sdev->format->depth; // can be 15 or 16
- drm_fbdev_generic_setup(dev, color_mode);
+ drm_fbdev_shmem_setup(dev, color_mode);
return 0;
}
diff --git a/drivers/gpu/drm/tiny/st7586.c b/drivers/gpu/drm/tiny/st7586.c
index 7336fa1ddaed..b9c6ed352182 100644
--- a/drivers/gpu/drm/tiny/st7586.c
+++ b/drivers/gpu/drm/tiny/st7586.c
@@ -16,7 +16,7 @@
#include <drm/drm_damage_helper.h>
#include <drm/drm_drv.h>
#include <drm/drm_fb_dma_helper.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_dma.h>
#include <drm/drm_format_helper.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_atomic_helper.h>
@@ -371,7 +371,7 @@ static int st7586_probe(struct spi_device *spi)
spi_set_drvdata(spi, drm);
- drm_fbdev_generic_setup(drm, 0);
+ drm_fbdev_dma_setup(drm, 0);
return 0;
}
@@ -392,7 +392,6 @@ static void st7586_shutdown(struct spi_device *spi)
static struct spi_driver st7586_spi_driver = {
.driver = {
.name = "st7586",
- .owner = THIS_MODULE,
.of_match_table = st7586_of_match,
},
.id_table = st7586_id,
diff --git a/drivers/gpu/drm/tiny/st7735r.c b/drivers/gpu/drm/tiny/st7735r.c
index 477eb36fbb70..1676da00883d 100644
--- a/drivers/gpu/drm/tiny/st7735r.c
+++ b/drivers/gpu/drm/tiny/st7735r.c
@@ -18,7 +18,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_dma.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_managed.h>
@@ -241,7 +241,7 @@ static int st7735r_probe(struct spi_device *spi)
spi_set_drvdata(spi, drm);
- drm_fbdev_generic_setup(drm, 0);
+ drm_fbdev_dma_setup(drm, 0);
return 0;
}
diff --git a/drivers/gpu/drm/ttm/tests/.kunitconfig b/drivers/gpu/drm/ttm/tests/.kunitconfig
index 75fdce0cd98e..1ae1ffabd51e 100644
--- a/drivers/gpu/drm/ttm/tests/.kunitconfig
+++ b/drivers/gpu/drm/ttm/tests/.kunitconfig
@@ -1,4 +1,3 @@
CONFIG_KUNIT=y
CONFIG_DRM=y
-CONFIG_DRM_KUNIT_TEST_HELPERS=y
CONFIG_DRM_TTM_KUNIT_TEST=y
diff --git a/drivers/gpu/drm/ttm/tests/Makefile b/drivers/gpu/drm/ttm/tests/Makefile
index 468535f7eed2..f3149de77541 100644
--- a/drivers/gpu/drm/ttm/tests/Makefile
+++ b/drivers/gpu/drm/ttm/tests/Makefile
@@ -6,4 +6,6 @@ obj-$(CONFIG_DRM_TTM_KUNIT_TEST) += \
ttm_resource_test.o \
ttm_tt_test.o \
ttm_bo_test.o \
+ ttm_bo_validate_test.o \
+ ttm_mock_manager.o \
ttm_kunit_helpers.o
diff --git a/drivers/gpu/drm/ttm/tests/TODO b/drivers/gpu/drm/ttm/tests/TODO
new file mode 100644
index 000000000000..45b03d184ccf
--- /dev/null
+++ b/drivers/gpu/drm/ttm/tests/TODO
@@ -0,0 +1,27 @@
+TODO
+=====
+
+- Add a test case where the only evictable BO is busy
+- Update eviction tests so they use parametrized "from" memory type
+- Improve mock manager's implementation, e.g. allocate a block of
+ dummy memory that can be used when testing page mapping functions
+- Suggestion: Add test cases with external BOs
+- Suggestion: randomize the number and size of tested buffers in
+ ttm_bo_validate()
+- Agree on the naming convention
+- Rewrite the mock manager: drop use_tt and manage mock memory using
+ drm_mm manager
+
+Notes and gotchas
+=================
+
+- These tests are built and run with a UML kernel, because
+ 1) We are interested in hardware-independent testing
+ 2) We don't want to have actual DRM devices interacting with TTM
+ at the same time as the test one. Getting these to work in
+ parallel would require some time (...and that's a "todo" in itself!)
+- Triggering ttm_bo_vm_ops callbacks from KUnit (i.e. kernel) might be
+ a challenge, but is worth trying. Look at selftests like
+ i915/gem/selftests/i915_gem_mman.c for inspiration
+- The test suite uses UML where ioremap() call returns NULL, meaning that
+ ttm_bo_ioremap() can't be tested, unless we find a way to stub it
diff --git a/drivers/gpu/drm/ttm/tests/ttm_bo_test.c b/drivers/gpu/drm/ttm/tests/ttm_bo_test.c
index 1f8a4f8adc92..d1b32303d051 100644
--- a/drivers/gpu/drm/ttm/tests/ttm_bo_test.c
+++ b/drivers/gpu/drm/ttm/tests/ttm_bo_test.c
@@ -18,6 +18,12 @@
#define BO_SIZE SZ_8K
+#ifdef CONFIG_PREEMPT_RT
+#define ww_mutex_base_lock(b) rt_mutex_lock(b)
+#else
+#define ww_mutex_base_lock(b) mutex_lock(b)
+#endif
+
struct ttm_bo_test_case {
const char *description;
bool interruptible;
@@ -56,7 +62,7 @@ static void ttm_bo_reserve_optimistic_no_ticket(struct kunit *test)
struct ttm_buffer_object *bo;
int err;
- bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+ bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
err = ttm_bo_reserve(bo, params->interruptible, params->no_wait, NULL);
KUNIT_ASSERT_EQ(test, err, 0);
@@ -71,7 +77,7 @@ static void ttm_bo_reserve_locked_no_sleep(struct kunit *test)
bool no_wait = true;
int err;
- bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+ bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
/* Let's lock it beforehand */
dma_resv_lock(bo->base.resv, NULL);
@@ -92,7 +98,7 @@ static void ttm_bo_reserve_no_wait_ticket(struct kunit *test)
ww_acquire_init(&ctx, &reservation_ww_class);
- bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+ bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
err = ttm_bo_reserve(bo, interruptible, no_wait, &ctx);
KUNIT_ASSERT_EQ(test, err, -EBUSY);
@@ -110,7 +116,7 @@ static void ttm_bo_reserve_double_resv(struct kunit *test)
ww_acquire_init(&ctx, &reservation_ww_class);
- bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+ bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
err = ttm_bo_reserve(bo, interruptible, no_wait, &ctx);
KUNIT_ASSERT_EQ(test, err, 0);
@@ -138,11 +144,11 @@ static void ttm_bo_reserve_deadlock(struct kunit *test)
bool no_wait = false;
int err;
- bo1 = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
- bo2 = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+ bo1 = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
+ bo2 = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
ww_acquire_init(&ctx1, &reservation_ww_class);
- mutex_lock(&bo2->base.resv->lock.base);
+ ww_mutex_base_lock(&bo2->base.resv->lock.base);
/* The deadlock will be caught by WW mutex, don't warn about it */
lock_release(&bo2->base.resv->lock.base.dep_map, 1);
@@ -208,7 +214,7 @@ static void ttm_bo_reserve_interrupted(struct kunit *test)
struct task_struct *task;
int err;
- bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+ bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
task = kthread_create(threaded_ttm_bo_reserve, bo, "ttm-bo-reserve");
@@ -237,7 +243,7 @@ static void ttm_bo_unreserve_basic(struct kunit *test)
struct ttm_place *place;
struct ttm_resource_manager *man;
unsigned int bo_prio = TTM_MAX_BO_PRIORITY - 1;
- uint32_t mem_type = TTM_PL_SYSTEM;
+ u32 mem_type = TTM_PL_SYSTEM;
int err;
place = ttm_place_kunit_init(test, mem_type, 0);
@@ -249,7 +255,7 @@ static void ttm_bo_unreserve_basic(struct kunit *test)
KUNIT_ASSERT_EQ(test, err, 0);
priv->ttm_dev = ttm_dev;
- bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+ bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
bo->priority = bo_prio;
err = ttm_resource_alloc(bo, place, &res1);
@@ -278,7 +284,7 @@ static void ttm_bo_unreserve_pinned(struct kunit *test)
struct ttm_device *ttm_dev;
struct ttm_resource *res1, *res2;
struct ttm_place *place;
- uint32_t mem_type = TTM_PL_SYSTEM;
+ u32 mem_type = TTM_PL_SYSTEM;
int err;
ttm_dev = kunit_kzalloc(test, sizeof(*ttm_dev), GFP_KERNEL);
@@ -288,7 +294,7 @@ static void ttm_bo_unreserve_pinned(struct kunit *test)
KUNIT_ASSERT_EQ(test, err, 0);
priv->ttm_dev = ttm_dev;
- bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+ bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
place = ttm_place_kunit_init(test, mem_type, 0);
dma_resv_lock(bo->base.resv, NULL);
@@ -321,7 +327,8 @@ static void ttm_bo_unreserve_bulk(struct kunit *test)
struct ttm_resource *res1, *res2;
struct ttm_device *ttm_dev;
struct ttm_place *place;
- uint32_t mem_type = TTM_PL_SYSTEM;
+ struct dma_resv *resv;
+ u32 mem_type = TTM_PL_SYSTEM;
unsigned int bo_priority = 0;
int err;
@@ -332,12 +339,17 @@ static void ttm_bo_unreserve_bulk(struct kunit *test)
ttm_dev = kunit_kzalloc(test, sizeof(*ttm_dev), GFP_KERNEL);
KUNIT_ASSERT_NOT_NULL(test, ttm_dev);
+ resv = kunit_kzalloc(test, sizeof(*resv), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, ttm_dev);
+
err = ttm_device_kunit_init(priv, ttm_dev, false, false);
KUNIT_ASSERT_EQ(test, err, 0);
priv->ttm_dev = ttm_dev;
- bo1 = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
- bo2 = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+ dma_resv_init(resv);
+
+ bo1 = ttm_bo_kunit_init(test, test->priv, BO_SIZE, resv);
+ bo2 = ttm_bo_kunit_init(test, test->priv, BO_SIZE, resv);
dma_resv_lock(bo1->base.resv, NULL);
ttm_bo_set_bulk_move(bo1, &lru_bulk_move);
@@ -363,6 +375,8 @@ static void ttm_bo_unreserve_bulk(struct kunit *test)
ttm_resource_free(bo1, &res1);
ttm_resource_free(bo2, &res2);
+
+ dma_resv_fini(resv);
}
static void ttm_bo_put_basic(struct kunit *test)
@@ -372,7 +386,7 @@ static void ttm_bo_put_basic(struct kunit *test)
struct ttm_resource *res;
struct ttm_device *ttm_dev;
struct ttm_place *place;
- uint32_t mem_type = TTM_PL_SYSTEM;
+ u32 mem_type = TTM_PL_SYSTEM;
int err;
place = ttm_place_kunit_init(test, mem_type, 0);
@@ -384,7 +398,7 @@ static void ttm_bo_put_basic(struct kunit *test)
KUNIT_ASSERT_EQ(test, err, 0);
priv->ttm_dev = ttm_dev;
- bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+ bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
bo->type = ttm_bo_type_device;
err = ttm_resource_alloc(bo, place, &res);
@@ -445,7 +459,7 @@ static void ttm_bo_put_shared_resv(struct kunit *test)
dma_fence_signal(fence);
- bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+ bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
bo->type = ttm_bo_type_device;
bo->base.resv = external_resv;
@@ -467,7 +481,7 @@ static void ttm_bo_pin_basic(struct kunit *test)
KUNIT_ASSERT_EQ(test, err, 0);
priv->ttm_dev = ttm_dev;
- bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+ bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
for (int i = 0; i < no_pins; i++) {
dma_resv_lock(bo->base.resv, NULL);
@@ -487,7 +501,7 @@ static void ttm_bo_pin_unpin_resource(struct kunit *test)
struct ttm_resource *res;
struct ttm_device *ttm_dev;
struct ttm_place *place;
- uint32_t mem_type = TTM_PL_SYSTEM;
+ u32 mem_type = TTM_PL_SYSTEM;
unsigned int bo_priority = 0;
int err;
@@ -502,7 +516,7 @@ static void ttm_bo_pin_unpin_resource(struct kunit *test)
KUNIT_ASSERT_EQ(test, err, 0);
priv->ttm_dev = ttm_dev;
- bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+ bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
err = ttm_resource_alloc(bo, place, &res);
KUNIT_ASSERT_EQ(test, err, 0);
@@ -538,7 +552,7 @@ static void ttm_bo_multiple_pin_one_unpin(struct kunit *test)
struct ttm_resource *res;
struct ttm_device *ttm_dev;
struct ttm_place *place;
- uint32_t mem_type = TTM_PL_SYSTEM;
+ u32 mem_type = TTM_PL_SYSTEM;
unsigned int bo_priority = 0;
int err;
@@ -553,7 +567,7 @@ static void ttm_bo_multiple_pin_one_unpin(struct kunit *test)
KUNIT_ASSERT_EQ(test, err, 0);
priv->ttm_dev = ttm_dev;
- bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+ bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
err = ttm_resource_alloc(bo, place, &res);
KUNIT_ASSERT_EQ(test, err, 0);
@@ -619,4 +633,5 @@ static struct kunit_suite ttm_bo_test_suite = {
kunit_test_suites(&ttm_bo_test_suite);
-MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("KUnit tests for ttm_bo APIs");
+MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c b/drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c
new file mode 100644
index 000000000000..1adf18481ea0
--- /dev/null
+++ b/drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c
@@ -0,0 +1,1225 @@
+// SPDX-License-Identifier: GPL-2.0 AND MIT
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+#include <linux/delay.h>
+#include <linux/kthread.h>
+
+#include <drm/ttm/ttm_resource.h>
+#include <drm/ttm/ttm_placement.h>
+#include <drm/ttm/ttm_tt.h>
+
+#include "ttm_kunit_helpers.h"
+#include "ttm_mock_manager.h"
+
+#define BO_SIZE SZ_4K
+#define MANAGER_SIZE SZ_1M
+
+static struct spinlock fence_lock;
+
+struct ttm_bo_validate_test_case {
+ const char *description;
+ enum ttm_bo_type bo_type;
+ u32 mem_type;
+ bool with_ttm;
+ bool no_gpu_wait;
+};
+
+static struct ttm_placement *ttm_placement_kunit_init(struct kunit *test,
+ struct ttm_place *places,
+ unsigned int num_places)
+{
+ struct ttm_placement *placement;
+
+ placement = kunit_kzalloc(test, sizeof(*placement), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, placement);
+
+ placement->num_placement = num_places;
+ placement->placement = places;
+
+ return placement;
+}
+
+static const char *fence_name(struct dma_fence *f)
+{
+ return "ttm-bo-validate-fence";
+}
+
+static const struct dma_fence_ops fence_ops = {
+ .get_driver_name = fence_name,
+ .get_timeline_name = fence_name,
+};
+
+static struct dma_fence *alloc_mock_fence(struct kunit *test)
+{
+ struct dma_fence *fence;
+
+ fence = kunit_kzalloc(test, sizeof(*fence), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, fence);
+
+ dma_fence_init(fence, &fence_ops, &fence_lock, 0, 0);
+
+ return fence;
+}
+
+static void dma_resv_kunit_active_fence_init(struct kunit *test,
+ struct dma_resv *resv,
+ enum dma_resv_usage usage)
+{
+ struct dma_fence *fence;
+
+ fence = alloc_mock_fence(test);
+ dma_fence_enable_sw_signaling(fence);
+
+ dma_resv_lock(resv, NULL);
+ dma_resv_reserve_fences(resv, 1);
+ dma_resv_add_fence(resv, fence, usage);
+ dma_resv_unlock(resv);
+}
+
+static void ttm_bo_validate_case_desc(const struct ttm_bo_validate_test_case *t,
+ char *desc)
+{
+ strscpy(desc, t->description, KUNIT_PARAM_DESC_SIZE);
+}
+
+static const struct ttm_bo_validate_test_case ttm_bo_type_cases[] = {
+ {
+ .description = "Buffer object for userspace",
+ .bo_type = ttm_bo_type_device,
+ },
+ {
+ .description = "Kernel buffer object",
+ .bo_type = ttm_bo_type_kernel,
+ },
+ {
+ .description = "Shared buffer object",
+ .bo_type = ttm_bo_type_sg,
+ },
+};
+
+KUNIT_ARRAY_PARAM(ttm_bo_types, ttm_bo_type_cases,
+ ttm_bo_validate_case_desc);
+
+static void ttm_bo_init_reserved_sys_man(struct kunit *test)
+{
+ const struct ttm_bo_validate_test_case *params = test->param_value;
+ struct ttm_test_devices *priv = test->priv;
+ enum ttm_bo_type bo_type = params->bo_type;
+ u32 size = ALIGN(BO_SIZE, PAGE_SIZE);
+ struct ttm_operation_ctx ctx = { };
+ struct ttm_placement *placement;
+ struct ttm_buffer_object *bo;
+ struct ttm_place *place;
+ int err;
+
+ bo = kunit_kzalloc(test, sizeof(*bo), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, bo);
+
+ place = ttm_place_kunit_init(test, TTM_PL_SYSTEM, 0);
+ placement = ttm_placement_kunit_init(test, place, 1);
+
+ drm_gem_private_object_init(priv->drm, &bo->base, size);
+
+ err = ttm_bo_init_reserved(priv->ttm_dev, bo, bo_type, placement,
+ PAGE_SIZE, &ctx, NULL, NULL,
+ &dummy_ttm_bo_destroy);
+ dma_resv_unlock(bo->base.resv);
+
+ KUNIT_EXPECT_EQ(test, err, 0);
+ KUNIT_EXPECT_EQ(test, kref_read(&bo->kref), 1);
+ KUNIT_EXPECT_PTR_EQ(test, bo->bdev, priv->ttm_dev);
+ KUNIT_EXPECT_EQ(test, bo->type, bo_type);
+ KUNIT_EXPECT_EQ(test, bo->page_alignment, PAGE_SIZE);
+ KUNIT_EXPECT_PTR_EQ(test, bo->destroy, &dummy_ttm_bo_destroy);
+ KUNIT_EXPECT_EQ(test, bo->pin_count, 0);
+ KUNIT_EXPECT_NULL(test, bo->bulk_move);
+ KUNIT_EXPECT_NOT_NULL(test, bo->ttm);
+ KUNIT_EXPECT_FALSE(test, ttm_tt_is_populated(bo->ttm));
+ KUNIT_EXPECT_NOT_NULL(test, (void *)bo->base.resv->fences);
+ KUNIT_EXPECT_EQ(test, ctx.bytes_moved, size);
+
+ if (bo_type != ttm_bo_type_kernel)
+ KUNIT_EXPECT_TRUE(test,
+ drm_mm_node_allocated(&bo->base.vma_node.vm_node));
+
+ ttm_resource_free(bo, &bo->resource);
+ ttm_bo_put(bo);
+}
+
+static void ttm_bo_init_reserved_mock_man(struct kunit *test)
+{
+ const struct ttm_bo_validate_test_case *params = test->param_value;
+ enum ttm_bo_type bo_type = params->bo_type;
+ struct ttm_test_devices *priv = test->priv;
+ u32 size = ALIGN(BO_SIZE, PAGE_SIZE);
+ struct ttm_operation_ctx ctx = { };
+ struct ttm_placement *placement;
+ u32 mem_type = TTM_PL_VRAM;
+ struct ttm_buffer_object *bo;
+ struct ttm_place *place;
+ int err;
+
+ ttm_mock_manager_init(priv->ttm_dev, mem_type, MANAGER_SIZE);
+
+ bo = kunit_kzalloc(test, sizeof(*bo), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, bo);
+
+ place = ttm_place_kunit_init(test, mem_type, 0);
+ placement = ttm_placement_kunit_init(test, place, 1);
+
+ drm_gem_private_object_init(priv->drm, &bo->base, size);
+
+ err = ttm_bo_init_reserved(priv->ttm_dev, bo, bo_type, placement,
+ PAGE_SIZE, &ctx, NULL, NULL,
+ &dummy_ttm_bo_destroy);
+ dma_resv_unlock(bo->base.resv);
+
+ KUNIT_EXPECT_EQ(test, err, 0);
+ KUNIT_EXPECT_EQ(test, kref_read(&bo->kref), 1);
+ KUNIT_EXPECT_PTR_EQ(test, bo->bdev, priv->ttm_dev);
+ KUNIT_EXPECT_EQ(test, bo->type, bo_type);
+ KUNIT_EXPECT_EQ(test, ctx.bytes_moved, size);
+
+ if (bo_type != ttm_bo_type_kernel)
+ KUNIT_EXPECT_TRUE(test,
+ drm_mm_node_allocated(&bo->base.vma_node.vm_node));
+
+ ttm_resource_free(bo, &bo->resource);
+ ttm_bo_put(bo);
+ ttm_mock_manager_fini(priv->ttm_dev, mem_type);
+}
+
+static void ttm_bo_init_reserved_resv(struct kunit *test)
+{
+ enum ttm_bo_type bo_type = ttm_bo_type_device;
+ struct ttm_test_devices *priv = test->priv;
+ u32 size = ALIGN(BO_SIZE, PAGE_SIZE);
+ struct ttm_operation_ctx ctx = { };
+ struct ttm_placement *placement;
+ struct ttm_buffer_object *bo;
+ struct ttm_place *place;
+ struct dma_resv resv;
+ int err;
+
+ bo = kunit_kzalloc(test, sizeof(*bo), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, bo);
+
+ place = ttm_place_kunit_init(test, TTM_PL_SYSTEM, 0);
+ placement = ttm_placement_kunit_init(test, place, 1);
+
+ drm_gem_private_object_init(priv->drm, &bo->base, size);
+ dma_resv_init(&resv);
+ dma_resv_lock(&resv, NULL);
+
+ err = ttm_bo_init_reserved(priv->ttm_dev, bo, bo_type, placement,
+ PAGE_SIZE, &ctx, NULL, &resv,
+ &dummy_ttm_bo_destroy);
+ dma_resv_unlock(bo->base.resv);
+
+ KUNIT_EXPECT_EQ(test, err, 0);
+ KUNIT_EXPECT_PTR_EQ(test, bo->base.resv, &resv);
+
+ ttm_resource_free(bo, &bo->resource);
+ ttm_bo_put(bo);
+}
+
+static void ttm_bo_validate_basic(struct kunit *test)
+{
+ const struct ttm_bo_validate_test_case *params = test->param_value;
+ u32 fst_mem = TTM_PL_SYSTEM, snd_mem = TTM_PL_VRAM;
+ struct ttm_operation_ctx ctx_init = { }, ctx_val = { };
+ struct ttm_placement *fst_placement, *snd_placement;
+ struct ttm_test_devices *priv = test->priv;
+ struct ttm_place *fst_place, *snd_place;
+ u32 size = ALIGN(SZ_8K, PAGE_SIZE);
+ struct ttm_buffer_object *bo;
+ int err;
+
+ ttm_mock_manager_init(priv->ttm_dev, snd_mem, MANAGER_SIZE);
+
+ fst_place = ttm_place_kunit_init(test, fst_mem, 0);
+ fst_placement = ttm_placement_kunit_init(test, fst_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, size);
+
+ err = ttm_bo_init_reserved(priv->ttm_dev, bo, params->bo_type,
+ fst_placement, PAGE_SIZE, &ctx_init, NULL,
+ NULL, &dummy_ttm_bo_destroy);
+ KUNIT_EXPECT_EQ(test, err, 0);
+
+ snd_place = ttm_place_kunit_init(test, snd_mem, DRM_BUDDY_TOPDOWN_ALLOCATION);
+ snd_placement = ttm_placement_kunit_init(test, snd_place, 1);
+
+ err = ttm_bo_validate(bo, snd_placement, &ctx_val);
+ dma_resv_unlock(bo->base.resv);
+
+ KUNIT_EXPECT_EQ(test, err, 0);
+ KUNIT_EXPECT_EQ(test, ctx_val.bytes_moved, bo->base.size);
+ KUNIT_EXPECT_NOT_NULL(test, bo->ttm);
+ KUNIT_EXPECT_TRUE(test, ttm_tt_is_populated(bo->ttm));
+ KUNIT_EXPECT_EQ(test, bo->resource->mem_type, snd_mem);
+ KUNIT_EXPECT_EQ(test, bo->resource->placement,
+ DRM_BUDDY_TOPDOWN_ALLOCATION);
+
+ ttm_bo_put(bo);
+ ttm_mock_manager_fini(priv->ttm_dev, snd_mem);
+}
+
+static void ttm_bo_validate_invalid_placement(struct kunit *test)
+{
+ enum ttm_bo_type bo_type = ttm_bo_type_device;
+ u32 unknown_mem_type = TTM_PL_PRIV + 1;
+ u32 size = ALIGN(BO_SIZE, PAGE_SIZE);
+ struct ttm_operation_ctx ctx = { };
+ struct ttm_placement *placement;
+ struct ttm_buffer_object *bo;
+ struct ttm_place *place;
+ int err;
+
+ place = ttm_place_kunit_init(test, unknown_mem_type, 0);
+ placement = ttm_placement_kunit_init(test, place, 1);
+
+ bo = ttm_bo_kunit_init(test, test->priv, size, NULL);
+ bo->type = bo_type;
+
+ ttm_bo_reserve(bo, false, false, NULL);
+ err = ttm_bo_validate(bo, placement, &ctx);
+ dma_resv_unlock(bo->base.resv);
+
+ KUNIT_EXPECT_EQ(test, err, -ENOMEM);
+
+ ttm_bo_put(bo);
+}
+
+static void ttm_bo_validate_failed_alloc(struct kunit *test)
+{
+ enum ttm_bo_type bo_type = ttm_bo_type_device;
+ struct ttm_test_devices *priv = test->priv;
+ u32 size = ALIGN(BO_SIZE, PAGE_SIZE);
+ struct ttm_operation_ctx ctx = { };
+ struct ttm_placement *placement;
+ u32 mem_type = TTM_PL_VRAM;
+ struct ttm_buffer_object *bo;
+ struct ttm_place *place;
+ int err;
+
+ bo = ttm_bo_kunit_init(test, test->priv, size, NULL);
+ bo->type = bo_type;
+
+ ttm_bad_manager_init(priv->ttm_dev, mem_type, MANAGER_SIZE);
+
+ place = ttm_place_kunit_init(test, mem_type, 0);
+ placement = ttm_placement_kunit_init(test, place, 1);
+
+ ttm_bo_reserve(bo, false, false, NULL);
+ err = ttm_bo_validate(bo, placement, &ctx);
+ dma_resv_unlock(bo->base.resv);
+
+ KUNIT_EXPECT_EQ(test, err, -ENOMEM);
+
+ ttm_bo_put(bo);
+ ttm_bad_manager_fini(priv->ttm_dev, mem_type);
+}
+
+static void ttm_bo_validate_pinned(struct kunit *test)
+{
+ enum ttm_bo_type bo_type = ttm_bo_type_device;
+ u32 size = ALIGN(BO_SIZE, PAGE_SIZE);
+ struct ttm_operation_ctx ctx = { };
+ u32 mem_type = TTM_PL_SYSTEM;
+ struct ttm_placement *placement;
+ struct ttm_buffer_object *bo;
+ struct ttm_place *place;
+ int err;
+
+ place = ttm_place_kunit_init(test, mem_type, 0);
+ placement = ttm_placement_kunit_init(test, place, 1);
+
+ bo = ttm_bo_kunit_init(test, test->priv, size, NULL);
+ bo->type = bo_type;
+
+ ttm_bo_reserve(bo, false, false, NULL);
+ ttm_bo_pin(bo);
+ err = ttm_bo_validate(bo, placement, &ctx);
+ dma_resv_unlock(bo->base.resv);
+
+ KUNIT_EXPECT_EQ(test, err, -EINVAL);
+
+ ttm_bo_reserve(bo, false, false, NULL);
+ ttm_bo_unpin(bo);
+ dma_resv_unlock(bo->base.resv);
+
+ ttm_bo_put(bo);
+}
+
+static const struct ttm_bo_validate_test_case ttm_mem_type_cases[] = {
+ {
+ .description = "System manager",
+ .mem_type = TTM_PL_SYSTEM,
+ },
+ {
+ .description = "VRAM manager",
+ .mem_type = TTM_PL_VRAM,
+ },
+};
+
+KUNIT_ARRAY_PARAM(ttm_bo_validate_mem, ttm_mem_type_cases,
+ ttm_bo_validate_case_desc);
+
+static void ttm_bo_validate_same_placement(struct kunit *test)
+{
+ const struct ttm_bo_validate_test_case *params = test->param_value;
+ struct ttm_operation_ctx ctx_init = { }, ctx_val = { };
+ struct ttm_test_devices *priv = test->priv;
+ u32 size = ALIGN(BO_SIZE, PAGE_SIZE);
+ struct ttm_placement *placement;
+ struct ttm_buffer_object *bo;
+ struct ttm_place *place;
+ int err;
+
+ place = ttm_place_kunit_init(test, params->mem_type, 0);
+ placement = ttm_placement_kunit_init(test, place, 1);
+
+ if (params->mem_type != TTM_PL_SYSTEM)
+ ttm_mock_manager_init(priv->ttm_dev, params->mem_type, MANAGER_SIZE);
+
+ bo = kunit_kzalloc(test, sizeof(*bo), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, bo);
+
+ drm_gem_private_object_init(priv->drm, &bo->base, size);
+
+ err = ttm_bo_init_reserved(priv->ttm_dev, bo, params->bo_type,
+ placement, PAGE_SIZE, &ctx_init, NULL,
+ NULL, &dummy_ttm_bo_destroy);
+ KUNIT_EXPECT_EQ(test, err, 0);
+
+ err = ttm_bo_validate(bo, placement, &ctx_val);
+ dma_resv_unlock(bo->base.resv);
+
+ KUNIT_EXPECT_EQ(test, err, 0);
+ KUNIT_EXPECT_EQ(test, ctx_val.bytes_moved, 0);
+
+ ttm_bo_put(bo);
+
+ if (params->mem_type != TTM_PL_SYSTEM)
+ ttm_mock_manager_fini(priv->ttm_dev, params->mem_type);
+}
+
+static void ttm_bo_validate_busy_placement(struct kunit *test)
+{
+ u32 fst_mem = TTM_PL_VRAM, snd_mem = TTM_PL_VRAM + 1;
+ struct ttm_operation_ctx ctx_init = { }, ctx_val = { };
+ struct ttm_placement *placement_init, *placement_val;
+ enum ttm_bo_type bo_type = ttm_bo_type_device;
+ struct ttm_test_devices *priv = test->priv;
+ u32 size = ALIGN(BO_SIZE, PAGE_SIZE);
+ struct ttm_place *init_place, places[2];
+ struct ttm_resource_manager *man;
+ struct ttm_buffer_object *bo;
+ int err;
+
+ ttm_bad_manager_init(priv->ttm_dev, fst_mem, MANAGER_SIZE);
+ ttm_mock_manager_init(priv->ttm_dev, snd_mem, MANAGER_SIZE);
+
+ init_place = ttm_place_kunit_init(test, TTM_PL_SYSTEM, 0);
+ placement_init = ttm_placement_kunit_init(test, init_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, size);
+
+ err = ttm_bo_init_reserved(priv->ttm_dev, bo, bo_type, placement_init,
+ PAGE_SIZE, &ctx_init, NULL, NULL,
+ &dummy_ttm_bo_destroy);
+ KUNIT_EXPECT_EQ(test, err, 0);
+
+ places[0] = (struct ttm_place){ .mem_type = fst_mem, .flags = TTM_PL_FLAG_DESIRED };
+ places[1] = (struct ttm_place){ .mem_type = snd_mem, .flags = TTM_PL_FLAG_FALLBACK };
+ placement_val = ttm_placement_kunit_init(test, places, 2);
+
+ err = ttm_bo_validate(bo, placement_val, &ctx_val);
+ dma_resv_unlock(bo->base.resv);
+
+ man = ttm_manager_type(priv->ttm_dev, snd_mem);
+
+ KUNIT_EXPECT_EQ(test, err, 0);
+ KUNIT_EXPECT_EQ(test, ctx_val.bytes_moved, bo->base.size);
+ KUNIT_EXPECT_EQ(test, bo->resource->mem_type, snd_mem);
+ KUNIT_ASSERT_TRUE(test, list_is_singular(&man->lru[bo->priority]));
+
+ ttm_bo_put(bo);
+ ttm_bad_manager_fini(priv->ttm_dev, fst_mem);
+ ttm_mock_manager_fini(priv->ttm_dev, snd_mem);
+}
+
+static void ttm_bo_validate_multihop(struct kunit *test)
+{
+ const struct ttm_bo_validate_test_case *params = test->param_value;
+ struct ttm_operation_ctx ctx_init = { }, ctx_val = { };
+ struct ttm_placement *placement_init, *placement_val;
+ u32 fst_mem = TTM_PL_VRAM, tmp_mem = TTM_PL_TT, final_mem = TTM_PL_SYSTEM;
+ struct ttm_test_devices *priv = test->priv;
+ struct ttm_place *fst_place, *final_place;
+ u32 size = ALIGN(BO_SIZE, PAGE_SIZE);
+ struct ttm_buffer_object *bo;
+ int err;
+
+ ttm_mock_manager_init(priv->ttm_dev, fst_mem, MANAGER_SIZE);
+ ttm_mock_manager_init(priv->ttm_dev, tmp_mem, MANAGER_SIZE);
+
+ fst_place = ttm_place_kunit_init(test, fst_mem, 0);
+ placement_init = ttm_placement_kunit_init(test, fst_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, size);
+
+ err = ttm_bo_init_reserved(priv->ttm_dev, bo, params->bo_type,
+ placement_init, PAGE_SIZE, &ctx_init, NULL,
+ NULL, &dummy_ttm_bo_destroy);
+ KUNIT_EXPECT_EQ(test, err, 0);
+
+ final_place = ttm_place_kunit_init(test, final_mem, 0);
+ placement_val = ttm_placement_kunit_init(test, final_place, 1);
+
+ err = ttm_bo_validate(bo, placement_val, &ctx_val);
+ dma_resv_unlock(bo->base.resv);
+
+ KUNIT_EXPECT_EQ(test, err, 0);
+ KUNIT_EXPECT_EQ(test, ctx_val.bytes_moved, size * 2);
+ KUNIT_EXPECT_EQ(test, bo->resource->mem_type, final_mem);
+
+ ttm_bo_put(bo);
+
+ ttm_mock_manager_fini(priv->ttm_dev, fst_mem);
+ ttm_mock_manager_fini(priv->ttm_dev, tmp_mem);
+}
+
+static const struct ttm_bo_validate_test_case ttm_bo_no_placement_cases[] = {
+ {
+ .description = "Buffer object in system domain, no page vector",
+ },
+ {
+ .description = "Buffer object in system domain with an existing page vector",
+ .with_ttm = true,
+ },
+};
+
+KUNIT_ARRAY_PARAM(ttm_bo_no_placement, ttm_bo_no_placement_cases,
+ ttm_bo_validate_case_desc);
+
+static void ttm_bo_validate_no_placement_signaled(struct kunit *test)
+{
+ const struct ttm_bo_validate_test_case *params = test->param_value;
+ enum ttm_bo_type bo_type = ttm_bo_type_device;
+ struct ttm_test_devices *priv = test->priv;
+ u32 size = ALIGN(BO_SIZE, PAGE_SIZE);
+ struct ttm_operation_ctx ctx = { };
+ u32 mem_type = TTM_PL_SYSTEM;
+ struct ttm_resource_manager *man;
+ struct ttm_placement *placement;
+ struct ttm_buffer_object *bo;
+ struct ttm_place *place;
+ struct ttm_tt *old_tt;
+ u32 flags;
+ int err;
+
+ place = ttm_place_kunit_init(test, mem_type, 0);
+ man = ttm_manager_type(priv->ttm_dev, mem_type);
+
+ bo = ttm_bo_kunit_init(test, test->priv, size, NULL);
+ bo->type = bo_type;
+
+ if (params->with_ttm) {
+ old_tt = priv->ttm_dev->funcs->ttm_tt_create(bo, 0);
+ ttm_pool_alloc(&priv->ttm_dev->pool, old_tt, &ctx);
+ bo->ttm = old_tt;
+ }
+
+ err = ttm_resource_alloc(bo, place, &bo->resource);
+ KUNIT_EXPECT_EQ(test, err, 0);
+ KUNIT_ASSERT_EQ(test, man->usage, size);
+
+ placement = kunit_kzalloc(test, sizeof(*placement), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, placement);
+
+ ttm_bo_reserve(bo, false, false, NULL);
+ err = ttm_bo_validate(bo, placement, &ctx);
+ ttm_bo_unreserve(bo);
+
+ KUNIT_EXPECT_EQ(test, err, 0);
+ KUNIT_ASSERT_EQ(test, man->usage, 0);
+ KUNIT_ASSERT_NOT_NULL(test, bo->ttm);
+ KUNIT_EXPECT_EQ(test, ctx.bytes_moved, 0);
+
+ if (params->with_ttm) {
+ flags = bo->ttm->page_flags;
+
+ KUNIT_ASSERT_PTR_EQ(test, bo->ttm, old_tt);
+ KUNIT_ASSERT_FALSE(test, flags & TTM_TT_FLAG_PRIV_POPULATED);
+ KUNIT_ASSERT_TRUE(test, flags & TTM_TT_FLAG_ZERO_ALLOC);
+ }
+
+ ttm_bo_put(bo);
+}
+
+static int threaded_dma_resv_signal(void *arg)
+{
+ struct ttm_buffer_object *bo = arg;
+ struct dma_resv *resv = bo->base.resv;
+ struct dma_resv_iter cursor;
+ struct dma_fence *fence;
+
+ dma_resv_iter_begin(&cursor, resv, DMA_RESV_USAGE_BOOKKEEP);
+ dma_resv_for_each_fence_unlocked(&cursor, fence) {
+ dma_fence_signal(fence);
+ }
+ dma_resv_iter_end(&cursor);
+
+ return 0;
+}
+
+static void ttm_bo_validate_no_placement_not_signaled(struct kunit *test)
+{
+ const struct ttm_bo_validate_test_case *params = test->param_value;
+ enum dma_resv_usage usage = DMA_RESV_USAGE_BOOKKEEP;
+ u32 size = ALIGN(BO_SIZE, PAGE_SIZE);
+ struct ttm_operation_ctx ctx = { };
+ u32 mem_type = TTM_PL_SYSTEM;
+ struct ttm_placement *placement;
+ struct ttm_buffer_object *bo;
+ struct task_struct *task;
+ struct ttm_place *place;
+ int err;
+
+ place = ttm_place_kunit_init(test, mem_type, 0);
+
+ bo = ttm_bo_kunit_init(test, test->priv, size, NULL);
+ bo->type = params->bo_type;
+
+ err = ttm_resource_alloc(bo, place, &bo->resource);
+ KUNIT_EXPECT_EQ(test, err, 0);
+
+ placement = kunit_kzalloc(test, sizeof(*placement), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, placement);
+
+ /* Create an active fence to simulate a non-idle resv object */
+ spin_lock_init(&fence_lock);
+ dma_resv_kunit_active_fence_init(test, bo->base.resv, usage);
+
+ task = kthread_create(threaded_dma_resv_signal, bo, "dma-resv-signal");
+ if (IS_ERR(task))
+ KUNIT_FAIL(test, "Couldn't create dma resv signal task\n");
+
+ wake_up_process(task);
+ ttm_bo_reserve(bo, false, false, NULL);
+ err = ttm_bo_validate(bo, placement, &ctx);
+ ttm_bo_unreserve(bo);
+
+ KUNIT_EXPECT_EQ(test, err, 0);
+ KUNIT_ASSERT_NOT_NULL(test, bo->ttm);
+ KUNIT_ASSERT_NULL(test, bo->resource);
+ KUNIT_ASSERT_NULL(test, bo->bulk_move);
+ KUNIT_EXPECT_EQ(test, ctx.bytes_moved, 0);
+
+ if (bo->type != ttm_bo_type_sg)
+ KUNIT_ASSERT_PTR_EQ(test, bo->base.resv, &bo->base._resv);
+
+ /* Make sure we have an idle object at this point */
+ dma_resv_wait_timeout(bo->base.resv, usage, false, MAX_SCHEDULE_TIMEOUT);
+
+ ttm_bo_put(bo);
+}
+
+static void ttm_bo_validate_move_fence_signaled(struct kunit *test)
+{
+ enum ttm_bo_type bo_type = ttm_bo_type_device;
+ struct ttm_test_devices *priv = test->priv;
+ u32 size = ALIGN(BO_SIZE, PAGE_SIZE);
+ struct ttm_operation_ctx ctx = { };
+ u32 mem_type = TTM_PL_SYSTEM;
+ struct ttm_resource_manager *man;
+ struct ttm_placement *placement;
+ struct ttm_buffer_object *bo;
+ struct ttm_place *place;
+ int err;
+
+ man = ttm_manager_type(priv->ttm_dev, mem_type);
+ man->move = dma_fence_get_stub();
+
+ bo = ttm_bo_kunit_init(test, test->priv, size, NULL);
+ bo->type = bo_type;
+
+ place = ttm_place_kunit_init(test, mem_type, 0);
+ placement = ttm_placement_kunit_init(test, place, 1);
+
+ ttm_bo_reserve(bo, false, false, NULL);
+ err = ttm_bo_validate(bo, placement, &ctx);
+ ttm_bo_unreserve(bo);
+
+ KUNIT_EXPECT_EQ(test, err, 0);
+ KUNIT_EXPECT_EQ(test, bo->resource->mem_type, mem_type);
+ KUNIT_EXPECT_EQ(test, ctx.bytes_moved, size);
+
+ ttm_bo_put(bo);
+ dma_fence_put(man->move);
+}
+
+static const struct ttm_bo_validate_test_case ttm_bo_validate_wait_cases[] = {
+ {
+ .description = "Waits for GPU",
+ .no_gpu_wait = false,
+ },
+ {
+ .description = "Tries to lock straight away",
+ .no_gpu_wait = true,
+ },
+};
+
+KUNIT_ARRAY_PARAM(ttm_bo_validate_wait, ttm_bo_validate_wait_cases,
+ ttm_bo_validate_case_desc);
+
+static int threaded_fence_signal(void *arg)
+{
+ struct dma_fence *fence = arg;
+
+ msleep(20);
+
+ return dma_fence_signal(fence);
+}
+
+static void ttm_bo_validate_move_fence_not_signaled(struct kunit *test)
+{
+ const struct ttm_bo_validate_test_case *params = test->param_value;
+ struct ttm_operation_ctx ctx_init = { },
+ ctx_val = { .no_wait_gpu = params->no_gpu_wait };
+ u32 fst_mem = TTM_PL_VRAM, snd_mem = TTM_PL_VRAM + 1;
+ struct ttm_placement *placement_init, *placement_val;
+ enum ttm_bo_type bo_type = ttm_bo_type_device;
+ struct ttm_test_devices *priv = test->priv;
+ u32 size = ALIGN(BO_SIZE, PAGE_SIZE);
+ struct ttm_place *init_place, places[2];
+ struct ttm_resource_manager *man;
+ struct ttm_buffer_object *bo;
+ struct task_struct *task;
+ int err;
+
+ init_place = ttm_place_kunit_init(test, TTM_PL_SYSTEM, 0);
+ placement_init = ttm_placement_kunit_init(test, init_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, size);
+
+ err = ttm_bo_init_reserved(priv->ttm_dev, bo, bo_type, placement_init,
+ PAGE_SIZE, &ctx_init, NULL, NULL,
+ &dummy_ttm_bo_destroy);
+ KUNIT_EXPECT_EQ(test, err, 0);
+
+ ttm_mock_manager_init(priv->ttm_dev, fst_mem, MANAGER_SIZE);
+ ttm_mock_manager_init(priv->ttm_dev, snd_mem, MANAGER_SIZE);
+
+ places[0] = (struct ttm_place){ .mem_type = fst_mem, .flags = TTM_PL_FLAG_DESIRED };
+ places[1] = (struct ttm_place){ .mem_type = snd_mem, .flags = TTM_PL_FLAG_FALLBACK };
+ placement_val = ttm_placement_kunit_init(test, places, 2);
+
+ spin_lock_init(&fence_lock);
+ man = ttm_manager_type(priv->ttm_dev, fst_mem);
+ man->move = alloc_mock_fence(test);
+
+ task = kthread_create(threaded_fence_signal, man->move, "move-fence-signal");
+ if (IS_ERR(task))
+ KUNIT_FAIL(test, "Couldn't create move fence signal task\n");
+
+ wake_up_process(task);
+ err = ttm_bo_validate(bo, placement_val, &ctx_val);
+ dma_resv_unlock(bo->base.resv);
+
+ dma_fence_wait_timeout(man->move, false, MAX_SCHEDULE_TIMEOUT);
+
+ KUNIT_EXPECT_EQ(test, err, 0);
+ KUNIT_EXPECT_EQ(test, ctx_val.bytes_moved, size);
+
+ if (params->no_gpu_wait)
+ KUNIT_EXPECT_EQ(test, bo->resource->mem_type, snd_mem);
+ else
+ KUNIT_EXPECT_EQ(test, bo->resource->mem_type, fst_mem);
+
+ ttm_bo_put(bo);
+ ttm_mock_manager_fini(priv->ttm_dev, fst_mem);
+ ttm_mock_manager_fini(priv->ttm_dev, snd_mem);
+}
+
+static void ttm_bo_validate_swapout(struct kunit *test)
+{
+ unsigned long size_big, size = ALIGN(BO_SIZE, PAGE_SIZE);
+ enum ttm_bo_type bo_type = ttm_bo_type_device;
+ struct ttm_buffer_object *bo_small, *bo_big;
+ struct ttm_test_devices *priv = test->priv;
+ struct ttm_operation_ctx ctx = { };
+ struct ttm_placement *placement;
+ u32 mem_type = TTM_PL_TT;
+ struct ttm_place *place;
+ struct sysinfo si;
+ int err;
+
+ si_meminfo(&si);
+ size_big = ALIGN(((u64)si.totalram * si.mem_unit / 2), PAGE_SIZE);
+
+ ttm_mock_manager_init(priv->ttm_dev, mem_type, size_big + size);
+
+ place = ttm_place_kunit_init(test, mem_type, 0);
+ placement = ttm_placement_kunit_init(test, place, 1);
+
+ bo_small = kunit_kzalloc(test, sizeof(*bo_small), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, bo_small);
+
+ drm_gem_private_object_init(priv->drm, &bo_small->base, size);
+
+ err = ttm_bo_init_reserved(priv->ttm_dev, bo_small, bo_type, placement,
+ PAGE_SIZE, &ctx, NULL, NULL,
+ &dummy_ttm_bo_destroy);
+ KUNIT_EXPECT_EQ(test, err, 0);
+ dma_resv_unlock(bo_small->base.resv);
+
+ bo_big = ttm_bo_kunit_init(test, priv, size_big, NULL);
+
+ dma_resv_lock(bo_big->base.resv, NULL);
+ err = ttm_bo_validate(bo_big, placement, &ctx);
+ dma_resv_unlock(bo_big->base.resv);
+
+ KUNIT_EXPECT_EQ(test, err, 0);
+ KUNIT_EXPECT_NOT_NULL(test, bo_big->resource);
+ KUNIT_EXPECT_EQ(test, bo_big->resource->mem_type, mem_type);
+ KUNIT_EXPECT_EQ(test, bo_small->resource->mem_type, TTM_PL_SYSTEM);
+ KUNIT_EXPECT_TRUE(test, bo_small->ttm->page_flags & TTM_TT_FLAG_SWAPPED);
+
+ ttm_bo_put(bo_big);
+ ttm_bo_put(bo_small);
+
+ 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,
+ mem_type_evict = TTM_PL_SYSTEM;
+ struct ttm_operation_ctx ctx_init = { }, ctx_val = { };
+ enum ttm_bo_type bo_type = ttm_bo_type_device;
+ u32 small = SZ_8K, medium = SZ_512K,
+ big = MANAGER_SIZE - (small + medium);
+ u32 bo_sizes[] = { small, medium, big };
+ struct ttm_test_devices *priv = test->priv;
+ struct ttm_buffer_object *bos, *bo_val;
+ struct ttm_placement *placement;
+ struct ttm_place *place;
+ u32 bo_no = 3;
+ int i, err;
+
+ ttm_mock_manager_init(priv->ttm_dev, mem_type, MANAGER_SIZE);
+ ttm_mock_manager_init(priv->ttm_dev, mem_multihop, MANAGER_SIZE);
+
+ place = ttm_place_kunit_init(test, mem_type, 0);
+ placement = ttm_placement_kunit_init(test, place, 1);
+
+ bos = kunit_kmalloc_array(test, bo_no, sizeof(*bos), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, bos);
+
+ memset(bos, 0, sizeof(*bos) * bo_no);
+ for (i = 0; i < bo_no; i++) {
+ drm_gem_private_object_init(priv->drm, &bos[i].base, bo_sizes[i]);
+ err = ttm_bo_init_reserved(priv->ttm_dev, &bos[i], bo_type, placement,
+ PAGE_SIZE, &ctx_init, NULL, NULL,
+ &dummy_ttm_bo_destroy);
+ dma_resv_unlock(bos[i].base.resv);
+ }
+
+ bo_val = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
+ bo_val->type = bo_type;
+
+ ttm_bo_reserve(bo_val, false, false, NULL);
+ err = ttm_bo_validate(bo_val, placement, &ctx_val);
+ ttm_bo_unreserve(bo_val);
+
+ KUNIT_EXPECT_EQ(test, err, 0);
+ KUNIT_EXPECT_EQ(test, bos[0].resource->mem_type, mem_type_evict);
+ KUNIT_EXPECT_TRUE(test, bos[0].ttm->page_flags & TTM_TT_FLAG_ZERO_ALLOC);
+ KUNIT_EXPECT_TRUE(test, bos[0].ttm->page_flags & TTM_TT_FLAG_PRIV_POPULATED);
+ KUNIT_EXPECT_EQ(test, ctx_val.bytes_moved, small * 2 + BO_SIZE);
+ KUNIT_EXPECT_EQ(test, bos[1].resource->mem_type, mem_type);
+
+ for (i = 0; i < bo_no; i++)
+ ttm_bo_put(&bos[i]);
+ ttm_bo_put(bo_val);
+
+ ttm_mock_manager_fini(priv->ttm_dev, mem_type);
+ ttm_mock_manager_fini(priv->ttm_dev, mem_multihop);
+}
+
+static void ttm_bo_validate_all_pinned_evict(struct kunit *test)
+{
+ struct ttm_operation_ctx ctx_init = { }, ctx_val = { };
+ enum ttm_bo_type bo_type = ttm_bo_type_device;
+ struct ttm_buffer_object *bo_big, *bo_small;
+ struct ttm_test_devices *priv = test->priv;
+ struct ttm_placement *placement;
+ u32 mem_type = TTM_PL_VRAM, mem_multihop = TTM_PL_TT;
+ struct ttm_place *place;
+ int err;
+
+ ttm_mock_manager_init(priv->ttm_dev, mem_type, MANAGER_SIZE);
+ ttm_mock_manager_init(priv->ttm_dev, mem_multihop, MANAGER_SIZE);
+
+ place = ttm_place_kunit_init(test, mem_type, 0);
+ placement = ttm_placement_kunit_init(test, place, 1);
+
+ bo_big = kunit_kzalloc(test, sizeof(*bo_big), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, bo_big);
+
+ drm_gem_private_object_init(priv->drm, &bo_big->base, MANAGER_SIZE);
+ err = ttm_bo_init_reserved(priv->ttm_dev, bo_big, bo_type, placement,
+ PAGE_SIZE, &ctx_init, NULL, NULL,
+ &dummy_ttm_bo_destroy);
+ KUNIT_EXPECT_EQ(test, err, 0);
+
+ ttm_bo_pin(bo_big);
+ dma_resv_unlock(bo_big->base.resv);
+
+ bo_small = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
+ bo_small->type = bo_type;
+
+ ttm_bo_reserve(bo_small, false, false, NULL);
+ err = ttm_bo_validate(bo_small, placement, &ctx_val);
+ ttm_bo_unreserve(bo_small);
+
+ KUNIT_EXPECT_EQ(test, err, -ENOMEM);
+
+ ttm_bo_put(bo_small);
+
+ ttm_bo_reserve(bo_big, false, false, NULL);
+ ttm_bo_unpin(bo_big);
+ dma_resv_unlock(bo_big->base.resv);
+ ttm_bo_put(bo_big);
+
+ ttm_mock_manager_fini(priv->ttm_dev, mem_type);
+ ttm_mock_manager_fini(priv->ttm_dev, mem_multihop);
+}
+
+static void ttm_bo_validate_allowed_only_evict(struct kunit *test)
+{
+ u32 mem_type = TTM_PL_VRAM, mem_multihop = TTM_PL_TT,
+ mem_type_evict = TTM_PL_SYSTEM;
+ struct ttm_buffer_object *bo, *bo_evictable, *bo_pinned;
+ struct ttm_operation_ctx ctx_init = { }, ctx_val = { };
+ enum ttm_bo_type bo_type = ttm_bo_type_device;
+ struct ttm_test_devices *priv = test->priv;
+ struct ttm_placement *placement;
+ struct ttm_place *place;
+ u32 size = SZ_512K;
+ int err;
+
+ ttm_mock_manager_init(priv->ttm_dev, mem_type, MANAGER_SIZE);
+ ttm_mock_manager_init(priv->ttm_dev, mem_multihop, MANAGER_SIZE);
+
+ place = ttm_place_kunit_init(test, mem_type, 0);
+ placement = ttm_placement_kunit_init(test, place, 1);
+
+ bo_pinned = kunit_kzalloc(test, sizeof(*bo_pinned), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, bo_pinned);
+
+ drm_gem_private_object_init(priv->drm, &bo_pinned->base, size);
+ err = ttm_bo_init_reserved(priv->ttm_dev, bo_pinned, bo_type, placement,
+ PAGE_SIZE, &ctx_init, NULL, NULL,
+ &dummy_ttm_bo_destroy);
+ KUNIT_EXPECT_EQ(test, err, 0);
+ ttm_bo_pin(bo_pinned);
+ dma_resv_unlock(bo_pinned->base.resv);
+
+ bo_evictable = kunit_kzalloc(test, sizeof(*bo_evictable), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, bo_evictable);
+
+ drm_gem_private_object_init(priv->drm, &bo_evictable->base, size);
+ err = ttm_bo_init_reserved(priv->ttm_dev, bo_evictable, bo_type, placement,
+ PAGE_SIZE, &ctx_init, NULL, NULL,
+ &dummy_ttm_bo_destroy);
+ KUNIT_EXPECT_EQ(test, err, 0);
+ dma_resv_unlock(bo_evictable->base.resv);
+
+ bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
+ bo->type = bo_type;
+
+ ttm_bo_reserve(bo, false, false, NULL);
+ err = ttm_bo_validate(bo, placement, &ctx_val);
+ ttm_bo_unreserve(bo);
+
+ KUNIT_EXPECT_EQ(test, err, 0);
+ KUNIT_EXPECT_EQ(test, bo->resource->mem_type, mem_type);
+ KUNIT_EXPECT_EQ(test, bo_pinned->resource->mem_type, mem_type);
+ KUNIT_EXPECT_EQ(test, bo_evictable->resource->mem_type, mem_type_evict);
+ KUNIT_EXPECT_EQ(test, ctx_val.bytes_moved, size * 2 + BO_SIZE);
+
+ ttm_bo_put(bo);
+ ttm_bo_put(bo_evictable);
+
+ ttm_bo_reserve(bo_pinned, false, false, NULL);
+ ttm_bo_unpin(bo_pinned);
+ dma_resv_unlock(bo_pinned->base.resv);
+ ttm_bo_put(bo_pinned);
+
+ ttm_mock_manager_fini(priv->ttm_dev, mem_type);
+ ttm_mock_manager_fini(priv->ttm_dev, mem_multihop);
+}
+
+static void ttm_bo_validate_deleted_evict(struct kunit *test)
+{
+ struct ttm_operation_ctx ctx_init = { }, ctx_val = { };
+ u32 small = SZ_8K, big = MANAGER_SIZE - BO_SIZE;
+ enum ttm_bo_type bo_type = ttm_bo_type_device;
+ struct ttm_buffer_object *bo_big, *bo_small;
+ struct ttm_test_devices *priv = test->priv;
+ struct ttm_resource_manager *man;
+ u32 mem_type = TTM_PL_VRAM;
+ struct ttm_placement *placement;
+ struct ttm_place *place;
+ int err;
+
+ ttm_mock_manager_init(priv->ttm_dev, mem_type, MANAGER_SIZE);
+ man = ttm_manager_type(priv->ttm_dev, mem_type);
+
+ place = ttm_place_kunit_init(test, mem_type, 0);
+ placement = ttm_placement_kunit_init(test, place, 1);
+
+ bo_big = kunit_kzalloc(test, sizeof(*bo_big), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, bo_big);
+
+ drm_gem_private_object_init(priv->drm, &bo_big->base, big);
+ err = ttm_bo_init_reserved(priv->ttm_dev, bo_big, bo_type, placement,
+ PAGE_SIZE, &ctx_init, NULL, NULL,
+ &dummy_ttm_bo_destroy);
+ KUNIT_EXPECT_EQ(test, err, 0);
+ KUNIT_EXPECT_EQ(test, ttm_resource_manager_usage(man), big);
+
+ dma_resv_unlock(bo_big->base.resv);
+ bo_big->deleted = true;
+
+ bo_small = ttm_bo_kunit_init(test, test->priv, small, NULL);
+ bo_small->type = bo_type;
+
+ ttm_bo_reserve(bo_small, false, false, NULL);
+ err = ttm_bo_validate(bo_small, placement, &ctx_val);
+ ttm_bo_unreserve(bo_small);
+
+ KUNIT_EXPECT_EQ(test, err, 0);
+ KUNIT_EXPECT_EQ(test, bo_small->resource->mem_type, mem_type);
+ KUNIT_EXPECT_EQ(test, ttm_resource_manager_usage(man), small);
+ KUNIT_EXPECT_NULL(test, bo_big->ttm);
+ KUNIT_EXPECT_NULL(test, bo_big->resource);
+
+ ttm_bo_put(bo_small);
+ ttm_bo_put(bo_big);
+ ttm_mock_manager_fini(priv->ttm_dev, mem_type);
+}
+
+static void ttm_bo_validate_busy_domain_evict(struct kunit *test)
+{
+ u32 mem_type = TTM_PL_VRAM, mem_type_evict = TTM_PL_MOCK1;
+ struct ttm_operation_ctx ctx_init = { }, ctx_val = { };
+ enum ttm_bo_type bo_type = ttm_bo_type_device;
+ struct ttm_test_devices *priv = test->priv;
+ struct ttm_buffer_object *bo_init, *bo_val;
+ struct ttm_placement *placement;
+ struct ttm_place *place;
+ int err;
+
+ /*
+ * Drop the default device and setup a new one that points to busy
+ * thus unsuitable eviction domain
+ */
+ ttm_device_fini(priv->ttm_dev);
+
+ err = ttm_device_kunit_init_bad_evict(test->priv, priv->ttm_dev, false, false);
+ KUNIT_ASSERT_EQ(test, err, 0);
+
+ ttm_mock_manager_init(priv->ttm_dev, mem_type, MANAGER_SIZE);
+ ttm_busy_manager_init(priv->ttm_dev, mem_type_evict, MANAGER_SIZE);
+
+ place = ttm_place_kunit_init(test, mem_type, 0);
+ placement = ttm_placement_kunit_init(test, place, 1);
+
+ bo_init = kunit_kzalloc(test, sizeof(*bo_init), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, bo_init);
+
+ drm_gem_private_object_init(priv->drm, &bo_init->base, MANAGER_SIZE);
+ err = ttm_bo_init_reserved(priv->ttm_dev, bo_init, bo_type, placement,
+ PAGE_SIZE, &ctx_init, NULL, NULL,
+ &dummy_ttm_bo_destroy);
+ KUNIT_EXPECT_EQ(test, err, 0);
+ dma_resv_unlock(bo_init->base.resv);
+
+ bo_val = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
+ bo_val->type = bo_type;
+
+ ttm_bo_reserve(bo_val, false, false, NULL);
+ err = ttm_bo_validate(bo_val, placement, &ctx_val);
+ ttm_bo_unreserve(bo_val);
+
+ KUNIT_EXPECT_EQ(test, err, -ENOMEM);
+ KUNIT_EXPECT_EQ(test, bo_init->resource->mem_type, mem_type);
+ KUNIT_EXPECT_NULL(test, bo_val->resource);
+
+ ttm_bo_put(bo_init);
+ ttm_bo_put(bo_val);
+
+ ttm_mock_manager_fini(priv->ttm_dev, mem_type);
+ ttm_bad_manager_fini(priv->ttm_dev, mem_type_evict);
+}
+
+static void ttm_bo_validate_evict_gutting(struct kunit *test)
+{
+ struct ttm_operation_ctx ctx_init = { }, ctx_val = { };
+ enum ttm_bo_type bo_type = ttm_bo_type_device;
+ struct ttm_test_devices *priv = test->priv;
+ struct ttm_buffer_object *bo, *bo_evict;
+ u32 mem_type = TTM_PL_MOCK1;
+ struct ttm_placement *placement;
+ struct ttm_place *place;
+ int err;
+
+ ttm_mock_manager_init(priv->ttm_dev, mem_type, MANAGER_SIZE);
+
+ place = ttm_place_kunit_init(test, mem_type, 0);
+ placement = ttm_placement_kunit_init(test, place, 1);
+
+ bo_evict = kunit_kzalloc(test, sizeof(*bo_evict), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, bo_evict);
+
+ drm_gem_private_object_init(priv->drm, &bo_evict->base, MANAGER_SIZE);
+ err = ttm_bo_init_reserved(priv->ttm_dev, bo_evict, bo_type, placement,
+ PAGE_SIZE, &ctx_init, NULL, NULL,
+ &dummy_ttm_bo_destroy);
+ KUNIT_EXPECT_EQ(test, err, 0);
+ dma_resv_unlock(bo_evict->base.resv);
+
+ bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
+ bo->type = bo_type;
+
+ ttm_bo_reserve(bo, false, false, NULL);
+ err = ttm_bo_validate(bo, placement, &ctx_val);
+ ttm_bo_unreserve(bo);
+
+ KUNIT_EXPECT_EQ(test, err, 0);
+ KUNIT_EXPECT_EQ(test, bo->resource->mem_type, mem_type);
+ KUNIT_ASSERT_NULL(test, bo_evict->resource);
+ KUNIT_ASSERT_TRUE(test, bo_evict->ttm->page_flags & TTM_TT_FLAG_ZERO_ALLOC);
+
+ ttm_bo_put(bo_evict);
+ ttm_bo_put(bo);
+
+ ttm_mock_manager_fini(priv->ttm_dev, mem_type);
+}
+
+static void ttm_bo_validate_recrusive_evict(struct kunit *test)
+{
+ u32 mem_type = TTM_PL_TT, mem_type_evict = TTM_PL_MOCK2;
+ struct ttm_operation_ctx ctx_init = { }, ctx_val = { };
+ struct ttm_placement *placement_tt, *placement_mock;
+ struct ttm_buffer_object *bo_tt, *bo_mock, *bo_val;
+ enum ttm_bo_type bo_type = ttm_bo_type_device;
+ struct ttm_test_devices *priv = test->priv;
+ struct ttm_place *place_tt, *place_mock;
+ int err;
+
+ ttm_mock_manager_init(priv->ttm_dev, mem_type, MANAGER_SIZE);
+ ttm_mock_manager_init(priv->ttm_dev, mem_type_evict, MANAGER_SIZE);
+
+ place_tt = ttm_place_kunit_init(test, mem_type, 0);
+ place_mock = ttm_place_kunit_init(test, mem_type_evict, 0);
+
+ placement_tt = ttm_placement_kunit_init(test, place_tt, 1);
+ placement_mock = ttm_placement_kunit_init(test, place_mock, 1);
+
+ bo_tt = kunit_kzalloc(test, sizeof(*bo_tt), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, bo_tt);
+
+ bo_mock = kunit_kzalloc(test, sizeof(*bo_mock), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, bo_mock);
+
+ drm_gem_private_object_init(priv->drm, &bo_tt->base, MANAGER_SIZE);
+ err = ttm_bo_init_reserved(priv->ttm_dev, bo_tt, bo_type, placement_tt,
+ PAGE_SIZE, &ctx_init, NULL, NULL,
+ &dummy_ttm_bo_destroy);
+ KUNIT_EXPECT_EQ(test, err, 0);
+ dma_resv_unlock(bo_tt->base.resv);
+
+ drm_gem_private_object_init(priv->drm, &bo_mock->base, MANAGER_SIZE);
+ err = ttm_bo_init_reserved(priv->ttm_dev, bo_mock, bo_type, placement_mock,
+ PAGE_SIZE, &ctx_init, NULL, NULL,
+ &dummy_ttm_bo_destroy);
+ KUNIT_EXPECT_EQ(test, err, 0);
+ dma_resv_unlock(bo_mock->base.resv);
+
+ bo_val = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
+ bo_val->type = bo_type;
+
+ ttm_bo_reserve(bo_val, false, false, NULL);
+ err = ttm_bo_validate(bo_val, placement_tt, &ctx_val);
+ ttm_bo_unreserve(bo_val);
+
+ KUNIT_EXPECT_EQ(test, err, 0);
+
+ ttm_mock_manager_fini(priv->ttm_dev, mem_type);
+ ttm_mock_manager_fini(priv->ttm_dev, mem_type_evict);
+
+ ttm_bo_put(bo_val);
+ ttm_bo_put(bo_tt);
+ ttm_bo_put(bo_mock);
+}
+
+static struct kunit_case ttm_bo_validate_test_cases[] = {
+ KUNIT_CASE_PARAM(ttm_bo_init_reserved_sys_man, ttm_bo_types_gen_params),
+ KUNIT_CASE_PARAM(ttm_bo_init_reserved_mock_man, ttm_bo_types_gen_params),
+ KUNIT_CASE(ttm_bo_init_reserved_resv),
+ KUNIT_CASE_PARAM(ttm_bo_validate_basic, ttm_bo_types_gen_params),
+ KUNIT_CASE(ttm_bo_validate_invalid_placement),
+ KUNIT_CASE_PARAM(ttm_bo_validate_same_placement,
+ ttm_bo_validate_mem_gen_params),
+ KUNIT_CASE(ttm_bo_validate_failed_alloc),
+ KUNIT_CASE(ttm_bo_validate_pinned),
+ KUNIT_CASE(ttm_bo_validate_busy_placement),
+ KUNIT_CASE_PARAM(ttm_bo_validate_multihop, ttm_bo_types_gen_params),
+ KUNIT_CASE_PARAM(ttm_bo_validate_no_placement_signaled,
+ ttm_bo_no_placement_gen_params),
+ KUNIT_CASE_PARAM(ttm_bo_validate_no_placement_not_signaled,
+ ttm_bo_types_gen_params),
+ 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),
+ KUNIT_CASE(ttm_bo_validate_deleted_evict),
+ KUNIT_CASE(ttm_bo_validate_busy_domain_evict),
+ KUNIT_CASE(ttm_bo_validate_evict_gutting),
+ KUNIT_CASE(ttm_bo_validate_recrusive_evict),
+ {}
+};
+
+static struct kunit_suite ttm_bo_validate_test_suite = {
+ .name = "ttm_bo_validate",
+ .init = ttm_test_devices_all_init,
+ .exit = ttm_test_devices_fini,
+ .test_cases = ttm_bo_validate_test_cases,
+};
+
+kunit_test_suites(&ttm_bo_validate_test_suite);
+
+MODULE_DESCRIPTION("KUnit tests for ttm_bo APIs");
+MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/gpu/drm/ttm/tests/ttm_device_test.c b/drivers/gpu/drm/ttm/tests/ttm_device_test.c
index 19eaff22e6ae..1621903818e5 100644
--- a/drivers/gpu/drm/ttm/tests/ttm_device_test.c
+++ b/drivers/gpu/drm/ttm/tests/ttm_device_test.c
@@ -209,4 +209,5 @@ static struct kunit_suite ttm_device_test_suite = {
kunit_test_suites(&ttm_device_test_suite);
-MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("KUnit tests for ttm_device APIs");
+MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.c b/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.c
index 7b7c1fa805fc..b91c13f46225 100644
--- a/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.c
+++ b/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.c
@@ -6,8 +6,43 @@
#include "ttm_kunit_helpers.h"
-static struct ttm_tt *ttm_tt_simple_create(struct ttm_buffer_object *bo,
- uint32_t page_flags)
+static const struct ttm_place sys_place = {
+ .fpfn = 0,
+ .lpfn = 0,
+ .mem_type = TTM_PL_SYSTEM,
+ .flags = TTM_PL_FLAG_FALLBACK,
+};
+
+static const struct ttm_place mock1_place = {
+ .fpfn = 0,
+ .lpfn = 0,
+ .mem_type = TTM_PL_MOCK1,
+ .flags = TTM_PL_FLAG_FALLBACK,
+};
+
+static const struct ttm_place mock2_place = {
+ .fpfn = 0,
+ .lpfn = 0,
+ .mem_type = TTM_PL_MOCK2,
+ .flags = TTM_PL_FLAG_FALLBACK,
+};
+
+static struct ttm_placement sys_placement = {
+ .num_placement = 1,
+ .placement = &sys_place,
+};
+
+static struct ttm_placement bad_placement = {
+ .num_placement = 1,
+ .placement = &mock1_place,
+};
+
+static struct ttm_placement mock_placement = {
+ .num_placement = 1,
+ .placement = &mock2_place,
+};
+
+static struct ttm_tt *ttm_tt_simple_create(struct ttm_buffer_object *bo, u32 page_flags)
{
struct ttm_tt *tt;
@@ -22,13 +57,84 @@ static void ttm_tt_simple_destroy(struct ttm_device *bdev, struct ttm_tt *ttm)
kfree(ttm);
}
-static void dummy_ttm_bo_destroy(struct ttm_buffer_object *bo)
+static int mock_move(struct ttm_buffer_object *bo, bool evict,
+ struct ttm_operation_ctx *ctx,
+ struct ttm_resource *new_mem,
+ struct ttm_place *hop)
+{
+ struct ttm_resource *old_mem = bo->resource;
+
+ if (!old_mem || (old_mem->mem_type == TTM_PL_SYSTEM && !bo->ttm)) {
+ ttm_bo_move_null(bo, new_mem);
+ return 0;
+ }
+
+ if (bo->resource->mem_type == TTM_PL_VRAM &&
+ new_mem->mem_type == TTM_PL_SYSTEM) {
+ hop->mem_type = TTM_PL_TT;
+ hop->flags = TTM_PL_FLAG_TEMPORARY;
+ hop->fpfn = 0;
+ hop->lpfn = 0;
+ return -EMULTIHOP;
+ }
+
+ if ((old_mem->mem_type == TTM_PL_SYSTEM &&
+ new_mem->mem_type == TTM_PL_TT) ||
+ (old_mem->mem_type == TTM_PL_TT &&
+ new_mem->mem_type == TTM_PL_SYSTEM)) {
+ ttm_bo_move_null(bo, new_mem);
+ return 0;
+ }
+
+ return ttm_bo_move_memcpy(bo, ctx, new_mem);
+}
+
+static void mock_evict_flags(struct ttm_buffer_object *bo,
+ struct ttm_placement *placement)
{
+ switch (bo->resource->mem_type) {
+ case TTM_PL_VRAM:
+ case TTM_PL_SYSTEM:
+ *placement = sys_placement;
+ break;
+ case TTM_PL_TT:
+ *placement = mock_placement;
+ break;
+ case TTM_PL_MOCK1:
+ /* Purge objects coming from this domain */
+ break;
+ }
+}
+
+static void bad_evict_flags(struct ttm_buffer_object *bo,
+ struct ttm_placement *placement)
+{
+ *placement = bad_placement;
+}
+
+static int ttm_device_kunit_init_with_funcs(struct ttm_test_devices *priv,
+ struct ttm_device *ttm,
+ bool use_dma_alloc,
+ bool use_dma32,
+ struct ttm_device_funcs *funcs)
+{
+ struct drm_device *drm = priv->drm;
+ int err;
+
+ err = ttm_device_init(ttm, funcs, drm->dev,
+ drm->anon_inode->i_mapping,
+ drm->vma_offset_manager,
+ use_dma_alloc, use_dma32);
+
+ return err;
}
struct ttm_device_funcs ttm_dev_funcs = {
.ttm_tt_create = ttm_tt_simple_create,
.ttm_tt_destroy = ttm_tt_simple_destroy,
+ .move = mock_move,
+ .eviction_valuable = ttm_bo_eviction_valuable,
+ .evict_flags = mock_evict_flags,
};
EXPORT_SYMBOL_GPL(ttm_dev_funcs);
@@ -37,21 +143,34 @@ int ttm_device_kunit_init(struct ttm_test_devices *priv,
bool use_dma_alloc,
bool use_dma32)
{
- struct drm_device *drm = priv->drm;
- int err;
+ return ttm_device_kunit_init_with_funcs(priv, ttm, use_dma_alloc,
+ use_dma32, &ttm_dev_funcs);
+}
+EXPORT_SYMBOL_GPL(ttm_device_kunit_init);
- err = ttm_device_init(ttm, &ttm_dev_funcs, drm->dev,
- drm->anon_inode->i_mapping,
- drm->vma_offset_manager,
- use_dma_alloc, use_dma32);
+struct ttm_device_funcs ttm_dev_funcs_bad_evict = {
+ .ttm_tt_create = ttm_tt_simple_create,
+ .ttm_tt_destroy = ttm_tt_simple_destroy,
+ .move = mock_move,
+ .eviction_valuable = ttm_bo_eviction_valuable,
+ .evict_flags = bad_evict_flags,
+};
+EXPORT_SYMBOL_GPL(ttm_dev_funcs_bad_evict);
- return err;
+int ttm_device_kunit_init_bad_evict(struct ttm_test_devices *priv,
+ struct ttm_device *ttm,
+ bool use_dma_alloc,
+ bool use_dma32)
+{
+ return ttm_device_kunit_init_with_funcs(priv, ttm, use_dma_alloc,
+ use_dma32, &ttm_dev_funcs_bad_evict);
}
-EXPORT_SYMBOL_GPL(ttm_device_kunit_init);
+EXPORT_SYMBOL_GPL(ttm_device_kunit_init_bad_evict);
struct ttm_buffer_object *ttm_bo_kunit_init(struct kunit *test,
struct ttm_test_devices *devs,
- size_t size)
+ size_t size,
+ struct dma_resv *obj)
{
struct drm_gem_object gem_obj = { };
struct ttm_buffer_object *bo;
@@ -61,6 +180,10 @@ struct ttm_buffer_object *ttm_bo_kunit_init(struct kunit *test,
KUNIT_ASSERT_NOT_NULL(test, bo);
bo->base = gem_obj;
+
+ if (obj)
+ bo->base.resv = obj;
+
err = drm_gem_object_init(devs->drm, &bo->base, size);
KUNIT_ASSERT_EQ(test, err, 0);
@@ -73,8 +196,7 @@ struct ttm_buffer_object *ttm_bo_kunit_init(struct kunit *test,
}
EXPORT_SYMBOL_GPL(ttm_bo_kunit_init);
-struct ttm_place *ttm_place_kunit_init(struct kunit *test,
- uint32_t mem_type, uint32_t flags)
+struct ttm_place *ttm_place_kunit_init(struct kunit *test, u32 mem_type, u32 flags)
{
struct ttm_place *place;
@@ -88,6 +210,12 @@ struct ttm_place *ttm_place_kunit_init(struct kunit *test,
}
EXPORT_SYMBOL_GPL(ttm_place_kunit_init);
+void dummy_ttm_bo_destroy(struct ttm_buffer_object *bo)
+{
+ drm_gem_object_release(&bo->base);
+}
+EXPORT_SYMBOL_GPL(dummy_ttm_bo_destroy);
+
struct ttm_test_devices *ttm_test_devices_basic(struct kunit *test)
{
struct ttm_test_devices *devs;
@@ -98,6 +226,9 @@ struct ttm_test_devices *ttm_test_devices_basic(struct kunit *test)
devs->dev = drm_kunit_helper_alloc_device(test);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, devs->dev);
+ /* Set mask for alloc_coherent mappings to enable ttm_pool_alloc testing */
+ devs->dev->coherent_dma_mask = -1;
+
devs->drm = __drm_kunit_helper_alloc_drm_device(test, devs->dev,
sizeof(*devs->drm), 0,
DRIVER_GEM);
@@ -150,10 +281,25 @@ int ttm_test_devices_init(struct kunit *test)
}
EXPORT_SYMBOL_GPL(ttm_test_devices_init);
+int ttm_test_devices_all_init(struct kunit *test)
+{
+ struct ttm_test_devices *priv;
+
+ priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, priv);
+
+ priv = ttm_test_devices_all(test);
+ test->priv = priv;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ttm_test_devices_all_init);
+
void ttm_test_devices_fini(struct kunit *test)
{
ttm_test_devices_put(test, test->priv);
}
EXPORT_SYMBOL_GPL(ttm_test_devices_fini);
-MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("TTM KUnit test helper functions");
+MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.h b/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.h
index 2f51c833a536..c7da23232ffa 100644
--- a/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.h
+++ b/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.h
@@ -13,7 +13,11 @@
#include <drm/drm_kunit_helpers.h>
#include <kunit/test.h>
+#define TTM_PL_MOCK1 (TTM_PL_PRIV + 1)
+#define TTM_PL_MOCK2 (TTM_PL_PRIV + 2)
+
extern struct ttm_device_funcs ttm_dev_funcs;
+extern struct ttm_device_funcs ttm_dev_funcs_bad_evict;
struct ttm_test_devices {
struct drm_device *drm;
@@ -26,11 +30,17 @@ int ttm_device_kunit_init(struct ttm_test_devices *priv,
struct ttm_device *ttm,
bool use_dma_alloc,
bool use_dma32);
+int ttm_device_kunit_init_bad_evict(struct ttm_test_devices *priv,
+ struct ttm_device *ttm,
+ bool use_dma_alloc,
+ bool use_dma32);
struct ttm_buffer_object *ttm_bo_kunit_init(struct kunit *test,
struct ttm_test_devices *devs,
- size_t size);
-struct ttm_place *ttm_place_kunit_init(struct kunit *test,
- uint32_t mem_type, uint32_t flags);
+ size_t size,
+ struct dma_resv *obj);
+struct ttm_place *ttm_place_kunit_init(struct kunit *test, u32 mem_type,
+ u32 flags);
+void dummy_ttm_bo_destroy(struct ttm_buffer_object *bo);
struct ttm_test_devices *ttm_test_devices_basic(struct kunit *test);
struct ttm_test_devices *ttm_test_devices_all(struct kunit *test);
@@ -39,6 +49,7 @@ void ttm_test_devices_put(struct kunit *test, struct ttm_test_devices *devs);
/* Generic init/fini for tests that only need DRM/TTM devices */
int ttm_test_devices_init(struct kunit *test);
+int ttm_test_devices_all_init(struct kunit *test);
void ttm_test_devices_fini(struct kunit *test);
#endif // TTM_KUNIT_HELPERS_H
diff --git a/drivers/gpu/drm/ttm/tests/ttm_mock_manager.c b/drivers/gpu/drm/ttm/tests/ttm_mock_manager.c
new file mode 100644
index 000000000000..f6d1c8a2845d
--- /dev/null
+++ b/drivers/gpu/drm/ttm/tests/ttm_mock_manager.c
@@ -0,0 +1,234 @@
+// SPDX-License-Identifier: GPL-2.0 AND MIT
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+#include <drm/ttm/ttm_resource.h>
+#include <drm/ttm/ttm_device.h>
+#include <drm/ttm/ttm_placement.h>
+
+#include "ttm_mock_manager.h"
+
+static inline struct ttm_mock_manager *
+to_mock_mgr(struct ttm_resource_manager *man)
+{
+ return container_of(man, struct ttm_mock_manager, man);
+}
+
+static inline struct ttm_mock_resource *
+to_mock_mgr_resource(struct ttm_resource *res)
+{
+ return container_of(res, struct ttm_mock_resource, base);
+}
+
+static int ttm_mock_manager_alloc(struct ttm_resource_manager *man,
+ struct ttm_buffer_object *bo,
+ const struct ttm_place *place,
+ struct ttm_resource **res)
+{
+ struct ttm_mock_manager *manager = to_mock_mgr(man);
+ struct ttm_mock_resource *mock_res;
+ struct drm_buddy *mm = &manager->mm;
+ u64 lpfn, fpfn, alloc_size;
+ int err;
+
+ mock_res = kzalloc(sizeof(*mock_res), GFP_KERNEL);
+
+ if (!mock_res)
+ return -ENOMEM;
+
+ fpfn = 0;
+ lpfn = man->size;
+
+ ttm_resource_init(bo, place, &mock_res->base);
+ INIT_LIST_HEAD(&mock_res->blocks);
+
+ if (place->flags & TTM_PL_FLAG_TOPDOWN)
+ mock_res->flags |= DRM_BUDDY_TOPDOWN_ALLOCATION;
+
+ if (place->flags & TTM_PL_FLAG_CONTIGUOUS)
+ mock_res->flags |= DRM_BUDDY_CONTIGUOUS_ALLOCATION;
+
+ alloc_size = (uint64_t)mock_res->base.size;
+ mutex_lock(&manager->lock);
+ err = drm_buddy_alloc_blocks(mm, fpfn, lpfn, alloc_size,
+ manager->default_page_size,
+ &mock_res->blocks,
+ mock_res->flags);
+
+ if (err)
+ goto error_free_blocks;
+ mutex_unlock(&manager->lock);
+
+ *res = &mock_res->base;
+ return 0;
+
+error_free_blocks:
+ drm_buddy_free_list(mm, &mock_res->blocks, 0);
+ ttm_resource_fini(man, &mock_res->base);
+ mutex_unlock(&manager->lock);
+
+ return err;
+}
+
+static void ttm_mock_manager_free(struct ttm_resource_manager *man,
+ struct ttm_resource *res)
+{
+ struct ttm_mock_manager *manager = to_mock_mgr(man);
+ struct ttm_mock_resource *mock_res = to_mock_mgr_resource(res);
+ struct drm_buddy *mm = &manager->mm;
+
+ mutex_lock(&manager->lock);
+ drm_buddy_free_list(mm, &mock_res->blocks, 0);
+ mutex_unlock(&manager->lock);
+
+ ttm_resource_fini(man, res);
+ kfree(mock_res);
+}
+
+static const struct ttm_resource_manager_func ttm_mock_manager_funcs = {
+ .alloc = ttm_mock_manager_alloc,
+ .free = ttm_mock_manager_free,
+};
+
+int ttm_mock_manager_init(struct ttm_device *bdev, u32 mem_type, u32 size)
+{
+ struct ttm_mock_manager *manager;
+ struct ttm_resource_manager *base;
+ int err;
+
+ manager = kzalloc(sizeof(*manager), GFP_KERNEL);
+ if (!manager)
+ return -ENOMEM;
+
+ mutex_init(&manager->lock);
+
+ err = drm_buddy_init(&manager->mm, size, PAGE_SIZE);
+
+ if (err) {
+ kfree(manager);
+ return err;
+ }
+
+ manager->default_page_size = PAGE_SIZE;
+ base = &manager->man;
+ base->func = &ttm_mock_manager_funcs;
+ base->use_tt = true;
+
+ ttm_resource_manager_init(base, bdev, size);
+ ttm_set_driver_manager(bdev, mem_type, base);
+ ttm_resource_manager_set_used(base, true);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ttm_mock_manager_init);
+
+void ttm_mock_manager_fini(struct ttm_device *bdev, u32 mem_type)
+{
+ struct ttm_resource_manager *man;
+ struct ttm_mock_manager *mock_man;
+ int err;
+
+ man = ttm_manager_type(bdev, mem_type);
+ mock_man = to_mock_mgr(man);
+
+ err = ttm_resource_manager_evict_all(bdev, man);
+ if (err)
+ return;
+
+ ttm_resource_manager_set_used(man, false);
+
+ mutex_lock(&mock_man->lock);
+ drm_buddy_fini(&mock_man->mm);
+ mutex_unlock(&mock_man->lock);
+
+ ttm_set_driver_manager(bdev, mem_type, NULL);
+}
+EXPORT_SYMBOL_GPL(ttm_mock_manager_fini);
+
+static int ttm_bad_manager_alloc(struct ttm_resource_manager *man,
+ struct ttm_buffer_object *bo,
+ const struct ttm_place *place,
+ struct ttm_resource **res)
+{
+ return -ENOSPC;
+}
+
+static int ttm_busy_manager_alloc(struct ttm_resource_manager *man,
+ struct ttm_buffer_object *bo,
+ const struct ttm_place *place,
+ struct ttm_resource **res)
+{
+ return -EBUSY;
+}
+
+static void ttm_bad_manager_free(struct ttm_resource_manager *man,
+ struct ttm_resource *res)
+{
+}
+
+static bool ttm_bad_manager_compatible(struct ttm_resource_manager *man,
+ struct ttm_resource *res,
+ const struct ttm_place *place,
+ size_t size)
+{
+ return true;
+}
+
+static const struct ttm_resource_manager_func ttm_bad_manager_funcs = {
+ .alloc = ttm_bad_manager_alloc,
+ .free = ttm_bad_manager_free,
+ .compatible = ttm_bad_manager_compatible
+};
+
+static const struct ttm_resource_manager_func ttm_bad_busy_manager_funcs = {
+ .alloc = ttm_busy_manager_alloc,
+ .free = ttm_bad_manager_free,
+ .compatible = ttm_bad_manager_compatible
+};
+
+int ttm_bad_manager_init(struct ttm_device *bdev, u32 mem_type, u32 size)
+{
+ struct ttm_resource_manager *man;
+
+ man = kzalloc(sizeof(*man), GFP_KERNEL);
+ if (!man)
+ return -ENOMEM;
+
+ man->func = &ttm_bad_manager_funcs;
+
+ ttm_resource_manager_init(man, bdev, size);
+ ttm_set_driver_manager(bdev, mem_type, man);
+ ttm_resource_manager_set_used(man, true);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ttm_bad_manager_init);
+
+int ttm_busy_manager_init(struct ttm_device *bdev, u32 mem_type, u32 size)
+{
+ struct ttm_resource_manager *man;
+
+ ttm_bad_manager_init(bdev, mem_type, size);
+ man = ttm_manager_type(bdev, mem_type);
+
+ man->func = &ttm_bad_busy_manager_funcs;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ttm_busy_manager_init);
+
+void ttm_bad_manager_fini(struct ttm_device *bdev, uint32_t mem_type)
+{
+ struct ttm_resource_manager *man;
+
+ man = ttm_manager_type(bdev, mem_type);
+
+ ttm_resource_manager_set_used(man, false);
+ ttm_set_driver_manager(bdev, mem_type, NULL);
+
+ kfree(man);
+}
+EXPORT_SYMBOL_GPL(ttm_bad_manager_fini);
+
+MODULE_DESCRIPTION("KUnit tests for ttm with mock resource managers");
+MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/gpu/drm/ttm/tests/ttm_mock_manager.h b/drivers/gpu/drm/ttm/tests/ttm_mock_manager.h
new file mode 100644
index 000000000000..e4c95f86a467
--- /dev/null
+++ b/drivers/gpu/drm/ttm/tests/ttm_mock_manager.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0 AND MIT */
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+#ifndef TTM_MOCK_MANAGER_H
+#define TTM_MOCK_MANAGER_H
+
+#include <drm/drm_buddy.h>
+
+struct ttm_mock_manager {
+ struct ttm_resource_manager man;
+ struct drm_buddy mm;
+ u64 default_page_size;
+ /* protects allocations of mock buffer objects */
+ struct mutex lock;
+};
+
+struct ttm_mock_resource {
+ struct ttm_resource base;
+ struct list_head blocks;
+ unsigned long flags;
+};
+
+int ttm_mock_manager_init(struct ttm_device *bdev, u32 mem_type, u32 size);
+int ttm_bad_manager_init(struct ttm_device *bdev, u32 mem_type, u32 size);
+int ttm_busy_manager_init(struct ttm_device *bdev, u32 mem_type, u32 size);
+void ttm_mock_manager_fini(struct ttm_device *bdev, u32 mem_type);
+void ttm_bad_manager_fini(struct ttm_device *bdev, u32 mem_type);
+
+#endif // TTM_MOCK_MANAGER_H
diff --git a/drivers/gpu/drm/ttm/tests/ttm_pool_test.c b/drivers/gpu/drm/ttm/tests/ttm_pool_test.c
index 0a3fede84da9..8ade53371f72 100644
--- a/drivers/gpu/drm/ttm/tests/ttm_pool_test.c
+++ b/drivers/gpu/drm/ttm/tests/ttm_pool_test.c
@@ -48,7 +48,7 @@ static void ttm_pool_test_fini(struct kunit *test)
}
static struct ttm_tt *ttm_tt_kunit_init(struct kunit *test,
- uint32_t page_flags,
+ u32 page_flags,
enum ttm_caching caching,
size_t size)
{
@@ -57,7 +57,7 @@ static struct ttm_tt *ttm_tt_kunit_init(struct kunit *test,
struct ttm_tt *tt;
int err;
- bo = ttm_bo_kunit_init(test, priv->devs, size);
+ bo = ttm_bo_kunit_init(test, priv->devs, size, NULL);
KUNIT_ASSERT_NOT_NULL(test, bo);
priv->mock_bo = bo;
@@ -209,7 +209,7 @@ static void ttm_pool_alloc_basic_dma_addr(struct kunit *test)
tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL);
KUNIT_ASSERT_NOT_NULL(test, tt);
- bo = ttm_bo_kunit_init(test, devs, size);
+ bo = ttm_bo_kunit_init(test, devs, size, NULL);
KUNIT_ASSERT_NOT_NULL(test, bo);
err = ttm_sg_tt_init(tt, bo, 0, caching);
@@ -433,4 +433,5 @@ static struct kunit_suite ttm_pool_test_suite = {
kunit_test_suites(&ttm_pool_test_suite);
-MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("KUnit tests for ttm_pool APIs");
+MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/gpu/drm/ttm/tests/ttm_resource_test.c b/drivers/gpu/drm/ttm/tests/ttm_resource_test.c
index 029e1f094bb0..9c2f13e53162 100644
--- a/drivers/gpu/drm/ttm/tests/ttm_resource_test.c
+++ b/drivers/gpu/drm/ttm/tests/ttm_resource_test.c
@@ -11,8 +11,8 @@
struct ttm_resource_test_case {
const char *description;
- uint32_t mem_type;
- uint32_t flags;
+ u32 mem_type;
+ u32 flags;
};
struct ttm_resource_test_priv {
@@ -47,20 +47,20 @@ static void ttm_resource_test_fini(struct kunit *test)
static void ttm_init_test_mocks(struct kunit *test,
struct ttm_resource_test_priv *priv,
- uint32_t mem_type, uint32_t flags)
+ u32 mem_type, u32 flags)
{
size_t size = RES_SIZE;
/* Make sure we have what we need for a good BO mock */
KUNIT_ASSERT_NOT_NULL(test, priv->devs->ttm_dev);
- priv->bo = ttm_bo_kunit_init(test, priv->devs, size);
+ priv->bo = ttm_bo_kunit_init(test, priv->devs, size, NULL);
priv->place = ttm_place_kunit_init(test, mem_type, flags);
}
static void ttm_init_test_manager(struct kunit *test,
struct ttm_resource_test_priv *priv,
- uint32_t mem_type)
+ u32 mem_type)
{
struct ttm_device *ttm_dev = priv->devs->ttm_dev;
struct ttm_resource_manager *man;
@@ -112,7 +112,7 @@ static void ttm_resource_init_basic(struct kunit *test)
struct ttm_buffer_object *bo;
struct ttm_place *place;
struct ttm_resource_manager *man;
- uint64_t expected_usage;
+ u64 expected_usage;
ttm_init_test_mocks(test, priv, params->mem_type, params->flags);
bo = priv->bo;
@@ -230,7 +230,7 @@ static void ttm_resource_manager_usage_basic(struct kunit *test)
struct ttm_buffer_object *bo;
struct ttm_place *place;
struct ttm_resource_manager *man;
- uint64_t actual_usage;
+ u64 actual_usage;
ttm_init_test_mocks(test, priv, TTM_PL_SYSTEM, TTM_PL_FLAG_TOPDOWN);
bo = priv->bo;
@@ -268,7 +268,7 @@ static void ttm_sys_man_alloc_basic(struct kunit *test)
struct ttm_buffer_object *bo;
struct ttm_place *place;
struct ttm_resource *res;
- uint32_t mem_type = TTM_PL_SYSTEM;
+ u32 mem_type = TTM_PL_SYSTEM;
int ret;
ttm_init_test_mocks(test, priv, mem_type, 0);
@@ -293,7 +293,7 @@ static void ttm_sys_man_free_basic(struct kunit *test)
struct ttm_buffer_object *bo;
struct ttm_place *place;
struct ttm_resource *res;
- uint32_t mem_type = TTM_PL_SYSTEM;
+ u32 mem_type = TTM_PL_SYSTEM;
ttm_init_test_mocks(test, priv, mem_type, 0);
bo = priv->bo;
@@ -332,4 +332,5 @@ static struct kunit_suite ttm_resource_test_suite = {
kunit_test_suites(&ttm_resource_test_suite);
-MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("KUnit tests for ttm_resource and ttm_sys_man APIs");
+MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/gpu/drm/ttm/tests/ttm_tt_test.c b/drivers/gpu/drm/ttm/tests/ttm_tt_test.c
index fd4502c18de6..61ec6f580b62 100644
--- a/drivers/gpu/drm/ttm/tests/ttm_tt_test.c
+++ b/drivers/gpu/drm/ttm/tests/ttm_tt_test.c
@@ -11,23 +11,10 @@
struct ttm_tt_test_case {
const char *description;
- uint32_t size;
- uint32_t extra_pages_num;
+ u32 size;
+ u32 extra_pages_num;
};
-static int ttm_tt_test_init(struct kunit *test)
-{
- struct ttm_test_devices *priv;
-
- priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
- KUNIT_ASSERT_NOT_NULL(test, priv);
-
- priv = ttm_test_devices_all(test);
- test->priv = priv;
-
- return 0;
-}
-
static const struct ttm_tt_test_case ttm_tt_init_basic_cases[] = {
{
.description = "Page-aligned size",
@@ -54,16 +41,16 @@ static void ttm_tt_init_basic(struct kunit *test)
const struct ttm_tt_test_case *params = test->param_value;
struct ttm_buffer_object *bo;
struct ttm_tt *tt;
- uint32_t page_flags = TTM_TT_FLAG_ZERO_ALLOC;
+ u32 page_flags = TTM_TT_FLAG_ZERO_ALLOC;
enum ttm_caching caching = ttm_cached;
- uint32_t extra_pages = params->extra_pages_num;
+ u32 extra_pages = params->extra_pages_num;
int num_pages = params->size >> PAGE_SHIFT;
int err;
tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL);
KUNIT_ASSERT_NOT_NULL(test, tt);
- bo = ttm_bo_kunit_init(test, test->priv, params->size);
+ bo = ttm_bo_kunit_init(test, test->priv, params->size, NULL);
err = ttm_tt_init(tt, bo, page_flags, caching, extra_pages);
KUNIT_ASSERT_EQ(test, err, 0);
@@ -82,14 +69,14 @@ static void ttm_tt_init_misaligned(struct kunit *test)
struct ttm_buffer_object *bo;
struct ttm_tt *tt;
enum ttm_caching caching = ttm_cached;
- uint32_t size = SZ_8K;
+ u32 size = SZ_8K;
int num_pages = (size + SZ_4K) >> PAGE_SHIFT;
int err;
tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL);
KUNIT_ASSERT_NOT_NULL(test, tt);
- bo = ttm_bo_kunit_init(test, test->priv, size);
+ bo = ttm_bo_kunit_init(test, test->priv, size, NULL);
/* Make the object size misaligned */
bo->base.size += 1;
@@ -110,7 +97,7 @@ static void ttm_tt_fini_basic(struct kunit *test)
tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL);
KUNIT_ASSERT_NOT_NULL(test, tt);
- bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+ bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
err = ttm_tt_init(tt, bo, 0, caching, 0);
KUNIT_ASSERT_EQ(test, err, 0);
@@ -130,7 +117,7 @@ static void ttm_tt_fini_sg(struct kunit *test)
tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL);
KUNIT_ASSERT_NOT_NULL(test, tt);
- bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+ bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
err = ttm_sg_tt_init(tt, bo, 0, caching);
KUNIT_ASSERT_EQ(test, err, 0);
@@ -151,7 +138,7 @@ static void ttm_tt_fini_shmem(struct kunit *test)
tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL);
KUNIT_ASSERT_NOT_NULL(test, tt);
- bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+ bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
err = ttm_tt_init(tt, bo, 0, caching, 0);
KUNIT_ASSERT_EQ(test, err, 0);
@@ -168,7 +155,7 @@ static void ttm_tt_create_basic(struct kunit *test)
struct ttm_buffer_object *bo;
int err;
- bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+ bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
bo->type = ttm_bo_type_device;
dma_resv_lock(bo->base.resv, NULL);
@@ -187,7 +174,7 @@ static void ttm_tt_create_invalid_bo_type(struct kunit *test)
struct ttm_buffer_object *bo;
int err;
- bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+ bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
bo->type = ttm_bo_type_sg + 1;
dma_resv_lock(bo->base.resv, NULL);
@@ -208,7 +195,7 @@ static void ttm_tt_create_ttm_exists(struct kunit *test)
tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL);
KUNIT_ASSERT_NOT_NULL(test, tt);
- bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+ bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
err = ttm_tt_init(tt, bo, 0, caching, 0);
KUNIT_ASSERT_EQ(test, err, 0);
@@ -224,7 +211,7 @@ static void ttm_tt_create_ttm_exists(struct kunit *test)
}
static struct ttm_tt *ttm_tt_null_create(struct ttm_buffer_object *bo,
- uint32_t page_flags)
+ u32 page_flags)
{
return NULL;
}
@@ -239,7 +226,7 @@ static void ttm_tt_create_failed(struct kunit *test)
struct ttm_buffer_object *bo;
int err;
- bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+ bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
/* Update ttm_device_funcs so we don't alloc ttm_tt */
devs->ttm_dev->funcs = &ttm_dev_empty_funcs;
@@ -257,7 +244,7 @@ static void ttm_tt_destroy_basic(struct kunit *test)
struct ttm_buffer_object *bo;
int err;
- bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+ bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
dma_resv_lock(bo->base.resv, NULL);
err = ttm_tt_create(bo, false);
@@ -269,6 +256,120 @@ static void ttm_tt_destroy_basic(struct kunit *test)
ttm_tt_destroy(devs->ttm_dev, bo->ttm);
}
+static void ttm_tt_populate_null_ttm(struct kunit *test)
+{
+ const struct ttm_test_devices *devs = test->priv;
+ struct ttm_operation_ctx ctx = { };
+ int err;
+
+ err = ttm_tt_populate(devs->ttm_dev, NULL, &ctx);
+ KUNIT_ASSERT_EQ(test, err, -EINVAL);
+}
+
+static void ttm_tt_populate_populated_ttm(struct kunit *test)
+{
+ const struct ttm_test_devices *devs = test->priv;
+ struct ttm_operation_ctx ctx = { };
+ struct ttm_buffer_object *bo;
+ struct ttm_tt *tt;
+ struct page *populated_page;
+ int err;
+
+ bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
+
+ tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, tt);
+
+ err = ttm_tt_init(tt, bo, 0, ttm_cached, 0);
+ KUNIT_ASSERT_EQ(test, err, 0);
+
+ err = ttm_tt_populate(devs->ttm_dev, tt, &ctx);
+ KUNIT_ASSERT_EQ(test, err, 0);
+ populated_page = *tt->pages;
+
+ err = ttm_tt_populate(devs->ttm_dev, tt, &ctx);
+ KUNIT_ASSERT_PTR_EQ(test, populated_page, *tt->pages);
+}
+
+static void ttm_tt_unpopulate_basic(struct kunit *test)
+{
+ const struct ttm_test_devices *devs = test->priv;
+ struct ttm_operation_ctx ctx = { };
+ struct ttm_buffer_object *bo;
+ struct ttm_tt *tt;
+ int err;
+
+ bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
+
+ tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, tt);
+
+ err = ttm_tt_init(tt, bo, 0, ttm_cached, 0);
+ KUNIT_ASSERT_EQ(test, err, 0);
+
+ err = ttm_tt_populate(devs->ttm_dev, tt, &ctx);
+ KUNIT_ASSERT_EQ(test, err, 0);
+ KUNIT_ASSERT_TRUE(test, ttm_tt_is_populated(tt));
+
+ ttm_tt_unpopulate(devs->ttm_dev, tt);
+ KUNIT_ASSERT_FALSE(test, ttm_tt_is_populated(tt));
+}
+
+static void ttm_tt_unpopulate_empty_ttm(struct kunit *test)
+{
+ const struct ttm_test_devices *devs = test->priv;
+ struct ttm_buffer_object *bo;
+ struct ttm_tt *tt;
+ int err;
+
+ bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
+
+ tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, tt);
+
+ err = ttm_tt_init(tt, bo, 0, ttm_cached, 0);
+ KUNIT_ASSERT_EQ(test, err, 0);
+
+ ttm_tt_unpopulate(devs->ttm_dev, tt);
+ /* Expect graceful handling of unpopulated TTs */
+}
+
+static void ttm_tt_swapin_basic(struct kunit *test)
+{
+ const struct ttm_test_devices *devs = test->priv;
+ int expected_num_pages = BO_SIZE >> PAGE_SHIFT;
+ struct ttm_operation_ctx ctx = { };
+ struct ttm_buffer_object *bo;
+ struct ttm_tt *tt;
+ int err, num_pages;
+
+ bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
+
+ tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, tt);
+
+ err = ttm_tt_init(tt, bo, 0, ttm_cached, 0);
+ KUNIT_ASSERT_EQ(test, err, 0);
+
+ err = ttm_tt_populate(devs->ttm_dev, tt, &ctx);
+ KUNIT_ASSERT_EQ(test, err, 0);
+ KUNIT_ASSERT_TRUE(test, ttm_tt_is_populated(tt));
+
+ num_pages = ttm_tt_swapout(devs->ttm_dev, tt, GFP_KERNEL);
+ KUNIT_ASSERT_EQ(test, num_pages, expected_num_pages);
+ KUNIT_ASSERT_NOT_NULL(test, tt->swap_storage);
+ KUNIT_ASSERT_TRUE(test, tt->page_flags & TTM_TT_FLAG_SWAPPED);
+
+ /* Swapout depopulates TT, allocate pages and then swap them in */
+ err = ttm_pool_alloc(&devs->ttm_dev->pool, tt, &ctx);
+ KUNIT_ASSERT_EQ(test, err, 0);
+
+ err = ttm_tt_swapin(tt);
+ KUNIT_ASSERT_EQ(test, err, 0);
+ KUNIT_ASSERT_NULL(test, tt->swap_storage);
+ KUNIT_ASSERT_FALSE(test, tt->page_flags & TTM_TT_FLAG_SWAPPED);
+}
+
static struct kunit_case ttm_tt_test_cases[] = {
KUNIT_CASE_PARAM(ttm_tt_init_basic, ttm_tt_init_basic_gen_params),
KUNIT_CASE(ttm_tt_init_misaligned),
@@ -280,16 +381,22 @@ static struct kunit_case ttm_tt_test_cases[] = {
KUNIT_CASE(ttm_tt_create_ttm_exists),
KUNIT_CASE(ttm_tt_create_failed),
KUNIT_CASE(ttm_tt_destroy_basic),
+ KUNIT_CASE(ttm_tt_populate_null_ttm),
+ KUNIT_CASE(ttm_tt_populate_populated_ttm),
+ KUNIT_CASE(ttm_tt_unpopulate_basic),
+ KUNIT_CASE(ttm_tt_unpopulate_empty_ttm),
+ KUNIT_CASE(ttm_tt_swapin_basic),
{}
};
static struct kunit_suite ttm_tt_test_suite = {
.name = "ttm_tt",
- .init = ttm_tt_test_init,
+ .init = ttm_test_devices_all_init,
.exit = ttm_test_devices_fini,
.test_cases = ttm_tt_test_cases,
};
kunit_test_suites(&ttm_tt_test_suite);
-MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("KUnit tests for ttm_tt APIs");
+MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index 6396dece0db1..2427be8bc97f 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -346,6 +346,7 @@ static void ttm_bo_release(struct kref *kref)
if (!dma_resv_test_signaled(bo->base.resv,
DMA_RESV_USAGE_BOOKKEEP) ||
(want_init_on_free() && (bo->ttm != NULL)) ||
+ bo->type == ttm_bo_type_sg ||
!dma_resv_trylock(bo->base.resv)) {
/* The BO is not idle, resurrect it for delayed destroy */
ttm_bo_flush_all_fences(bo);
diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c
index 7b00ddf0ce49..4b51b9023126 100644
--- a/drivers/gpu/drm/ttm/ttm_tt.c
+++ b/drivers/gpu/drm/ttm/ttm_tt.c
@@ -251,6 +251,7 @@ int ttm_tt_swapin(struct ttm_tt *ttm)
out_err:
return ret;
}
+EXPORT_SYMBOL_FOR_TESTS_ONLY(ttm_tt_swapin);
/**
* ttm_tt_swapout - swap out tt object
@@ -308,6 +309,7 @@ out_err:
return ret;
}
+EXPORT_SYMBOL_FOR_TESTS_ONLY(ttm_tt_swapout);
int ttm_tt_populate(struct ttm_device *bdev,
struct ttm_tt *ttm, struct ttm_operation_ctx *ctx)
@@ -386,6 +388,7 @@ void ttm_tt_unpopulate(struct ttm_device *bdev, struct ttm_tt *ttm)
ttm->page_flags &= ~TTM_TT_FLAG_PRIV_POPULATED;
}
+EXPORT_SYMBOL_FOR_TESTS_ONLY(ttm_tt_unpopulate);
#ifdef CONFIG_DEBUG_FS
diff --git a/drivers/gpu/drm/udl/Makefile b/drivers/gpu/drm/udl/Makefile
index 3f6db179455d..43d69a16af18 100644
--- a/drivers/gpu/drm/udl/Makefile
+++ b/drivers/gpu/drm/udl/Makefile
@@ -1,4 +1,10 @@
# SPDX-License-Identifier: GPL-2.0-only
-udl-y := udl_drv.o udl_modeset.o udl_main.o udl_transfer.o
+
+udl-y := \
+ udl_drv.o \
+ udl_edid.o \
+ udl_main.o \
+ udl_modeset.o \
+ udl_transfer.o
obj-$(CONFIG_DRM_UDL) := udl.o
diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c
index 1506094a8009..280a09a6e2ad 100644
--- a/drivers/gpu/drm/udl/udl_drv.c
+++ b/drivers/gpu/drm/udl/udl_drv.c
@@ -6,7 +6,7 @@
#include <linux/module.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_shmem.h>
#include <drm/drm_file.h>
#include <drm/drm_gem_shmem_helper.h>
#include <drm/drm_managed.h>
@@ -117,7 +117,7 @@ static int udl_usb_probe(struct usb_interface *interface,
DRM_INFO("Initialized udl on minor %d\n", udl->drm.primary->index);
- drm_fbdev_generic_setup(&udl->drm, 0);
+ drm_fbdev_shmem_setup(&udl->drm, 0);
return 0;
}
@@ -160,4 +160,5 @@ static struct usb_driver udl_driver = {
.id_table = id_table,
};
module_usb_driver(udl_driver);
+MODULE_DESCRIPTION("KMS driver for the USB displaylink video adapters");
MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h
index 282ebd6c02fd..1eb716d9dad5 100644
--- a/drivers/gpu/drm/udl/udl_drv.h
+++ b/drivers/gpu/drm/udl/udl_drv.h
@@ -49,17 +49,6 @@ struct urb_list {
size_t size;
};
-struct udl_connector {
- struct drm_connector connector;
- /* last udl_detect edid */
- struct edid *edid;
-};
-
-static inline struct udl_connector *to_udl_connector(struct drm_connector *connector)
-{
- return container_of(connector, struct udl_connector, connector);
-}
-
struct udl_device {
struct drm_device drm;
struct device *dev;
@@ -68,6 +57,7 @@ struct udl_device {
struct drm_plane primary_plane;
struct drm_crtc crtc;
struct drm_encoder encoder;
+ struct drm_connector connector;
struct mutex gem_lock;
diff --git a/drivers/gpu/drm/udl/udl_edid.c b/drivers/gpu/drm/udl/udl_edid.c
new file mode 100644
index 000000000000..d67e6bf1f2ae
--- /dev/null
+++ b/drivers/gpu/drm/udl/udl_edid.c
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/string.h>
+
+#include <drm/drm_drv.h>
+#include <drm/drm_edid.h>
+
+#include "udl_drv.h"
+#include "udl_edid.h"
+
+static int udl_read_edid_block(void *data, u8 *buf, unsigned int block, size_t len)
+{
+ struct udl_device *udl = data;
+ struct drm_device *dev = &udl->drm;
+ struct usb_device *udev = udl_to_usb_device(udl);
+ u8 *read_buff;
+ int idx, ret;
+ size_t i;
+
+ read_buff = kmalloc(2, GFP_KERNEL);
+ if (!read_buff)
+ return -ENOMEM;
+
+ if (!drm_dev_enter(dev, &idx)) {
+ ret = -ENODEV;
+ goto err_kfree;
+ }
+
+ for (i = 0; i < len; i++) {
+ int bval = (i + block * EDID_LENGTH) << 8;
+
+ ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+ 0x02, (0x80 | (0x02 << 5)), bval,
+ 0xA1, read_buff, 2, USB_CTRL_GET_TIMEOUT);
+ if (ret < 0) {
+ drm_err(dev, "Read EDID byte %zu failed err %x\n", i, ret);
+ goto err_drm_dev_exit;
+ } else if (ret < 1) {
+ ret = -EIO;
+ drm_err(dev, "Read EDID byte %zu failed\n", i);
+ goto err_drm_dev_exit;
+ }
+
+ buf[i] = read_buff[1];
+ }
+
+ drm_dev_exit(idx);
+ kfree(read_buff);
+
+ return 0;
+
+err_drm_dev_exit:
+ drm_dev_exit(idx);
+err_kfree:
+ kfree(read_buff);
+ return ret;
+}
+
+bool udl_probe_edid(struct udl_device *udl)
+{
+ u8 hdr[8];
+ int ret;
+
+ ret = udl_read_edid_block(udl, hdr, 0, sizeof(hdr));
+ if (ret)
+ return false;
+
+ /*
+ * The adapter sends all-zeros if no monitor has been
+ * connected. We consider anything else a connection.
+ */
+ return !!memchr_inv(hdr, 0, sizeof(hdr));
+}
+
+const struct drm_edid *udl_edid_read(struct drm_connector *connector)
+{
+ struct udl_device *udl = to_udl(connector->dev);
+
+ return drm_edid_read_custom(connector, udl_read_edid_block, udl);
+}
diff --git a/drivers/gpu/drm/udl/udl_edid.h b/drivers/gpu/drm/udl/udl_edid.h
new file mode 100644
index 000000000000..fe15ff3752b7
--- /dev/null
+++ b/drivers/gpu/drm/udl/udl_edid.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef UDL_EDID_H
+#define UDL_EDID_H
+
+#include <linux/types.h>
+
+struct drm_connector;
+struct drm_edid;
+struct udl_device;
+
+bool udl_probe_edid(struct udl_device *udl);
+const struct drm_edid *udl_edid_read(struct drm_connector *connector);
+
+#endif
diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c
index 7702359c90c2..bbb04f98886a 100644
--- a/drivers/gpu/drm/udl/udl_modeset.c
+++ b/drivers/gpu/drm/udl/udl_modeset.c
@@ -25,6 +25,7 @@
#include <drm/drm_vblank.h>
#include "udl_drv.h"
+#include "udl_edid.h"
#include "udl_proto.h"
/*
@@ -415,129 +416,42 @@ static const struct drm_encoder_funcs udl_encoder_funcs = {
static int udl_connector_helper_get_modes(struct drm_connector *connector)
{
- struct udl_connector *udl_connector = to_udl_connector(connector);
+ const struct drm_edid *drm_edid;
+ int count;
- drm_connector_update_edid_property(connector, udl_connector->edid);
- if (udl_connector->edid)
- return drm_add_edid_modes(connector, udl_connector->edid);
+ drm_edid = udl_edid_read(connector);
+ drm_edid_connector_update(connector, drm_edid);
+ count = drm_edid_connector_add_modes(connector);
+ drm_edid_free(drm_edid);
- return 0;
-}
-
-static const struct drm_connector_helper_funcs udl_connector_helper_funcs = {
- .get_modes = udl_connector_helper_get_modes,
-};
-
-static int udl_get_edid_block(void *data, u8 *buf, unsigned int block, size_t len)
-{
- struct udl_device *udl = data;
- struct drm_device *dev = &udl->drm;
- struct usb_device *udev = udl_to_usb_device(udl);
- u8 *read_buff;
- int ret;
- size_t i;
-
- read_buff = kmalloc(2, GFP_KERNEL);
- if (!read_buff)
- return -ENOMEM;
-
- for (i = 0; i < len; i++) {
- int bval = (i + block * EDID_LENGTH) << 8;
-
- ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
- 0x02, (0x80 | (0x02 << 5)), bval,
- 0xA1, read_buff, 2, USB_CTRL_GET_TIMEOUT);
- if (ret < 0) {
- drm_err(dev, "Read EDID byte %zu failed err %x\n", i, ret);
- goto err_kfree;
- } else if (ret < 1) {
- ret = -EIO;
- drm_err(dev, "Read EDID byte %zu failed\n", i);
- goto err_kfree;
- }
-
- buf[i] = read_buff[1];
- }
-
- kfree(read_buff);
-
- return 0;
-
-err_kfree:
- kfree(read_buff);
- return ret;
+ return count;
}
-static enum drm_connector_status udl_connector_detect(struct drm_connector *connector, bool force)
+static int udl_connector_helper_detect_ctx(struct drm_connector *connector,
+ struct drm_modeset_acquire_ctx *ctx,
+ bool force)
{
- struct drm_device *dev = connector->dev;
- struct udl_device *udl = to_udl(dev);
- struct udl_connector *udl_connector = to_udl_connector(connector);
- enum drm_connector_status status = connector_status_disconnected;
- int idx;
+ struct udl_device *udl = to_udl(connector->dev);
- /* cleanup previous EDID */
- kfree(udl_connector->edid);
- udl_connector->edid = NULL;
+ if (udl_probe_edid(udl))
+ return connector_status_connected;
- if (!drm_dev_enter(dev, &idx))
- return connector_status_disconnected;
-
- udl_connector->edid = drm_do_get_edid(connector, udl_get_edid_block, udl);
- if (udl_connector->edid)
- status = connector_status_connected;
-
- drm_dev_exit(idx);
-
- return status;
+ return connector_status_disconnected;
}
-static void udl_connector_destroy(struct drm_connector *connector)
-{
- struct udl_connector *udl_connector = to_udl_connector(connector);
-
- drm_connector_cleanup(connector);
- kfree(udl_connector->edid);
- kfree(udl_connector);
-}
+static const struct drm_connector_helper_funcs udl_connector_helper_funcs = {
+ .get_modes = udl_connector_helper_get_modes,
+ .detect_ctx = udl_connector_helper_detect_ctx,
+};
static const struct drm_connector_funcs udl_connector_funcs = {
.reset = drm_atomic_helper_connector_reset,
- .detect = udl_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
- .destroy = udl_connector_destroy,
+ .destroy = drm_connector_cleanup,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};
-struct drm_connector *udl_connector_init(struct drm_device *dev)
-{
- struct udl_connector *udl_connector;
- struct drm_connector *connector;
- int ret;
-
- udl_connector = kzalloc(sizeof(*udl_connector), GFP_KERNEL);
- if (!udl_connector)
- return ERR_PTR(-ENOMEM);
-
- connector = &udl_connector->connector;
- ret = drm_connector_init(dev, connector, &udl_connector_funcs, DRM_MODE_CONNECTOR_VGA);
- if (ret)
- goto err_kfree;
-
- drm_connector_helper_add(connector, &udl_connector_helper_funcs);
-
- connector->polled = DRM_CONNECTOR_POLL_HPD |
- DRM_CONNECTOR_POLL_CONNECT |
- DRM_CONNECTOR_POLL_DISCONNECT;
-
- return connector;
-
-err_kfree:
- kfree(udl_connector);
- return ERR_PTR(ret);
-}
-
/*
* Modesetting
*/
@@ -607,9 +521,15 @@ int udl_modeset_init(struct drm_device *dev)
return ret;
encoder->possible_crtcs = drm_crtc_mask(crtc);
- connector = udl_connector_init(dev);
- if (IS_ERR(connector))
- return PTR_ERR(connector);
+ connector = &udl->connector;
+ ret = drm_connector_init(dev, connector, &udl_connector_funcs, DRM_MODE_CONNECTOR_VGA);
+ if (ret)
+ return ret;
+ drm_connector_helper_add(connector, &udl_connector_helper_funcs);
+
+ connector->polled = DRM_CONNECTOR_POLL_CONNECT |
+ DRM_CONNECTOR_POLL_DISCONNECT;
+
ret = drm_connector_attach_encoder(connector, encoder);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/v3d/v3d_drv.c b/drivers/gpu/drm/v3d/v3d_drv.c
index 28b7ddce7747..5982941d933b 100644
--- a/drivers/gpu/drm/v3d/v3d_drv.c
+++ b/drivers/gpu/drm/v3d/v3d_drv.c
@@ -94,6 +94,9 @@ static int v3d_get_param_ioctl(struct drm_device *dev, void *data,
case DRM_V3D_PARAM_SUPPORTS_CPU_QUEUE:
args->value = 1;
return 0;
+ case DRM_V3D_PARAM_MAX_PERF_COUNTERS:
+ args->value = v3d->max_counters;
+ return 0;
default:
DRM_DEBUG("Unknown parameter %d\n", args->param);
return -EINVAL;
@@ -208,6 +211,7 @@ static const struct drm_ioctl_desc v3d_drm_ioctls[] = {
DRM_IOCTL_DEF_DRV(V3D_PERFMON_DESTROY, v3d_perfmon_destroy_ioctl, DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(V3D_PERFMON_GET_VALUES, v3d_perfmon_get_values_ioctl, DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(V3D_SUBMIT_CPU, v3d_submit_cpu_ioctl, DRM_RENDER_ALLOW | DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(V3D_PERFMON_GET_COUNTER, v3d_perfmon_get_counter_ioctl, DRM_RENDER_ALLOW),
};
static const struct drm_driver v3d_drm_driver = {
@@ -261,7 +265,7 @@ static int v3d_platform_drm_probe(struct platform_device *pdev)
struct v3d_dev *v3d;
int ret;
u32 mmu_debug;
- u32 ident1;
+ u32 ident1, ident3;
u64 mask;
v3d = devm_drm_dev_alloc(dev, &v3d_drm_driver, struct v3d_dev, drm);
@@ -294,6 +298,16 @@ static int v3d_platform_drm_probe(struct platform_device *pdev)
v3d->cores = V3D_GET_FIELD(ident1, V3D_HUB_IDENT1_NCORES);
WARN_ON(v3d->cores > 1); /* multicore not yet implemented */
+ ident3 = V3D_READ(V3D_HUB_IDENT3);
+ v3d->rev = V3D_GET_FIELD(ident3, V3D_HUB_IDENT3_IPREV);
+
+ if (v3d->ver >= 71)
+ v3d->max_counters = V3D_V71_NUM_PERFCOUNTERS;
+ else if (v3d->ver >= 42)
+ v3d->max_counters = V3D_V42_NUM_PERFCOUNTERS;
+ else
+ v3d->max_counters = 0;
+
v3d->reset = devm_reset_control_get_exclusive(dev, NULL);
if (IS_ERR(v3d->reset)) {
ret = PTR_ERR(v3d->reset);
diff --git a/drivers/gpu/drm/v3d/v3d_drv.h b/drivers/gpu/drm/v3d/v3d_drv.h
index a2c516fe6d79..49089eefb7c7 100644
--- a/drivers/gpu/drm/v3d/v3d_drv.h
+++ b/drivers/gpu/drm/v3d/v3d_drv.h
@@ -11,6 +11,8 @@
#include <drm/drm_gem_shmem_helper.h>
#include <drm/gpu_scheduler.h>
+#include "v3d_performance_counters.h"
+
#include "uapi/drm/v3d_drm.h"
struct clk;
@@ -96,12 +98,19 @@ struct v3d_perfmon {
struct v3d_dev {
struct drm_device drm;
- /* Short representation (e.g. 33, 41) of the V3D tech version
- * and revision.
- */
+ /* Short representation (e.g. 33, 41) of the V3D tech version */
int ver;
+
+ /* Short representation (e.g. 5, 6) of the V3D tech revision */
+ int rev;
+
bool single_irq_line;
+ /* Different revisions of V3D have different total number of performance
+ * counters
+ */
+ unsigned int max_counters;
+
void __iomem *hub_regs;
void __iomem *core_regs[3];
void __iomem *bridge_regs;
@@ -345,7 +354,7 @@ struct v3d_timestamp_query {
};
/* Number of perfmons required to handle all supported performance counters */
-#define V3D_MAX_PERFMONS DIV_ROUND_UP(V3D_PERFCNT_NUM, \
+#define V3D_MAX_PERFMONS DIV_ROUND_UP(V3D_MAX_COUNTERS, \
DRM_V3D_MAX_PERF_COUNTERS)
struct v3d_performance_query {
@@ -575,6 +584,8 @@ int v3d_perfmon_destroy_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
int v3d_perfmon_get_values_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
+int v3d_perfmon_get_counter_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
/* v3d_sysfs.c */
int v3d_sysfs_init(struct device *dev);
diff --git a/drivers/gpu/drm/v3d/v3d_perfmon.c b/drivers/gpu/drm/v3d/v3d_perfmon.c
index e1be7368b87d..b7d0b02e1a95 100644
--- a/drivers/gpu/drm/v3d/v3d_perfmon.c
+++ b/drivers/gpu/drm/v3d/v3d_perfmon.c
@@ -9,6 +9,192 @@
#define V3D_PERFMONID_MIN 1
#define V3D_PERFMONID_MAX U32_MAX
+static const struct v3d_perf_counter_desc v3d_v42_performance_counters[] = {
+ {"FEP", "FEP-valid-primitives-no-rendered-pixels", "[FEP] Valid primitives that result in no rendered pixels, for all rendered tiles"},
+ {"FEP", "FEP-valid-primitives-rendered-pixels", "[FEP] Valid primitives for all rendered tiles (primitives may be counted in more than one tile)"},
+ {"FEP", "FEP-clipped-quads", "[FEP] Early-Z/Near/Far clipped quads"},
+ {"FEP", "FEP-valid-quads", "[FEP] Valid quads"},
+ {"TLB", "TLB-quads-not-passing-stencil-test", "[TLB] Quads with no pixels passing the stencil test"},
+ {"TLB", "TLB-quads-not-passing-z-and-stencil-test", "[TLB] Quads with no pixels passing the Z and stencil tests"},
+ {"TLB", "TLB-quads-passing-z-and-stencil-test", "[TLB] Quads with any pixels passing the Z and stencil tests"},
+ {"TLB", "TLB-quads-with-zero-coverage", "[TLB] Quads with all pixels having zero coverage"},
+ {"TLB", "TLB-quads-with-non-zero-coverage", "[TLB] Quads with any pixels having non-zero coverage"},
+ {"TLB", "TLB-quads-written-to-color-buffer", "[TLB] Quads with valid pixels written to colour buffer"},
+ {"PTB", "PTB-primitives-discarded-outside-viewport", "[PTB] Primitives discarded by being outside the viewport"},
+ {"PTB", "PTB-primitives-need-clipping", "[PTB] Primitives that need clipping"},
+ {"PTB", "PTB-primitives-discarded-reversed", "[PTB] Primitives that are discarded because they are reversed"},
+ {"QPU", "QPU-total-idle-clk-cycles", "[QPU] Total idle clock cycles for all QPUs"},
+ {"QPU", "QPU-total-active-clk-cycles-vertex-coord-shading", "[QPU] Total active clock cycles for all QPUs doing vertex/coordinate/user shading (counts only when QPU is not stalled)"},
+ {"QPU", "QPU-total-active-clk-cycles-fragment-shading", "[QPU] Total active clock cycles for all QPUs doing fragment shading (counts only when QPU is not stalled)"},
+ {"QPU", "QPU-total-clk-cycles-executing-valid-instr", "[QPU] Total clock cycles for all QPUs executing valid instructions"},
+ {"QPU", "QPU-total-clk-cycles-waiting-TMU", "[QPU] Total clock cycles for all QPUs stalled waiting for TMUs only (counter won't increment if QPU also stalling for another reason)"},
+ {"QPU", "QPU-total-clk-cycles-waiting-scoreboard", "[QPU] Total clock cycles for all QPUs stalled waiting for Scoreboard only (counter won't increment if QPU also stalling for another reason)"},
+ {"QPU", "QPU-total-clk-cycles-waiting-varyings", "[QPU] Total clock cycles for all QPUs stalled waiting for Varyings only (counter won't increment if QPU also stalling for another reason)"},
+ {"QPU", "QPU-total-instr-cache-hit", "[QPU] Total instruction cache hits for all slices"},
+ {"QPU", "QPU-total-instr-cache-miss", "[QPU] Total instruction cache misses for all slices"},
+ {"QPU", "QPU-total-uniform-cache-hit", "[QPU] Total uniforms cache hits for all slices"},
+ {"QPU", "QPU-total-uniform-cache-miss", "[QPU] Total uniforms cache misses for all slices"},
+ {"TMU", "TMU-total-text-quads-access", "[TMU] Total texture cache accesses"},
+ {"TMU", "TMU-total-text-cache-miss", "[TMU] Total texture cache misses (number of fetches from memory/L2cache)"},
+ {"VPM", "VPM-total-clk-cycles-VDW-stalled", "[VPM] Total clock cycles VDW is stalled waiting for VPM access"},
+ {"VPM", "VPM-total-clk-cycles-VCD-stalled", "[VPM] Total clock cycles VCD is stalled waiting for VPM access"},
+ {"CLE", "CLE-bin-thread-active-cycles", "[CLE] Bin thread active cycles"},
+ {"CLE", "CLE-render-thread-active-cycles", "[CLE] Render thread active cycles"},
+ {"L2T", "L2T-total-cache-hit", "[L2T] Total Level 2 cache hits"},
+ {"L2T", "L2T-total-cache-miss", "[L2T] Total Level 2 cache misses"},
+ {"CORE", "cycle-count", "[CORE] Cycle counter"},
+ {"QPU", "QPU-total-clk-cycles-waiting-vertex-coord-shading", "[QPU] Total stalled clock cycles for all QPUs doing vertex/coordinate/user shading"},
+ {"QPU", "QPU-total-clk-cycles-waiting-fragment-shading", "[QPU] Total stalled clock cycles for all QPUs doing fragment shading"},
+ {"PTB", "PTB-primitives-binned", "[PTB] Total primitives binned"},
+ {"AXI", "AXI-writes-seen-watch-0", "[AXI] Writes seen by watch 0"},
+ {"AXI", "AXI-reads-seen-watch-0", "[AXI] Reads seen by watch 0"},
+ {"AXI", "AXI-writes-stalled-seen-watch-0", "[AXI] Write stalls seen by watch 0"},
+ {"AXI", "AXI-reads-stalled-seen-watch-0", "[AXI] Read stalls seen by watch 0"},
+ {"AXI", "AXI-write-bytes-seen-watch-0", "[AXI] Total bytes written seen by watch 0"},
+ {"AXI", "AXI-read-bytes-seen-watch-0", "[AXI] Total bytes read seen by watch 0"},
+ {"AXI", "AXI-writes-seen-watch-1", "[AXI] Writes seen by watch 1"},
+ {"AXI", "AXI-reads-seen-watch-1", "[AXI] Reads seen by watch 1"},
+ {"AXI", "AXI-writes-stalled-seen-watch-1", "[AXI] Write stalls seen by watch 1"},
+ {"AXI", "AXI-reads-stalled-seen-watch-1", "[AXI] Read stalls seen by watch 1"},
+ {"AXI", "AXI-write-bytes-seen-watch-1", "[AXI] Total bytes written seen by watch 1"},
+ {"AXI", "AXI-read-bytes-seen-watch-1", "[AXI] Total bytes read seen by watch 1"},
+ {"TLB", "TLB-partial-quads-written-to-color-buffer", "[TLB] Partial quads written to the colour buffer"},
+ {"TMU", "TMU-total-config-access", "[TMU] Total config accesses"},
+ {"L2T", "L2T-no-id-stalled", "[L2T] No ID stall"},
+ {"L2T", "L2T-command-queue-stalled", "[L2T] Command queue full stall"},
+ {"L2T", "L2T-TMU-writes", "[L2T] TMU write accesses"},
+ {"TMU", "TMU-active-cycles", "[TMU] Active cycles"},
+ {"TMU", "TMU-stalled-cycles", "[TMU] Stalled cycles"},
+ {"CLE", "CLE-thread-active-cycles", "[CLE] Bin or render thread active cycles"},
+ {"L2T", "L2T-TMU-reads", "[L2T] TMU read accesses"},
+ {"L2T", "L2T-CLE-reads", "[L2T] CLE read accesses"},
+ {"L2T", "L2T-VCD-reads", "[L2T] VCD read accesses"},
+ {"L2T", "L2T-TMU-config-reads", "[L2T] TMU CFG read accesses"},
+ {"L2T", "L2T-SLC0-reads", "[L2T] SLC0 read accesses"},
+ {"L2T", "L2T-SLC1-reads", "[L2T] SLC1 read accesses"},
+ {"L2T", "L2T-SLC2-reads", "[L2T] SLC2 read accesses"},
+ {"L2T", "L2T-TMU-write-miss", "[L2T] TMU write misses"},
+ {"L2T", "L2T-TMU-read-miss", "[L2T] TMU read misses"},
+ {"L2T", "L2T-CLE-read-miss", "[L2T] CLE read misses"},
+ {"L2T", "L2T-VCD-read-miss", "[L2T] VCD read misses"},
+ {"L2T", "L2T-TMU-config-read-miss", "[L2T] TMU CFG read misses"},
+ {"L2T", "L2T-SLC0-read-miss", "[L2T] SLC0 read misses"},
+ {"L2T", "L2T-SLC1-read-miss", "[L2T] SLC1 read misses"},
+ {"L2T", "L2T-SLC2-read-miss", "[L2T] SLC2 read misses"},
+ {"CORE", "core-memory-writes", "[CORE] Total memory writes"},
+ {"L2T", "L2T-memory-writes", "[L2T] Total memory writes"},
+ {"PTB", "PTB-memory-writes", "[PTB] Total memory writes"},
+ {"TLB", "TLB-memory-writes", "[TLB] Total memory writes"},
+ {"CORE", "core-memory-reads", "[CORE] Total memory reads"},
+ {"L2T", "L2T-memory-reads", "[L2T] Total memory reads"},
+ {"PTB", "PTB-memory-reads", "[PTB] Total memory reads"},
+ {"PSE", "PSE-memory-reads", "[PSE] Total memory reads"},
+ {"TLB", "TLB-memory-reads", "[TLB] Total memory reads"},
+ {"GMP", "GMP-memory-reads", "[GMP] Total memory reads"},
+ {"PTB", "PTB-memory-words-writes", "[PTB] Total memory words written"},
+ {"TLB", "TLB-memory-words-writes", "[TLB] Total memory words written"},
+ {"PSE", "PSE-memory-words-reads", "[PSE] Total memory words read"},
+ {"TLB", "TLB-memory-words-reads", "[TLB] Total memory words read"},
+ {"TMU", "TMU-MRU-hits", "[TMU] Total MRU hits"},
+ {"CORE", "compute-active-cycles", "[CORE] Compute active cycles"},
+};
+
+static const struct v3d_perf_counter_desc v3d_v71_performance_counters[] = {
+ {"CORE", "cycle-count", "[CORE] Cycle counter"},
+ {"CORE", "core-active", "[CORE] Bin/Render/Compute active cycles"},
+ {"CLE", "CLE-bin-thread-active-cycles", "[CLE] Bin thread active cycles"},
+ {"CLE", "CLE-render-thread-active-cycles", "[CLE] Render thread active cycles"},
+ {"CORE", "compute-active-cycles", "[CORE] Compute active cycles"},
+ {"FEP", "FEP-valid-primitives-no-rendered-pixels", "[FEP] Valid primitives that result in no rendered pixels, for all rendered tiles"},
+ {"FEP", "FEP-valid-primitives-rendered-pixels", "[FEP] Valid primitives for all rendered tiles (primitives may be counted in more than one tile)"},
+ {"FEP", "FEP-clipped-quads", "[FEP] Early-Z/Near/Far clipped quads"},
+ {"FEP", "FEP-valid-quads", "[FEP] Valid quads"},
+ {"TLB", "TLB-quads-not-passing-stencil-test", "[TLB] Quads with no pixels passing the stencil test"},
+ {"TLB", "TLB-quads-not-passing-z-and-stencil-test", "[TLB] Quads with no pixels passing the Z and stencil tests"},
+ {"TLB", "TLB-quads-passing-z-and-stencil-test", "[TLB] Quads with any pixels passing the Z and stencil tests"},
+ {"TLB", "TLB-quads-written-to-color-buffer", "[TLB] Quads with valid pixels written to colour buffer"},
+ {"TLB", "TLB-partial-quads-written-to-color-buffer", "[TLB] Partial quads written to the colour buffer"},
+ {"PTB", "PTB-primitives-need-clipping", "[PTB] Primitives that need clipping"},
+ {"PTB", "PTB-primitives-discarded-outside-viewport", "[PTB] Primitives discarded by being outside the viewport"},
+ {"PTB", "PTB-primitives-binned", "[PTB] Total primitives binned"},
+ {"PTB", "PTB-primitives-discarded-reversed", "[PTB] Primitives that are discarded because they are reversed"},
+ {"QPU", "QPU-total-instr-cache-hit", "[QPU] Total instruction cache hits for all slices"},
+ {"QPU", "QPU-total-instr-cache-miss", "[QPU] Total instruction cache misses for all slices"},
+ {"QPU", "QPU-total-uniform-cache-hit", "[QPU] Total uniforms cache hits for all slices"},
+ {"QPU", "QPU-total-uniform-cache-miss", "[QPU] Total uniforms cache misses for all slices"},
+ {"TMU", "TMU-active-cycles", "[TMU] Active cycles"},
+ {"TMU", "TMU-stalled-cycles", "[TMU] Stalled cycles"},
+ {"TMU", "TMU-total-text-quads-access", "[TMU] Total texture cache accesses"},
+ {"TMU", "TMU-cache-x4-active-cycles", "[TMU] Cache active cycles for x4 access"},
+ {"TMU", "TMU-cache-x4-stalled-cycles", "[TMU] Cache stalled cycles for x4 access"},
+ {"TMU", "TMU-total-text-quads-x4-access", "[TMU] Total texture cache x4 access"},
+ {"L2T", "L2T-total-cache-hit", "[L2T] Total Level 2 cache hits"},
+ {"L2T", "L2T-total-cache-miss", "[L2T] Total Level 2 cache misses"},
+ {"L2T", "L2T-local", "[L2T] Local mode access"},
+ {"L2T", "L2T-writeback", "[L2T] Writeback"},
+ {"L2T", "L2T-zero", "[L2T] Zero"},
+ {"L2T", "L2T-merge", "[L2T] Merge"},
+ {"L2T", "L2T-fill", "[L2T] Fill"},
+ {"L2T", "L2T-stalls-no-wid", "[L2T] Stalls because no WID available"},
+ {"L2T", "L2T-stalls-no-rid", "[L2T] Stalls because no RID available"},
+ {"L2T", "L2T-stalls-queue-full", "[L2T] Stalls because internal queue full"},
+ {"L2T", "L2T-stalls-wrightback", "[L2T] Stalls because writeback in flight"},
+ {"L2T", "L2T-stalls-mem", "[L2T] Stalls because AXI blocks read"},
+ {"L2T", "L2T-stalls-fill", "[L2T] Stalls because fill pending for victim cache-line"},
+ {"L2T", "L2T-hitq", "[L2T] Sent request via hit queue"},
+ {"L2T", "L2T-hitq-full", "[L2T] Sent request via main queue because hit queue is full"},
+ {"L2T", "L2T-stalls-read-data", "[L2T] Stalls because waiting for data from SDRAM"},
+ {"L2T", "L2T-TMU-read-hits", "[L2T] TMU read hits"},
+ {"L2T", "L2T-TMU-read-miss", "[L2T] TMU read misses"},
+ {"L2T", "L2T-VCD-read-hits", "[L2T] VCD read hits"},
+ {"L2T", "L2T-VCD-read-miss", "[L2T] VCD read misses"},
+ {"L2T", "L2T-SLC-read-hits", "[L2T] SLC read hits (all slices)"},
+ {"L2T", "L2T-SLC-read-miss", "[L2T] SLC read misses (all slices)"},
+ {"AXI", "AXI-writes-seen-watch-0", "[AXI] Writes seen by watch 0"},
+ {"AXI", "AXI-reads-seen-watch-0", "[AXI] Reads seen by watch 0"},
+ {"AXI", "AXI-writes-stalled-seen-watch-0", "[AXI] Write stalls seen by watch 0"},
+ {"AXI", "AXI-reads-stalled-seen-watch-0", "[AXI] Read stalls seen by watch 0"},
+ {"AXI", "AXI-write-bytes-seen-watch-0", "[AXI] Total bytes written seen by watch 0"},
+ {"AXI", "AXI-read-bytes-seen-watch-0", "[AXI] Total bytes read seen by watch 0"},
+ {"AXI", "AXI-writes-seen-watch-1", "[AXI] Writes seen by watch 1"},
+ {"AXI", "AXI-reads-seen-watch-1", "[AXI] Reads seen by watch 1"},
+ {"AXI", "AXI-writes-stalled-seen-watch-1", "[AXI] Write stalls seen by watch 1"},
+ {"AXI", "AXI-reads-stalled-seen-watch-1", "[AXI] Read stalls seen by watch 1"},
+ {"AXI", "AXI-write-bytes-seen-watch-1", "[AXI] Total bytes written seen by watch 1"},
+ {"AXI", "AXI-read-bytes-seen-watch-1", "[AXI] Total bytes read seen by watch 1"},
+ {"CORE", "core-memory-writes", "[CORE] Total memory writes"},
+ {"L2T", "L2T-memory-writes", "[L2T] Total memory writes"},
+ {"PTB", "PTB-memory-writes", "[PTB] Total memory writes"},
+ {"TLB", "TLB-memory-writes", "[TLB] Total memory writes"},
+ {"CORE", "core-memory-reads", "[CORE] Total memory reads"},
+ {"L2T", "L2T-memory-reads", "[L2T] Total memory reads"},
+ {"PTB", "PTB-memory-reads", "[PTB] Total memory reads"},
+ {"PSE", "PSE-memory-reads", "[PSE] Total memory reads"},
+ {"TLB", "TLB-memory-reads", "[TLB] Total memory reads"},
+ {"PTB", "PTB-memory-words-writes", "[PTB] Total memory words written"},
+ {"TLB", "TLB-memory-words-writes", "[TLB] Total memory words written"},
+ {"PSE", "PSE-memory-words-reads", "[PSE] Total memory words read"},
+ {"TLB", "TLB-memory-words-reads", "[TLB] Total memory words read"},
+ {"AXI", "AXI-read-trans", "[AXI] Read transaction count"},
+ {"AXI", "AXI-write-trans", "[AXI] Write transaction count"},
+ {"AXI", "AXI-read-wait-cycles", "[AXI] Read total wait cycles"},
+ {"AXI", "AXI-write-wait-cycles", "[AXI] Write total wait cycles"},
+ {"AXI", "AXI-max-outstanding-reads", "[AXI] Maximum outstanding read transactions"},
+ {"AXI", "AXI-max-outstanding-writes", "[AXI] Maximum outstanding write transactions"},
+ {"QPU", "QPU-wait-bubble", "[QPU] Pipeline bubble in qcycles due all threads waiting"},
+ {"QPU", "QPU-ic-miss-bubble", "[QPU] Pipeline bubble in qcycles due instruction-cache miss"},
+ {"QPU", "QPU-active", "[QPU] Executed shader instruction"},
+ {"QPU", "QPU-total-active-clk-cycles-fragment-shading", "[QPU] Total active clock cycles for all QPUs doing fragment shading (counts only when QPU is not stalled)"},
+ {"QPU", "QPU-stalls", "[QPU] Stalled qcycles executing shader instruction"},
+ {"QPU", "QPU-total-clk-cycles-waiting-fragment-shading", "[QPU] Total stalled clock cycles for all QPUs doing fragment shading"},
+ {"QPU", "QPU-stalls-TMU", "[QPU] Stalled qcycles waiting for TMU"},
+ {"QPU", "QPU-stalls-TLB", "[QPU] Stalled qcycles waiting for TLB"},
+ {"QPU", "QPU-stalls-VPM", "[QPU] Stalled qcycles waiting for VPM"},
+ {"QPU", "QPU-stalls-uniforms", "[QPU] Stalled qcycles waiting for uniforms"},
+ {"QPU", "QPU-stalls-SFU", "[QPU] Stalled qcycles waiting for SFU"},
+ {"QPU", "QPU-stalls-other", "[QPU] Stalled qcycles waiting for any other reason (vary/W/Z)"},
+};
+
void v3d_perfmon_get(struct v3d_perfmon *perfmon)
{
if (perfmon)
@@ -123,6 +309,7 @@ int v3d_perfmon_create_ioctl(struct drm_device *dev, void *data,
{
struct v3d_file_priv *v3d_priv = file_priv->driver_priv;
struct drm_v3d_perfmon_create *req = data;
+ struct v3d_dev *v3d = v3d_priv->v3d;
struct v3d_perfmon *perfmon;
unsigned int i;
int ret;
@@ -134,7 +321,7 @@ int v3d_perfmon_create_ioctl(struct drm_device *dev, void *data,
/* Make sure all counters are valid. */
for (i = 0; i < req->ncounters; i++) {
- if (req->counters[i] >= V3D_PERFCNT_NUM)
+ if (req->counters[i] >= v3d->max_counters)
return -EINVAL;
}
@@ -216,3 +403,42 @@ int v3d_perfmon_get_values_ioctl(struct drm_device *dev, void *data,
return ret;
}
+
+int v3d_perfmon_get_counter_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_v3d_perfmon_get_counter *req = data;
+ struct v3d_dev *v3d = to_v3d_dev(dev);
+ const struct v3d_perf_counter_desc *counter;
+
+ for (int i = 0; i < ARRAY_SIZE(req->reserved); i++) {
+ if (req->reserved[i] != 0)
+ return -EINVAL;
+ }
+
+ /* Make sure that the counter ID is valid */
+ if (req->counter >= v3d->max_counters)
+ return -EINVAL;
+
+ BUILD_BUG_ON(ARRAY_SIZE(v3d_v42_performance_counters) !=
+ V3D_V42_NUM_PERFCOUNTERS);
+ BUILD_BUG_ON(ARRAY_SIZE(v3d_v71_performance_counters) !=
+ V3D_V71_NUM_PERFCOUNTERS);
+ BUILD_BUG_ON(V3D_MAX_COUNTERS < V3D_V42_NUM_PERFCOUNTERS);
+ BUILD_BUG_ON(V3D_MAX_COUNTERS < V3D_V71_NUM_PERFCOUNTERS);
+ BUILD_BUG_ON((V3D_MAX_COUNTERS != V3D_V42_NUM_PERFCOUNTERS) &&
+ (V3D_MAX_COUNTERS != V3D_V71_NUM_PERFCOUNTERS));
+
+ if (v3d->ver >= 71)
+ counter = &v3d_v71_performance_counters[req->counter];
+ else if (v3d->ver >= 42)
+ counter = &v3d_v42_performance_counters[req->counter];
+ else
+ return -EOPNOTSUPP;
+
+ strscpy(req->name, counter->name, sizeof(req->name));
+ strscpy(req->category, counter->category, sizeof(req->category));
+ strscpy(req->description, counter->description, sizeof(req->description));
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/v3d/v3d_performance_counters.h b/drivers/gpu/drm/v3d/v3d_performance_counters.h
new file mode 100644
index 000000000000..131b2909522a
--- /dev/null
+++ b/drivers/gpu/drm/v3d/v3d_performance_counters.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2024 Raspberry Pi
+ */
+#ifndef V3D_PERFORMANCE_COUNTERS_H
+#define V3D_PERFORMANCE_COUNTERS_H
+
+/* Holds a description of a given performance counter. The index of performance
+ * counter is given by the array on v3d_performance_counter.h
+ */
+struct v3d_perf_counter_desc {
+ /* Category of the counter */
+ char category[32];
+
+ /* Name of the counter */
+ char name[64];
+
+ /* Description of the counter */
+ char description[256];
+};
+
+
+#define V3D_V42_NUM_PERFCOUNTERS (87)
+#define V3D_V71_NUM_PERFCOUNTERS (93)
+
+/* Maximum number of performance counters supported by any version of V3D */
+#define V3D_MAX_COUNTERS (93)
+
+#endif
diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c
index 7cd8c335cd9b..271a6d0f5aca 100644
--- a/drivers/gpu/drm/v3d/v3d_sched.c
+++ b/drivers/gpu/drm/v3d/v3d_sched.c
@@ -331,7 +331,8 @@ v3d_rewrite_csd_job_wg_counts_from_indirect(struct v3d_cpu_job *job)
struct v3d_bo *bo = to_v3d_bo(job->base.bo[0]);
struct v3d_bo *indirect = to_v3d_bo(indirect_csd->indirect);
struct drm_v3d_submit_csd *args = &indirect_csd->job->args;
- u32 *wg_counts;
+ struct v3d_dev *v3d = job->base.v3d;
+ u32 num_batches, *wg_counts;
v3d_get_bo_vaddr(bo);
v3d_get_bo_vaddr(indirect);
@@ -344,8 +345,17 @@ v3d_rewrite_csd_job_wg_counts_from_indirect(struct v3d_cpu_job *job)
args->cfg[0] = wg_counts[0] << V3D_CSD_CFG012_WG_COUNT_SHIFT;
args->cfg[1] = wg_counts[1] << V3D_CSD_CFG012_WG_COUNT_SHIFT;
args->cfg[2] = wg_counts[2] << V3D_CSD_CFG012_WG_COUNT_SHIFT;
- args->cfg[4] = DIV_ROUND_UP(indirect_csd->wg_size, 16) *
- (wg_counts[0] * wg_counts[1] * wg_counts[2]) - 1;
+
+ num_batches = DIV_ROUND_UP(indirect_csd->wg_size, 16) *
+ (wg_counts[0] * wg_counts[1] * wg_counts[2]);
+
+ /* V3D 7.1.6 and later don't subtract 1 from the number of batches */
+ if (v3d->ver < 71 || (v3d->ver == 71 && v3d->rev < 6))
+ args->cfg[4] = num_batches - 1;
+ else
+ args->cfg[4] = num_batches;
+
+ WARN_ON(args->cfg[4] == ~0);
for (int i = 0; i < 3; i++) {
/* 0xffffffff indicates that the uniform rewrite is not needed */
@@ -490,7 +500,7 @@ v3d_write_performance_query_result(struct v3d_cpu_job *job, void *data, u32 quer
struct v3d_file_priv *v3d_priv = job->base.file->driver_priv;
struct v3d_dev *v3d = job->base.v3d;
struct v3d_perfmon *perfmon;
- u64 counter_values[V3D_PERFCNT_NUM];
+ u64 counter_values[V3D_MAX_COUNTERS];
for (int i = 0; i < performance_query->nperfmons; i++) {
perfmon = v3d_perfmon_find(v3d_priv,
diff --git a/drivers/gpu/drm/vboxvideo/vbox_drv.c b/drivers/gpu/drm/vboxvideo/vbox_drv.c
index cd9e66a06596..ef36834c8673 100644
--- a/drivers/gpu/drm/vboxvideo/vbox_drv.c
+++ b/drivers/gpu/drm/vboxvideo/vbox_drv.c
@@ -14,7 +14,7 @@
#include <drm/drm_aperture.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_ttm.h>
#include <drm/drm_file.h>
#include <drm/drm_ioctl.h>
#include <drm/drm_managed.h>
@@ -80,7 +80,7 @@ static int vbox_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (ret)
goto err_irq_fini;
- drm_fbdev_generic_setup(&vbox->ddev, 32);
+ drm_fbdev_ttm_setup(&vbox->ddev, 32);
return 0;
diff --git a/drivers/gpu/drm/vboxvideo/vbox_main.c b/drivers/gpu/drm/vboxvideo/vbox_main.c
index 42c2d8a99509..d4ade9325401 100644
--- a/drivers/gpu/drm/vboxvideo/vbox_main.c
+++ b/drivers/gpu/drm/vboxvideo/vbox_main.c
@@ -42,12 +42,11 @@ static int vbox_accel_init(struct vbox_private *vbox)
/* Take a command buffer for each screen from the end of usable VRAM. */
vbox->available_vram_size -= vbox->num_crtcs * VBVA_MIN_BUFFER_SIZE;
- vbox->vbva_buffers = pci_iomap_range(pdev, 0,
- vbox->available_vram_size,
- vbox->num_crtcs *
- VBVA_MIN_BUFFER_SIZE);
- if (!vbox->vbva_buffers)
- return -ENOMEM;
+ vbox->vbva_buffers = pcim_iomap_range(
+ pdev, 0, vbox->available_vram_size,
+ vbox->num_crtcs * VBVA_MIN_BUFFER_SIZE);
+ if (IS_ERR(vbox->vbva_buffers))
+ return PTR_ERR(vbox->vbva_buffers);
for (i = 0; i < vbox->num_crtcs; ++i) {
vbva_setup_buffer_context(&vbox->vbva_info[i],
@@ -116,11 +115,10 @@ int vbox_hw_init(struct vbox_private *vbox)
DRM_INFO("VRAM %08x\n", vbox->full_vram_size);
/* Map guest-heap at end of vram */
- vbox->guest_heap =
- pci_iomap_range(pdev, 0, GUEST_HEAP_OFFSET(vbox),
- GUEST_HEAP_SIZE);
- if (!vbox->guest_heap)
- return -ENOMEM;
+ vbox->guest_heap = pcim_iomap_range(pdev, 0,
+ GUEST_HEAP_OFFSET(vbox), GUEST_HEAP_SIZE);
+ if (IS_ERR(vbox->guest_heap))
+ return PTR_ERR(vbox->guest_heap);
/* Create guest-heap mem-pool use 2^4 = 16 byte chunks */
vbox->guest_pool = devm_gen_pool_create(vbox->ddev.dev, 4, -1,
diff --git a/drivers/gpu/drm/vc4/Kconfig b/drivers/gpu/drm/vc4/Kconfig
index 91dcf8d174d6..269b5f26b2ea 100644
--- a/drivers/gpu/drm/vc4/Kconfig
+++ b/drivers/gpu/drm/vc4/Kconfig
@@ -10,6 +10,7 @@ config DRM_VC4
depends on COMMON_CLK
depends on PM
select DRM_DISPLAY_HDMI_HELPER
+ select DRM_DISPLAY_HDMI_STATE_HELPER
select DRM_DISPLAY_HELPER
select DRM_KMS_HELPER
select DRM_GEM_DMA_HELPER
diff --git a/drivers/gpu/drm/vc4/tests/vc4_mock.c b/drivers/gpu/drm/vc4/tests/vc4_mock.c
index becb3dbaa548..0731a7d85d7a 100644
--- a/drivers/gpu/drm/vc4/tests/vc4_mock.c
+++ b/drivers/gpu/drm/vc4/tests/vc4_mock.c
@@ -109,16 +109,14 @@ static const struct vc4_mock_desc vc5_mock =
static int __build_one_pipe(struct kunit *test, struct drm_device *drm,
const struct vc4_mock_pipe_desc *pipe)
{
- struct vc4_dummy_plane *dummy_plane;
struct drm_plane *plane;
struct vc4_dummy_crtc *dummy_crtc;
struct drm_crtc *crtc;
unsigned int i;
- dummy_plane = vc4_dummy_plane(test, drm, DRM_PLANE_TYPE_PRIMARY);
- KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dummy_plane);
+ plane = vc4_dummy_plane(test, drm, DRM_PLANE_TYPE_PRIMARY);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane);
- plane = &dummy_plane->plane.base;
dummy_crtc = vc4_mock_pv(test, drm, plane, pipe->data);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dummy_crtc);
diff --git a/drivers/gpu/drm/vc4/tests/vc4_mock.h b/drivers/gpu/drm/vc4/tests/vc4_mock.h
index 2d0b339bd9f3..002b6218960c 100644
--- a/drivers/gpu/drm/vc4/tests/vc4_mock.h
+++ b/drivers/gpu/drm/vc4/tests/vc4_mock.h
@@ -21,13 +21,8 @@ struct drm_crtc *vc4_find_crtc_for_encoder(struct kunit *test,
return NULL;
}
-struct vc4_dummy_plane {
- struct vc4_plane plane;
-};
-
-struct vc4_dummy_plane *vc4_dummy_plane(struct kunit *test,
- struct drm_device *drm,
- enum drm_plane_type type);
+struct drm_plane *vc4_dummy_plane(struct kunit *test, struct drm_device *drm,
+ enum drm_plane_type type);
struct vc4_dummy_crtc {
struct vc4_crtc crtc;
diff --git a/drivers/gpu/drm/vc4/tests/vc4_mock_plane.c b/drivers/gpu/drm/vc4/tests/vc4_mock_plane.c
index 62b18f5f41db..14357db82238 100644
--- a/drivers/gpu/drm/vc4/tests/vc4_mock_plane.c
+++ b/drivers/gpu/drm/vc4/tests/vc4_mock_plane.c
@@ -1,47 +1,25 @@
// SPDX-License-Identifier: GPL-2.0
-#include <drm/drm_atomic_state_helper.h>
-#include <drm/drm_fourcc.h>
-#include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_kunit_helpers.h>
#include <drm/drm_plane.h>
#include <kunit/test.h>
#include "vc4_mock.h"
-static const struct drm_plane_helper_funcs vc4_dummy_plane_helper_funcs = {
-};
-
-static const struct drm_plane_funcs vc4_dummy_plane_funcs = {
- .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
- .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
- .reset = drm_atomic_helper_plane_reset,
-};
-
-static const uint32_t vc4_dummy_plane_formats[] = {
- DRM_FORMAT_XRGB8888,
-};
-
-struct vc4_dummy_plane *vc4_dummy_plane(struct kunit *test,
- struct drm_device *drm,
- enum drm_plane_type type)
+struct drm_plane *vc4_dummy_plane(struct kunit *test, struct drm_device *drm,
+ enum drm_plane_type type)
{
- struct vc4_dummy_plane *dummy_plane;
struct drm_plane *plane;
- dummy_plane = drmm_universal_plane_alloc(drm,
- struct vc4_dummy_plane, plane.base,
- 0,
- &vc4_dummy_plane_funcs,
- vc4_dummy_plane_formats,
- ARRAY_SIZE(vc4_dummy_plane_formats),
- NULL,
- DRM_PLANE_TYPE_PRIMARY,
- NULL);
- KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dummy_plane);
+ KUNIT_ASSERT_EQ(test, type, DRM_PLANE_TYPE_PRIMARY);
- plane = &dummy_plane->plane.base;
- drm_plane_helper_add(plane, &vc4_dummy_plane_helper_funcs);
+ plane = drm_kunit_helper_create_primary_plane(test, drm,
+ NULL,
+ NULL,
+ NULL, 0,
+ NULL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane);
- return dummy_plane;
+ return plane;
}
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index d30f8e8e8967..d57c4a5948c8 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -32,6 +32,7 @@
*/
#include <drm/display/drm_hdmi_helper.h>
+#include <drm/display/drm_hdmi_state_helper.h>
#include <drm/display/drm_scdc_helper.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
@@ -110,25 +111,6 @@
#define HDMI_14_MAX_TMDS_CLK (340 * 1000 * 1000)
-static const char * const output_format_str[] = {
- [VC4_HDMI_OUTPUT_RGB] = "RGB",
- [VC4_HDMI_OUTPUT_YUV420] = "YUV 4:2:0",
- [VC4_HDMI_OUTPUT_YUV422] = "YUV 4:2:2",
- [VC4_HDMI_OUTPUT_YUV444] = "YUV 4:4:4",
-};
-
-static const char *vc4_hdmi_output_fmt_str(enum vc4_hdmi_output_format fmt)
-{
- if (fmt >= ARRAY_SIZE(output_format_str))
- return "invalid";
-
- return output_format_str[fmt];
-}
-
-static unsigned long long
-vc4_hdmi_encoder_compute_mode_clock(const struct drm_display_mode *mode,
- unsigned int bpc, enum vc4_hdmi_output_format fmt);
-
static bool vc4_hdmi_supports_scrambling(struct vc4_hdmi *vc4_hdmi)
{
struct drm_display_info *display = &vc4_hdmi->connector.display_info;
@@ -147,28 +129,13 @@ 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 vc4_hdmi_output_format fmt)
+ enum hdmi_colorspace fmt)
{
- unsigned long long clock = vc4_hdmi_encoder_compute_mode_clock(mode, bpc, fmt);
+ unsigned long long clock = drm_hdmi_compute_mode_clock(mode, bpc, fmt);
return clock > HDMI_14_MAX_TMDS_CLK;
}
-static bool vc4_hdmi_is_full_range(struct vc4_hdmi *vc4_hdmi,
- struct vc4_hdmi_connector_state *vc4_state)
-{
- const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode;
- struct drm_display_info *display = &vc4_hdmi->connector.display_info;
-
- if (vc4_state->broadcast_rgb == VC4_HDMI_BROADCAST_RGB_LIMITED)
- return false;
- else if (vc4_state->broadcast_rgb == VC4_HDMI_BROADCAST_RGB_FULL)
- return true;
-
- return !display->is_hdmi ||
- drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_FULL;
-}
-
static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
{
struct drm_debugfs_entry *entry = m->private;
@@ -524,7 +491,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, VC4_HDMI_OUTPUT_RGB)) {
+ if (vc4_hdmi_mode_needs_scrambling(mode, 8, HDMI_COLORSPACE_RGB)) {
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.");
}
@@ -539,12 +506,8 @@ static int vc4_hdmi_connector_atomic_check(struct drm_connector *connector,
{
struct drm_connector_state *old_state =
drm_atomic_get_old_connector_state(state, connector);
- struct vc4_hdmi_connector_state *old_vc4_state =
- conn_state_to_vc4_hdmi_conn_state(old_state);
struct drm_connector_state *new_state =
drm_atomic_get_new_connector_state(state, connector);
- struct vc4_hdmi_connector_state *new_vc4_state =
- conn_state_to_vc4_hdmi_conn_state(new_state);
struct drm_crtc *crtc = new_state->crtc;
if (!crtc)
@@ -576,9 +539,7 @@ static int vc4_hdmi_connector_atomic_check(struct drm_connector *connector,
return ret;
}
- if (old_state->colorspace != new_state->colorspace ||
- old_vc4_state->broadcast_rgb != new_vc4_state->broadcast_rgb ||
- !drm_connector_atomic_hdr_metadata_equal(old_state, new_state)) {
+ if (old_state->colorspace != new_state->colorspace) {
struct drm_crtc_state *crtc_state;
crtc_state = drm_atomic_get_crtc_state(state, crtc);
@@ -588,112 +549,21 @@ static int vc4_hdmi_connector_atomic_check(struct drm_connector *connector,
crtc_state->mode_changed = true;
}
- return 0;
-}
-
-static int vc4_hdmi_connector_get_property(struct drm_connector *connector,
- const struct drm_connector_state *state,
- struct drm_property *property,
- uint64_t *val)
-{
- struct drm_device *drm = connector->dev;
- struct vc4_hdmi *vc4_hdmi =
- connector_to_vc4_hdmi(connector);
- const struct vc4_hdmi_connector_state *vc4_conn_state =
- conn_state_to_vc4_hdmi_conn_state(state);
-
- if (property == vc4_hdmi->broadcast_rgb_property) {
- *val = vc4_conn_state->broadcast_rgb;
- } else {
- drm_dbg(drm, "Unknown property [PROP:%d:%s]\n",
- property->base.id, property->name);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int vc4_hdmi_connector_set_property(struct drm_connector *connector,
- struct drm_connector_state *state,
- struct drm_property *property,
- uint64_t val)
-{
- struct drm_device *drm = connector->dev;
- struct vc4_hdmi *vc4_hdmi =
- connector_to_vc4_hdmi(connector);
- struct vc4_hdmi_connector_state *vc4_conn_state =
- conn_state_to_vc4_hdmi_conn_state(state);
-
- if (property == vc4_hdmi->broadcast_rgb_property) {
- vc4_conn_state->broadcast_rgb = val;
- return 0;
- }
-
- drm_dbg(drm, "Unknown property [PROP:%d:%s]\n",
- property->base.id, property->name);
- return -EINVAL;
+ return drm_atomic_helper_connector_hdmi_check(connector, state);
}
static void vc4_hdmi_connector_reset(struct drm_connector *connector)
{
- struct vc4_hdmi_connector_state *old_state =
- conn_state_to_vc4_hdmi_conn_state(connector->state);
- struct vc4_hdmi_connector_state *new_state =
- kzalloc(sizeof(*new_state), GFP_KERNEL);
-
- if (connector->state)
- __drm_atomic_helper_connector_destroy_state(connector->state);
-
- kfree(old_state);
- __drm_atomic_helper_connector_reset(connector, &new_state->base);
-
- if (!new_state)
- return;
-
- new_state->base.max_bpc = 8;
- new_state->base.max_requested_bpc = 8;
- new_state->output_format = VC4_HDMI_OUTPUT_RGB;
- new_state->broadcast_rgb = VC4_HDMI_BROADCAST_RGB_AUTO;
+ drm_atomic_helper_connector_reset(connector);
+ __drm_atomic_helper_connector_hdmi_reset(connector, connector->state);
drm_atomic_helper_connector_tv_margins_reset(connector);
}
-static struct drm_connector_state *
-vc4_hdmi_connector_duplicate_state(struct drm_connector *connector)
-{
- struct drm_connector_state *conn_state = connector->state;
- struct vc4_hdmi_connector_state *vc4_state = conn_state_to_vc4_hdmi_conn_state(conn_state);
- struct vc4_hdmi_connector_state *new_state;
-
- new_state = kzalloc(sizeof(*new_state), GFP_KERNEL);
- if (!new_state)
- return NULL;
-
- new_state->tmds_char_rate = vc4_state->tmds_char_rate;
- new_state->output_bpc = vc4_state->output_bpc;
- new_state->output_format = vc4_state->output_format;
- new_state->broadcast_rgb = vc4_state->broadcast_rgb;
- __drm_atomic_helper_connector_duplicate_state(connector, &new_state->base);
-
- return &new_state->base;
-}
-
-static void vc4_hdmi_connector_destroy_state(struct drm_connector *connector,
- struct drm_connector_state *state)
-{
- struct vc4_hdmi_connector_state *vc4_state =
- conn_state_to_vc4_hdmi_conn_state(state);
-
- __drm_atomic_helper_connector_destroy_state(state);
- kfree(vc4_state);
-}
-
static const struct drm_connector_funcs vc4_hdmi_connector_funcs = {
.fill_modes = drm_helper_probe_single_connector_modes,
.reset = vc4_hdmi_connector_reset,
- .atomic_duplicate_state = vc4_hdmi_connector_duplicate_state,
- .atomic_destroy_state = vc4_hdmi_connector_destroy_state,
- .atomic_get_property = vc4_hdmi_connector_get_property,
- .atomic_set_property = vc4_hdmi_connector_set_property,
+ .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 vc4_hdmi_connector_helper_funcs = {
@@ -702,44 +572,29 @@ static const struct drm_connector_helper_funcs vc4_hdmi_connector_helper_funcs =
.atomic_check = vc4_hdmi_connector_atomic_check,
};
-static const struct drm_prop_enum_list broadcast_rgb_names[] = {
- { VC4_HDMI_BROADCAST_RGB_AUTO, "Automatic" },
- { VC4_HDMI_BROADCAST_RGB_FULL, "Full" },
- { VC4_HDMI_BROADCAST_RGB_LIMITED, "Limited 16:235" },
-};
-
-static void
-vc4_hdmi_attach_broadcast_rgb_property(struct drm_device *dev,
- struct vc4_hdmi *vc4_hdmi)
-{
- struct drm_property *prop = vc4_hdmi->broadcast_rgb_property;
-
- if (!prop) {
- prop = drm_property_create_enum(dev, DRM_MODE_PROP_ENUM,
- "Broadcast RGB",
- broadcast_rgb_names,
- ARRAY_SIZE(broadcast_rgb_names));
- if (!prop)
- return;
-
- vc4_hdmi->broadcast_rgb_property = prop;
- }
-
- drm_object_attach_property(&vc4_hdmi->connector.base, prop,
- VC4_HDMI_BROADCAST_RGB_AUTO);
-}
+static const struct drm_connector_hdmi_funcs vc4_hdmi_hdmi_connector_funcs;
static int vc4_hdmi_connector_init(struct drm_device *dev,
struct vc4_hdmi *vc4_hdmi)
{
struct drm_connector *connector = &vc4_hdmi->connector;
struct drm_encoder *encoder = &vc4_hdmi->encoder.base;
+ unsigned int max_bpc = 8;
int ret;
- ret = drmm_connector_init(dev, connector,
- &vc4_hdmi_connector_funcs,
- DRM_MODE_CONNECTOR_HDMIA,
- vc4_hdmi->ddc);
+ if (vc4_hdmi->variant->supports_hdr)
+ max_bpc = 12;
+
+ ret = drmm_connector_hdmi_init(dev, connector,
+ "Broadcom", "Videocore",
+ &vc4_hdmi_connector_funcs,
+ &vc4_hdmi_hdmi_connector_funcs,
+ DRM_MODE_CONNECTOR_HDMIA,
+ vc4_hdmi->ddc,
+ BIT(HDMI_COLORSPACE_RGB) |
+ BIT(HDMI_COLORSPACE_YUV422) |
+ BIT(HDMI_COLORSPACE_YUV444),
+ max_bpc);
if (ret)
return ret;
@@ -763,7 +618,6 @@ static int vc4_hdmi_connector_init(struct drm_device *dev,
drm_connector_attach_colorspace_property(connector);
drm_connector_attach_tv_margin_properties(connector);
- drm_connector_attach_max_bpc_property(connector, 8, 12);
connector->polled = (DRM_CONNECTOR_POLL_CONNECT |
DRM_CONNECTOR_POLL_DISCONNECT);
@@ -772,21 +626,19 @@ static int vc4_hdmi_connector_init(struct drm_device *dev,
connector->doublescan_allowed = 0;
connector->stereo_allowed = 1;
- if (vc4_hdmi->variant->supports_hdr)
- drm_connector_attach_hdr_output_metadata_property(connector);
-
- vc4_hdmi_attach_broadcast_rgb_property(dev, vc4_hdmi);
+ ret = drm_connector_attach_broadcast_rgb_property(connector);
+ if (ret)
+ return ret;
drm_connector_attach_encoder(connector, encoder);
return 0;
}
-static int vc4_hdmi_stop_packet(struct drm_encoder *encoder,
+static int vc4_hdmi_stop_packet(struct vc4_hdmi *vc4_hdmi,
enum hdmi_infoframe_type type,
bool poll)
{
- struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
struct drm_device *drm = vc4_hdmi->connector.dev;
u32 packet_id = type - 0x80;
unsigned long flags;
@@ -810,12 +662,13 @@ static int vc4_hdmi_stop_packet(struct drm_encoder *encoder,
return ret;
}
-static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder,
- union hdmi_infoframe *frame)
+static int vc4_hdmi_write_infoframe(struct drm_connector *connector,
+ enum hdmi_infoframe_type type,
+ const u8 *infoframe, size_t len)
{
- struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
- struct drm_device *drm = vc4_hdmi->connector.dev;
- u32 packet_id = frame->any.type - 0x80;
+ struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector);
+ struct drm_device *drm = connector->dev;
+ u32 packet_id = type - 0x80;
const struct vc4_hdmi_register *ram_packet_start =
&vc4_hdmi->variant->registers[HDMI_RAM_PACKET_START];
u32 packet_reg = ram_packet_start->offset + VC4_HDMI_PACKET_STRIDE * packet_id;
@@ -825,22 +678,25 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder,
ram_packet_start->reg);
uint8_t buffer[VC4_HDMI_PACKET_STRIDE] = {};
unsigned long flags;
- ssize_t len, i;
+ ssize_t i;
int ret;
int idx;
if (!drm_dev_enter(drm, &idx))
- return;
+ return 0;
+
+ if (len > sizeof(buffer)) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ memcpy(buffer, infoframe, len);
WARN_ONCE(!(HDMI_READ(HDMI_RAM_PACKET_CONFIG) &
VC4_HDMI_RAM_PACKET_ENABLE),
"Packet RAM has to be on to store the packet.");
- len = hdmi_infoframe_pack(frame, buffer, sizeof(buffer));
- if (len < 0)
- goto out;
-
- ret = vc4_hdmi_stop_packet(encoder, frame->any.type, true);
+ ret = vc4_hdmi_stop_packet(vc4_hdmi, type, true);
if (ret) {
DRM_ERROR("Failed to wait for infoframe to go idle: %d\n", ret);
goto out;
@@ -882,130 +738,7 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder,
out:
drm_dev_exit(idx);
-}
-
-static void vc4_hdmi_avi_infoframe_colorspace(struct hdmi_avi_infoframe *frame,
- enum vc4_hdmi_output_format fmt)
-{
- switch (fmt) {
- case VC4_HDMI_OUTPUT_RGB:
- frame->colorspace = HDMI_COLORSPACE_RGB;
- break;
-
- case VC4_HDMI_OUTPUT_YUV420:
- frame->colorspace = HDMI_COLORSPACE_YUV420;
- break;
-
- case VC4_HDMI_OUTPUT_YUV422:
- frame->colorspace = HDMI_COLORSPACE_YUV422;
- break;
-
- case VC4_HDMI_OUTPUT_YUV444:
- frame->colorspace = HDMI_COLORSPACE_YUV444;
- break;
-
- default:
- break;
- }
-}
-
-static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
-{
- struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
- struct drm_connector *connector = &vc4_hdmi->connector;
- struct drm_connector_state *cstate = connector->state;
- struct vc4_hdmi_connector_state *vc4_state =
- conn_state_to_vc4_hdmi_conn_state(cstate);
- const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode;
- union hdmi_infoframe frame;
- int ret;
-
- lockdep_assert_held(&vc4_hdmi->mutex);
-
- ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
- connector, mode);
- if (ret < 0) {
- DRM_ERROR("couldn't fill AVI infoframe\n");
- return;
- }
-
- drm_hdmi_avi_infoframe_quant_range(&frame.avi,
- connector, mode,
- vc4_hdmi_is_full_range(vc4_hdmi, vc4_state) ?
- HDMI_QUANTIZATION_RANGE_FULL :
- HDMI_QUANTIZATION_RANGE_LIMITED);
- drm_hdmi_avi_infoframe_colorimetry(&frame.avi, cstate);
- vc4_hdmi_avi_infoframe_colorspace(&frame.avi, vc4_state->output_format);
- drm_hdmi_avi_infoframe_bars(&frame.avi, cstate);
-
- vc4_hdmi_write_infoframe(encoder, &frame);
-}
-
-static void vc4_hdmi_set_spd_infoframe(struct drm_encoder *encoder)
-{
- union hdmi_infoframe frame;
- int ret;
-
- ret = hdmi_spd_infoframe_init(&frame.spd, "Broadcom", "Videocore");
- if (ret < 0) {
- DRM_ERROR("couldn't fill SPD infoframe\n");
- return;
- }
-
- frame.spd.sdi = HDMI_SPD_SDI_PC;
-
- vc4_hdmi_write_infoframe(encoder, &frame);
-}
-
-static void vc4_hdmi_set_audio_infoframe(struct drm_encoder *encoder)
-{
- struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
- struct hdmi_audio_infoframe *audio = &vc4_hdmi->audio.infoframe;
- union hdmi_infoframe frame;
-
- memcpy(&frame.audio, audio, sizeof(*audio));
-
- if (vc4_hdmi->packet_ram_enabled)
- vc4_hdmi_write_infoframe(encoder, &frame);
-}
-
-static void vc4_hdmi_set_hdr_infoframe(struct drm_encoder *encoder)
-{
- struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
- struct drm_connector *connector = &vc4_hdmi->connector;
- struct drm_connector_state *conn_state = connector->state;
- union hdmi_infoframe frame;
-
- lockdep_assert_held(&vc4_hdmi->mutex);
-
- if (!vc4_hdmi->variant->supports_hdr)
- return;
-
- if (!conn_state->hdr_output_metadata)
- return;
-
- if (drm_hdmi_infoframe_set_hdr_metadata(&frame.drm, conn_state))
- return;
-
- vc4_hdmi_write_infoframe(encoder, &frame);
-}
-
-static void vc4_hdmi_set_infoframes(struct drm_encoder *encoder)
-{
- struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
-
- lockdep_assert_held(&vc4_hdmi->mutex);
-
- vc4_hdmi_set_avi_infoframe(encoder);
- vc4_hdmi_set_spd_infoframe(encoder);
- /*
- * If audio was streaming, then we need to reenabled the audio
- * infoframe here during encoder_enable.
- */
- if (vc4_hdmi->audio.streaming)
- vc4_hdmi_set_audio_infoframe(encoder);
-
- vc4_hdmi_set_hdr_infoframe(encoder);
+ return ret;
}
#define SCRAMBLING_POLLING_DELAY_MS 1000
@@ -1174,8 +907,6 @@ static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi,
struct drm_connector_state *state,
const struct drm_display_mode *mode)
{
- struct vc4_hdmi_connector_state *vc4_state =
- conn_state_to_vc4_hdmi_conn_state(state);
struct drm_device *drm = vc4_hdmi->connector.dev;
unsigned long flags;
u32 csc_ctl;
@@ -1189,7 +920,7 @@ static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi,
csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR,
VC4_HD_CSC_CTL_ORDER);
- if (!vc4_hdmi_is_full_range(vc4_hdmi, vc4_state)) {
+ if (state->hdmi.is_limited_range) {
/* CEA VICs other than #1 requre limited range RGB
* output unless overridden by an AVI infoframe.
* Apply a colorspace conversion to squash 0-255 down
@@ -1412,9 +1143,7 @@ static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi,
const struct drm_display_mode *mode)
{
struct drm_device *drm = vc4_hdmi->connector.dev;
- struct vc4_hdmi_connector_state *vc4_state =
- conn_state_to_vc4_hdmi_conn_state(state);
- unsigned int lim_range = vc4_hdmi_is_full_range(vc4_hdmi, vc4_state) ? 0 : 1;
+ unsigned int lim_range = state->hdmi.is_limited_range ? 1 : 0;
unsigned long flags;
const u16 (*csc)[4];
u32 if_cfg = 0;
@@ -1429,14 +1158,14 @@ static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi,
spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
- switch (vc4_state->output_format) {
- case VC4_HDMI_OUTPUT_YUV444:
+ switch (state->hdmi.output_format) {
+ case HDMI_COLORSPACE_YUV444:
csc = vc5_hdmi_find_yuv_csc_coeffs(vc4_hdmi, state->colorspace, !!lim_range);
vc5_hdmi_set_csc_coeffs_swap(vc4_hdmi, csc);
break;
- case VC4_HDMI_OUTPUT_YUV422:
+ case HDMI_COLORSPACE_YUV422:
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,
@@ -1453,7 +1182,7 @@ static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi,
vc5_hdmi_set_csc_coeffs(vc4_hdmi, csc);
break;
- case VC4_HDMI_OUTPUT_RGB:
+ case HDMI_COLORSPACE_RGB:
if_xbar = 0x354021;
vc5_hdmi_set_csc_coeffs(vc4_hdmi, vc5_hdmi_csc_full_rgb_to_rgb[lim_range]);
@@ -1542,8 +1271,6 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
const struct drm_display_mode *mode)
{
struct drm_device *drm = vc4_hdmi->connector.dev;
- const struct vc4_hdmi_connector_state *vc4_state =
- conn_state_to_vc4_hdmi_conn_state(state);
bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE;
@@ -1595,7 +1322,7 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
HDMI_WRITE(HDMI_VERTB0, vertb_even);
HDMI_WRITE(HDMI_VERTB1, vertb);
- switch (vc4_state->output_bpc) {
+ switch (state->hdmi.output_bpc) {
case 12:
gcp = 6;
break;
@@ -1612,7 +1339,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 (vc4_state->output_format == VC4_HDMI_OUTPUT_YUV422) {
+ if (state->hdmi.output_format == HDMI_COLORSPACE_YUV422) {
gcp = 0;
}
@@ -1696,10 +1423,8 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
struct drm_connector *connector = &vc4_hdmi->connector;
struct drm_connector_state *conn_state =
drm_atomic_get_new_connector_state(state, connector);
- struct vc4_hdmi_connector_state *vc4_conn_state =
- conn_state_to_vc4_hdmi_conn_state(conn_state);
const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode;
- unsigned long tmds_char_rate = vc4_conn_state->tmds_char_rate;
+ unsigned long long tmds_char_rate = conn_state->hdmi.tmds_char_rate;
unsigned long bvb_rate, hsm_rate;
unsigned long flags;
int ret;
@@ -1734,7 +1459,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
*/
hsm_rate = max_t(unsigned long,
HSM_MIN_CLOCK_FREQ,
- (tmds_char_rate / 100) * 101);
+ div_u64(tmds_char_rate, 100) * 101);
ret = clk_set_min_rate(vc4_hdmi->hsm_clock, hsm_rate);
if (ret) {
DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
@@ -1776,7 +1501,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
}
if (vc4_hdmi->variant->phy_init)
- vc4_hdmi->variant->phy_init(vc4_hdmi, vc4_conn_state);
+ vc4_hdmi->variant->phy_init(vc4_hdmi, conn_state);
spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
@@ -1841,7 +1566,8 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder,
struct drm_atomic_state *state)
{
struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
- struct drm_device *drm = vc4_hdmi->connector.dev;
+ struct drm_connector *connector = &vc4_hdmi->connector;
+ struct drm_device *drm = connector->dev;
const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode;
struct drm_display_info *display = &vc4_hdmi->connector.display_info;
bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
@@ -1907,7 +1633,7 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder,
spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
vc4_hdmi->packet_ram_enabled = true;
- vc4_hdmi_set_infoframes(encoder);
+ drm_atomic_helper_connector_hdmi_update_infoframes(connector, state);
}
vc4_hdmi_recenter_fifo(vc4_hdmi);
@@ -1924,108 +1650,21 @@ static void vc4_hdmi_encoder_atomic_mode_set(struct drm_encoder *encoder,
struct drm_connector_state *conn_state)
{
struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
- struct vc4_hdmi_connector_state *vc4_state =
- conn_state_to_vc4_hdmi_conn_state(conn_state);
mutex_lock(&vc4_hdmi->mutex);
drm_mode_copy(&vc4_hdmi->saved_adjusted_mode,
&crtc_state->adjusted_mode);
- vc4_hdmi->output_bpc = vc4_state->output_bpc;
- vc4_hdmi->output_format = vc4_state->output_format;
+ vc4_hdmi->output_bpc = conn_state->hdmi.output_bpc;
+ vc4_hdmi->output_format = conn_state->hdmi.output_format;
mutex_unlock(&vc4_hdmi->mutex);
}
-static bool
-vc4_hdmi_sink_supports_format_bpc(const struct vc4_hdmi *vc4_hdmi,
- const struct drm_display_info *info,
- const struct drm_display_mode *mode,
- unsigned int format, unsigned int bpc)
-{
- struct drm_device *dev = vc4_hdmi->connector.dev;
- u8 vic = drm_match_cea_mode(mode);
-
- if (vic == 1 && bpc != 8) {
- drm_dbg(dev, "VIC1 requires a bpc of 8, got %u\n", bpc);
- return false;
- }
-
- if (!info->is_hdmi &&
- (format != VC4_HDMI_OUTPUT_RGB || bpc != 8)) {
- drm_dbg(dev, "DVI Monitors require an RGB output at 8 bpc\n");
- return false;
- }
-
- switch (format) {
- case VC4_HDMI_OUTPUT_RGB:
- drm_dbg(dev, "RGB Format, checking the constraints.\n");
-
- if (!(info->color_formats & DRM_COLOR_FORMAT_RGB444))
- return false;
-
- if (bpc == 10 && !(info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_30)) {
- drm_dbg(dev, "10 BPC but sink doesn't support Deep Color 30.\n");
- return false;
- }
-
- if (bpc == 12 && !(info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_36)) {
- drm_dbg(dev, "12 BPC but sink doesn't support Deep Color 36.\n");
- return false;
- }
-
- drm_dbg(dev, "RGB format supported in that configuration.\n");
-
- return true;
-
- case VC4_HDMI_OUTPUT_YUV422:
- drm_dbg(dev, "YUV422 format, checking the constraints.\n");
-
- if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR422)) {
- drm_dbg(dev, "Sink doesn't support YUV422.\n");
- return false;
- }
-
- if (bpc != 12) {
- drm_dbg(dev, "YUV422 only supports 12 bpc.\n");
- return false;
- }
-
- drm_dbg(dev, "YUV422 format supported in that configuration.\n");
-
- return true;
-
- case VC4_HDMI_OUTPUT_YUV444:
- drm_dbg(dev, "YUV444 format, checking the constraints.\n");
-
- if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR444)) {
- drm_dbg(dev, "Sink doesn't support YUV444.\n");
- return false;
- }
-
- if (bpc == 10 && !(info->edid_hdmi_ycbcr444_dc_modes & DRM_EDID_HDMI_DC_30)) {
- drm_dbg(dev, "10 BPC but sink doesn't support Deep Color 30.\n");
- return false;
- }
-
- if (bpc == 12 && !(info->edid_hdmi_ycbcr444_dc_modes & DRM_EDID_HDMI_DC_36)) {
- drm_dbg(dev, "12 BPC but sink doesn't support Deep Color 36.\n");
- return false;
- }
-
- drm_dbg(dev, "YUV444 format supported in that configuration.\n");
-
- return true;
- }
-
- return false;
-}
-
static enum drm_mode_status
-vc4_hdmi_encoder_clock_valid(const struct vc4_hdmi *vc4_hdmi,
- const struct drm_display_mode *mode,
- unsigned long long clock)
+vc4_hdmi_connector_clock_valid(const struct drm_connector *connector,
+ const struct drm_display_mode *mode,
+ unsigned long long clock)
{
- const struct drm_connector *connector = &vc4_hdmi->connector;
- const struct drm_display_info *info = &connector->display_info;
+ const struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector);
struct vc4_dev *vc4 = to_vc4_dev(connector->dev);
if (clock > vc4_hdmi->variant->max_pixel_clock)
@@ -2040,125 +1679,13 @@ vc4_hdmi_encoder_clock_valid(const struct vc4_hdmi *vc4_hdmi,
drm_mode_vrefresh(mode) >= 50)
return MODE_CLOCK_HIGH;
- if (info->max_tmds_clock && clock > (info->max_tmds_clock * 1000))
- return MODE_CLOCK_HIGH;
-
return MODE_OK;
}
-static unsigned long long
-vc4_hdmi_encoder_compute_mode_clock(const struct drm_display_mode *mode,
- unsigned int bpc,
- enum vc4_hdmi_output_format fmt)
-{
- unsigned long long clock = mode->clock * 1000ULL;
-
- if (mode->flags & DRM_MODE_FLAG_DBLCLK)
- clock = clock * 2;
-
- if (fmt == VC4_HDMI_OUTPUT_YUV422)
- bpc = 8;
-
- clock = clock * bpc;
- do_div(clock, 8);
-
- return clock;
-}
-
-static int
-vc4_hdmi_encoder_compute_clock(const struct vc4_hdmi *vc4_hdmi,
- struct vc4_hdmi_connector_state *vc4_state,
- const struct drm_display_mode *mode,
- unsigned int bpc, unsigned int fmt)
-{
- unsigned long long clock;
-
- clock = vc4_hdmi_encoder_compute_mode_clock(mode, bpc, fmt);
- if (vc4_hdmi_encoder_clock_valid(vc4_hdmi, mode, clock) != MODE_OK)
- return -EINVAL;
-
- vc4_state->tmds_char_rate = clock;
-
- return 0;
-}
-
-static int
-vc4_hdmi_encoder_compute_format(const struct vc4_hdmi *vc4_hdmi,
- struct vc4_hdmi_connector_state *vc4_state,
- const struct drm_display_mode *mode,
- unsigned int bpc)
-{
- struct drm_device *dev = vc4_hdmi->connector.dev;
- const struct drm_connector *connector = &vc4_hdmi->connector;
- const struct drm_display_info *info = &connector->display_info;
- unsigned int format;
-
- drm_dbg(dev, "Trying with an RGB output\n");
-
- format = VC4_HDMI_OUTPUT_RGB;
- if (vc4_hdmi_sink_supports_format_bpc(vc4_hdmi, info, mode, format, bpc)) {
- int ret;
-
- ret = vc4_hdmi_encoder_compute_clock(vc4_hdmi, vc4_state,
- mode, bpc, format);
- if (!ret) {
- vc4_state->output_format = format;
- return 0;
- }
- }
-
- drm_dbg(dev, "Failed, Trying with an YUV422 output\n");
-
- format = VC4_HDMI_OUTPUT_YUV422;
- if (vc4_hdmi_sink_supports_format_bpc(vc4_hdmi, info, mode, format, bpc)) {
- int ret;
-
- ret = vc4_hdmi_encoder_compute_clock(vc4_hdmi, vc4_state,
- mode, bpc, format);
- if (!ret) {
- vc4_state->output_format = format;
- return 0;
- }
- }
-
- drm_dbg(dev, "Failed. No Format Supported for that bpc count.\n");
-
- return -EINVAL;
-}
-
-static int
-vc4_hdmi_encoder_compute_config(const struct vc4_hdmi *vc4_hdmi,
- struct vc4_hdmi_connector_state *vc4_state,
- const struct drm_display_mode *mode)
-{
- struct drm_device *dev = vc4_hdmi->connector.dev;
- struct drm_connector_state *conn_state = &vc4_state->base;
- unsigned int max_bpc = clamp_t(unsigned int, conn_state->max_bpc, 8, 12);
- unsigned int bpc;
- int ret;
-
- for (bpc = max_bpc; bpc >= 8; bpc -= 2) {
- drm_dbg(dev, "Trying with a %d bpc output\n", bpc);
-
- ret = vc4_hdmi_encoder_compute_format(vc4_hdmi, vc4_state,
- mode, bpc);
- if (ret)
- continue;
-
- vc4_state->output_bpc = bpc;
-
- drm_dbg(dev,
- "Mode %ux%u @ %uHz: Found configuration: bpc: %u, fmt: %s, clock: %llu\n",
- mode->hdisplay, mode->vdisplay, drm_mode_vrefresh(mode),
- vc4_state->output_bpc,
- vc4_hdmi_output_fmt_str(vc4_state->output_format),
- vc4_state->tmds_char_rate);
-
- break;
- }
-
- return ret;
-}
+static const struct drm_connector_hdmi_funcs vc4_hdmi_hdmi_connector_funcs = {
+ .tmds_char_rate_valid = vc4_hdmi_connector_clock_valid,
+ .write_infoframe = vc4_hdmi_write_infoframe,
+};
#define WIFI_2_4GHz_CH1_MIN_FREQ 2400000000ULL
#define WIFI_2_4GHz_CH1_MAX_FREQ 2422000000ULL
@@ -2168,16 +1695,9 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
struct drm_connector_state *conn_state)
{
struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
- struct drm_connector *connector = &vc4_hdmi->connector;
- struct drm_connector_state *old_conn_state =
- drm_atomic_get_old_connector_state(conn_state->state, connector);
- struct vc4_hdmi_connector_state *old_vc4_state =
- conn_state_to_vc4_hdmi_conn_state(old_conn_state);
- struct vc4_hdmi_connector_state *vc4_state = conn_state_to_vc4_hdmi_conn_state(conn_state);
struct drm_display_mode *mode = &crtc_state->adjusted_mode;
unsigned long long tmds_char_rate = mode->clock * 1000;
unsigned long long tmds_bit_rate;
- int ret;
if (vc4_hdmi->variant->unsupported_odd_h_timings) {
if (mode->flags & DRM_MODE_FLAG_DBLCLK) {
@@ -2213,15 +1733,6 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
tmds_char_rate = mode->clock * 1000;
}
- ret = vc4_hdmi_encoder_compute_config(vc4_hdmi, vc4_state, mode);
- if (ret)
- return ret;
-
- /* vc4_hdmi_encoder_compute_config may have changed output_bpc and/or output_format */
- if (vc4_state->output_bpc != old_vc4_state->output_bpc ||
- vc4_state->output_format != old_vc4_state->output_format)
- crtc_state->mode_changed = true;
-
return 0;
}
@@ -2230,6 +1741,7 @@ vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder,
const struct drm_display_mode *mode)
{
struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
+ unsigned long long rate;
if (vc4_hdmi->variant->unsupported_odd_h_timings &&
!(mode->flags & DRM_MODE_FLAG_DBLCLK) &&
@@ -2237,7 +1749,8 @@ vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder,
(mode->hsync_end % 2) || (mode->htotal % 2)))
return MODE_H_ILLEGAL;
- return vc4_hdmi_encoder_clock_valid(vc4_hdmi, mode, mode->clock * 1000);
+ rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_RGB);
+ return vc4_hdmi_connector_clock_valid(&vc4_hdmi->connector, mode, rate);
}
static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = {
@@ -2429,7 +1942,6 @@ out:
static void vc4_hdmi_audio_reset(struct vc4_hdmi *vc4_hdmi)
{
- struct drm_encoder *encoder = &vc4_hdmi->encoder.base;
struct device *dev = &vc4_hdmi->pdev->dev;
unsigned long flags;
int ret;
@@ -2437,7 +1949,7 @@ static void vc4_hdmi_audio_reset(struct vc4_hdmi *vc4_hdmi)
lockdep_assert_held(&vc4_hdmi->mutex);
vc4_hdmi->audio.streaming = false;
- ret = vc4_hdmi_stop_packet(encoder, HDMI_INFOFRAME_TYPE_AUDIO, false);
+ ret = vc4_hdmi_stop_packet(vc4_hdmi, HDMI_INFOFRAME_TYPE_AUDIO, false);
if (ret)
dev_err(dev, "Failed to stop audio infoframe: %d\n", ret);
@@ -2528,7 +2040,7 @@ static int vc4_hdmi_audio_prepare(struct device *dev, void *data,
{
struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev);
struct drm_device *drm = vc4_hdmi->connector.dev;
- struct drm_encoder *encoder = &vc4_hdmi->encoder.base;
+ struct drm_connector *connector = &vc4_hdmi->connector;
unsigned int sample_rate = params->sample_rate;
unsigned int channels = params->channels;
unsigned long flags;
@@ -2605,8 +2117,10 @@ static int vc4_hdmi_audio_prepare(struct device *dev, void *data,
spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
- memcpy(&vc4_hdmi->audio.infoframe, &params->cea, sizeof(params->cea));
- vc4_hdmi_set_audio_infoframe(encoder);
+ ret = drm_atomic_helper_connector_hdmi_update_audio_infoframe(connector,
+ &params->cea);
+ if (ret)
+ goto out_dev_exit;
out_dev_exit:
drm_dev_exit(idx);
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 934d5d61485a..b37f1d2c3fe5 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -10,7 +10,6 @@
struct vc4_hdmi;
struct vc4_hdmi_register;
-struct vc4_hdmi_connector_state;
enum vc4_hdmi_phy_channel {
PHY_LANE_0 = 0,
@@ -76,7 +75,7 @@ struct vc4_hdmi_variant {
/* Callback to initialize the PHY according to the connector state */
void (*phy_init)(struct vc4_hdmi *vc4_hdmi,
- struct vc4_hdmi_connector_state *vc4_conn_state);
+ struct drm_connector_state *conn_state);
/* Callback to disable the PHY */
void (*phy_disable)(struct vc4_hdmi *vc4_hdmi);
@@ -110,19 +109,6 @@ struct vc4_hdmi_audio {
bool streaming;
};
-enum vc4_hdmi_output_format {
- VC4_HDMI_OUTPUT_RGB,
- VC4_HDMI_OUTPUT_YUV422,
- VC4_HDMI_OUTPUT_YUV444,
- VC4_HDMI_OUTPUT_YUV420,
-};
-
-enum vc4_hdmi_broadcast_rgb {
- VC4_HDMI_BROADCAST_RGB_AUTO,
- VC4_HDMI_BROADCAST_RGB_FULL,
- VC4_HDMI_BROADCAST_RGB_LIMITED,
-};
-
/* General HDMI hardware state. */
struct vc4_hdmi {
struct vc4_hdmi_audio audio;
@@ -135,8 +121,6 @@ struct vc4_hdmi {
struct delayed_work scrambling_work;
- struct drm_property *broadcast_rgb_property;
-
struct i2c_adapter *ddc;
void __iomem *hdmicore_regs;
void __iomem *hd_regs;
@@ -218,16 +202,17 @@ struct vc4_hdmi {
bool scdc_enabled;
/**
- * @output_bpc: Copy of @vc4_connector_state.output_bpc for use
- * outside of KMS hooks. Protected by @mutex.
+ * @output_bpc: Copy of @drm_connector_state.hdmi.output_bpc for
+ * use outside of KMS hooks. Protected by @mutex.
*/
unsigned int output_bpc;
/**
- * @output_format: Copy of @vc4_connector_state.output_format
- * for use outside of KMS hooks. Protected by @mutex.
+ * @output_format: Copy of
+ * @drm_connector_state.hdmi.output_format for use outside of
+ * KMS hooks. Protected by @mutex.
*/
- enum vc4_hdmi_output_format output_format;
+ enum hdmi_colorspace output_format;
};
#define connector_to_vc4_hdmi(_connector) \
@@ -240,25 +225,14 @@ encoder_to_vc4_hdmi(struct drm_encoder *encoder)
return container_of_const(_encoder, struct vc4_hdmi, encoder);
}
-struct vc4_hdmi_connector_state {
- struct drm_connector_state base;
- unsigned long long tmds_char_rate;
- unsigned int output_bpc;
- enum vc4_hdmi_output_format output_format;
- enum vc4_hdmi_broadcast_rgb broadcast_rgb;
-};
-
-#define conn_state_to_vc4_hdmi_conn_state(_state) \
- container_of_const(_state, struct vc4_hdmi_connector_state, base)
-
void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
- struct vc4_hdmi_connector_state *vc4_conn_state);
+ struct drm_connector_state *conn_state);
void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
void vc4_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi);
void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi);
void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
- struct vc4_hdmi_connector_state *vc4_conn_state);
+ struct drm_connector_state *conn_state);
void vc5_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
void vc5_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi);
void vc5_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi);
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
index ec24999bf96d..1f5507fc7a03 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
@@ -128,7 +128,7 @@
#define OSCILLATOR_FREQUENCY 54000000
void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
- struct vc4_hdmi_connector_state *conn_state)
+ struct drm_connector_state *conn_state)
{
unsigned long flags;
@@ -361,11 +361,11 @@ static void vc5_hdmi_reset_phy(struct vc4_hdmi *vc4_hdmi)
}
void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
- struct vc4_hdmi_connector_state *conn_state)
+ struct drm_connector_state *conn_state)
{
const struct phy_lane_settings *chan0_settings, *chan1_settings, *chan2_settings, *clock_settings;
const struct vc4_hdmi_variant *variant = vc4_hdmi->variant;
- unsigned long long pixel_freq = conn_state->tmds_char_rate;
+ unsigned long long pixel_freq = conn_state->hdmi.tmds_char_rate;
unsigned long long vco_freq;
unsigned char word_sel;
unsigned long flags;
diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c
index 268f18b10ee0..070813b8aff8 100644
--- a/drivers/gpu/drm/vc4/vc4_vec.c
+++ b/drivers/gpu/drm/vc4/vc4_vec.c
@@ -234,6 +234,7 @@ enum vc4_vec_tv_mode_id {
VC4_VEC_TV_MODE_PAL_60,
VC4_VEC_TV_MODE_PAL_N,
VC4_VEC_TV_MODE_SECAM,
+ VC4_VEC_TV_MODE_MONOCHROME,
};
struct vc4_vec_tv_mode {
@@ -324,6 +325,22 @@ static const struct vc4_vec_tv_mode vc4_vec_tv_modes[] = {
.config1 = VEC_CONFIG1_C_CVBS_CVBS,
.custom_freq = 0x29c71c72,
},
+ {
+ /* 50Hz mono */
+ .mode = DRM_MODE_TV_MODE_MONOCHROME,
+ .expected_htotal = 864,
+ .config0 = VEC_CONFIG0_PAL_BDGHI_STD | VEC_CONFIG0_BURDIS |
+ VEC_CONFIG0_CHRDIS,
+ .config1 = VEC_CONFIG1_C_CVBS_CVBS,
+ },
+ {
+ /* 60Hz mono */
+ .mode = DRM_MODE_TV_MODE_MONOCHROME,
+ .expected_htotal = 858,
+ .config0 = VEC_CONFIG0_PAL_M_STD | VEC_CONFIG0_BURDIS |
+ VEC_CONFIG0_CHRDIS,
+ .config1 = VEC_CONFIG1_C_CVBS_CVBS,
+ },
};
static inline const struct vc4_vec_tv_mode *
@@ -351,6 +368,7 @@ static const struct drm_prop_enum_list legacy_tv_mode_names[] = {
{ VC4_VEC_TV_MODE_PAL_M, "PAL-M", },
{ VC4_VEC_TV_MODE_PAL_N, "PAL-N", },
{ VC4_VEC_TV_MODE_SECAM, "SECAM", },
+ { VC4_VEC_TV_MODE_MONOCHROME, "Mono", },
};
static enum drm_connector_status
@@ -406,6 +424,10 @@ vc4_vec_connector_set_property(struct drm_connector *connector,
state->tv.mode = DRM_MODE_TV_MODE_SECAM;
break;
+ case VC4_VEC_TV_MODE_MONOCHROME:
+ state->tv.mode = DRM_MODE_TV_MODE_MONOCHROME;
+ break;
+
default:
return -EINVAL;
}
@@ -453,6 +475,10 @@ vc4_vec_connector_get_property(struct drm_connector *connector,
*val = VC4_VEC_TV_MODE_SECAM;
break;
+ case DRM_MODE_TV_MODE_MONOCHROME:
+ *val = VC4_VEC_TV_MODE_MONOCHROME;
+ break;
+
default:
return -EINVAL;
}
@@ -503,6 +529,8 @@ static int vc4_vec_connector_init(struct drm_device *dev, struct vc4_vec *vec)
drm_object_attach_property(&connector->base, prop, VC4_VEC_TV_MODE_NTSC);
+ drm_connector_attach_tv_margin_properties(connector);
+
drm_connector_attach_encoder(connector, &vec->encoder.base);
return 0;
@@ -754,7 +782,8 @@ static int vc4_vec_bind(struct device *dev, struct device *master, void *data)
BIT(DRM_MODE_TV_MODE_PAL) |
BIT(DRM_MODE_TV_MODE_PAL_M) |
BIT(DRM_MODE_TV_MODE_PAL_N) |
- BIT(DRM_MODE_TV_MODE_SECAM));
+ BIT(DRM_MODE_TV_MODE_SECAM) |
+ BIT(DRM_MODE_TV_MODE_MONOCHROME));
if (ret)
return ret;
diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c
index ad924a8502e9..64baf2f22d9f 100644
--- a/drivers/gpu/drm/virtio/virtgpu_display.c
+++ b/drivers/gpu/drm/virtio/virtgpu_display.c
@@ -164,11 +164,9 @@ static int virtio_gpu_conn_get_modes(struct drm_connector *connector)
struct drm_display_mode *mode = NULL;
int count, width, height;
- if (output->edid) {
- count = drm_add_edid_modes(connector, output->edid);
- if (count)
- return count;
- }
+ count = drm_edid_connector_add_modes(connector);
+ if (count)
+ return count;
width = le32_to_cpu(output->info.r.width);
height = le32_to_cpu(output->info.r.height);
@@ -369,5 +367,5 @@ void virtio_gpu_modeset_fini(struct virtio_gpu_device *vgdev)
return;
for (i = 0 ; i < vgdev->num_scanouts; ++i)
- kfree(vgdev->outputs[i].edid);
+ drm_edid_free(vgdev->outputs[i].drm_edid);
}
diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.c b/drivers/gpu/drm/virtio/virtgpu_drv.c
index 188e126383c2..e5a2665e50ea 100644
--- a/drivers/gpu/drm/virtio/virtgpu_drv.c
+++ b/drivers/gpu/drm/virtio/virtgpu_drv.c
@@ -35,7 +35,7 @@
#include <drm/drm_aperture.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_shmem.h>
#include <drm/drm_file.h>
#include "virtgpu_drv.h"
@@ -103,7 +103,7 @@ static int virtio_gpu_probe(struct virtio_device *vdev)
if (ret)
goto err_deinit;
- drm_fbdev_generic_setup(vdev->priv, 32);
+ drm_fbdev_shmem_setup(vdev->priv, 32);
return 0;
err_deinit:
diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h
index bb7d86a0c6a1..64c236169db8 100644
--- a/drivers/gpu/drm/virtio/virtgpu_drv.h
+++ b/drivers/gpu/drm/virtio/virtgpu_drv.h
@@ -179,7 +179,7 @@ struct virtio_gpu_output {
struct drm_encoder enc;
struct virtio_gpu_display_one info;
struct virtio_gpu_update_cursor cursor;
- struct edid *edid;
+ const struct drm_edid *drm_edid;
int cur_x;
int cur_y;
bool needs_modeset;
diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c
index 5a3b5aaed1f3..7dfb2006c561 100644
--- a/drivers/gpu/drm/virtio/virtgpu_kms.c
+++ b/drivers/gpu/drm/virtio/virtgpu_kms.c
@@ -116,11 +116,10 @@ static void virtio_gpu_get_capsets(struct virtio_gpu_device *vgdev,
int virtio_gpu_init(struct virtio_device *vdev, struct drm_device *dev)
{
- static vq_callback_t *callbacks[] = {
- virtio_gpu_ctrl_ack, virtio_gpu_cursor_ack
+ struct virtqueue_info vqs_info[] = {
+ { "control", virtio_gpu_ctrl_ack },
+ { "cursor", virtio_gpu_cursor_ack },
};
- static const char * const names[] = { "control", "cursor" };
-
struct virtio_gpu_device *vgdev;
/* this will expand later */
struct virtqueue *vqs[2];
@@ -207,7 +206,7 @@ int virtio_gpu_init(struct virtio_device *vdev, struct drm_device *dev)
DRM_INFO("features: %ccontext_init\n",
vgdev->has_context_init ? '+' : '-');
- ret = virtio_find_vqs(vgdev->vdev, 2, vqs, callbacks, names, NULL);
+ ret = virtio_find_vqs(vgdev->vdev, 2, vqs, vqs_info, NULL);
if (ret) {
DRM_ERROR("failed to find virt queues\n");
goto err_vqs;
diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c
index b1a00c0c25a7..0d3d0d09f39b 100644
--- a/drivers/gpu/drm/virtio/virtgpu_vq.c
+++ b/drivers/gpu/drm/virtio/virtgpu_vq.c
@@ -741,21 +741,21 @@ static void virtio_gpu_cmd_get_edid_cb(struct virtio_gpu_device *vgdev,
(struct virtio_gpu_resp_edid *)vbuf->resp_buf;
uint32_t scanout = le32_to_cpu(cmd->scanout);
struct virtio_gpu_output *output;
- struct edid *new_edid, *old_edid;
+ const struct drm_edid *new_edid, *old_edid;
if (scanout >= vgdev->num_scanouts)
return;
output = vgdev->outputs + scanout;
- new_edid = drm_do_get_edid(&output->conn, virtio_get_edid_block, resp);
- drm_connector_update_edid_property(&output->conn, new_edid);
+ new_edid = drm_edid_read_custom(&output->conn, virtio_get_edid_block, resp);
+ drm_edid_connector_update(&output->conn, new_edid);
spin_lock(&vgdev->display_info_lock);
- old_edid = output->edid;
- output->edid = new_edid;
+ old_edid = output->drm_edid;
+ output->drm_edid = new_edid;
spin_unlock(&vgdev->display_info_lock);
- kfree(old_edid);
+ drm_edid_free(old_edid);
wake_up(&vgdev->resp_wq);
}
diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c
index dd0af086e7fa..8dc9dc13896e 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.c
+++ b/drivers/gpu/drm/vkms/vkms_drv.c
@@ -17,7 +17,7 @@
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_shmem.h>
#include <drm/drm_file.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_ioctl.h>
@@ -223,7 +223,7 @@ static int vkms_create(struct vkms_config *config)
if (ret)
goto out_devres;
- drm_fbdev_generic_setup(&vkms_device->drm, 0);
+ drm_fbdev_shmem_setup(&vkms_device->drm, 0);
return 0;
diff --git a/drivers/gpu/drm/vmwgfx/Kconfig b/drivers/gpu/drm/vmwgfx/Kconfig
index faddae3d6ac2..6f1ac940cbae 100644
--- a/drivers/gpu/drm/vmwgfx/Kconfig
+++ b/drivers/gpu/drm/vmwgfx/Kconfig
@@ -2,7 +2,7 @@
config DRM_VMWGFX
tristate "DRM driver for VMware Virtual GPU"
depends on DRM && PCI && MMU
- depends on X86 || ARM64
+ depends on (X86 && HYPERVISOR_GUEST) || ARM64
select DRM_TTM
select DRM_TTM_HELPER
select MAPPING_DIRTY_HELPERS
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 823d8d2da17c..50ad3105c16e 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -37,7 +37,7 @@
#include <drm/drm_aperture.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fbdev_ttm.h>
#include <drm/drm_gem_ttm_helper.h>
#include <drm/drm_ioctl.h>
#include <drm/drm_module.h>
@@ -1679,7 +1679,7 @@ static int vmw_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
vmw_fifo_resource_inc(vmw);
vmw_svga_enable(vmw);
- drm_fbdev_generic_setup(&vmw->drm, 0);
+ drm_fbdev_ttm_setup(&vmw->drm, 0);
vmw_debugfs_gem_init(vmw);
vmw_debugfs_resource_managers_init(vmw);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c b/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c
index 2651fe0ef518..1f15990d3934 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c
@@ -48,8 +48,6 @@
#define RETRIES 3
-#define VMW_HYPERVISOR_MAGIC 0x564D5868
-
#define VMW_PORT_CMD_MSG 30
#define VMW_PORT_CMD_HB_MSG 0
#define VMW_PORT_CMD_OPEN_CHANNEL (MSG_TYPE_OPEN << 16 | VMW_PORT_CMD_MSG)
@@ -104,20 +102,18 @@ static const char* const mksstat_kern_name_desc[MKSSTAT_KERN_COUNT][2] =
*/
static int vmw_open_channel(struct rpc_channel *channel, unsigned int protocol)
{
- unsigned long eax, ebx, ecx, edx, si = 0, di = 0;
+ u32 ecx, edx, esi, edi;
- VMW_PORT(VMW_PORT_CMD_OPEN_CHANNEL,
- (protocol | GUESTMSG_FLAG_COOKIE), si, di,
- 0,
- VMW_HYPERVISOR_MAGIC,
- eax, ebx, ecx, edx, si, di);
+ vmware_hypercall6(VMW_PORT_CMD_OPEN_CHANNEL,
+ (protocol | GUESTMSG_FLAG_COOKIE), 0,
+ &ecx, &edx, &esi, &edi);
if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0)
return -EINVAL;
channel->channel_id = HIGH_WORD(edx);
- channel->cookie_high = si;
- channel->cookie_low = di;
+ channel->cookie_high = esi;
+ channel->cookie_low = edi;
return 0;
}
@@ -133,17 +129,13 @@ static int vmw_open_channel(struct rpc_channel *channel, unsigned int protocol)
*/
static int vmw_close_channel(struct rpc_channel *channel)
{
- unsigned long eax, ebx, ecx, edx, si, di;
-
- /* Set up additional parameters */
- si = channel->cookie_high;
- di = channel->cookie_low;
+ u32 ecx;
- VMW_PORT(VMW_PORT_CMD_CLOSE_CHANNEL,
- 0, si, di,
- channel->channel_id << 16,
- VMW_HYPERVISOR_MAGIC,
- eax, ebx, ecx, edx, si, di);
+ vmware_hypercall5(VMW_PORT_CMD_CLOSE_CHANNEL,
+ 0, channel->channel_id << 16,
+ channel->cookie_high,
+ channel->cookie_low,
+ &ecx);
if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0)
return -EINVAL;
@@ -163,24 +155,18 @@ static int vmw_close_channel(struct rpc_channel *channel)
static unsigned long vmw_port_hb_out(struct rpc_channel *channel,
const char *msg, bool hb)
{
- unsigned long si, di, eax, ebx, ecx, edx;
+ u32 ebx, ecx;
unsigned long msg_len = strlen(msg);
/* HB port can't access encrypted memory. */
if (hb && !cc_platform_has(CC_ATTR_MEM_ENCRYPT)) {
- unsigned long bp = channel->cookie_high;
- u32 channel_id = (channel->channel_id << 16);
-
- si = (uintptr_t) msg;
- di = channel->cookie_low;
-
- VMW_PORT_HB_OUT(
+ vmware_hypercall_hb_out(
(MESSAGE_STATUS_SUCCESS << 16) | VMW_PORT_CMD_HB_MSG,
- msg_len, si, di,
- VMWARE_HYPERVISOR_HB | channel_id |
- VMWARE_HYPERVISOR_OUT,
- VMW_HYPERVISOR_MAGIC, bp,
- eax, ebx, ecx, edx, si, di);
+ msg_len,
+ channel->channel_id << 16,
+ (uintptr_t) msg, channel->cookie_low,
+ channel->cookie_high,
+ &ebx);
return ebx;
}
@@ -194,14 +180,13 @@ static unsigned long vmw_port_hb_out(struct rpc_channel *channel,
memcpy(&word, msg, bytes);
msg_len -= bytes;
msg += bytes;
- si = channel->cookie_high;
- di = channel->cookie_low;
-
- VMW_PORT(VMW_PORT_CMD_MSG | (MSG_TYPE_SENDPAYLOAD << 16),
- word, si, di,
- channel->channel_id << 16,
- VMW_HYPERVISOR_MAGIC,
- eax, ebx, ecx, edx, si, di);
+
+ vmware_hypercall5(VMW_PORT_CMD_MSG |
+ (MSG_TYPE_SENDPAYLOAD << 16),
+ word, channel->channel_id << 16,
+ channel->cookie_high,
+ channel->cookie_low,
+ &ecx);
}
return ecx;
@@ -220,22 +205,17 @@ static unsigned long vmw_port_hb_out(struct rpc_channel *channel,
static unsigned long vmw_port_hb_in(struct rpc_channel *channel, char *reply,
unsigned long reply_len, bool hb)
{
- unsigned long si, di, eax, ebx, ecx, edx;
+ u32 ebx, ecx, edx;
/* HB port can't access encrypted memory */
if (hb && !cc_platform_has(CC_ATTR_MEM_ENCRYPT)) {
- unsigned long bp = channel->cookie_low;
- u32 channel_id = (channel->channel_id << 16);
-
- si = channel->cookie_high;
- di = (uintptr_t) reply;
-
- VMW_PORT_HB_IN(
+ vmware_hypercall_hb_in(
(MESSAGE_STATUS_SUCCESS << 16) | VMW_PORT_CMD_HB_MSG,
- reply_len, si, di,
- VMWARE_HYPERVISOR_HB | channel_id,
- VMW_HYPERVISOR_MAGIC, bp,
- eax, ebx, ecx, edx, si, di);
+ reply_len,
+ channel->channel_id << 16,
+ channel->cookie_high,
+ (uintptr_t) reply, channel->cookie_low,
+ &ebx);
return ebx;
}
@@ -245,14 +225,13 @@ static unsigned long vmw_port_hb_in(struct rpc_channel *channel, char *reply,
while (reply_len) {
unsigned int bytes = min_t(unsigned long, reply_len, 4);
- si = channel->cookie_high;
- di = channel->cookie_low;
-
- VMW_PORT(VMW_PORT_CMD_MSG | (MSG_TYPE_RECVPAYLOAD << 16),
- MESSAGE_STATUS_SUCCESS, si, di,
- channel->channel_id << 16,
- VMW_HYPERVISOR_MAGIC,
- eax, ebx, ecx, edx, si, di);
+ vmware_hypercall7(VMW_PORT_CMD_MSG |
+ (MSG_TYPE_RECVPAYLOAD << 16),
+ MESSAGE_STATUS_SUCCESS,
+ channel->channel_id << 16,
+ channel->cookie_high,
+ channel->cookie_low,
+ &ebx, &ecx, &edx);
if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0)
break;
@@ -276,22 +255,18 @@ static unsigned long vmw_port_hb_in(struct rpc_channel *channel, char *reply,
*/
static int vmw_send_msg(struct rpc_channel *channel, const char *msg)
{
- unsigned long eax, ebx, ecx, edx, si, di;
+ u32 ebx, ecx;
size_t msg_len = strlen(msg);
int retries = 0;
while (retries < RETRIES) {
retries++;
- /* Set up additional parameters */
- si = channel->cookie_high;
- di = channel->cookie_low;
-
- VMW_PORT(VMW_PORT_CMD_SENDSIZE,
- msg_len, si, di,
- channel->channel_id << 16,
- VMW_HYPERVISOR_MAGIC,
- eax, ebx, ecx, edx, si, di);
+ vmware_hypercall5(VMW_PORT_CMD_SENDSIZE,
+ msg_len, channel->channel_id << 16,
+ channel->cookie_high,
+ channel->cookie_low,
+ &ecx);
if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0) {
/* Expected success. Give up. */
@@ -329,7 +304,7 @@ STACK_FRAME_NON_STANDARD(vmw_send_msg);
static int vmw_recv_msg(struct rpc_channel *channel, void **msg,
size_t *msg_len)
{
- unsigned long eax, ebx, ecx, edx, si, di;
+ u32 ebx, ecx, edx;
char *reply;
size_t reply_len;
int retries = 0;
@@ -341,15 +316,11 @@ static int vmw_recv_msg(struct rpc_channel *channel, void **msg,
while (retries < RETRIES) {
retries++;
- /* Set up additional parameters */
- si = channel->cookie_high;
- di = channel->cookie_low;
-
- VMW_PORT(VMW_PORT_CMD_RECVSIZE,
- 0, si, di,
- channel->channel_id << 16,
- VMW_HYPERVISOR_MAGIC,
- eax, ebx, ecx, edx, si, di);
+ vmware_hypercall7(VMW_PORT_CMD_RECVSIZE,
+ 0, channel->channel_id << 16,
+ channel->cookie_high,
+ channel->cookie_low,
+ &ebx, &ecx, &edx);
if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0) {
DRM_ERROR("Failed to get reply size for host message.\n");
@@ -384,16 +355,12 @@ static int vmw_recv_msg(struct rpc_channel *channel, void **msg,
reply[reply_len] = '\0';
-
- /* Ack buffer */
- si = channel->cookie_high;
- di = channel->cookie_low;
-
- VMW_PORT(VMW_PORT_CMD_RECVSTATUS,
- MESSAGE_STATUS_SUCCESS, si, di,
- channel->channel_id << 16,
- VMW_HYPERVISOR_MAGIC,
- eax, ebx, ecx, edx, si, di);
+ vmware_hypercall5(VMW_PORT_CMD_RECVSTATUS,
+ MESSAGE_STATUS_SUCCESS,
+ channel->channel_id << 16,
+ channel->cookie_high,
+ channel->cookie_low,
+ &ecx);
if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0) {
kfree(reply);
@@ -652,13 +619,7 @@ static inline void reset_ppn_array(PPN64 *arr, size_t size)
*/
static inline void hypervisor_ppn_reset_all(void)
{
- unsigned long eax, ebx, ecx, edx, si = 0, di = 0;
-
- VMW_PORT(VMW_PORT_CMD_MKSGS_RESET,
- 0, si, di,
- 0,
- VMW_HYPERVISOR_MAGIC,
- eax, ebx, ecx, edx, si, di);
+ vmware_hypercall1(VMW_PORT_CMD_MKSGS_RESET, 0);
}
/**
@@ -669,13 +630,7 @@ static inline void hypervisor_ppn_reset_all(void)
*/
static inline void hypervisor_ppn_add(PPN64 pfn)
{
- unsigned long eax, ebx, ecx, edx, si = 0, di = 0;
-
- VMW_PORT(VMW_PORT_CMD_MKSGS_ADD_PPN,
- (unsigned long)pfn, si, di,
- 0,
- VMW_HYPERVISOR_MAGIC,
- eax, ebx, ecx, edx, si, di);
+ vmware_hypercall1(VMW_PORT_CMD_MKSGS_ADD_PPN, (unsigned long)pfn);
}
/**
@@ -686,13 +641,7 @@ static inline void hypervisor_ppn_add(PPN64 pfn)
*/
static inline void hypervisor_ppn_remove(PPN64 pfn)
{
- unsigned long eax, ebx, ecx, edx, si = 0, di = 0;
-
- VMW_PORT(VMW_PORT_CMD_MKSGS_REMOVE_PPN,
- (unsigned long)pfn, si, di,
- 0,
- VMW_HYPERVISOR_MAGIC,
- eax, ebx, ecx, edx, si, di);
+ vmware_hypercall1(VMW_PORT_CMD_MKSGS_REMOVE_PPN, (unsigned long)pfn);
}
#if IS_ENABLED(CONFIG_DRM_VMWGFX_MKSSTATS)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_msg_arm64.h b/drivers/gpu/drm/vmwgfx/vmwgfx_msg_arm64.h
index 4f40167ad61f..3c78e9338b54 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_msg_arm64.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_msg_arm64.h
@@ -34,6 +34,8 @@
#define VMWARE_HYPERVISOR_HB BIT(0)
#define VMWARE_HYPERVISOR_OUT BIT(1)
+#define VMWARE_HYPERVISOR_MAGIC 0x564D5868
+
#define X86_IO_MAGIC 0x86
#define X86_IO_W7_SIZE_SHIFT 0
@@ -45,86 +47,158 @@
#define X86_IO_W7_IMM_SHIFT 5
#define X86_IO_W7_IMM_MASK (0xff << X86_IO_W7_IMM_SHIFT)
-static inline void vmw_port(unsigned long cmd, unsigned long in_ebx,
- unsigned long in_si, unsigned long in_di,
- unsigned long flags, unsigned long magic,
- unsigned long *eax, unsigned long *ebx,
- unsigned long *ecx, unsigned long *edx,
- unsigned long *si, unsigned long *di)
+static inline
+unsigned long vmware_hypercall1(unsigned long cmd, unsigned long in1)
{
- register u64 x0 asm("x0") = magic;
- register u64 x1 asm("x1") = in_ebx;
+ register u64 x0 asm("x0") = VMWARE_HYPERVISOR_MAGIC;
+ register u64 x1 asm("x1") = in1;
register u64 x2 asm("x2") = cmd;
- register u64 x3 asm("x3") = flags | VMWARE_HYPERVISOR_PORT;
- register u64 x4 asm("x4") = in_si;
- register u64 x5 asm("x5") = in_di;
+ register u64 x3 asm("x3") = VMWARE_HYPERVISOR_PORT;
+ register u64 x7 asm("x7") = ((u64)X86_IO_MAGIC << 32) |
+ X86_IO_W7_WITH |
+ X86_IO_W7_DIR |
+ (2 << X86_IO_W7_SIZE_SHIFT);
+ asm_inline volatile (
+ "mrs xzr, mdccsr_el0; "
+ : "+r" (x0)
+ : "r" (x1), "r" (x2), "r" (x3), "r" (x7)
+ : "memory");
+
+ return x0;
+}
+
+static inline
+unsigned long vmware_hypercall5(unsigned long cmd, unsigned long in1,
+ unsigned long in3, unsigned long in4,
+ unsigned long in5, u32 *out2)
+{
+ register u64 x0 asm("x0") = VMWARE_HYPERVISOR_MAGIC;
+ register u64 x1 asm("x1") = in1;
+ register u64 x2 asm("x2") = cmd;
+ register u64 x3 asm("x3") = in3 | VMWARE_HYPERVISOR_PORT;
+ register u64 x4 asm("x4") = in4;
+ register u64 x5 asm("x5") = in5;
register u64 x7 asm("x7") = ((u64)X86_IO_MAGIC << 32) |
X86_IO_W7_WITH |
X86_IO_W7_DIR |
(2 << X86_IO_W7_SIZE_SHIFT);
- asm volatile("mrs xzr, mdccsr_el0 \n\t"
- : "+r"(x0), "+r"(x1), "+r"(x2),
- "+r"(x3), "+r"(x4), "+r"(x5)
- : "r"(x7)
- :);
- *eax = x0;
- *ebx = x1;
- *ecx = x2;
- *edx = x3;
- *si = x4;
- *di = x5;
+ asm_inline volatile (
+ "mrs xzr, mdccsr_el0; "
+ : "+r" (x0), "+r" (x2)
+ : "r" (x1), "r" (x3), "r" (x4), "r" (x5), "r" (x7)
+ : "memory");
+
+ *out2 = x2;
+ return x0;
}
-static inline void vmw_port_hb(unsigned long cmd, unsigned long in_ecx,
- unsigned long in_si, unsigned long in_di,
- unsigned long flags, unsigned long magic,
- unsigned long bp, u32 w7dir,
- unsigned long *eax, unsigned long *ebx,
- unsigned long *ecx, unsigned long *edx,
- unsigned long *si, unsigned long *di)
+static inline
+unsigned long vmware_hypercall6(unsigned long cmd, unsigned long in1,
+ unsigned long in3, u32 *out2,
+ u32 *out3, u32 *out4, u32 *out5)
{
- register u64 x0 asm("x0") = magic;
+ register u64 x0 asm("x0") = VMWARE_HYPERVISOR_MAGIC;
+ register u64 x1 asm("x1") = in1;
+ register u64 x2 asm("x2") = cmd;
+ register u64 x3 asm("x3") = in3 | VMWARE_HYPERVISOR_PORT;
+ register u64 x4 asm("x4");
+ register u64 x5 asm("x5");
+ register u64 x7 asm("x7") = ((u64)X86_IO_MAGIC << 32) |
+ X86_IO_W7_WITH |
+ X86_IO_W7_DIR |
+ (2 << X86_IO_W7_SIZE_SHIFT);
+
+ asm_inline volatile (
+ "mrs xzr, mdccsr_el0; "
+ : "+r" (x0), "+r" (x2), "+r" (x3), "=r" (x4), "=r" (x5)
+ : "r" (x1), "r" (x7)
+ : "memory");
+
+ *out2 = x2;
+ *out3 = x3;
+ *out4 = x4;
+ *out5 = x5;
+ return x0;
+}
+
+static inline
+unsigned long vmware_hypercall7(unsigned long cmd, unsigned long in1,
+ unsigned long in3, unsigned long in4,
+ unsigned long in5, u32 *out1,
+ u32 *out2, u32 *out3)
+{
+ register u64 x0 asm("x0") = VMWARE_HYPERVISOR_MAGIC;
+ register u64 x1 asm("x1") = in1;
+ register u64 x2 asm("x2") = cmd;
+ register u64 x3 asm("x3") = in3 | VMWARE_HYPERVISOR_PORT;
+ register u64 x4 asm("x4") = in4;
+ register u64 x5 asm("x5") = in5;
+ register u64 x7 asm("x7") = ((u64)X86_IO_MAGIC << 32) |
+ X86_IO_W7_WITH |
+ X86_IO_W7_DIR |
+ (2 << X86_IO_W7_SIZE_SHIFT);
+
+ asm_inline volatile (
+ "mrs xzr, mdccsr_el0; "
+ : "+r" (x0), "+r" (x1), "+r" (x2), "+r" (x3)
+ : "r" (x4), "r" (x5), "r" (x7)
+ : "memory");
+
+ *out1 = x1;
+ *out2 = x2;
+ *out3 = x3;
+ return x0;
+}
+
+static inline
+unsigned long vmware_hypercall_hb(unsigned long cmd, unsigned long in2,
+ unsigned long in3, unsigned long in4,
+ unsigned long in5, unsigned long in6,
+ u32 *out1, int dir)
+{
+ register u64 x0 asm("x0") = VMWARE_HYPERVISOR_MAGIC;
register u64 x1 asm("x1") = cmd;
- register u64 x2 asm("x2") = in_ecx;
- register u64 x3 asm("x3") = flags | VMWARE_HYPERVISOR_PORT_HB;
- register u64 x4 asm("x4") = in_si;
- register u64 x5 asm("x5") = in_di;
- register u64 x6 asm("x6") = bp;
+ register u64 x2 asm("x2") = in2;
+ register u64 x3 asm("x3") = in3 | VMWARE_HYPERVISOR_PORT_HB;
+ register u64 x4 asm("x4") = in4;
+ register u64 x5 asm("x5") = in5;
+ register u64 x6 asm("x6") = in6;
register u64 x7 asm("x7") = ((u64)X86_IO_MAGIC << 32) |
X86_IO_W7_STR |
X86_IO_W7_WITH |
- w7dir;
-
- asm volatile("mrs xzr, mdccsr_el0 \n\t"
- : "+r"(x0), "+r"(x1), "+r"(x2),
- "+r"(x3), "+r"(x4), "+r"(x5)
- : "r"(x6), "r"(x7)
- :);
- *eax = x0;
- *ebx = x1;
- *ecx = x2;
- *edx = x3;
- *si = x4;
- *di = x5;
-}
+ dir;
-#define VMW_PORT(cmd, in_ebx, in_si, in_di, flags, magic, eax, ebx, ecx, edx, \
- si, di) \
- vmw_port(cmd, in_ebx, in_si, in_di, flags, magic, &eax, &ebx, &ecx, \
- &edx, &si, &di)
+ asm_inline volatile (
+ "mrs xzr, mdccsr_el0; "
+ : "+r" (x0), "+r" (x1)
+ : "r" (x2), "r" (x3), "r" (x4), "r" (x5),
+ "r" (x6), "r" (x7)
+ : "memory");
-#define VMW_PORT_HB_OUT(cmd, in_ecx, in_si, in_di, flags, magic, bp, eax, ebx, \
- ecx, edx, si, di) \
- vmw_port_hb(cmd, in_ecx, in_si, in_di, flags, magic, bp, \
- 0, &eax, &ebx, &ecx, &edx, &si, &di)
+ *out1 = x1;
+ return x0;
+}
-#define VMW_PORT_HB_IN(cmd, in_ecx, in_si, in_di, flags, magic, bp, eax, ebx, \
- ecx, edx, si, di) \
- vmw_port_hb(cmd, in_ecx, in_si, in_di, flags, magic, bp, \
- X86_IO_W7_DIR, &eax, &ebx, &ecx, &edx, &si, &di)
+static inline
+unsigned long vmware_hypercall_hb_out(unsigned long cmd, unsigned long in2,
+ unsigned long in3, unsigned long in4,
+ unsigned long in5, unsigned long in6,
+ u32 *out1)
+{
+ return vmware_hypercall_hb(cmd, in2, in3, in4, in5, in6, out1, 0);
+}
+static inline
+unsigned long vmware_hypercall_hb_in(unsigned long cmd, unsigned long in2,
+ unsigned long in3, unsigned long in4,
+ unsigned long in5, unsigned long in6,
+ u32 *out1)
+{
+ return vmware_hypercall_hb(cmd, in2, in3, in4, in5, in6, out1,
+ X86_IO_W7_DIR);
+}
#endif
#endif /* _VMWGFX_MSG_ARM64_H */
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_msg_x86.h b/drivers/gpu/drm/vmwgfx/vmwgfx_msg_x86.h
index 23899d743a90..13304d34cc6e 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_msg_x86.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_msg_x86.h
@@ -37,191 +37,6 @@
#include <asm/vmware.h>
-/**
- * Hypervisor-specific bi-directional communication channel. Should never
- * execute on bare metal hardware. The caller must make sure to check for
- * supported hypervisor before using these macros.
- *
- * The last two parameters are both input and output and must be initialized.
- *
- * @cmd: [IN] Message Cmd
- * @in_ebx: [IN] Message Len, through EBX
- * @in_si: [IN] Input argument through SI, set to 0 if not used
- * @in_di: [IN] Input argument through DI, set ot 0 if not used
- * @flags: [IN] hypercall flags + [channel id]
- * @magic: [IN] hypervisor magic value
- * @eax: [OUT] value of EAX register
- * @ebx: [OUT] e.g. status from an HB message status command
- * @ecx: [OUT] e.g. status from a non-HB message status command
- * @edx: [OUT] e.g. channel id
- * @si: [OUT]
- * @di: [OUT]
- */
-#define VMW_PORT(cmd, in_ebx, in_si, in_di, \
- flags, magic, \
- eax, ebx, ecx, edx, si, di) \
-({ \
- asm volatile (VMWARE_HYPERCALL : \
- "=a"(eax), \
- "=b"(ebx), \
- "=c"(ecx), \
- "=d"(edx), \
- "=S"(si), \
- "=D"(di) : \
- "a"(magic), \
- "b"(in_ebx), \
- "c"(cmd), \
- "d"(flags), \
- "S"(in_si), \
- "D"(in_di) : \
- "memory"); \
-})
-
-
-/**
- * Hypervisor-specific bi-directional communication channel. Should never
- * execute on bare metal hardware. The caller must make sure to check for
- * supported hypervisor before using these macros.
- *
- * The last 3 parameters are both input and output and must be initialized.
- *
- * @cmd: [IN] Message Cmd
- * @in_ecx: [IN] Message Len, through ECX
- * @in_si: [IN] Input argument through SI, set to 0 if not used
- * @in_di: [IN] Input argument through DI, set to 0 if not used
- * @flags: [IN] hypercall flags + [channel id]
- * @magic: [IN] hypervisor magic value
- * @bp: [IN]
- * @eax: [OUT] value of EAX register
- * @ebx: [OUT] e.g. status from an HB message status command
- * @ecx: [OUT] e.g. status from a non-HB message status command
- * @edx: [OUT] e.g. channel id
- * @si: [OUT]
- * @di: [OUT]
- */
-#ifdef __x86_64__
-
-#define VMW_PORT_HB_OUT(cmd, in_ecx, in_si, in_di, \
- flags, magic, bp, \
- eax, ebx, ecx, edx, si, di) \
-({ \
- asm volatile ( \
- UNWIND_HINT_SAVE \
- "push %%rbp;" \
- UNWIND_HINT_UNDEFINED \
- "mov %12, %%rbp;" \
- VMWARE_HYPERCALL_HB_OUT \
- "pop %%rbp;" \
- UNWIND_HINT_RESTORE : \
- "=a"(eax), \
- "=b"(ebx), \
- "=c"(ecx), \
- "=d"(edx), \
- "=S"(si), \
- "=D"(di) : \
- "a"(magic), \
- "b"(cmd), \
- "c"(in_ecx), \
- "d"(flags), \
- "S"(in_si), \
- "D"(in_di), \
- "r"(bp) : \
- "memory", "cc"); \
-})
-
-
-#define VMW_PORT_HB_IN(cmd, in_ecx, in_si, in_di, \
- flags, magic, bp, \
- eax, ebx, ecx, edx, si, di) \
-({ \
- asm volatile ( \
- UNWIND_HINT_SAVE \
- "push %%rbp;" \
- UNWIND_HINT_UNDEFINED \
- "mov %12, %%rbp;" \
- VMWARE_HYPERCALL_HB_IN \
- "pop %%rbp;" \
- UNWIND_HINT_RESTORE : \
- "=a"(eax), \
- "=b"(ebx), \
- "=c"(ecx), \
- "=d"(edx), \
- "=S"(si), \
- "=D"(di) : \
- "a"(magic), \
- "b"(cmd), \
- "c"(in_ecx), \
- "d"(flags), \
- "S"(in_si), \
- "D"(in_di), \
- "r"(bp) : \
- "memory", "cc"); \
-})
-
-#elif defined(__i386__)
-
-/*
- * In the 32-bit version of this macro, we store bp in a memory location
- * because we've ran out of registers.
- * Now we can't reference that memory location while we've modified
- * %esp or %ebp, so we first push it on the stack, just before we push
- * %ebp, and then when we need it we read it from the stack where we
- * just pushed it.
- */
-#define VMW_PORT_HB_OUT(cmd, in_ecx, in_si, in_di, \
- flags, magic, bp, \
- eax, ebx, ecx, edx, si, di) \
-({ \
- asm volatile ("push %12;" \
- "push %%ebp;" \
- "mov 0x04(%%esp), %%ebp;" \
- VMWARE_HYPERCALL_HB_OUT \
- "pop %%ebp;" \
- "add $0x04, %%esp;" : \
- "=a"(eax), \
- "=b"(ebx), \
- "=c"(ecx), \
- "=d"(edx), \
- "=S"(si), \
- "=D"(di) : \
- "a"(magic), \
- "b"(cmd), \
- "c"(in_ecx), \
- "d"(flags), \
- "S"(in_si), \
- "D"(in_di), \
- "m"(bp) : \
- "memory", "cc"); \
-})
-
-
-#define VMW_PORT_HB_IN(cmd, in_ecx, in_si, in_di, \
- flags, magic, bp, \
- eax, ebx, ecx, edx, si, di) \
-({ \
- asm volatile ("push %12;" \
- "push %%ebp;" \
- "mov 0x04(%%esp), %%ebp;" \
- VMWARE_HYPERCALL_HB_IN \
- "pop %%ebp;" \
- "add $0x04, %%esp;" : \
- "=a"(eax), \
- "=b"(ebx), \
- "=c"(ecx), \
- "=d"(edx), \
- "=S"(si), \
- "=D"(di) : \
- "a"(magic), \
- "b"(cmd), \
- "c"(in_ecx), \
- "d"(flags), \
- "S"(in_si), \
- "D"(in_di), \
- "m"(bp) : \
- "memory", "cc"); \
-})
-#endif /* defined(__i386__) */
-
#endif /* defined(__i386__) || defined(__x86_64__) */
#endif /* _VMWGFX_MSG_X86_H */
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_vkms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_vkms.c
index 7e93a45948f7..3bfcf671fcd5 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_vkms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_vkms.c
@@ -31,7 +31,6 @@
#include "vmwgfx_bo.h"
#include "vmwgfx_drv.h"
#include "vmwgfx_kms.h"
-#include "vmwgfx_vkms.h"
#include "vmw_surface_cache.h"
diff --git a/drivers/gpu/drm/xe/Kconfig b/drivers/gpu/drm/xe/Kconfig
index 63f1e2d1649f..7bbe46a98ff1 100644
--- a/drivers/gpu/drm/xe/Kconfig
+++ b/drivers/gpu/drm/xe/Kconfig
@@ -25,7 +25,6 @@ config DRM_XE
select BACKLIGHT_CLASS_DEVICE if ACPI
select INPUT if ACPI
select ACPI_VIDEO if X86 && ACPI
- select ACPI_BUTTON if ACPI
select X86_PLATFORM_DEVICES if X86 && ACPI
select ACPI_WMI if X86 && ACPI
select SYNC_FILE
diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
index cd076d0c52a5..628c245c4822 100644
--- a/drivers/gpu/drm/xe/Makefile
+++ b/drivers/gpu/drm/xe/Makefile
@@ -24,9 +24,12 @@ $(obj)/generated/%_wa_oob.c $(obj)/generated/%_wa_oob.h: $(obj)/xe_gen_wa_oob \
$(call cmd,wa_oob)
uses_generated_oob := \
+ $(obj)/xe_ggtt.o \
$(obj)/xe_gsc.o \
+ $(obj)/xe_gt.o \
$(obj)/xe_guc.o \
$(obj)/xe_guc_ads.o \
+ $(obj)/xe_guc_pc.o \
$(obj)/xe_migrate.o \
$(obj)/xe_ring_ops.o \
$(obj)/xe_vm.o \
@@ -92,6 +95,8 @@ xe-y += xe_bb.o \
xe_mmio.o \
xe_mocs.o \
xe_module.o \
+ xe_oa.o \
+ xe_observation.o \
xe_pat.o \
xe_pci.o \
xe_pcode.o \
@@ -112,6 +117,8 @@ xe-y += xe_bb.o \
xe_tile.o \
xe_tile_sysfs.o \
xe_trace.o \
+ xe_trace_bo.o \
+ xe_trace_guc.o \
xe_ttm_sys_mgr.o \
xe_ttm_stolen_mgr.o \
xe_ttm_vram_mgr.o \
diff --git a/drivers/gpu/drm/xe/abi/guc_actions_abi.h b/drivers/gpu/drm/xe/abi/guc_actions_abi.h
index 79ba98a169f9..43ad4652c2b2 100644
--- a/drivers/gpu/drm/xe/abi/guc_actions_abi.h
+++ b/drivers/gpu/drm/xe/abi/guc_actions_abi.h
@@ -128,7 +128,6 @@ enum xe_guc_action {
XE_GUC_ACTION_CONTEXT_RESET_NOTIFICATION = 0x1008,
XE_GUC_ACTION_ENGINE_FAILURE_NOTIFICATION = 0x1009,
XE_GUC_ACTION_HOST2GUC_UPDATE_CONTEXT_POLICIES = 0x100B,
- XE_GUC_ACTION_SETUP_PC_GUCRC = 0x3004,
XE_GUC_ACTION_AUTHENTICATE_HUC = 0x4000,
XE_GUC_ACTION_GET_HWCONFIG = 0x4100,
XE_GUC_ACTION_REGISTER_CONTEXT = 0x4502,
@@ -153,11 +152,6 @@ enum xe_guc_action {
XE_GUC_ACTION_LIMIT
};
-enum xe_guc_rc_options {
- XE_GUCRC_HOST_CONTROL,
- XE_GUCRC_FIRMWARE_CONTROL,
-};
-
enum xe_guc_preempt_options {
XE_GUC_PREEMPT_OPTION_DROP_WORK_Q = 0x4,
XE_GUC_PREEMPT_OPTION_DROP_SUBMIT_Q = 0x8,
diff --git a/drivers/gpu/drm/xe/abi/guc_actions_slpc_abi.h b/drivers/gpu/drm/xe/abi/guc_actions_slpc_abi.h
index c165e26c0976..85abe4f09ae2 100644
--- a/drivers/gpu/drm/xe/abi/guc_actions_slpc_abi.h
+++ b/drivers/gpu/drm/xe/abi/guc_actions_slpc_abi.h
@@ -246,4 +246,26 @@ struct slpc_shared_data {
#define HOST2GUC_PC_SLPC_REQUEST_MSG_1_EVENT_ARGC (0xffu << 0)
#define HOST2GUC_PC_SLPC_REQUEST_MSG_N_EVENT_DATA_N GUC_HXG_REQUEST_MSG_n_DATAn
+/**
+ * DOC: SETUP_PC_GUCRC
+ *
+ * +---+-------+--------------------------------------------------------------+
+ * | | Bits | Description |
+ * +===+=======+==============================================================+
+ * | 0 | 31 | ORIGIN = GUC_HXG_ORIGIN_HOST_ |
+ * | +-------+--------------------------------------------------------------+
+ * | | 30:28 | TYPE = GUC_HXG_TYPE_FAST_REQUEST_ |
+ * | +-------+--------------------------------------------------------------+
+ * | | 27:16 | DATA0 = MBZ |
+ * | +-------+--------------------------------------------------------------+
+ * | | 15:0 | ACTION = _`GUC_ACTION_HOST2GUC_SETUP_PC_GUCRC` = 0x3004 |
+ * +---+-------+--------------------------------------------------------------+
+ * | 1 | 31:0 | **MODE** = GUCRC_HOST_CONTROL(0), GUCRC_FIRMWARE_CONTROL(1) |
+ * +---+-------+--------------------------------------------------------------+
+ */
+
+#define GUC_ACTION_HOST2GUC_SETUP_PC_GUCRC 0x3004u
+#define GUCRC_HOST_CONTROL 0u
+#define GUCRC_FIRMWARE_CONTROL 1u
+
#endif
diff --git a/drivers/gpu/drm/xe/abi/guc_errors_abi.h b/drivers/gpu/drm/xe/abi/guc_errors_abi.h
index d0b5fed6876f..2c627a21648f 100644
--- a/drivers/gpu/drm/xe/abi/guc_errors_abi.h
+++ b/drivers/gpu/drm/xe/abi/guc_errors_abi.h
@@ -8,10 +8,41 @@
enum xe_guc_response_status {
XE_GUC_RESPONSE_STATUS_SUCCESS = 0x0,
+ XE_GUC_RESPONSE_ERROR_PROTOCOL = 0x04,
+ XE_GUC_RESPONSE_INVALID_STATE = 0x0A,
+ XE_GUC_RESPONSE_UNSUPPORTED_VERSION = 0x0B,
+ XE_GUC_RESPONSE_INVALID_VFID = 0x0C,
+ XE_GUC_RESPONSE_UNPROVISIONED_VF = 0x0D,
+ XE_GUC_RESPONSE_INVALID_EVENT = 0x0E,
XE_GUC_RESPONSE_NOT_SUPPORTED = 0x20,
+ XE_GUC_RESPONSE_UNKNOWN_ACTION = 0x30,
+ XE_GUC_RESPONSE_ACTION_ABORTED = 0x31,
+ XE_GUC_RESPONSE_NO_PERMISSION = 0x40,
+ XE_GUC_RESPONSE_CANNOT_COMPLETE_ACTION = 0x41,
+ XE_GUC_RESPONSE_INVALID_KLV_DATA = 0x50,
+ XE_GUC_RESPONSE_INVALID_PARAMS = 0x60,
+ XE_GUC_RESPONSE_INVALID_BUFFER_RANGE = 0x70,
+ XE_GUC_RESPONSE_INVALID_BUFFER = 0x71,
+ XE_GUC_RESPONSE_INVALID_GGTT_ADDRESS = 0x80,
+ XE_GUC_RESPONSE_PENDING_ACTION = 0x90,
+ XE_GUC_RESPONSE_INVALID_SIZE = 0x102,
+ XE_GUC_RESPONSE_MALFORMED_KLV = 0x103,
+ XE_GUC_RESPONSE_INVALID_KLV_KEY = 0x105,
+ XE_GUC_RESPONSE_DATA_TOO_LARGE = 0x106,
+ XE_GUC_RESPONSE_VF_MIGRATED = 0x107,
XE_GUC_RESPONSE_NO_ATTRIBUTE_TABLE = 0x201,
XE_GUC_RESPONSE_NO_DECRYPTION_KEY = 0x202,
XE_GUC_RESPONSE_DECRYPTION_FAILED = 0x204,
+ XE_GUC_RESPONSE_VGT_DISABLED = 0x300,
+ XE_GUC_RESPONSE_CTB_FULL = 0x301,
+ XE_GUC_RESPONSE_VGT_UNAUTHORIZED_REQUEST = 0x302,
+ XE_GUC_RESPONSE_CTB_INVALID = 0x303,
+ XE_GUC_RESPONSE_CTB_NOT_REGISTERED = 0x304,
+ XE_GUC_RESPONSE_CTB_IN_USE = 0x305,
+ XE_GUC_RESPONSE_CTB_INVALID_DESC = 0x306,
+ XE_GUC_RESPONSE_CTB_SOURCE_INVALID_DESCRIPTOR = 0x30D,
+ XE_GUC_RESPONSE_CTB_DESTINATION_INVALID_DESCRIPTOR = 0x30E,
+ XE_GUC_RESPONSE_INVALID_CONFIG_STATE = 0x30F,
XE_GUC_RESPONSE_STATUS_GENERIC_FAIL = 0xF000,
};
diff --git a/drivers/gpu/drm/xe/abi/guc_messages_abi.h b/drivers/gpu/drm/xe/abi/guc_messages_abi.h
index 534a39db7772..f6ed4dfd215c 100644
--- a/drivers/gpu/drm/xe/abi/guc_messages_abi.h
+++ b/drivers/gpu/drm/xe/abi/guc_messages_abi.h
@@ -92,6 +92,34 @@
#define GUC_HXG_REQUEST_MSG_n_DATAn GUC_HXG_MSG_n_PAYLOAD
/**
+ * DOC: HXG Fast Request
+ *
+ * The `HXG Request`_ message should be used to initiate asynchronous activity
+ * for which confirmation or return data is not expected.
+ *
+ * If confirmation is required then `HXG Request`_ shall be used instead.
+ *
+ * The recipient of this message may only use `HXG Failure`_ message if it was
+ * unable to accept this request (like invalid data).
+ *
+ * Format of `HXG Fast Request`_ message is same as `HXG Request`_ except @TYPE.
+ *
+ * +---+-------+--------------------------------------------------------------+
+ * | | Bits | Description |
+ * +===+=======+==============================================================+
+ * | 0 | 31 | ORIGIN - see `HXG Message`_ |
+ * | +-------+--------------------------------------------------------------+
+ * | | 30:28 | TYPE = `GUC_HXG_TYPE_FAST_REQUEST`_ |
+ * | +-------+--------------------------------------------------------------+
+ * | | 27:16 | DATA0 - see `HXG Request`_ |
+ * | +-------+--------------------------------------------------------------+
+ * | | 15:0 | ACTION - see `HXG Request`_ |
+ * +---+-------+--------------------------------------------------------------+
+ * |...| | DATAn - see `HXG Request`_ |
+ * +---+-------+--------------------------------------------------------------+
+ */
+
+/**
* DOC: HXG Event
*
* The `HXG Event`_ message should be used to initiate asynchronous activity
@@ -220,17 +248,4 @@
#define GUC_HXG_RESPONSE_MSG_0_DATA0 GUC_HXG_MSG_0_AUX
#define GUC_HXG_RESPONSE_MSG_n_DATAn GUC_HXG_MSG_n_PAYLOAD
-/* deprecated */
-#define INTEL_GUC_MSG_TYPE_SHIFT 28
-#define INTEL_GUC_MSG_TYPE_MASK (0xF << INTEL_GUC_MSG_TYPE_SHIFT)
-#define INTEL_GUC_MSG_DATA_SHIFT 16
-#define INTEL_GUC_MSG_DATA_MASK (0xFFF << INTEL_GUC_MSG_DATA_SHIFT)
-#define INTEL_GUC_MSG_CODE_SHIFT 0
-#define INTEL_GUC_MSG_CODE_MASK (0xFFFF << INTEL_GUC_MSG_CODE_SHIFT)
-
-enum intel_guc_msg_type {
- INTEL_GUC_MSG_TYPE_REQUEST = 0x0,
- INTEL_GUC_MSG_TYPE_RESPONSE = 0xF,
-};
-
#endif
diff --git a/drivers/gpu/drm/xe/display/xe_fb_pin.c b/drivers/gpu/drm/xe/display/xe_fb_pin.c
index a807f869d39f..423f367c7065 100644
--- a/drivers/gpu/drm/xe/display/xe_fb_pin.c
+++ b/drivers/gpu/drm/xe/display/xe_fb_pin.c
@@ -171,7 +171,7 @@ write_ggtt_rotated(struct xe_bo *bo, struct xe_ggtt *ggtt, u32 *ggtt_ofs, u32 bo
u64 pte = ggtt->pt_ops->pte_encode_bo(bo, src_idx * XE_PAGE_SIZE,
xe->pat.idx[XE_CACHE_NONE]);
- xe_ggtt_set_pte(ggtt, *ggtt_ofs, pte);
+ ggtt->pt_ops->ggtt_set_pte(ggtt, *ggtt_ofs, pte);
*ggtt_ofs += XE_PAGE_SIZE;
src_idx -= src_stride;
}
@@ -217,7 +217,7 @@ static int __xe_pin_fb_vma_ggtt(const struct intel_framebuffer *fb,
u64 pte = ggtt->pt_ops->pte_encode_bo(bo, x,
xe->pat.idx[XE_CACHE_NONE]);
- xe_ggtt_set_pte(ggtt, vma->node.start + x, pte);
+ ggtt->pt_ops->ggtt_set_pte(ggtt, vma->node.start + x, pte);
}
} else {
u32 i, ggtt_ofs;
diff --git a/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c b/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c
index 3550f7360a64..0af667ebebf9 100644
--- a/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c
+++ b/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c
@@ -164,12 +164,16 @@ void intel_hdcp_gsc_fini(struct xe_device *xe)
{
struct intel_hdcp_gsc_message *hdcp_message =
xe->display.hdcp.hdcp_message;
+ struct i915_hdcp_arbiter *arb = xe->display.hdcp.arbiter;
- if (!hdcp_message)
- return;
+ if (hdcp_message) {
+ xe_bo_unpin_map_no_vm(hdcp_message->hdcp_bo);
+ kfree(hdcp_message);
+ xe->display.hdcp.hdcp_message = NULL;
+ }
- xe_bo_unpin_map_no_vm(hdcp_message->hdcp_bo);
- kfree(hdcp_message);
+ kfree(arb);
+ xe->display.hdcp.arbiter = NULL;
}
static int xe_gsc_send_sync(struct xe_device *xe,
diff --git a/drivers/gpu/drm/xe/instructions/xe_mi_commands.h b/drivers/gpu/drm/xe/instructions/xe_mi_commands.h
index c74ceb550dce..10ec2920d31b 100644
--- a/drivers/gpu/drm/xe/instructions/xe_mi_commands.h
+++ b/drivers/gpu/drm/xe/instructions/xe_mi_commands.h
@@ -45,6 +45,7 @@
#define MI_LRI_MMIO_REMAP_EN REG_BIT(17)
#define MI_LRI_NUM_REGS(x) XE_INSTR_NUM_DW(2 * (x) + 1)
#define MI_LRI_FORCE_POSTED REG_BIT(12)
+#define MI_LRI_LEN(x) (((x) & 0xff) + 1)
#define MI_FLUSH_DW __MI_INSTR(0x26)
#define MI_FLUSH_DW_STORE_INDEX REG_BIT(21)
@@ -59,6 +60,10 @@
#define MI_LOAD_REGISTER_MEM (__MI_INSTR(0x29) | XE_INSTR_NUM_DW(4))
#define MI_LRM_USE_GGTT REG_BIT(22)
+#define MI_COPY_MEM_MEM (__MI_INSTR(0x2e) | XE_INSTR_NUM_DW(5))
+#define MI_COPY_MEM_MEM_SRC_GGTT REG_BIT(22)
+#define MI_COPY_MEM_MEM_DST_GGTT REG_BIT(21)
+
#define MI_BATCH_BUFFER_START __MI_INSTR(0x31)
#endif
diff --git a/drivers/gpu/drm/xe/regs/xe_engine_regs.h b/drivers/gpu/drm/xe/regs/xe_engine_regs.h
index 263ffc7bc2ef..c38db2a74614 100644
--- a/drivers/gpu/drm/xe/regs/xe_engine_regs.h
+++ b/drivers/gpu/drm/xe/regs/xe_engine_regs.h
@@ -129,6 +129,8 @@
#define RING_EXECLIST_STATUS_HI(base) XE_REG((base) + 0x234 + 4)
#define RING_CONTEXT_CONTROL(base) XE_REG((base) + 0x244, XE_REG_OPTION_MASKED)
+#define CTX_CTRL_OAC_CONTEXT_ENABLE REG_BIT(8)
+#define CTX_CTRL_RUN_ALONE REG_BIT(7)
#define CTX_CTRL_INDIRECT_RING_STATE_ENABLE REG_BIT(4)
#define CTX_CTRL_INHIBIT_SYN_CTX_SWITCH REG_BIT(3)
#define CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT REG_BIT(0)
diff --git a/drivers/gpu/drm/xe/regs/xe_gt_regs.h b/drivers/gpu/drm/xe/regs/xe_gt_regs.h
index 011fbbe00168..d44564bad009 100644
--- a/drivers/gpu/drm/xe/regs/xe_gt_regs.h
+++ b/drivers/gpu/drm/xe/regs/xe_gt_regs.h
@@ -170,6 +170,8 @@
#define SQCNT1 XE_REG_MCR(0x8718)
#define XELPMP_SQCNT1 XE_REG(0x8718)
+#define SQCNT1_PMON_ENABLE REG_BIT(30)
+#define SQCNT1_OABPC REG_BIT(29)
#define ENFORCE_RAR REG_BIT(23)
#define XEHP_SQCM XE_REG_MCR(0x8724)
@@ -432,6 +434,7 @@
#define ROW_CHICKEN XE_REG_MCR(0xe4f0, XE_REG_OPTION_MASKED)
#define UGM_BACKUP_MODE REG_BIT(13)
#define MDQ_ARBITRATION_MODE REG_BIT(12)
+#define STALL_DOP_GATING_DISABLE REG_BIT(5)
#define EARLY_EOT_DIS REG_BIT(1)
#define ROW_CHICKEN2 XE_REG_MCR(0xe4f4, XE_REG_OPTION_MASKED)
@@ -490,9 +493,11 @@
((ccs) << ((cslice) * CCS_MODE_CSLICE_WIDTH))
#define FORCEWAKE_ACK_GT XE_REG(0x130044)
-#define FORCEWAKE_KERNEL BIT(0)
-#define FORCEWAKE_USER BIT(1)
-#define FORCEWAKE_KERNEL_FALLBACK BIT(15)
+
+/* Applicable for all FORCEWAKE_DOMAIN and FORCEWAKE_ACK_DOMAIN regs */
+#define FORCEWAKE_KERNEL 0
+#define FORCEWAKE_MT(bit) BIT(bit)
+#define FORCEWAKE_MT_MASK(bit) BIT((bit) + 16)
#define MTL_MEDIA_PERF_LIMIT_REASONS XE_REG(0x138030)
#define MTL_MEDIA_MC6 XE_REG(0x138048)
diff --git a/drivers/gpu/drm/xe/regs/xe_oa_regs.h b/drivers/gpu/drm/xe/regs/xe_oa_regs.h
new file mode 100644
index 000000000000..1189f5a540a8
--- /dev/null
+++ b/drivers/gpu/drm/xe/regs/xe_oa_regs.h
@@ -0,0 +1,100 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#ifndef __XE_OA_REGS__
+#define __XE_OA_REGS__
+
+#define RPM_CONFIG1 XE_REG(0xd04)
+#define GT_NOA_ENABLE REG_BIT(9)
+
+#define EU_PERF_CNTL0 XE_REG(0xe458)
+#define EU_PERF_CNTL4 XE_REG(0xe45c)
+#define EU_PERF_CNTL1 XE_REG(0xe558)
+#define EU_PERF_CNTL5 XE_REG(0xe55c)
+#define EU_PERF_CNTL2 XE_REG(0xe658)
+#define EU_PERF_CNTL6 XE_REG(0xe65c)
+#define EU_PERF_CNTL3 XE_REG(0xe758)
+
+#define OA_TLB_INV_CR XE_REG(0xceec)
+
+/* OAR unit */
+#define OAR_OACONTROL XE_REG(0x2960)
+#define OAR_OACONTROL_COUNTER_SEL_MASK REG_GENMASK(3, 1)
+#define OAR_OACONTROL_COUNTER_ENABLE REG_BIT(0)
+
+#define OACTXCONTROL(base) XE_REG((base) + 0x360)
+#define OAR_OASTATUS XE_REG(0x2968)
+#define OA_COUNTER_RESUME REG_BIT(0)
+
+/* OAG unit */
+#define OAG_OAGLBCTXCTRL XE_REG(0x2b28)
+#define OAG_OAGLBCTXCTRL_TIMER_PERIOD_MASK REG_GENMASK(7, 2)
+#define OAG_OAGLBCTXCTRL_TIMER_ENABLE REG_BIT(1)
+#define OAG_OAGLBCTXCTRL_COUNTER_RESUME REG_BIT(0)
+
+#define OAG_OAHEADPTR XE_REG(0xdb00)
+#define OAG_OAHEADPTR_MASK REG_GENMASK(31, 6)
+#define OAG_OATAILPTR XE_REG(0xdb04)
+#define OAG_OATAILPTR_MASK REG_GENMASK(31, 6)
+
+#define OAG_OABUFFER XE_REG(0xdb08)
+#define OABUFFER_SIZE_MASK REG_GENMASK(5, 3)
+#define OABUFFER_SIZE_128K REG_FIELD_PREP(OABUFFER_SIZE_MASK, 0)
+#define OABUFFER_SIZE_256K REG_FIELD_PREP(OABUFFER_SIZE_MASK, 1)
+#define OABUFFER_SIZE_512K REG_FIELD_PREP(OABUFFER_SIZE_MASK, 2)
+#define OABUFFER_SIZE_1M REG_FIELD_PREP(OABUFFER_SIZE_MASK, 3)
+#define OABUFFER_SIZE_2M REG_FIELD_PREP(OABUFFER_SIZE_MASK, 4)
+#define OABUFFER_SIZE_4M REG_FIELD_PREP(OABUFFER_SIZE_MASK, 5)
+#define OABUFFER_SIZE_8M REG_FIELD_PREP(OABUFFER_SIZE_MASK, 6)
+#define OABUFFER_SIZE_16M REG_FIELD_PREP(OABUFFER_SIZE_MASK, 7)
+#define OAG_OABUFFER_MEMORY_SELECT REG_BIT(0) /* 0: PPGTT, 1: GGTT */
+
+#define OAG_OACONTROL XE_REG(0xdaf4)
+#define OAG_OACONTROL_OA_CCS_SELECT_MASK REG_GENMASK(18, 16)
+#define OAG_OACONTROL_OA_COUNTER_SEL_MASK REG_GENMASK(4, 2)
+#define OAG_OACONTROL_OA_COUNTER_ENABLE REG_BIT(0)
+/* Common to all OA units */
+#define OA_OACONTROL_REPORT_BC_MASK REG_GENMASK(9, 9)
+#define OA_OACONTROL_COUNTER_SIZE_MASK REG_GENMASK(8, 8)
+
+#define OAG_OA_DEBUG XE_REG(0xdaf8, XE_REG_OPTION_MASKED)
+#define OAG_OA_DEBUG_DISABLE_MMIO_TRG REG_BIT(14)
+#define OAG_OA_DEBUG_START_TRIGGER_SCOPE_CONTROL REG_BIT(13)
+#define OAG_OA_DEBUG_DISABLE_START_TRG_2_COUNT_QUAL REG_BIT(8)
+#define OAG_OA_DEBUG_DISABLE_START_TRG_1_COUNT_QUAL REG_BIT(7)
+#define OAG_OA_DEBUG_INCLUDE_CLK_RATIO REG_BIT(6)
+#define OAG_OA_DEBUG_DISABLE_CLK_RATIO_REPORTS REG_BIT(5)
+#define OAG_OA_DEBUG_DISABLE_CTX_SWITCH_REPORTS REG_BIT(1)
+
+#define OAG_OASTATUS XE_REG(0xdafc)
+#define OASTATUS_MMIO_TRG_Q_FULL REG_BIT(6)
+#define OASTATUS_COUNTER_OVERFLOW REG_BIT(2)
+#define OASTATUS_BUFFER_OVERFLOW REG_BIT(1)
+#define OASTATUS_REPORT_LOST REG_BIT(0)
+#define OAG_MMIOTRIGGER XE_REG(0xdb1c)
+/* OAC unit */
+#define OAC_OACONTROL XE_REG(0x15114)
+
+/* OAM unit */
+#define OAM_HEAD_POINTER_OFFSET (0x1a0)
+#define OAM_TAIL_POINTER_OFFSET (0x1a4)
+#define OAM_BUFFER_OFFSET (0x1a8)
+#define OAM_CONTEXT_CONTROL_OFFSET (0x1bc)
+#define OAM_CONTROL_OFFSET (0x194)
+#define OAM_CONTROL_COUNTER_SEL_MASK REG_GENMASK(3, 1)
+#define OAM_DEBUG_OFFSET (0x198)
+#define OAM_STATUS_OFFSET (0x19c)
+#define OAM_MMIO_TRG_OFFSET (0x1d0)
+
+#define OAM_HEAD_POINTER(base) XE_REG((base) + OAM_HEAD_POINTER_OFFSET)
+#define OAM_TAIL_POINTER(base) XE_REG((base) + OAM_TAIL_POINTER_OFFSET)
+#define OAM_BUFFER(base) XE_REG((base) + OAM_BUFFER_OFFSET)
+#define OAM_CONTEXT_CONTROL(base) XE_REG((base) + OAM_CONTEXT_CONTROL_OFFSET)
+#define OAM_CONTROL(base) XE_REG((base) + OAM_CONTROL_OFFSET)
+#define OAM_DEBUG(base) XE_REG((base) + OAM_DEBUG_OFFSET)
+#define OAM_STATUS(base) XE_REG((base) + OAM_STATUS_OFFSET)
+#define OAM_MMIO_TRG(base) XE_REG((base) + OAM_MMIO_TRG_OFFSET)
+
+#endif
diff --git a/drivers/gpu/drm/xe/tests/xe_mocs.c b/drivers/gpu/drm/xe/tests/xe_mocs.c
index 1b8617075b37..67c65e88c384 100644
--- a/drivers/gpu/drm/xe/tests/xe_mocs.c
+++ b/drivers/gpu/drm/xe/tests/xe_mocs.c
@@ -31,9 +31,9 @@ static int live_mocs_init(struct live_mocs *arg, struct xe_gt *gt)
kunit_info(test, "gt %d", gt->info.id);
kunit_info(test, "gt type %d", gt->info.type);
- kunit_info(test, "table size %d", arg->table.size);
+ kunit_info(test, "table size %d", arg->table.table_size);
kunit_info(test, "table uc_index %d", arg->table.uc_index);
- kunit_info(test, "table n_entries %d", arg->table.n_entries);
+ kunit_info(test, "table num_mocs_regs %d", arg->table.num_mocs_regs);
return flags;
}
@@ -50,7 +50,7 @@ static void read_l3cc_table(struct xe_gt *gt,
ret = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
KUNIT_ASSERT_EQ_MSG(test, ret, 0, "Forcewake Failed.\n");
- for (i = 0; i < info->n_entries; i++) {
+ for (i = 0; i < info->num_mocs_regs; i++) {
if (!(i & 1)) {
if (regs_are_mcr(gt))
reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_LNCFCMOCS(i >> 1));
@@ -90,7 +90,7 @@ static void read_mocs_table(struct xe_gt *gt,
ret = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
KUNIT_ASSERT_EQ_MSG(test, ret, 0, "Forcewake Failed.\n");
- for (i = 0; i < info->n_entries; i++) {
+ for (i = 0; i < info->num_mocs_regs; i++) {
if (regs_are_mcr(gt))
reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_GLOBAL_MOCS(i));
else
diff --git a/drivers/gpu/drm/xe/tests/xe_rtp_test.c b/drivers/gpu/drm/xe/tests/xe_rtp_test.c
index 06759d754783..f217445c246a 100644
--- a/drivers/gpu/drm/xe/tests/xe_rtp_test.c
+++ b/drivers/gpu/drm/xe/tests/xe_rtp_test.c
@@ -91,6 +91,59 @@ static const struct rtp_test_case cases[] = {
},
},
{
+ .name = "match-or",
+ .expected_reg = REGULAR_REG1,
+ .expected_set_bits = REG_BIT(0) | REG_BIT(1) | REG_BIT(2),
+ .expected_clr_bits = REG_BIT(0) | REG_BIT(1) | REG_BIT(2),
+ .expected_count = 1,
+ .entries = (const struct xe_rtp_entry_sr[]) {
+ { XE_RTP_NAME("first"),
+ XE_RTP_RULES(FUNC(match_yes), OR, FUNC(match_no)),
+ XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))
+ },
+ { XE_RTP_NAME("middle"),
+ XE_RTP_RULES(FUNC(match_no), FUNC(match_no), OR,
+ FUNC(match_yes), OR,
+ FUNC(match_no)),
+ XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(1)))
+ },
+ { XE_RTP_NAME("last"),
+ XE_RTP_RULES(FUNC(match_no), OR, FUNC(match_yes)),
+ XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(2)))
+ },
+ { XE_RTP_NAME("no-match"),
+ XE_RTP_RULES(FUNC(match_no), OR, FUNC(match_no)),
+ XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(3)))
+ },
+ {}
+ },
+ },
+ {
+ .name = "match-or-xfail",
+ .expected_reg = REGULAR_REG1,
+ .expected_count = 0,
+ .entries = (const struct xe_rtp_entry_sr[]) {
+ { XE_RTP_NAME("leading-or"),
+ XE_RTP_RULES(OR, FUNC(match_yes)),
+ XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))
+ },
+ { XE_RTP_NAME("trailing-or"),
+ /*
+ * First condition is match_no, otherwise the failure
+ * wouldn't really trigger as RTP stops processing as
+ * soon as it has a matching set of rules
+ */
+ XE_RTP_RULES(FUNC(match_no), OR),
+ XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(1)))
+ },
+ { XE_RTP_NAME("no-or-or-yes"),
+ XE_RTP_RULES(FUNC(match_no), OR, OR, FUNC(match_yes)),
+ XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(2)))
+ },
+ {}
+ },
+ },
+ {
.name = "no-match-no-add-multiple-rules",
.expected_reg = REGULAR_REG1,
.expected_set_bits = REG_BIT(0),
@@ -255,9 +308,14 @@ static void xe_rtp_process_tests(struct kunit *test)
}
KUNIT_EXPECT_EQ(test, count, param->expected_count);
- KUNIT_EXPECT_EQ(test, sr_entry->clr_bits, param->expected_clr_bits);
- KUNIT_EXPECT_EQ(test, sr_entry->set_bits, param->expected_set_bits);
- KUNIT_EXPECT_EQ(test, sr_entry->reg.raw, param->expected_reg.raw);
+ if (count) {
+ KUNIT_EXPECT_EQ(test, sr_entry->clr_bits, param->expected_clr_bits);
+ KUNIT_EXPECT_EQ(test, sr_entry->set_bits, param->expected_set_bits);
+ KUNIT_EXPECT_EQ(test, sr_entry->reg.raw, param->expected_reg.raw);
+ } else {
+ KUNIT_EXPECT_NULL(test, sr_entry);
+ }
+
KUNIT_EXPECT_EQ(test, reg_sr->errors, param->expected_sr_errors);
}
diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c
index 2bae01ce4e5b..31192d983d9e 100644
--- a/drivers/gpu/drm/xe/xe_bo.c
+++ b/drivers/gpu/drm/xe/xe_bo.c
@@ -25,7 +25,7 @@
#include "xe_pm.h"
#include "xe_preempt_fence.h"
#include "xe_res_cursor.h"
-#include "xe_trace.h"
+#include "xe_trace_bo.h"
#include "xe_ttm_stolen_mgr.h"
#include "xe_vm.h"
@@ -343,7 +343,7 @@ static struct ttm_tt *xe_ttm_tt_create(struct ttm_buffer_object *ttm_bo,
struct xe_device *xe = xe_bo_device(bo);
struct xe_ttm_tt *tt;
unsigned long extra_pages;
- enum ttm_caching caching;
+ enum ttm_caching caching = ttm_cached;
int err;
tt = kzalloc(sizeof(*tt), GFP_KERNEL);
@@ -357,26 +357,44 @@ static struct ttm_tt *xe_ttm_tt_create(struct ttm_buffer_object *ttm_bo,
extra_pages = DIV_ROUND_UP(xe_device_ccs_bytes(xe, bo->size),
PAGE_SIZE);
- switch (bo->cpu_caching) {
- case DRM_XE_GEM_CPU_CACHING_WC:
- caching = ttm_write_combined;
- break;
- default:
- caching = ttm_cached;
- break;
- }
-
- WARN_ON((bo->flags & XE_BO_FLAG_USER) && !bo->cpu_caching);
-
/*
- * Display scanout is always non-coherent with the CPU cache.
- *
- * For Xe_LPG and beyond, PPGTT PTE lookups are also non-coherent and
- * require a CPU:WC mapping.
+ * DGFX system memory is always WB / ttm_cached, since
+ * other caching modes are only supported on x86. DGFX
+ * GPU system memory accesses are always coherent with the
+ * CPU.
*/
- if ((!bo->cpu_caching && bo->flags & XE_BO_FLAG_SCANOUT) ||
- (xe->info.graphics_verx100 >= 1270 && bo->flags & XE_BO_FLAG_PAGETABLE))
- caching = ttm_write_combined;
+ if (!IS_DGFX(xe)) {
+ switch (bo->cpu_caching) {
+ case DRM_XE_GEM_CPU_CACHING_WC:
+ caching = ttm_write_combined;
+ break;
+ default:
+ caching = ttm_cached;
+ break;
+ }
+
+ WARN_ON((bo->flags & XE_BO_FLAG_USER) && !bo->cpu_caching);
+
+ /*
+ * Display scanout is always non-coherent with the CPU cache.
+ *
+ * For Xe_LPG and beyond, PPGTT PTE lookups are also
+ * non-coherent and require a CPU:WC mapping.
+ */
+ if ((!bo->cpu_caching && bo->flags & XE_BO_FLAG_SCANOUT) ||
+ (xe->info.graphics_verx100 >= 1270 &&
+ bo->flags & XE_BO_FLAG_PAGETABLE))
+ caching = ttm_write_combined;
+ }
+
+ if (bo->flags & XE_BO_FLAG_NEEDS_UC) {
+ /*
+ * Valid only for internally-created buffers only, for
+ * which cpu_caching is never initialized.
+ */
+ xe_assert(xe, bo->cpu_caching == 0);
+ caching = ttm_uncached;
+ }
err = ttm_tt_init(&tt->ttm, &bo->ttm, page_flags, caching, extra_pages);
if (err) {
diff --git a/drivers/gpu/drm/xe/xe_bo_types.h b/drivers/gpu/drm/xe/xe_bo_types.h
index 86422e113d39..10450f1fbbde 100644
--- a/drivers/gpu/drm/xe/xe_bo_types.h
+++ b/drivers/gpu/drm/xe/xe_bo_types.h
@@ -66,7 +66,8 @@ struct xe_bo {
/**
* @cpu_caching: CPU caching mode. Currently only used for userspace
- * objects.
+ * objects. Exceptions are system memory on DGFX, which is always
+ * WB.
*/
u16 cpu_caching;
diff --git a/drivers/gpu/drm/xe/xe_devcoredump.c b/drivers/gpu/drm/xe/xe_devcoredump.c
index d7f2d19a77c1..62c2b10fbf1d 100644
--- a/drivers/gpu/drm/xe/xe_devcoredump.c
+++ b/drivers/gpu/drm/xe/xe_devcoredump.c
@@ -53,6 +53,9 @@
#ifdef CONFIG_DEV_COREDUMP
+/* 1 hour timeout */
+#define XE_COREDUMP_TIMEOUT_JIFFIES (60 * 60 * HZ)
+
static struct xe_device *coredump_to_xe(const struct xe_devcoredump *coredump)
{
return container_of(coredump, struct xe_device, devcoredump);
@@ -247,8 +250,9 @@ void xe_devcoredump(struct xe_sched_job *job)
drm_info(&xe->drm, "Check your /sys/class/drm/card%d/device/devcoredump/data\n",
xe->drm.primary->index);
- dev_coredumpm(xe->drm.dev, THIS_MODULE, coredump, 0, GFP_KERNEL,
- xe_devcoredump_read, xe_devcoredump_free);
+ dev_coredumpm_timeout(xe->drm.dev, THIS_MODULE, coredump, 0, GFP_KERNEL,
+ xe_devcoredump_read, xe_devcoredump_free,
+ XE_COREDUMP_TIMEOUT_JIFFIES);
}
static void xe_driver_devcoredump_fini(void *arg)
diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c
index 94dbfe5cf19c..76109415eba6 100644
--- a/drivers/gpu/drm/xe/xe_device.c
+++ b/drivers/gpu/drm/xe/xe_device.c
@@ -42,6 +42,7 @@
#include "xe_memirq.h"
#include "xe_mmio.h"
#include "xe_module.h"
+#include "xe_observation.h"
#include "xe_pat.h"
#include "xe_pcode.h"
#include "xe_pm.h"
@@ -141,6 +142,7 @@ static const struct drm_ioctl_desc xe_ioctls[] = {
DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(XE_WAIT_USER_FENCE, xe_wait_user_fence_ioctl,
DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(XE_OBSERVATION, xe_observation_ioctl, DRM_RENDER_ALLOW),
};
static long xe_drm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
@@ -484,6 +486,17 @@ static int wait_for_lmem_ready(struct xe_device *xe)
return 0;
}
+static void update_device_info(struct xe_device *xe)
+{
+ /* disable features that are not available/applicable to VFs */
+ if (IS_SRIOV_VF(xe)) {
+ xe->info.enable_display = 0;
+ xe->info.has_heci_gscfi = 0;
+ xe->info.skip_guc_pc = 1;
+ xe->info.skip_pcode = 1;
+ }
+}
+
/**
* xe_device_probe_early: Device early probe
* @xe: xe device instance
@@ -504,6 +517,8 @@ int xe_device_probe_early(struct xe_device *xe)
xe_sriov_probe_early(xe);
+ update_device_info(xe);
+
err = xe_pcode_probe_early(xe);
if (err)
return err;
@@ -619,16 +634,16 @@ int xe_device_probe(struct xe_device *xe)
err = xe_device_set_has_flat_ccs(xe);
if (err)
- goto err_irq_shutdown;
+ goto err;
err = xe_vram_probe(xe);
if (err)
- goto err_irq_shutdown;
+ goto err;
for_each_tile(tile, xe, id) {
err = xe_tile_init_noalloc(tile);
if (err)
- goto err_irq_shutdown;
+ goto err;
}
/* Allocate and map stolen after potential VRAM resize */
@@ -642,7 +657,7 @@ int xe_device_probe(struct xe_device *xe)
*/
err = xe_display_init_noaccel(xe);
if (err)
- goto err_irq_shutdown;
+ goto err;
for_each_gt(gt, xe, id) {
last_gt = id;
@@ -654,25 +669,37 @@ int xe_device_probe(struct xe_device *xe)
xe_heci_gsc_init(xe);
- err = xe_display_init(xe);
+ err = xe_oa_init(xe);
if (err)
goto err_fini_gt;
+ err = xe_display_init(xe);
+ if (err)
+ goto err_fini_oa;
+
err = drm_dev_register(&xe->drm, 0);
if (err)
goto err_fini_display;
xe_display_register(xe);
+ xe_oa_register(xe);
+
xe_debugfs_register(xe);
xe_hwmon_register(xe);
+ for_each_gt(gt, xe, id)
+ xe_gt_sanitize_freq(gt);
+
return devm_add_action_or_reset(xe->drm.dev, xe_device_sanitize, xe);
err_fini_display:
xe_display_driver_remove(xe);
+err_fini_oa:
+ xe_oa_fini(xe);
+
err_fini_gt:
for_each_gt(gt, xe, id) {
if (id < last_gt)
@@ -681,8 +708,6 @@ err_fini_gt:
break;
}
-err_irq_shutdown:
- xe_irq_shutdown(xe);
err:
xe_display_fini(xe);
return err;
@@ -701,16 +726,18 @@ void xe_device_remove(struct xe_device *xe)
struct xe_gt *gt;
u8 id;
+ xe_oa_unregister(xe);
+
xe_device_remove_display(xe);
xe_display_fini(xe);
+ xe_oa_fini(xe);
+
xe_heci_gsc_fini(xe);
for_each_gt(gt, xe, id)
xe_gt_remove(gt);
-
- xe_irq_shutdown(xe);
}
void xe_device_shutdown(struct xe_device *xe)
@@ -827,6 +854,13 @@ u64 xe_device_uncanonicalize_addr(struct xe_device *xe, u64 address)
return address & GENMASK_ULL(xe->info.va_bits - 1, 0);
}
+static void xe_device_wedged_fini(struct drm_device *drm, void *arg)
+{
+ struct xe_device *xe = arg;
+
+ xe_pm_runtime_put(xe);
+}
+
/**
* xe_device_declare_wedged - Declare device wedged
* @xe: xe device instance
@@ -843,11 +877,21 @@ u64 xe_device_uncanonicalize_addr(struct xe_device *xe, u64 address)
*/
void xe_device_declare_wedged(struct xe_device *xe)
{
+ struct xe_gt *gt;
+ u8 id;
+
if (xe->wedged.mode == 0) {
drm_dbg(&xe->drm, "Wedged mode is forcibly disabled\n");
return;
}
+ if (drmm_add_action_or_reset(&xe->drm, xe_device_wedged_fini, xe)) {
+ drm_err(&xe->drm, "Failed to register xe_device_wedged_fini clean-up. Although device is wedged.\n");
+ return;
+ }
+
+ xe_pm_runtime_get_noresume(xe);
+
if (!atomic_xchg(&xe->wedged.flag, 1)) {
xe->needs_flr_on_fini = true;
drm_err(&xe->drm,
@@ -856,4 +900,7 @@ void xe_device_declare_wedged(struct xe_device *xe)
"Please file a _new_ bug report at https://gitlab.freedesktop.org/drm/xe/kernel/issues/new\n",
dev_name(xe->drm.dev));
}
+
+ for_each_gt(gt, xe, id)
+ xe_gt_declare_wedged(gt);
}
diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h
index f1c09824b145..3bca6d344744 100644
--- a/drivers/gpu/drm/xe/xe_device_types.h
+++ b/drivers/gpu/drm/xe/xe_device_types.h
@@ -17,6 +17,7 @@
#include "xe_gt_types.h"
#include "xe_lmtt_types.h"
#include "xe_memirq_types.h"
+#include "xe_oa.h"
#include "xe_platform_types.h"
#include "xe_pt_types.h"
#include "xe_sriov_types.h"
@@ -462,6 +463,9 @@ struct xe_device {
/** @heci_gsc: graphics security controller */
struct xe_heci_gsc heci_gsc;
+ /** @oa: oa observation subsystem */
+ struct xe_oa oa;
+
/** @needs_flr_on_fini: requests function-reset on fini */
bool needs_flr_on_fini;
diff --git a/drivers/gpu/drm/xe/xe_drm_client.c b/drivers/gpu/drm/xe/xe_drm_client.c
index 4a19b771e3a0..6a26923fa10e 100644
--- a/drivers/gpu/drm/xe/xe_drm_client.c
+++ b/drivers/gpu/drm/xe/xe_drm_client.c
@@ -260,13 +260,20 @@ static void show_run_ticks(struct drm_printer *p, struct drm_file *file)
/* Get the total GPU cycles */
for_each_gt(gt, xe, gt_id) {
+ enum xe_force_wake_domains fw;
+
hwe = xe_gt_any_hw_engine(gt);
if (!hwe)
continue;
- xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
+ fw = xe_hw_engine_to_fw_domain(hwe);
+ if (xe_force_wake_get(gt_to_fw(gt), fw)) {
+ hwe = NULL;
+ break;
+ }
+
gpu_timestamp = xe_hw_engine_read_timestamp(hwe);
- xe_force_wake_put(gt_to_fw(gt), XE_FW_GT);
+ XE_WARN_ON(xe_force_wake_put(gt_to_fw(gt), fw));
break;
}
diff --git a/drivers/gpu/drm/xe/xe_exec.c b/drivers/gpu/drm/xe/xe_exec.c
index 97eeb973e897..f36980aa26e6 100644
--- a/drivers/gpu/drm/xe/xe_exec.c
+++ b/drivers/gpu/drm/xe/xe_exec.c
@@ -118,7 +118,7 @@ int xe_exec_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
u64 addresses[XE_HW_ENGINE_MAX_INSTANCE];
struct drm_gpuvm_exec vm_exec = {.extra.fn = xe_exec_fn};
struct drm_exec *exec = &vm_exec.exec;
- u32 i, num_syncs = 0, num_ufence = 0;
+ u32 i, num_syncs, num_ufence = 0;
struct xe_sched_job *job;
struct xe_vm *vm;
bool write_locked, skip_retry = false;
@@ -141,7 +141,7 @@ int xe_exec_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
q->width != args->num_batch_buffer))
return -EINVAL;
- if (XE_IOCTL_DBG(xe, q->flags & EXEC_QUEUE_FLAG_BANNED)) {
+ if (XE_IOCTL_DBG(xe, q->ops->reset_status(q))) {
err = -ECANCELED;
goto err_exec_queue;
}
@@ -156,15 +156,15 @@ int xe_exec_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
vm = q->vm;
- for (i = 0; i < args->num_syncs; i++) {
- err = xe_sync_entry_parse(xe, xef, &syncs[num_syncs++],
- &syncs_user[i], SYNC_PARSE_FLAG_EXEC |
+ for (num_syncs = 0; num_syncs < args->num_syncs; num_syncs++) {
+ err = xe_sync_entry_parse(xe, xef, &syncs[num_syncs],
+ &syncs_user[num_syncs], SYNC_PARSE_FLAG_EXEC |
(xe_vm_in_lr_mode(vm) ?
SYNC_PARSE_FLAG_LR_MODE : 0));
if (err)
goto err_syncs;
- if (xe_sync_is_ufence(&syncs[i]))
+ if (xe_sync_is_ufence(&syncs[num_syncs]))
num_ufence++;
}
@@ -259,9 +259,9 @@ retry:
/* Wait behind rebinds */
if (!xe_vm_in_lr_mode(vm)) {
- err = drm_sched_job_add_resv_dependencies(&job->drm,
- xe_vm_resv(vm),
- DMA_RESV_USAGE_KERNEL);
+ err = xe_sched_job_add_deps(job,
+ xe_vm_resv(vm),
+ DMA_RESV_USAGE_KERNEL);
if (err)
goto err_put_job;
}
@@ -325,8 +325,8 @@ err_unlock_list:
if (err == -EAGAIN && !skip_retry)
goto retry;
err_syncs:
- for (i = 0; i < num_syncs; i++)
- xe_sync_entry_cleanup(&syncs[i]);
+ while (num_syncs--)
+ xe_sync_entry_cleanup(&syncs[num_syncs]);
kfree(syncs);
err_exec_queue:
xe_exec_queue_put(q);
diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c
index 27215075c799..0ba37835849b 100644
--- a/drivers/gpu/drm/xe/xe_exec_queue.c
+++ b/drivers/gpu/drm/xe/xe_exec_queue.c
@@ -67,7 +67,7 @@ static struct xe_exec_queue *__xe_exec_queue_alloc(struct xe_device *xe,
q->fence_irq = &gt->fence_irq[hwe->class];
q->ring_ops = gt->ring_ops[hwe->class];
q->ops = gt->exec_queue_ops;
- INIT_LIST_HEAD(&q->compute.link);
+ INIT_LIST_HEAD(&q->lr.link);
INIT_LIST_HEAD(&q->multi_gt_link);
q->sched_props.timeslice_us = hwe->eclass->sched_props.timeslice_us;
@@ -633,8 +633,8 @@ int xe_exec_queue_create_ioctl(struct drm_device *dev, void *data,
return PTR_ERR(q);
if (xe_vm_in_preempt_fence_mode(vm)) {
- q->compute.context = dma_fence_context_alloc(1);
- spin_lock_init(&q->compute.lock);
+ q->lr.context = dma_fence_context_alloc(1);
+ spin_lock_init(&q->lr.lock);
err = xe_vm_add_compute_exec_queue(vm, q);
if (XE_IOCTL_DBG(xe, err))
@@ -677,7 +677,7 @@ int xe_exec_queue_get_property_ioctl(struct drm_device *dev, void *data,
switch (args->property) {
case DRM_XE_EXEC_QUEUE_GET_PROPERTY_BAN:
- args->value = !!(q->flags & EXEC_QUEUE_FLAG_BANNED);
+ args->value = q->ops->reset_status(q);
ret = 0;
break;
default:
diff --git a/drivers/gpu/drm/xe/xe_exec_queue_types.h b/drivers/gpu/drm/xe/xe_exec_queue_types.h
index 18d8b2a60928..201588ec33c3 100644
--- a/drivers/gpu/drm/xe/xe_exec_queue_types.h
+++ b/drivers/gpu/drm/xe/xe_exec_queue_types.h
@@ -70,18 +70,16 @@ struct xe_exec_queue {
*/
struct dma_fence *last_fence;
-/* queue no longer allowed to submit */
-#define EXEC_QUEUE_FLAG_BANNED BIT(0)
/* queue used for kernel submission only */
-#define EXEC_QUEUE_FLAG_KERNEL BIT(1)
+#define EXEC_QUEUE_FLAG_KERNEL BIT(0)
/* kernel engine only destroyed at driver unload */
-#define EXEC_QUEUE_FLAG_PERMANENT BIT(2)
+#define EXEC_QUEUE_FLAG_PERMANENT BIT(1)
/* for VM jobs. Caller needs to hold rpm ref when creating queue with this flag */
-#define EXEC_QUEUE_FLAG_VM BIT(3)
+#define EXEC_QUEUE_FLAG_VM BIT(2)
/* child of VM queue for multi-tile VM jobs */
-#define EXEC_QUEUE_FLAG_BIND_ENGINE_CHILD BIT(4)
+#define EXEC_QUEUE_FLAG_BIND_ENGINE_CHILD BIT(3)
/* kernel exec_queue only, set priority to highest level */
-#define EXEC_QUEUE_FLAG_HIGH_PRIORITY BIT(5)
+#define EXEC_QUEUE_FLAG_HIGH_PRIORITY BIT(4)
/**
* @flags: flags for this exec queue, should statically setup aside from ban
@@ -115,19 +113,19 @@ struct xe_exec_queue {
enum xe_exec_queue_priority priority;
} sched_props;
- /** @compute: compute exec queue state */
+ /** @lr: long-running exec queue state */
struct {
- /** @compute.pfence: preemption fence */
+ /** @lr.pfence: preemption fence */
struct dma_fence *pfence;
- /** @compute.context: preemption fence context */
+ /** @lr.context: preemption fence context */
u64 context;
- /** @compute.seqno: preemption fence seqno */
+ /** @lr.seqno: preemption fence seqno */
u32 seqno;
- /** @compute.link: link into VM's list of exec queues */
+ /** @lr.link: link into VM's list of exec queues */
struct list_head link;
- /** @compute.lock: preemption fences lock */
+ /** @lr.lock: preemption fences lock */
spinlock_t lock;
- } compute;
+ } lr;
/** @ops: submission backend exec queue operations */
const struct xe_exec_queue_ops *ops;
diff --git a/drivers/gpu/drm/xe/xe_force_wake.c b/drivers/gpu/drm/xe/xe_force_wake.c
index 9bbe8a5040da..b263fff15273 100644
--- a/drivers/gpu/drm/xe/xe_force_wake.c
+++ b/drivers/gpu/drm/xe/xe_force_wake.c
@@ -10,31 +10,26 @@
#include "regs/xe_gt_regs.h"
#include "regs/xe_reg_defs.h"
#include "xe_gt.h"
+#include "xe_gt_printk.h"
#include "xe_mmio.h"
+#include "xe_sriov.h"
#define XE_FORCE_WAKE_ACK_TIMEOUT_MS 50
-static struct xe_gt *
-fw_to_gt(struct xe_force_wake *fw)
+static const char *str_wake_sleep(bool wake)
{
- return fw->gt;
-}
-
-static struct xe_device *
-fw_to_xe(struct xe_force_wake *fw)
-{
- return gt_to_xe(fw_to_gt(fw));
+ return wake ? "wake" : "sleep";
}
static void domain_init(struct xe_force_wake_domain *domain,
enum xe_force_wake_domain_id id,
- struct xe_reg reg, struct xe_reg ack, u32 val, u32 mask)
+ struct xe_reg reg, struct xe_reg ack)
{
domain->id = id;
domain->reg_ctl = reg;
domain->reg_ack = ack;
- domain->val = val;
- domain->mask = mask;
+ domain->val = FORCEWAKE_MT(FORCEWAKE_KERNEL);
+ domain->mask = FORCEWAKE_MT_MASK(FORCEWAKE_KERNEL);
}
void xe_force_wake_init_gt(struct xe_gt *gt, struct xe_force_wake *fw)
@@ -51,14 +46,12 @@ void xe_force_wake_init_gt(struct xe_gt *gt, struct xe_force_wake *fw)
domain_init(&fw->domains[XE_FW_DOMAIN_ID_GT],
XE_FW_DOMAIN_ID_GT,
FORCEWAKE_GT,
- FORCEWAKE_ACK_GT_MTL,
- BIT(0), BIT(16));
+ FORCEWAKE_ACK_GT_MTL);
} else {
domain_init(&fw->domains[XE_FW_DOMAIN_ID_GT],
XE_FW_DOMAIN_ID_GT,
FORCEWAKE_GT,
- FORCEWAKE_ACK_GT,
- BIT(0), BIT(16));
+ FORCEWAKE_ACK_GT);
}
}
@@ -73,8 +66,7 @@ void xe_force_wake_init_engines(struct xe_gt *gt, struct xe_force_wake *fw)
domain_init(&fw->domains[XE_FW_DOMAIN_ID_RENDER],
XE_FW_DOMAIN_ID_RENDER,
FORCEWAKE_RENDER,
- FORCEWAKE_ACK_RENDER,
- BIT(0), BIT(16));
+ FORCEWAKE_ACK_RENDER);
for (i = XE_HW_ENGINE_VCS0, j = 0; i <= XE_HW_ENGINE_VCS7; ++i, ++j) {
if (!(gt->info.engine_mask & BIT(i)))
@@ -83,8 +75,7 @@ void xe_force_wake_init_engines(struct xe_gt *gt, struct xe_force_wake *fw)
domain_init(&fw->domains[XE_FW_DOMAIN_ID_MEDIA_VDBOX0 + j],
XE_FW_DOMAIN_ID_MEDIA_VDBOX0 + j,
FORCEWAKE_MEDIA_VDBOX(j),
- FORCEWAKE_ACK_MEDIA_VDBOX(j),
- BIT(0), BIT(16));
+ FORCEWAKE_ACK_MEDIA_VDBOX(j));
}
for (i = XE_HW_ENGINE_VECS0, j = 0; i <= XE_HW_ENGINE_VECS3; ++i, ++j) {
@@ -94,42 +85,63 @@ void xe_force_wake_init_engines(struct xe_gt *gt, struct xe_force_wake *fw)
domain_init(&fw->domains[XE_FW_DOMAIN_ID_MEDIA_VEBOX0 + j],
XE_FW_DOMAIN_ID_MEDIA_VEBOX0 + j,
FORCEWAKE_MEDIA_VEBOX(j),
- FORCEWAKE_ACK_MEDIA_VEBOX(j),
- BIT(0), BIT(16));
+ FORCEWAKE_ACK_MEDIA_VEBOX(j));
}
if (gt->info.engine_mask & BIT(XE_HW_ENGINE_GSCCS0))
domain_init(&fw->domains[XE_FW_DOMAIN_ID_GSC],
XE_FW_DOMAIN_ID_GSC,
FORCEWAKE_GSC,
- FORCEWAKE_ACK_GSC,
- BIT(0), BIT(16));
+ FORCEWAKE_ACK_GSC);
+}
+
+static void __domain_ctl(struct xe_gt *gt, struct xe_force_wake_domain *domain, bool wake)
+{
+ if (IS_SRIOV_VF(gt_to_xe(gt)))
+ return;
+
+ xe_mmio_write32(gt, domain->reg_ctl, domain->mask | (wake ? domain->val : 0));
+}
+
+static int __domain_wait(struct xe_gt *gt, struct xe_force_wake_domain *domain, bool wake)
+{
+ u32 value;
+ int ret;
+
+ if (IS_SRIOV_VF(gt_to_xe(gt)))
+ return 0;
+
+ ret = xe_mmio_wait32(gt, domain->reg_ack, domain->val, wake ? domain->val : 0,
+ XE_FORCE_WAKE_ACK_TIMEOUT_MS * USEC_PER_MSEC,
+ &value, true);
+ if (ret)
+ xe_gt_notice(gt, "Force wake domain %d failed to ack %s (%pe) reg[%#x] = %#x\n",
+ domain->id, str_wake_sleep(wake), ERR_PTR(ret),
+ domain->reg_ack.addr, value);
+
+ return ret;
}
static void domain_wake(struct xe_gt *gt, struct xe_force_wake_domain *domain)
{
- xe_mmio_write32(gt, domain->reg_ctl, domain->mask | domain->val);
+ __domain_ctl(gt, domain, true);
}
static int domain_wake_wait(struct xe_gt *gt,
struct xe_force_wake_domain *domain)
{
- return xe_mmio_wait32(gt, domain->reg_ack, domain->val, domain->val,
- XE_FORCE_WAKE_ACK_TIMEOUT_MS * USEC_PER_MSEC,
- NULL, true);
+ return __domain_wait(gt, domain, true);
}
static void domain_sleep(struct xe_gt *gt, struct xe_force_wake_domain *domain)
{
- xe_mmio_write32(gt, domain->reg_ctl, domain->mask);
+ __domain_ctl(gt, domain, false);
}
static int domain_sleep_wait(struct xe_gt *gt,
struct xe_force_wake_domain *domain)
{
- return xe_mmio_wait32(gt, domain->reg_ack, domain->val, 0,
- XE_FORCE_WAKE_ACK_TIMEOUT_MS * USEC_PER_MSEC,
- NULL, true);
+ return __domain_wait(gt, domain, false);
}
#define for_each_fw_domain_masked(domain__, mask__, fw__, tmp__) \
@@ -141,12 +153,11 @@ static int domain_sleep_wait(struct xe_gt *gt,
int xe_force_wake_get(struct xe_force_wake *fw,
enum xe_force_wake_domains domains)
{
- struct xe_device *xe = fw_to_xe(fw);
- struct xe_gt *gt = fw_to_gt(fw);
+ struct xe_gt *gt = fw->gt;
struct xe_force_wake_domain *domain;
enum xe_force_wake_domains tmp, woken = 0;
unsigned long flags;
- int ret, ret2 = 0;
+ int ret = 0;
spin_lock_irqsave(&fw->lock, flags);
for_each_fw_domain_masked(domain, domains, fw, tmp) {
@@ -156,27 +167,22 @@ int xe_force_wake_get(struct xe_force_wake *fw,
}
}
for_each_fw_domain_masked(domain, woken, fw, tmp) {
- ret = domain_wake_wait(gt, domain);
- ret2 |= ret;
- if (ret)
- drm_notice(&xe->drm, "Force wake domain (%d) failed to ack wake, ret=%d\n",
- domain->id, ret);
+ ret |= domain_wake_wait(gt, domain);
}
fw->awake_domains |= woken;
spin_unlock_irqrestore(&fw->lock, flags);
- return ret2;
+ return ret;
}
int xe_force_wake_put(struct xe_force_wake *fw,
enum xe_force_wake_domains domains)
{
- struct xe_device *xe = fw_to_xe(fw);
- struct xe_gt *gt = fw_to_gt(fw);
+ struct xe_gt *gt = fw->gt;
struct xe_force_wake_domain *domain;
enum xe_force_wake_domains tmp, sleep = 0;
unsigned long flags;
- int ret, ret2 = 0;
+ int ret = 0;
spin_lock_irqsave(&fw->lock, flags);
for_each_fw_domain_masked(domain, domains, fw, tmp) {
@@ -186,14 +192,10 @@ int xe_force_wake_put(struct xe_force_wake *fw,
}
}
for_each_fw_domain_masked(domain, sleep, fw, tmp) {
- ret = domain_sleep_wait(gt, domain);
- ret2 |= ret;
- if (ret)
- drm_notice(&xe->drm, "Force wake domain (%d) failed to ack sleep, ret=%d\n",
- domain->id, ret);
+ ret |= domain_sleep_wait(gt, domain);
}
fw->awake_domains &= ~sleep;
spin_unlock_irqrestore(&fw->lock, flags);
- return ret2;
+ return ret;
}
diff --git a/drivers/gpu/drm/xe/xe_force_wake.h b/drivers/gpu/drm/xe/xe_force_wake.h
index 83cb157da7cc..a2577672f4e3 100644
--- a/drivers/gpu/drm/xe/xe_force_wake.h
+++ b/drivers/gpu/drm/xe/xe_force_wake.h
@@ -24,14 +24,25 @@ static inline int
xe_force_wake_ref(struct xe_force_wake *fw,
enum xe_force_wake_domains domain)
{
- xe_gt_assert(fw->gt, domain);
+ xe_gt_assert(fw->gt, domain != XE_FORCEWAKE_ALL);
return fw->domains[ffs(domain) - 1].ref;
}
+/**
+ * xe_force_wake_assert_held - asserts domain is awake
+ * @fw : xe_force_wake structure
+ * @domain: xe_force_wake_domains apart from XE_FORCEWAKE_ALL
+ *
+ * xe_force_wake_assert_held() is designed to confirm a particular
+ * forcewake domain's wakefulness; it doesn't verify the wakefulness of
+ * multiple domains. Make sure the caller doesn't input multiple
+ * domains(XE_FORCEWAKE_ALL) as a parameter.
+ */
static inline void
xe_force_wake_assert_held(struct xe_force_wake *fw,
enum xe_force_wake_domains domain)
{
+ xe_gt_assert(fw->gt, domain != XE_FORCEWAKE_ALL);
xe_gt_assert(fw->gt, fw->awake_domains & domain);
}
diff --git a/drivers/gpu/drm/xe/xe_ggtt.c b/drivers/gpu/drm/xe/xe_ggtt.c
index 8ff91fd1b7c8..0cdbc1296e88 100644
--- a/drivers/gpu/drm/xe/xe_ggtt.c
+++ b/drivers/gpu/drm/xe/xe_ggtt.c
@@ -11,6 +11,7 @@
#include <drm/drm_drv.h>
#include <drm/drm_managed.h>
#include <drm/intel/i915_drm.h>
+#include <generated/xe_wa_oob.h>
#include "regs/xe_gt_regs.h"
#include "regs/xe_gtt_defs.h"
@@ -23,8 +24,10 @@
#include "xe_gt_sriov_vf.h"
#include "xe_gt_tlb_invalidation.h"
#include "xe_map.h"
+#include "xe_mmio.h"
#include "xe_pm.h"
#include "xe_sriov.h"
+#include "xe_wa.h"
#include "xe_wopcm.h"
static u64 xelp_ggtt_pte_encode_bo(struct xe_bo *bo, u64 bo_offset,
@@ -69,7 +72,25 @@ static unsigned int probe_gsm_size(struct pci_dev *pdev)
return ggms ? SZ_1M << ggms : 0;
}
-void xe_ggtt_set_pte(struct xe_ggtt *ggtt, u64 addr, u64 pte)
+static void ggtt_update_access_counter(struct xe_ggtt *ggtt)
+{
+ struct xe_gt *gt = XE_WA(ggtt->tile->primary_gt, 22019338487) ? ggtt->tile->primary_gt :
+ ggtt->tile->media_gt;
+ u32 max_gtt_writes = XE_WA(ggtt->tile->primary_gt, 22019338487) ? 1100 : 63;
+ /*
+ * Wa_22019338487: GMD_ID is a RO register, a dummy write forces gunit
+ * to wait for completion of prior GTT writes before letting this through.
+ * This needs to be done for all GGTT writes originating from the CPU.
+ */
+ lockdep_assert_held(&ggtt->lock);
+
+ if ((++ggtt->access_count % max_gtt_writes) == 0) {
+ xe_mmio_write32(gt, GMD_ID, 0x0);
+ ggtt->access_count = 0;
+ }
+}
+
+static void xe_ggtt_set_pte(struct xe_ggtt *ggtt, u64 addr, u64 pte)
{
xe_tile_assert(ggtt->tile, !(addr & XE_PTE_MASK));
xe_tile_assert(ggtt->tile, addr < ggtt->size);
@@ -77,6 +98,12 @@ void xe_ggtt_set_pte(struct xe_ggtt *ggtt, u64 addr, u64 pte)
writeq(pte, &ggtt->gsm[addr >> XE_PTE_SHIFT]);
}
+static void xe_ggtt_set_pte_and_flush(struct xe_ggtt *ggtt, u64 addr, u64 pte)
+{
+ xe_ggtt_set_pte(ggtt, addr, pte);
+ ggtt_update_access_counter(ggtt);
+}
+
static void xe_ggtt_clear(struct xe_ggtt *ggtt, u64 start, u64 size)
{
u16 pat_index = tile_to_xe(ggtt->tile)->pat.idx[XE_CACHE_WB];
@@ -92,7 +119,7 @@ static void xe_ggtt_clear(struct xe_ggtt *ggtt, u64 start, u64 size)
scratch_pte = 0;
while (start < end) {
- xe_ggtt_set_pte(ggtt, start, scratch_pte);
+ ggtt->pt_ops->ggtt_set_pte(ggtt, start, scratch_pte);
start += XE_PAGE_SIZE;
}
}
@@ -124,10 +151,17 @@ static void primelockdep(struct xe_ggtt *ggtt)
static const struct xe_ggtt_pt_ops xelp_pt_ops = {
.pte_encode_bo = xelp_ggtt_pte_encode_bo,
+ .ggtt_set_pte = xe_ggtt_set_pte,
};
static const struct xe_ggtt_pt_ops xelpg_pt_ops = {
.pte_encode_bo = xelpg_ggtt_pte_encode_bo,
+ .ggtt_set_pte = xe_ggtt_set_pte,
+};
+
+static const struct xe_ggtt_pt_ops xelpg_pt_wa_ops = {
+ .pte_encode_bo = xelpg_ggtt_pte_encode_bo,
+ .ggtt_set_pte = xe_ggtt_set_pte_and_flush,
};
/*
@@ -187,7 +221,10 @@ int xe_ggtt_init_early(struct xe_ggtt *ggtt)
ggtt->size = GUC_GGTT_TOP;
if (GRAPHICS_VERx100(xe) >= 1270)
- ggtt->pt_ops = &xelpg_pt_ops;
+ ggtt->pt_ops = (ggtt->tile->media_gt &&
+ XE_WA(ggtt->tile->media_gt, 22019338487)) ||
+ XE_WA(ggtt->tile->primary_gt, 22019338487) ?
+ &xelpg_pt_wa_ops : &xelpg_pt_ops;
else
ggtt->pt_ops = &xelp_pt_ops;
@@ -394,7 +431,7 @@ void xe_ggtt_map_bo(struct xe_ggtt *ggtt, struct xe_bo *bo)
for (offset = 0; offset < bo->size; offset += XE_PAGE_SIZE) {
pte = ggtt->pt_ops->pte_encode_bo(bo, offset, pat_index);
- xe_ggtt_set_pte(ggtt, start + offset, pte);
+ ggtt->pt_ops->ggtt_set_pte(ggtt, start + offset, pte);
}
}
@@ -502,7 +539,7 @@ static void xe_ggtt_assign_locked(struct xe_ggtt *ggtt, const struct drm_mm_node
return;
while (start < end) {
- xe_ggtt_set_pte(ggtt, start, pte);
+ ggtt->pt_ops->ggtt_set_pte(ggtt, start, pte);
start += XE_PAGE_SIZE;
}
diff --git a/drivers/gpu/drm/xe/xe_ggtt.h b/drivers/gpu/drm/xe/xe_ggtt.h
index 4a41a1762358..6a96fd54bf60 100644
--- a/drivers/gpu/drm/xe/xe_ggtt.h
+++ b/drivers/gpu/drm/xe/xe_ggtt.h
@@ -10,7 +10,6 @@
struct drm_printer;
-void xe_ggtt_set_pte(struct xe_ggtt *ggtt, u64 addr, u64 pte);
int xe_ggtt_init_early(struct xe_ggtt *ggtt);
int xe_ggtt_init(struct xe_ggtt *ggtt);
void xe_ggtt_printk(struct xe_ggtt *ggtt, const char *prefix);
diff --git a/drivers/gpu/drm/xe/xe_ggtt_types.h b/drivers/gpu/drm/xe/xe_ggtt_types.h
index d8c584d9a8c3..2245d88d8f39 100644
--- a/drivers/gpu/drm/xe/xe_ggtt_types.h
+++ b/drivers/gpu/drm/xe/xe_ggtt_types.h
@@ -13,10 +13,6 @@
struct xe_bo;
struct xe_gt;
-struct xe_ggtt_pt_ops {
- u64 (*pte_encode_bo)(struct xe_bo *bo, u64 bo_offset, u16 pat_index);
-};
-
struct xe_ggtt {
struct xe_tile *tile;
@@ -34,6 +30,14 @@ struct xe_ggtt {
const struct xe_ggtt_pt_ops *pt_ops;
struct drm_mm mm;
+
+ /** @access_count: counts GGTT writes */
+ unsigned int access_count;
+};
+
+struct xe_ggtt_pt_ops {
+ u64 (*pte_encode_bo)(struct xe_bo *bo, u64 bo_offset, u16 pat_index);
+ void (*ggtt_set_pte)(struct xe_ggtt *ggtt, u64 addr, u64 pte);
};
#endif
diff --git a/drivers/gpu/drm/xe/xe_gsc.c b/drivers/gpu/drm/xe/xe_gsc.c
index 80a61934decc..f8239a13fa2b 100644
--- a/drivers/gpu/drm/xe/xe_gsc.c
+++ b/drivers/gpu/drm/xe/xe_gsc.c
@@ -22,6 +22,7 @@
#include "xe_gt.h"
#include "xe_gt_mcr.h"
#include "xe_gt_printk.h"
+#include "xe_guc_pc.h"
#include "xe_huc.h"
#include "xe_map.h"
#include "xe_mmio.h"
@@ -284,6 +285,10 @@ static int gsc_upload_and_init(struct xe_gsc *gsc)
return ret;
xe_uc_fw_change_status(&gsc->fw, XE_UC_FIRMWARE_TRANSFERRED);
+
+ /* GSC load is done, restore expected GT frequencies */
+ xe_gt_sanitize_freq(gt);
+
xe_gt_dbg(gt, "GSC FW async load completed\n");
/* HuC auth failure is not fatal */
diff --git a/drivers/gpu/drm/xe/xe_gt.c b/drivers/gpu/drm/xe/xe_gt.c
index 57d84751e160..31b2e64c70c6 100644
--- a/drivers/gpu/drm/xe/xe_gt.c
+++ b/drivers/gpu/drm/xe/xe_gt.c
@@ -9,6 +9,7 @@
#include <drm/drm_managed.h>
#include <drm/xe_drm.h>
+#include <generated/xe_wa_oob.h>
#include "instructions/xe_gfxpipe_commands.h"
#include "instructions/xe_mi_commands.h"
@@ -54,6 +55,7 @@
#include "xe_sriov.h"
#include "xe_tuning.h"
#include "xe_uc.h"
+#include "xe_uc_fw.h"
#include "xe_vm.h"
#include "xe_wa.h"
#include "xe_wopcm.h"
@@ -678,6 +680,12 @@ static int do_gt_restart(struct xe_gt *gt)
/* Get CCS mode in sync between sw/hw */
xe_gt_apply_ccs_mode(gt);
+ /* Restore GT freq to expected values */
+ xe_gt_sanitize_freq(gt);
+
+ if (IS_SRIOV_PF(gt_to_xe(gt)))
+ xe_gt_sriov_pf_restart(gt);
+
return 0;
}
@@ -801,6 +809,24 @@ err_msg:
return err;
}
+/**
+ * xe_gt_sanitize_freq() - Restore saved frequencies if necessary.
+ * @gt: the GT object
+ *
+ * Called after driver init/GSC load completes to restore GT frequencies if we
+ * limited them for any WAs.
+ */
+int xe_gt_sanitize_freq(struct xe_gt *gt)
+{
+ int ret = 0;
+
+ if ((!xe_uc_fw_is_available(&gt->uc.gsc.fw) ||
+ xe_uc_fw_is_loaded(&gt->uc.gsc.fw)) && XE_WA(gt, 22019338487))
+ ret = xe_guc_pc_restore_stashed_freq(&gt->uc.guc.pc);
+
+ return ret;
+}
+
int xe_gt_resume(struct xe_gt *gt)
{
int err;
@@ -878,3 +904,18 @@ struct xe_hw_engine *xe_gt_any_hw_engine(struct xe_gt *gt)
return NULL;
}
+
+/**
+ * xe_gt_declare_wedged() - Declare GT wedged
+ * @gt: the GT object
+ *
+ * Wedge the GT which stops all submission, saves desired debug state, and
+ * cleans up anything which could timeout.
+ */
+void xe_gt_declare_wedged(struct xe_gt *gt)
+{
+ xe_gt_assert(gt, gt_to_xe(gt)->wedged.mode);
+
+ xe_uc_declare_wedged(&gt->uc);
+ xe_gt_tlb_invalidation_reset(gt);
+}
diff --git a/drivers/gpu/drm/xe/xe_gt.h b/drivers/gpu/drm/xe/xe_gt.h
index 9073ac68a777..8b1a5027dcf2 100644
--- a/drivers/gpu/drm/xe/xe_gt.h
+++ b/drivers/gpu/drm/xe/xe_gt.h
@@ -37,6 +37,7 @@ struct xe_gt *xe_gt_alloc(struct xe_tile *tile);
int xe_gt_init_hwconfig(struct xe_gt *gt);
int xe_gt_init_early(struct xe_gt *gt);
int xe_gt_init(struct xe_gt *gt);
+void xe_gt_declare_wedged(struct xe_gt *gt);
int xe_gt_record_default_lrcs(struct xe_gt *gt);
/**
@@ -56,6 +57,7 @@ int xe_gt_suspend(struct xe_gt *gt);
int xe_gt_resume(struct xe_gt *gt);
void xe_gt_reset_async(struct xe_gt *gt);
void xe_gt_sanitize(struct xe_gt *gt);
+int xe_gt_sanitize_freq(struct xe_gt *gt);
void xe_gt_remove(struct xe_gt *gt);
/**
diff --git a/drivers/gpu/drm/xe/xe_gt_ccs_mode.c b/drivers/gpu/drm/xe/xe_gt_ccs_mode.c
index 5d4cdbd69bc3..d2e4dc3aaf61 100644
--- a/drivers/gpu/drm/xe/xe_gt_ccs_mode.c
+++ b/drivers/gpu/drm/xe/xe_gt_ccs_mode.c
@@ -12,6 +12,7 @@
#include "xe_gt_printk.h"
#include "xe_gt_sysfs.h"
#include "xe_mmio.h"
+#include "xe_sriov.h"
static void __xe_gt_apply_ccs_mode(struct xe_gt *gt, u32 num_engines)
{
@@ -75,7 +76,7 @@ static void __xe_gt_apply_ccs_mode(struct xe_gt *gt, u32 num_engines)
void xe_gt_apply_ccs_mode(struct xe_gt *gt)
{
- if (!gt->ccs_mode)
+ if (!gt->ccs_mode || IS_SRIOV_VF(gt_to_xe(gt)))
return;
__xe_gt_apply_ccs_mode(gt, gt->ccs_mode);
@@ -110,6 +111,12 @@ ccs_mode_store(struct device *kdev, struct device_attribute *attr,
u32 num_engines, num_slices;
int ret;
+ if (IS_SRIOV(xe)) {
+ xe_gt_dbg(gt, "Can't change compute mode when running as %s\n",
+ xe_sriov_mode_to_string(xe_device_sriov_mode(xe)));
+ return -EOPNOTSUPP;
+ }
+
ret = kstrtou32(buff, 0, &num_engines);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/xe/xe_gt_clock.c b/drivers/gpu/drm/xe/xe_gt_clock.c
index 9ff2061133df..86c2d62b4bdc 100644
--- a/drivers/gpu/drm/xe/xe_gt_clock.c
+++ b/drivers/gpu/drm/xe/xe_gt_clock.c
@@ -3,6 +3,8 @@
* Copyright © 2022 Intel Corporation
*/
+#include <linux/math64.h>
+
#include "xe_gt_clock.h"
#include "regs/xe_gt_regs.h"
@@ -79,3 +81,21 @@ int xe_gt_clock_init(struct xe_gt *gt)
gt->info.reference_clock = freq;
return 0;
}
+
+static u64 div_u64_roundup(u64 n, u32 d)
+{
+ return div_u64(n + d - 1, d);
+}
+
+/**
+ * xe_gt_clock_interval_to_ms - Convert sampled GT clock ticks to msec
+ *
+ * @gt: the &xe_gt
+ * @count: count of GT clock ticks
+ *
+ * Returns: time in msec
+ */
+u64 xe_gt_clock_interval_to_ms(struct xe_gt *gt, u64 count)
+{
+ return div_u64_roundup(count * MSEC_PER_SEC, gt->info.reference_clock);
+}
diff --git a/drivers/gpu/drm/xe/xe_gt_clock.h b/drivers/gpu/drm/xe/xe_gt_clock.h
index 44fa0371b973..3adeb7baaca4 100644
--- a/drivers/gpu/drm/xe/xe_gt_clock.h
+++ b/drivers/gpu/drm/xe/xe_gt_clock.h
@@ -11,5 +11,6 @@
struct xe_gt;
int xe_gt_clock_init(struct xe_gt *gt);
+u64 xe_gt_clock_interval_to_ms(struct xe_gt *gt, u64 count);
#endif
diff --git a/drivers/gpu/drm/xe/xe_gt_idle.c b/drivers/gpu/drm/xe/xe_gt_idle.c
index 5d6181117ab2..67aba4140510 100644
--- a/drivers/gpu/drm/xe/xe_gt_idle.c
+++ b/drivers/gpu/drm/xe/xe_gt_idle.c
@@ -15,6 +15,7 @@
#include "xe_macros.h"
#include "xe_mmio.h"
#include "xe_pm.h"
+#include "xe_sriov.h"
/**
* DOC: Xe GT Idle
@@ -100,6 +101,9 @@ void xe_gt_idle_enable_pg(struct xe_gt *gt)
u32 pg_enable;
int i, j;
+ if (IS_SRIOV_VF(xe))
+ return;
+
/* Disable CPG for PVC */
if (xe->info.platform == XE_PVC)
return;
@@ -130,6 +134,9 @@ void xe_gt_idle_enable_pg(struct xe_gt *gt)
void xe_gt_idle_disable_pg(struct xe_gt *gt)
{
+ if (IS_SRIOV_VF(gt_to_xe(gt)))
+ return;
+
xe_device_assert_mem_access(gt_to_xe(gt));
XE_WARN_ON(xe_force_wake_get(gt_to_fw(gt), XE_FW_GT));
@@ -214,6 +221,9 @@ int xe_gt_idle_init(struct xe_gt_idle *gtidle)
struct kobject *kobj;
int err;
+ if (IS_SRIOV_VF(xe))
+ return 0;
+
kobj = kobject_create_and_add("gtidle", gt->sysfs);
if (!kobj)
return -ENOMEM;
@@ -246,6 +256,9 @@ void xe_gt_idle_enable_c6(struct xe_gt *gt)
xe_device_assert_mem_access(gt_to_xe(gt));
xe_force_wake_assert_held(gt_to_fw(gt), XE_FW_GT);
+ if (IS_SRIOV_VF(gt_to_xe(gt)))
+ return;
+
/* Units of 1280 ns for a total of 5s */
xe_mmio_write32(gt, RC_IDLE_HYSTERSIS, 0x3B9ACA);
/* Enable RC6 */
@@ -258,6 +271,9 @@ void xe_gt_idle_disable_c6(struct xe_gt *gt)
xe_device_assert_mem_access(gt_to_xe(gt));
xe_force_wake_assert_held(gt_to_fw(gt), XE_FW_GT);
+ if (IS_SRIOV_VF(gt_to_xe(gt)))
+ return;
+
xe_mmio_write32(gt, RC_CONTROL, 0);
xe_mmio_write32(gt, RC_STATE, 0);
}
diff --git a/drivers/gpu/drm/xe/xe_gt_mcr.c b/drivers/gpu/drm/xe/xe_gt_mcr.c
index 386ac3269909..6d948a469126 100644
--- a/drivers/gpu/drm/xe/xe_gt_mcr.c
+++ b/drivers/gpu/drm/xe/xe_gt_mcr.c
@@ -342,7 +342,7 @@ static void init_steering_oaddrm(struct xe_gt *gt)
else
gt->steering[OADDRM].group_target = 1;
- gt->steering[DSS].instance_target = 0; /* unused */
+ gt->steering[OADDRM].instance_target = 0; /* unused */
}
static void init_steering_sqidi_psmi(struct xe_gt *gt)
@@ -357,8 +357,8 @@ static void init_steering_sqidi_psmi(struct xe_gt *gt)
static void init_steering_inst0(struct xe_gt *gt)
{
- gt->steering[DSS].group_target = 0; /* unused */
- gt->steering[DSS].instance_target = 0; /* unused */
+ gt->steering[INSTANCE0].group_target = 0; /* unused */
+ gt->steering[INSTANCE0].instance_target = 0; /* unused */
}
static const struct {
diff --git a/drivers/gpu/drm/xe/xe_gt_pagefault.c b/drivers/gpu/drm/xe/xe_gt_pagefault.c
index 040dd142c49c..9292d5468868 100644
--- a/drivers/gpu/drm/xe/xe_gt_pagefault.c
+++ b/drivers/gpu/drm/xe/xe_gt_pagefault.c
@@ -19,7 +19,7 @@
#include "xe_guc.h"
#include "xe_guc_ct.h"
#include "xe_migrate.h"
-#include "xe_trace.h"
+#include "xe_trace_bo.h"
#include "xe_vm.h"
struct pagefault {
@@ -125,126 +125,108 @@ static int xe_pf_begin(struct drm_exec *exec, struct xe_vma *vma,
return 0;
}
-static int handle_pagefault(struct xe_gt *gt, struct pagefault *pf)
+static int handle_vma_pagefault(struct xe_tile *tile, struct pagefault *pf,
+ struct xe_vma *vma)
{
- struct xe_device *xe = gt_to_xe(gt);
- struct xe_tile *tile = gt_to_tile(gt);
+ struct xe_vm *vm = xe_vma_vm(vma);
struct drm_exec exec;
- struct xe_vm *vm;
- struct xe_vma *vma = NULL;
struct dma_fence *fence;
- bool write_locked;
- int ret = 0;
+ ktime_t end = 0;
+ int err;
bool atomic;
- /* SW isn't expected to handle TRTT faults */
- if (pf->trva_fault)
- return -EFAULT;
-
- /* ASID to VM */
- mutex_lock(&xe->usm.lock);
- vm = xa_load(&xe->usm.asid_to_vm, pf->asid);
- if (vm && xe_vm_in_fault_mode(vm))
- xe_vm_get(vm);
- else
- vm = NULL;
- mutex_unlock(&xe->usm.lock);
- if (!vm)
- return -EINVAL;
-
-retry_userptr:
- /*
- * TODO: Avoid exclusive lock if VM doesn't have userptrs, or
- * start out read-locked?
- */
- down_write(&vm->lock);
- write_locked = true;
- vma = lookup_vma(vm, pf->page_addr);
- if (!vma) {
- ret = -EINVAL;
- goto unlock_vm;
- }
-
- if (!xe_vma_is_userptr(vma) ||
- !xe_vma_userptr_check_repin(to_userptr_vma(vma))) {
- downgrade_write(&vm->lock);
- write_locked = false;
- }
-
trace_xe_vma_pagefault(vma);
-
atomic = access_is_atomic(pf->access_type);
/* Check if VMA is valid */
if (vma_is_valid(tile, vma) && !atomic)
- goto unlock_vm;
-
- /* TODO: Validate fault */
+ return 0;
- if (xe_vma_is_userptr(vma) && write_locked) {
+retry_userptr:
+ if (xe_vma_is_userptr(vma) &&
+ xe_vma_userptr_check_repin(to_userptr_vma(vma))) {
struct xe_userptr_vma *uvma = to_userptr_vma(vma);
- spin_lock(&vm->userptr.invalidated_lock);
- list_del_init(&uvma->userptr.invalidate_link);
- spin_unlock(&vm->userptr.invalidated_lock);
-
- ret = xe_vma_userptr_pin_pages(uvma);
- if (ret)
- goto unlock_vm;
-
- downgrade_write(&vm->lock);
- write_locked = false;
+ err = xe_vma_userptr_pin_pages(uvma);
+ if (err)
+ return err;
}
/* Lock VM and BOs dma-resv */
drm_exec_init(&exec, 0, 0);
drm_exec_until_all_locked(&exec) {
- ret = xe_pf_begin(&exec, vma, atomic, tile->id);
+ err = xe_pf_begin(&exec, vma, atomic, tile->id);
drm_exec_retry_on_contention(&exec);
- if (ret)
+ if (xe_vm_validate_should_retry(&exec, err, &end))
+ err = -EAGAIN;
+ if (err)
goto unlock_dma_resv;
/* Bind VMA only to the GT that has faulted */
trace_xe_vma_pf_bind(vma);
fence = xe_vma_rebind(vm, vma, BIT(tile->id));
if (IS_ERR(fence)) {
- ret = PTR_ERR(fence);
+ err = PTR_ERR(fence);
+ if (xe_vm_validate_should_retry(&exec, err, &end))
+ err = -EAGAIN;
goto unlock_dma_resv;
}
}
- /*
- * XXX: Should we drop the lock before waiting? This only helps if doing
- * GPU binds which is currently only done if we have to wait for more
- * than 10ms on a move.
- */
dma_fence_wait(fence, false);
dma_fence_put(fence);
-
- if (xe_vma_is_userptr(vma))
- ret = xe_vma_userptr_check_repin(to_userptr_vma(vma));
vma->tile_invalidated &= ~BIT(tile->id);
unlock_dma_resv:
drm_exec_fini(&exec);
-unlock_vm:
- if (!ret)
- vm->usm.last_fault_vma = vma;
- if (write_locked)
- up_write(&vm->lock);
- else
- up_read(&vm->lock);
- if (ret == -EAGAIN)
+ if (err == -EAGAIN)
goto retry_userptr;
- if (!ret) {
- ret = xe_gt_tlb_invalidation_vma(gt, NULL, vma);
- if (ret >= 0)
- ret = 0;
+ return err;
+}
+
+static int handle_pagefault(struct xe_gt *gt, struct pagefault *pf)
+{
+ struct xe_device *xe = gt_to_xe(gt);
+ struct xe_tile *tile = gt_to_tile(gt);
+ struct xe_vm *vm;
+ struct xe_vma *vma = NULL;
+ int err;
+
+ /* SW isn't expected to handle TRTT faults */
+ if (pf->trva_fault)
+ return -EFAULT;
+
+ /* ASID to VM */
+ mutex_lock(&xe->usm.lock);
+ vm = xa_load(&xe->usm.asid_to_vm, pf->asid);
+ if (vm && xe_vm_in_fault_mode(vm))
+ xe_vm_get(vm);
+ else
+ vm = NULL;
+ mutex_unlock(&xe->usm.lock);
+ if (!vm)
+ return -EINVAL;
+
+ /*
+ * TODO: Change to read lock? Using write lock for simplicity.
+ */
+ down_write(&vm->lock);
+ vma = lookup_vma(vm, pf->page_addr);
+ if (!vma) {
+ err = -EINVAL;
+ goto unlock_vm;
}
+
+ err = handle_vma_pagefault(tile, pf, vma);
+
+unlock_vm:
+ if (!err)
+ vm->usm.last_fault_vma = vma;
+ up_write(&vm->lock);
xe_vm_put(vm);
- return ret;
+ return err;
}
static int send_pagefault_reply(struct xe_guc *guc,
diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf.c
index 7decf71c2b7d..9dbba9ab7a9a 100644
--- a/drivers/gpu/drm/xe/xe_gt_sriov_pf.c
+++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf.c
@@ -8,6 +8,7 @@
#include "regs/xe_sriov_regs.h"
#include "xe_gt_sriov_pf.h"
+#include "xe_gt_sriov_pf_config.h"
#include "xe_gt_sriov_pf_helpers.h"
#include "xe_gt_sriov_pf_service.h"
#include "xe_mmio.h"
@@ -82,3 +83,14 @@ void xe_gt_sriov_pf_init_hw(struct xe_gt *gt)
xe_gt_sriov_pf_service_update(gt);
}
+
+/**
+ * xe_gt_sriov_pf_restart - Restart SR-IOV support after a GT reset.
+ * @gt: the &xe_gt
+ *
+ * This function can only be called on PF.
+ */
+void xe_gt_sriov_pf_restart(struct xe_gt *gt)
+{
+ xe_gt_sriov_pf_config_restart(gt);
+}
diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf.h b/drivers/gpu/drm/xe/xe_gt_sriov_pf.h
index 37d7d6c3df03..f0cb726a6919 100644
--- a/drivers/gpu/drm/xe/xe_gt_sriov_pf.h
+++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf.h
@@ -11,6 +11,7 @@ struct xe_gt;
#ifdef CONFIG_PCI_IOV
int xe_gt_sriov_pf_init_early(struct xe_gt *gt);
void xe_gt_sriov_pf_init_hw(struct xe_gt *gt);
+void xe_gt_sriov_pf_restart(struct xe_gt *gt);
#else
static inline int xe_gt_sriov_pf_init_early(struct xe_gt *gt)
{
@@ -20,6 +21,10 @@ static inline int xe_gt_sriov_pf_init_early(struct xe_gt *gt)
static inline void xe_gt_sriov_pf_init_hw(struct xe_gt *gt)
{
}
+
+static inline void xe_gt_sriov_pf_restart(struct xe_gt *gt)
+{
+}
#endif
#endif
diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c
index f49fc2917f93..4699b7836001 100644
--- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c
+++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c
@@ -1290,6 +1290,9 @@ static void pf_reset_vf_lmtt(struct xe_device *xe, unsigned int vfid)
struct xe_tile *tile;
unsigned int tid;
+ xe_assert(xe, IS_DGFX(xe));
+ xe_assert(xe, IS_SRIOV_PF(xe));
+
for_each_tile(tile, xe, tid) {
lmtt = &tile->sriov.pf.lmtt;
xe_lmtt_drop_pages(lmtt, vfid);
@@ -1308,6 +1311,9 @@ static int pf_update_vf_lmtt(struct xe_device *xe, unsigned int vfid)
unsigned int tid;
int err;
+ xe_assert(xe, IS_DGFX(xe));
+ xe_assert(xe, IS_SRIOV_PF(xe));
+
total = 0;
for_each_tile(tile, xe, tid)
total += pf_get_vf_config_lmem(tile->primary_gt, vfid);
@@ -1353,6 +1359,7 @@ fail:
static void pf_release_vf_config_lmem(struct xe_gt *gt, struct xe_gt_sriov_config *config)
{
+ xe_gt_assert(gt, IS_DGFX(gt_to_xe(gt)));
xe_gt_assert(gt, !xe_gt_is_media_type(gt));
lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt));
@@ -1371,6 +1378,7 @@ static int pf_provision_vf_lmem(struct xe_gt *gt, unsigned int vfid, u64 size)
int err;
xe_gt_assert(gt, vfid);
+ xe_gt_assert(gt, IS_DGFX(xe));
xe_gt_assert(gt, !xe_gt_is_media_type(gt));
size = round_up(size, pf_get_lmem_alignment(gt));
@@ -1535,6 +1543,7 @@ static u64 pf_estimate_fair_lmem(struct xe_gt *gt, unsigned int num_vfs)
u64 fair;
fair = div_u64(available, num_vfs);
+ fair = rounddown_pow_of_two(fair); /* XXX: ttm_vram_mgr & drm_buddy limitation */
fair = ALIGN_DOWN(fair, alignment);
#ifdef MAX_FAIR_LMEM
fair = min_t(u64, MAX_FAIR_LMEM, fair);
@@ -1838,11 +1847,14 @@ u32 xe_gt_sriov_pf_config_get_threshold(struct xe_gt *gt, unsigned int vfid,
static void pf_release_vf_config(struct xe_gt *gt, unsigned int vfid)
{
struct xe_gt_sriov_config *config = pf_pick_vf_config(gt, vfid);
+ struct xe_device *xe = gt_to_xe(gt);
if (!xe_gt_is_media_type(gt)) {
pf_release_vf_config_ggtt(gt, config);
- pf_release_vf_config_lmem(gt, config);
- pf_update_vf_lmtt(gt_to_xe(gt), vfid);
+ if (IS_DGFX(xe)) {
+ pf_release_vf_config_lmem(gt, config);
+ pf_update_vf_lmtt(xe, vfid);
+ }
}
pf_release_config_ctxs(gt, config);
pf_release_config_dbs(gt, config);
@@ -1911,6 +1923,84 @@ int xe_gt_sriov_pf_config_push(struct xe_gt *gt, unsigned int vfid, bool refresh
return err;
}
+static int pf_validate_vf_config(struct xe_gt *gt, unsigned int vfid)
+{
+ struct xe_gt *primary_gt = gt_to_tile(gt)->primary_gt;
+ struct xe_device *xe = gt_to_xe(gt);
+ bool valid_ggtt, valid_ctxs, valid_dbs;
+ bool valid_any, valid_all;
+
+ valid_ggtt = pf_get_vf_config_ggtt(primary_gt, vfid);
+ valid_ctxs = pf_get_vf_config_ctxs(gt, vfid);
+ valid_dbs = pf_get_vf_config_dbs(gt, vfid);
+
+ /* note that GuC doorbells are optional */
+ valid_any = valid_ggtt || valid_ctxs || valid_dbs;
+ valid_all = valid_ggtt && valid_ctxs;
+
+ if (IS_DGFX(xe)) {
+ bool valid_lmem = pf_get_vf_config_ggtt(primary_gt, vfid);
+
+ valid_any = valid_any || valid_lmem;
+ valid_all = valid_all && valid_lmem;
+ }
+
+ return valid_all ? 1 : valid_any ? -ENOKEY : -ENODATA;
+}
+
+/**
+ * xe_gt_sriov_pf_config_is_empty - Check VF's configuration.
+ * @gt: the &xe_gt
+ * @vfid: the VF identifier (can't be PF)
+ *
+ * This function can only be called on PF.
+ *
+ * Return: true if VF mandatory configuration (GGTT, LMEM, ...) is empty.
+ */
+bool xe_gt_sriov_pf_config_is_empty(struct xe_gt *gt, unsigned int vfid)
+{
+ bool empty;
+
+ xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt)));
+ xe_gt_assert(gt, vfid);
+
+ mutex_lock(xe_gt_sriov_pf_master_mutex(gt));
+ empty = pf_validate_vf_config(gt, vfid) == -ENODATA;
+ mutex_unlock(xe_gt_sriov_pf_master_mutex(gt));
+
+ return empty;
+}
+
+/**
+ * xe_gt_sriov_pf_config_restart - Restart SR-IOV configurations after a GT reset.
+ * @gt: the &xe_gt
+ *
+ * Any prior configurations pushed to GuC are lost when the GT is reset.
+ * Push again all non-empty VF configurations to the GuC.
+ *
+ * This function can only be called on PF.
+ */
+void xe_gt_sriov_pf_config_restart(struct xe_gt *gt)
+{
+ unsigned int n, total_vfs = xe_sriov_pf_get_totalvfs(gt_to_xe(gt));
+ unsigned int fail = 0, skip = 0;
+
+ for (n = 1; n <= total_vfs; n++) {
+ if (xe_gt_sriov_pf_config_is_empty(gt, n))
+ skip++;
+ else if (xe_gt_sriov_pf_config_push(gt, n, false))
+ fail++;
+ }
+
+ if (fail)
+ xe_gt_sriov_notice(gt, "Failed to push %u of %u VF%s configurations\n",
+ fail, total_vfs - skip, str_plural(total_vfs));
+
+ if (fail != total_vfs)
+ xe_gt_sriov_dbg(gt, "pushed %u skip %u of %u VF%s configurations\n",
+ total_vfs - skip - fail, skip, total_vfs, str_plural(total_vfs));
+}
+
/**
* xe_gt_sriov_pf_config_print_ggtt - Print GGTT configurations.
* @gt: the &xe_gt
diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.h b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.h
index e8238c1ad06a..c0e6e4743dc2 100644
--- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.h
+++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.h
@@ -53,6 +53,10 @@ int xe_gt_sriov_pf_config_set_fair(struct xe_gt *gt, unsigned int vfid, unsigned
int xe_gt_sriov_pf_config_release(struct xe_gt *gt, unsigned int vfid, bool force);
int xe_gt_sriov_pf_config_push(struct xe_gt *gt, unsigned int vfid, bool refresh);
+bool xe_gt_sriov_pf_config_is_empty(struct xe_gt *gt, unsigned int vfid);
+
+void xe_gt_sriov_pf_config_restart(struct xe_gt *gt);
+
int xe_gt_sriov_pf_config_print_ggtt(struct xe_gt *gt, struct drm_printer *p);
int xe_gt_sriov_pf_config_print_ctxs(struct xe_gt *gt, struct drm_printer *p);
int xe_gt_sriov_pf_config_print_dbs(struct xe_gt *gt, struct drm_printer *p);
diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_control.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_control.c
index 40b8f881fe04..ebf06e037750 100644
--- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_control.c
+++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_control.c
@@ -130,6 +130,27 @@ int xe_gt_sriov_pf_control_stop_vf(struct xe_gt *gt, unsigned int vfid)
}
/**
+ * xe_gt_sriov_pf_control_trigger_flr - Start a VF FLR sequence.
+ * @gt: the &xe_gt
+ * @vfid: the VF identifier
+ *
+ * This function is for PF only.
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+int xe_gt_sriov_pf_control_trigger_flr(struct xe_gt *gt, unsigned int vfid)
+{
+ int err;
+
+ /* XXX pf_send_vf_flr_start() expects ct->lock */
+ mutex_lock(&gt->uc.guc.ct.lock);
+ err = pf_send_vf_flr_start(gt, vfid);
+ mutex_unlock(&gt->uc.guc.ct.lock);
+
+ return err;
+}
+
+/**
* DOC: The VF FLR Flow with GuC
*
* PF GUC PCI
diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_control.h b/drivers/gpu/drm/xe/xe_gt_sriov_pf_control.h
index 850a3e37661f..405d1586f991 100644
--- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_control.h
+++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_control.h
@@ -14,6 +14,7 @@ struct xe_gt;
int xe_gt_sriov_pf_control_pause_vf(struct xe_gt *gt, unsigned int vfid);
int xe_gt_sriov_pf_control_resume_vf(struct xe_gt *gt, unsigned int vfid);
int xe_gt_sriov_pf_control_stop_vf(struct xe_gt *gt, unsigned int vfid);
+int xe_gt_sriov_pf_control_trigger_flr(struct xe_gt *gt, unsigned int vfid);
#ifdef CONFIG_PCI_IOV
int xe_gt_sriov_pf_control_process_guc2pf(struct xe_gt *gt, const u32 *msg, u32 len);
diff --git a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c
index 105797776a6c..d9359976ab8b 100644
--- a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c
+++ b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c
@@ -13,15 +13,32 @@
#include "xe_guc.h"
#include "xe_guc_ct.h"
#include "xe_mmio.h"
+#include "xe_sriov.h"
#include "xe_trace.h"
#include "regs/xe_guc_regs.h"
-#define TLB_TIMEOUT (HZ / 4)
+/*
+ * TLB inval depends on pending commands in the CT queue and then the real
+ * invalidation time. Double up the time to process full CT queue
+ * just to be on the safe side.
+ */
+static long tlb_timeout_jiffies(struct xe_gt *gt)
+{
+ /* this reflects what HW/GuC needs to process TLB inv request */
+ const long hw_tlb_timeout = HZ / 4;
+
+ /* this estimates actual delay caused by the CTB transport */
+ long delay = xe_guc_ct_queue_proc_time_jiffies(&gt->uc.guc.ct);
+
+ return hw_tlb_timeout + 2 * delay;
+}
+
static void xe_gt_tlb_fence_timeout(struct work_struct *work)
{
struct xe_gt *gt = container_of(work, struct xe_gt,
tlb_invalidation.fence_tdr.work);
+ struct xe_device *xe = gt_to_xe(gt);
struct xe_gt_tlb_invalidation_fence *fence, *next;
spin_lock_irq(&gt->tlb_invalidation.pending_lock);
@@ -30,10 +47,10 @@ static void xe_gt_tlb_fence_timeout(struct work_struct *work)
s64 since_inval_ms = ktime_ms_delta(ktime_get(),
fence->invalidation_time);
- if (msecs_to_jiffies(since_inval_ms) < TLB_TIMEOUT)
+ if (msecs_to_jiffies(since_inval_ms) < tlb_timeout_jiffies(gt))
break;
- trace_xe_gt_tlb_invalidation_fence_timeout(fence);
+ trace_xe_gt_tlb_invalidation_fence_timeout(xe, fence);
xe_gt_err(gt, "TLB invalidation fence timeout, seqno=%d recv=%d",
fence->seqno, gt->tlb_invalidation.seqno_recv);
@@ -45,7 +62,7 @@ static void xe_gt_tlb_fence_timeout(struct work_struct *work)
if (!list_empty(&gt->tlb_invalidation.pending_fences))
queue_delayed_work(system_wq,
&gt->tlb_invalidation.fence_tdr,
- TLB_TIMEOUT);
+ tlb_timeout_jiffies(gt));
spin_unlock_irq(&gt->tlb_invalidation.pending_lock);
}
@@ -71,18 +88,18 @@ int xe_gt_tlb_invalidation_init(struct xe_gt *gt)
}
static void
-__invalidation_fence_signal(struct xe_gt_tlb_invalidation_fence *fence)
+__invalidation_fence_signal(struct xe_device *xe, struct xe_gt_tlb_invalidation_fence *fence)
{
- trace_xe_gt_tlb_invalidation_fence_signal(fence);
+ trace_xe_gt_tlb_invalidation_fence_signal(xe, fence);
dma_fence_signal(&fence->base);
dma_fence_put(&fence->base);
}
static void
-invalidation_fence_signal(struct xe_gt_tlb_invalidation_fence *fence)
+invalidation_fence_signal(struct xe_device *xe, struct xe_gt_tlb_invalidation_fence *fence)
{
list_del(&fence->link);
- __invalidation_fence_signal(fence);
+ __invalidation_fence_signal(xe, fence);
}
/**
@@ -121,7 +138,7 @@ void xe_gt_tlb_invalidation_reset(struct xe_gt *gt)
list_for_each_entry_safe(fence, next,
&gt->tlb_invalidation.pending_fences, link)
- invalidation_fence_signal(fence);
+ invalidation_fence_signal(gt_to_xe(gt), fence);
spin_unlock_irq(&gt->tlb_invalidation.pending_lock);
mutex_unlock(&gt->uc.guc.ct.lock);
}
@@ -144,6 +161,7 @@ static int send_tlb_invalidation(struct xe_guc *guc,
u32 *action, int len)
{
struct xe_gt *gt = guc_to_gt(guc);
+ struct xe_device *xe = gt_to_xe(gt);
int seqno;
int ret;
@@ -157,7 +175,7 @@ static int send_tlb_invalidation(struct xe_guc *guc,
seqno = gt->tlb_invalidation.seqno;
if (fence) {
fence->seqno = seqno;
- trace_xe_gt_tlb_invalidation_fence_send(fence);
+ trace_xe_gt_tlb_invalidation_fence_send(xe, fence);
}
action[1] = seqno;
ret = xe_guc_ct_send_locked(&guc->ct, action, len,
@@ -171,7 +189,7 @@ static int send_tlb_invalidation(struct xe_guc *guc,
* we can just go ahead and signal the fence here.
*/
if (tlb_invalidation_seqno_past(gt, seqno)) {
- __invalidation_fence_signal(fence);
+ __invalidation_fence_signal(xe, fence);
} else {
fence->invalidation_time = ktime_get();
list_add_tail(&fence->link,
@@ -180,11 +198,11 @@ static int send_tlb_invalidation(struct xe_guc *guc,
if (list_is_singular(&gt->tlb_invalidation.pending_fences))
queue_delayed_work(system_wq,
&gt->tlb_invalidation.fence_tdr,
- TLB_TIMEOUT);
+ tlb_timeout_jiffies(gt));
}
spin_unlock_irq(&gt->tlb_invalidation.pending_lock);
} else if (ret < 0 && fence) {
- __invalidation_fence_signal(fence);
+ __invalidation_fence_signal(xe, fence);
}
if (!ret) {
gt->tlb_invalidation.seqno = (gt->tlb_invalidation.seqno + 1) %
@@ -247,6 +265,9 @@ int xe_gt_tlb_invalidation_ggtt(struct xe_gt *gt)
xe_gt_tlb_invalidation_wait(gt, seqno);
} else if (xe_device_uc_enabled(xe) && !xe_device_wedged(xe)) {
+ if (IS_SRIOV_VF(xe))
+ return 0;
+
xe_gt_WARN_ON(gt, xe_force_wake_get(gt_to_fw(gt), XE_FW_GT));
if (xe->info.platform == XE_PVC || GRAPHICS_VER(xe) >= 20) {
xe_mmio_write32(gt, PVC_GUC_TLB_INV_DESC1,
@@ -294,7 +315,7 @@ int xe_gt_tlb_invalidation_range(struct xe_gt *gt,
/* Execlists not supported */
if (gt_to_xe(gt)->info.force_execlist) {
if (fence)
- __invalidation_fence_signal(fence);
+ __invalidation_fence_signal(xe, fence);
return 0;
}
@@ -384,8 +405,7 @@ int xe_gt_tlb_invalidation_vma(struct xe_gt *gt,
* @gt: graphics tile
* @seqno: seqno to wait which was returned from xe_gt_tlb_invalidation
*
- * Wait for 200ms for a TLB invalidation to complete, in practice we always
- * should receive the TLB invalidation within 200ms.
+ * Wait for tlb_timeout_jiffies() for a TLB invalidation to complete.
*
* Return: 0 on success, -ETIME on TLB invalidation timeout
*/
@@ -404,7 +424,7 @@ int xe_gt_tlb_invalidation_wait(struct xe_gt *gt, int seqno)
*/
ret = wait_event_timeout(guc->ct.wq,
tlb_invalidation_seqno_past(gt, seqno),
- TLB_TIMEOUT);
+ tlb_timeout_jiffies(gt));
if (!ret) {
struct drm_printer p = xe_gt_err_printer(gt);
@@ -432,6 +452,7 @@ int xe_gt_tlb_invalidation_wait(struct xe_gt *gt, int seqno)
int xe_guc_tlb_invalidation_done_handler(struct xe_guc *guc, u32 *msg, u32 len)
{
struct xe_gt *gt = guc_to_gt(guc);
+ struct xe_device *xe = gt_to_xe(gt);
struct xe_gt_tlb_invalidation_fence *fence, *next;
unsigned long flags;
@@ -468,18 +489,18 @@ int xe_guc_tlb_invalidation_done_handler(struct xe_guc *guc, u32 *msg, u32 len)
list_for_each_entry_safe(fence, next,
&gt->tlb_invalidation.pending_fences, link) {
- trace_xe_gt_tlb_invalidation_fence_recv(fence);
+ trace_xe_gt_tlb_invalidation_fence_recv(xe, fence);
if (!tlb_invalidation_seqno_past(gt, fence->seqno))
break;
- invalidation_fence_signal(fence);
+ invalidation_fence_signal(xe, fence);
}
if (!list_empty(&gt->tlb_invalidation.pending_fences))
mod_delayed_work(system_wq,
&gt->tlb_invalidation.fence_tdr,
- TLB_TIMEOUT);
+ tlb_timeout_jiffies(gt));
else
cancel_delayed_work(&gt->tlb_invalidation.fence_tdr);
diff --git a/drivers/gpu/drm/xe/xe_gt_types.h b/drivers/gpu/drm/xe/xe_gt_types.h
index 10a9a9529377..6b5e0b45efb0 100644
--- a/drivers/gpu/drm/xe/xe_gt_types.h
+++ b/drivers/gpu/drm/xe/xe_gt_types.h
@@ -12,6 +12,7 @@
#include "xe_gt_sriov_vf_types.h"
#include "xe_hw_engine_types.h"
#include "xe_hw_fence_types.h"
+#include "xe_oa.h"
#include "xe_reg_sr_types.h"
#include "xe_sa_types.h"
#include "xe_uc_types.h"
@@ -387,6 +388,9 @@ struct xe_gt {
*/
u8 instances_per_class[XE_ENGINE_CLASS_MAX];
} user_engines;
+
+ /** @oa: oa observation subsystem per gt info */
+ struct xe_oa_gt oa;
};
#endif
diff --git a/drivers/gpu/drm/xe/xe_guc.c b/drivers/gpu/drm/xe/xe_guc.c
index 0bf6e01b8910..de0fe9e65746 100644
--- a/drivers/gpu/drm/xe/xe_guc.c
+++ b/drivers/gpu/drm/xe/xe_guc.c
@@ -476,6 +476,9 @@ static void guc_prepare_xfer(struct xe_guc *guc)
xe_mmio_write32(gt, GUC_SHIM_CONTROL, shim_flags);
xe_mmio_write32(gt, GT_PM_CONFIG, GT_DOORBELL_ENABLE);
+
+ /* Make sure GuC receives ARAT interrupts */
+ xe_mmio_rmw32(gt, PMINTRMSK, ARAT_EXPIRED_INTRMSK, 0);
}
/*
@@ -699,6 +702,9 @@ static int __xe_guc_upload(struct xe_guc *guc)
{
int ret;
+ /* Raise GT freq to speed up HuC/GuC load */
+ xe_guc_pc_raise_unslice(&guc->pc);
+
guc_write_params(guc);
guc_prepare_xfer(guc);
@@ -784,7 +790,6 @@ int xe_guc_min_load_for_hwconfig(struct xe_guc *guc)
xe_guc_ads_populate_minimal(&guc->ads);
- /* Raise GT freq to speed up HuC/GuC load */
xe_guc_pc_init_early(&guc->pc);
ret = __xe_guc_upload(guc);
@@ -854,8 +859,6 @@ int xe_guc_enable_communication(struct xe_guc *guc)
struct xe_device *xe = guc_to_xe(guc);
int err;
- guc_enable_irq(guc);
-
if (IS_SRIOV_VF(xe) && xe_device_has_memirq(xe)) {
struct xe_gt *gt = guc_to_gt(guc);
struct xe_tile *tile = gt_to_tile(gt);
@@ -863,11 +866,10 @@ int xe_guc_enable_communication(struct xe_guc *guc)
err = xe_memirq_init_guc(&tile->sriov.vf.memirq, guc);
if (err)
return err;
+ } else {
+ guc_enable_irq(guc);
}
- xe_mmio_rmw32(guc_to_gt(guc), PMINTRMSK,
- ARAT_EXPIRED_INTRMSK, 0);
-
err = xe_guc_ct_enable(&guc->ct);
if (err)
return err;
@@ -1094,7 +1096,7 @@ void xe_guc_irq_handler(struct xe_guc *guc, const u16 iir)
void xe_guc_sanitize(struct xe_guc *guc)
{
- xe_uc_fw_change_status(&guc->fw, XE_UC_FIRMWARE_LOADABLE);
+ xe_uc_fw_sanitize(&guc->fw);
xe_guc_ct_disable(&guc->ct);
guc->submission_state.enabled = false;
}
@@ -1111,7 +1113,13 @@ void xe_guc_reset_wait(struct xe_guc *guc)
void xe_guc_stop_prepare(struct xe_guc *guc)
{
- XE_WARN_ON(xe_guc_pc_stop(&guc->pc));
+ if (!IS_SRIOV_VF(guc_to_xe(guc))) {
+ int err;
+
+ err = xe_guc_pc_stop(&guc->pc);
+ xe_gt_WARN(guc_to_gt(guc), err, "Failed to stop GuC PC: %pe\n",
+ ERR_PTR(err));
+ }
}
void xe_guc_stop(struct xe_guc *guc)
@@ -1123,10 +1131,13 @@ void xe_guc_stop(struct xe_guc *guc)
int xe_guc_start(struct xe_guc *guc)
{
- int ret;
+ if (!IS_SRIOV_VF(guc_to_xe(guc))) {
+ int err;
- ret = xe_guc_pc_start(&guc->pc);
- XE_WARN_ON(ret);
+ err = xe_guc_pc_start(&guc->pc);
+ xe_gt_WARN(guc_to_gt(guc), err, "Failed to start GuC PC: %pe\n",
+ ERR_PTR(err));
+ }
return xe_guc_submit_start(guc);
}
@@ -1167,3 +1178,19 @@ void xe_guc_print_info(struct xe_guc *guc, struct drm_printer *p)
xe_guc_ct_print(&guc->ct, p, false);
xe_guc_submit_print(guc, p);
}
+
+/**
+ * xe_guc_declare_wedged() - Declare GuC wedged
+ * @guc: the GuC object
+ *
+ * Wedge the GuC which stops all submission, saves desired debug state, and
+ * cleans up anything which could timeout.
+ */
+void xe_guc_declare_wedged(struct xe_guc *guc)
+{
+ xe_gt_assert(guc_to_gt(guc), guc_to_xe(guc)->wedged.mode);
+
+ xe_guc_reset_prepare(guc);
+ xe_guc_ct_stop(&guc->ct);
+ xe_guc_submit_wedge(guc);
+}
diff --git a/drivers/gpu/drm/xe/xe_guc.h b/drivers/gpu/drm/xe/xe_guc.h
index af59c9545753..e0bbf98f849d 100644
--- a/drivers/gpu/drm/xe/xe_guc.h
+++ b/drivers/gpu/drm/xe/xe_guc.h
@@ -37,6 +37,7 @@ void xe_guc_reset_wait(struct xe_guc *guc);
void xe_guc_stop_prepare(struct xe_guc *guc);
void xe_guc_stop(struct xe_guc *guc);
int xe_guc_start(struct xe_guc *guc);
+void xe_guc_declare_wedged(struct xe_guc *guc);
static inline u16 xe_engine_class_to_guc_class(enum xe_engine_class class)
{
diff --git a/drivers/gpu/drm/xe/xe_guc_ct.c b/drivers/gpu/drm/xe/xe_guc_ct.c
index c1f258348f5c..7d2e937da1d8 100644
--- a/drivers/gpu/drm/xe/xe_guc_ct.c
+++ b/drivers/gpu/drm/xe/xe_guc_ct.c
@@ -29,7 +29,7 @@
#include "xe_guc_submit.h"
#include "xe_map.h"
#include "xe_pm.h"
-#include "xe_trace.h"
+#include "xe_trace_guc.h"
/* Used when a CT send wants to block and / or receive data */
struct g2h_fence {
@@ -112,6 +112,23 @@ ct_to_xe(struct xe_guc_ct *ct)
#define CTB_G2H_BUFFER_SIZE (4 * CTB_H2G_BUFFER_SIZE)
#define G2H_ROOM_BUFFER_SIZE (CTB_G2H_BUFFER_SIZE / 4)
+/**
+ * xe_guc_ct_queue_proc_time_jiffies - Return maximum time to process a full
+ * CT command queue
+ * @ct: the &xe_guc_ct. Unused at this moment but will be used in the future.
+ *
+ * Observation is that a 4KiB buffer full of commands takes a little over a
+ * second to process. Use that to calculate maximum time to process a full CT
+ * command queue.
+ *
+ * Return: Maximum time to process a full CT queue in jiffies.
+ */
+long xe_guc_ct_queue_proc_time_jiffies(struct xe_guc_ct *ct)
+{
+ BUILD_BUG_ON(!IS_ALIGNED(CTB_H2G_BUFFER_SIZE, SZ_4));
+ return (CTB_H2G_BUFFER_SIZE / SZ_4K) * HZ;
+}
+
static size_t guc_ct_size(void)
{
return 2 * CTB_DESC_SIZE + CTB_H2G_BUFFER_SIZE +
@@ -126,7 +143,9 @@ static void guc_ct_fini(struct drm_device *drm, void *arg)
xa_destroy(&ct->fence_lookup);
}
+static void receive_g2h(struct xe_guc_ct *ct);
static void g2h_worker_func(struct work_struct *w);
+static void safe_mode_worker_func(struct work_struct *w);
static void primelockdep(struct xe_guc_ct *ct)
{
@@ -155,6 +174,7 @@ int xe_guc_ct_init(struct xe_guc_ct *ct)
spin_lock_init(&ct->fast_lock);
xa_init(&ct->fence_lookup);
INIT_WORK(&ct->g2h_worker, g2h_worker_func);
+ INIT_DELAYED_WORK(&ct->safe_mode_worker, safe_mode_worker_func);
init_waitqueue_head(&ct->wq);
init_waitqueue_head(&ct->g2h_fence_wq);
@@ -321,6 +341,42 @@ static void xe_guc_ct_set_state(struct xe_guc_ct *ct,
mutex_unlock(&ct->lock);
}
+static bool ct_needs_safe_mode(struct xe_guc_ct *ct)
+{
+ return !pci_dev_msi_enabled(to_pci_dev(ct_to_xe(ct)->drm.dev));
+}
+
+static bool ct_restart_safe_mode_worker(struct xe_guc_ct *ct)
+{
+ if (!ct_needs_safe_mode(ct))
+ return false;
+
+ queue_delayed_work(ct->g2h_wq, &ct->safe_mode_worker, HZ / 10);
+ return true;
+}
+
+static void safe_mode_worker_func(struct work_struct *w)
+{
+ struct xe_guc_ct *ct = container_of(w, struct xe_guc_ct, safe_mode_worker.work);
+
+ receive_g2h(ct);
+
+ if (!ct_restart_safe_mode_worker(ct))
+ xe_gt_dbg(ct_to_gt(ct), "GuC CT safe-mode canceled\n");
+}
+
+static void ct_enter_safe_mode(struct xe_guc_ct *ct)
+{
+ if (ct_restart_safe_mode_worker(ct))
+ xe_gt_dbg(ct_to_gt(ct), "GuC CT safe-mode enabled\n");
+}
+
+static void ct_exit_safe_mode(struct xe_guc_ct *ct)
+{
+ if (cancel_delayed_work_sync(&ct->safe_mode_worker))
+ xe_gt_dbg(ct_to_gt(ct), "GuC CT safe-mode disabled\n");
+}
+
int xe_guc_ct_enable(struct xe_guc_ct *ct)
{
struct xe_device *xe = ct_to_xe(ct);
@@ -350,6 +406,9 @@ int xe_guc_ct_enable(struct xe_guc_ct *ct)
wake_up_all(&ct->wq);
xe_gt_dbg(gt, "GuC CT communication channel enabled\n");
+ if (ct_needs_safe_mode(ct))
+ ct_enter_safe_mode(ct);
+
return 0;
err_out:
@@ -373,6 +432,7 @@ static void stop_g2h_handler(struct xe_guc_ct *ct)
void xe_guc_ct_disable(struct xe_guc_ct *ct)
{
xe_guc_ct_set_state(ct, XE_GUC_CT_STATE_DISABLED);
+ ct_exit_safe_mode(ct);
stop_g2h_handler(ct);
}
@@ -528,7 +588,7 @@ static int h2g_write(struct xe_guc_ct *ct, const u32 *action, u32 len,
/* Update descriptor */
desc_write(xe, h2g, tail, h2g->info.tail);
- trace_xe_guc_ctb_h2g(gt->info.id, *(action - 1), full_len,
+ trace_xe_guc_ctb_h2g(xe, gt->info.id, *(action - 1), full_len,
desc_read(xe, h2g, head), h2g->info.tail);
return 0;
@@ -641,6 +701,7 @@ static int guc_ct_send_locked(struct xe_guc_ct *ct, const u32 *action, u32 len,
u32 g2h_len, u32 num_g2h,
struct g2h_fence *g2h_fence)
{
+ struct xe_device *xe = ct_to_xe(ct);
struct xe_gt *gt = ct_to_gt(ct);
struct drm_printer p = xe_gt_info_printer(gt);
unsigned int sleep_period_ms = 1;
@@ -668,7 +729,7 @@ try_again:
if (sleep_period_ms == 1024)
goto broken;
- trace_xe_guc_ct_h2g_flow_control(h2g->info.head, h2g->info.tail,
+ trace_xe_guc_ct_h2g_flow_control(xe, h2g->info.head, h2g->info.tail,
h2g->info.size,
h2g->info.space,
len + GUC_CTB_HDR_LEN);
@@ -680,7 +741,7 @@ try_again:
struct xe_device *xe = ct_to_xe(ct);
struct guc_ctb *g2h = &ct->ctbs.g2h;
- trace_xe_guc_ct_g2h_flow_control(g2h->info.head,
+ trace_xe_guc_ct_g2h_flow_control(xe, g2h->info.head,
desc_read(xe, g2h, tail),
g2h->info.size,
g2h->info.space,
@@ -833,12 +894,12 @@ retry_same_fence:
}
if (g2h_fence.retry) {
- xe_gt_warn(gt, "H2G retry, action 0x%04x, reason %u",
- action[0], g2h_fence.reason);
+ xe_gt_dbg(gt, "H2G action %#x retrying: reason %#x\n",
+ action[0], g2h_fence.reason);
goto retry;
}
if (g2h_fence.fail) {
- xe_gt_err(gt, "H2G send failed, action 0x%04x, error %d, hint %u",
+ xe_gt_err(gt, "H2G request %#x failed: error %#x hint %#x\n",
action[0], g2h_fence.error, g2h_fence.hint);
ret = -EIO;
}
@@ -1170,8 +1231,8 @@ static int g2h_read(struct xe_guc_ct *ct, u32 *msg, bool fast_path)
g2h->info.head = (head + avail) % g2h->info.size;
desc_write(xe, g2h, head, g2h->info.head);
- trace_xe_guc_ctb_g2h(ct_to_gt(ct)->info.id, action, len,
- g2h->info.head, tail);
+ trace_xe_guc_ctb_g2h(xe, ct_to_gt(ct)->info.id,
+ action, len, g2h->info.head, tail);
return len;
}
@@ -1260,9 +1321,8 @@ static int dequeue_one_g2h(struct xe_guc_ct *ct)
return 1;
}
-static void g2h_worker_func(struct work_struct *w)
+static void receive_g2h(struct xe_guc_ct *ct)
{
- struct xe_guc_ct *ct = container_of(w, struct xe_guc_ct, g2h_worker);
struct xe_gt *gt = ct_to_gt(ct);
bool ongoing;
int ret;
@@ -1311,6 +1371,13 @@ static void g2h_worker_func(struct work_struct *w)
xe_pm_runtime_put(ct_to_xe(ct));
}
+static void g2h_worker_func(struct work_struct *w)
+{
+ struct xe_guc_ct *ct = container_of(w, struct xe_guc_ct, g2h_worker);
+
+ receive_g2h(ct);
+}
+
static void guc_ctb_snapshot_capture(struct xe_device *xe, struct guc_ctb *ctb,
struct guc_ctb_snapshot *snapshot,
bool atomic)
diff --git a/drivers/gpu/drm/xe/xe_guc_ct.h b/drivers/gpu/drm/xe/xe_guc_ct.h
index 105bb8e99a8d..190202fce2d0 100644
--- a/drivers/gpu/drm/xe/xe_guc_ct.h
+++ b/drivers/gpu/drm/xe/xe_guc_ct.h
@@ -64,4 +64,6 @@ xe_guc_ct_send_block_no_fail(struct xe_guc_ct *ct, const u32 *action, u32 len)
return xe_guc_ct_send_recv_no_fail(ct, action, len, NULL);
}
+long xe_guc_ct_queue_proc_time_jiffies(struct xe_guc_ct *ct);
+
#endif
diff --git a/drivers/gpu/drm/xe/xe_guc_ct_types.h b/drivers/gpu/drm/xe/xe_guc_ct_types.h
index fede4c6e93cb..761cb9031298 100644
--- a/drivers/gpu/drm/xe/xe_guc_ct_types.h
+++ b/drivers/gpu/drm/xe/xe_guc_ct_types.h
@@ -110,6 +110,8 @@ struct xe_guc_ct {
u32 g2h_outstanding;
/** @g2h_worker: worker to process G2H messages */
struct work_struct g2h_worker;
+ /** @safe_mode_worker: worker to check G2H messages with IRQ disabled */
+ struct delayed_work safe_mode_worker;
/** @state: CT state */
enum xe_guc_ct_state state;
/** @fence_seqno: G2H fence seqno - 16 bits used by CT */
diff --git a/drivers/gpu/drm/xe/xe_guc_pc.c b/drivers/gpu/drm/xe/xe_guc_pc.c
index 508f0d39b4ad..32e93a8127d4 100644
--- a/drivers/gpu/drm/xe/xe_guc_pc.c
+++ b/drivers/gpu/drm/xe/xe_guc_pc.c
@@ -8,8 +8,8 @@
#include <linux/delay.h>
#include <drm/drm_managed.h>
+#include <generated/xe_wa_oob.h>
-#include "abi/guc_actions_abi.h"
#include "abi/guc_actions_slpc_abi.h"
#include "regs/xe_gt_regs.h"
#include "regs/xe_regs.h"
@@ -18,12 +18,16 @@
#include "xe_force_wake.h"
#include "xe_gt.h"
#include "xe_gt_idle.h"
-#include "xe_gt_sysfs.h"
+#include "xe_gt_printk.h"
#include "xe_gt_types.h"
+#include "xe_guc.h"
#include "xe_guc_ct.h"
#include "xe_map.h"
#include "xe_mmio.h"
#include "xe_pcode.h"
+#include "xe_pm.h"
+#include "xe_sriov.h"
+#include "xe_wa.h"
#define MCHBAR_MIRROR_BASE_SNB 0x140000
@@ -41,6 +45,9 @@
#define GT_FREQUENCY_MULTIPLIER 50
#define GT_FREQUENCY_SCALER 3
+#define LNL_MERT_FREQ_CAP 800
+#define BMG_MERT_FREQ_CAP 2133
+
/**
* DOC: GuC Power Conservation (PC)
*
@@ -67,29 +74,27 @@
*
*/
-static struct xe_guc *
-pc_to_guc(struct xe_guc_pc *pc)
+static struct xe_guc *pc_to_guc(struct xe_guc_pc *pc)
{
return container_of(pc, struct xe_guc, pc);
}
-static struct xe_device *
-pc_to_xe(struct xe_guc_pc *pc)
+static struct xe_guc_ct *pc_to_ct(struct xe_guc_pc *pc)
{
- struct xe_guc *guc = pc_to_guc(pc);
- struct xe_gt *gt = container_of(guc, struct xe_gt, uc.guc);
+ return &pc_to_guc(pc)->ct;
+}
- return gt_to_xe(gt);
+static struct xe_gt *pc_to_gt(struct xe_guc_pc *pc)
+{
+ return guc_to_gt(pc_to_guc(pc));
}
-static struct xe_gt *
-pc_to_gt(struct xe_guc_pc *pc)
+static struct xe_device *pc_to_xe(struct xe_guc_pc *pc)
{
- return container_of(pc, struct xe_gt, uc.guc.pc);
+ return guc_to_xe(pc_to_guc(pc));
}
-static struct iosys_map *
-pc_to_maps(struct xe_guc_pc *pc)
+static struct iosys_map *pc_to_maps(struct xe_guc_pc *pc)
{
return &pc->bo->vmap;
}
@@ -130,32 +135,33 @@ static int wait_for_pc_state(struct xe_guc_pc *pc,
static int pc_action_reset(struct xe_guc_pc *pc)
{
- struct xe_guc_ct *ct = &pc_to_guc(pc)->ct;
- int ret;
+ struct xe_guc_ct *ct = pc_to_ct(pc);
u32 action[] = {
GUC_ACTION_HOST2GUC_PC_SLPC_REQUEST,
SLPC_EVENT(SLPC_EVENT_RESET, 2),
xe_bo_ggtt_addr(pc->bo),
0,
};
+ int ret;
ret = xe_guc_ct_send(ct, action, ARRAY_SIZE(action), 0, 0);
if (ret)
- drm_err(&pc_to_xe(pc)->drm, "GuC PC reset: %pe", ERR_PTR(ret));
+ xe_gt_err(pc_to_gt(pc), "GuC PC reset failed: %pe\n",
+ ERR_PTR(ret));
return ret;
}
static int pc_action_query_task_state(struct xe_guc_pc *pc)
{
- struct xe_guc_ct *ct = &pc_to_guc(pc)->ct;
- int ret;
+ struct xe_guc_ct *ct = pc_to_ct(pc);
u32 action[] = {
GUC_ACTION_HOST2GUC_PC_SLPC_REQUEST,
SLPC_EVENT(SLPC_EVENT_QUERY_TASK_STATE, 2),
xe_bo_ggtt_addr(pc->bo),
0,
};
+ int ret;
if (wait_for_pc_state(pc, SLPC_GLOBAL_STATE_RUNNING))
return -EAGAIN;
@@ -163,47 +169,68 @@ static int pc_action_query_task_state(struct xe_guc_pc *pc)
/* Blocking here to ensure the results are ready before reading them */
ret = xe_guc_ct_send_block(ct, action, ARRAY_SIZE(action));
if (ret)
- drm_err(&pc_to_xe(pc)->drm,
- "GuC PC query task state failed: %pe", ERR_PTR(ret));
+ xe_gt_err(pc_to_gt(pc), "GuC PC query task state failed: %pe\n",
+ ERR_PTR(ret));
return ret;
}
static int pc_action_set_param(struct xe_guc_pc *pc, u8 id, u32 value)
{
- struct xe_guc_ct *ct = &pc_to_guc(pc)->ct;
- int ret;
+ struct xe_guc_ct *ct = pc_to_ct(pc);
u32 action[] = {
GUC_ACTION_HOST2GUC_PC_SLPC_REQUEST,
SLPC_EVENT(SLPC_EVENT_PARAMETER_SET, 2),
id,
value,
};
+ int ret;
if (wait_for_pc_state(pc, SLPC_GLOBAL_STATE_RUNNING))
return -EAGAIN;
ret = xe_guc_ct_send(ct, action, ARRAY_SIZE(action), 0, 0);
if (ret)
- drm_err(&pc_to_xe(pc)->drm, "GuC PC set param failed: %pe",
- ERR_PTR(ret));
+ xe_gt_err(pc_to_gt(pc), "GuC PC set param[%u]=%u failed: %pe\n",
+ id, value, ERR_PTR(ret));
return ret;
}
-static int pc_action_setup_gucrc(struct xe_guc_pc *pc, u32 mode)
+static int pc_action_unset_param(struct xe_guc_pc *pc, u8 id)
{
+ u32 action[] = {
+ GUC_ACTION_HOST2GUC_PC_SLPC_REQUEST,
+ SLPC_EVENT(SLPC_EVENT_PARAMETER_UNSET, 1),
+ id,
+ };
struct xe_guc_ct *ct = &pc_to_guc(pc)->ct;
+ int ret;
+
+ if (wait_for_pc_state(pc, SLPC_GLOBAL_STATE_RUNNING))
+ return -EAGAIN;
+
+ ret = xe_guc_ct_send(ct, action, ARRAY_SIZE(action), 0, 0);
+ if (ret)
+ xe_gt_err(pc_to_gt(pc), "GuC PC unset param failed: %pe",
+ ERR_PTR(ret));
+
+ return ret;
+}
+
+static int pc_action_setup_gucrc(struct xe_guc_pc *pc, u32 mode)
+{
+ struct xe_guc_ct *ct = pc_to_ct(pc);
u32 action[] = {
- XE_GUC_ACTION_SETUP_PC_GUCRC,
+ GUC_ACTION_HOST2GUC_SETUP_PC_GUCRC,
mode,
};
int ret;
ret = xe_guc_ct_send(ct, action, ARRAY_SIZE(action), 0, 0);
if (ret)
- drm_err(&pc_to_xe(pc)->drm, "GuC RC enable failed: %pe",
- ERR_PTR(ret));
+ xe_gt_err(pc_to_gt(pc), "GuC RC enable mode=%u failed: %pe\n",
+ mode, ERR_PTR(ret));
return ret;
}
@@ -674,18 +701,43 @@ static void pc_init_fused_rp_values(struct xe_guc_pc *pc)
tgl_init_fused_rp_values(pc);
}
+static u32 pc_max_freq_cap(struct xe_guc_pc *pc)
+{
+ struct xe_gt *gt = pc_to_gt(pc);
+
+ if (XE_WA(gt, 22019338487)) {
+ if (xe_gt_is_media_type(gt))
+ return min(LNL_MERT_FREQ_CAP, pc->rp0_freq);
+ else
+ return min(BMG_MERT_FREQ_CAP, pc->rp0_freq);
+ } else {
+ return pc->rp0_freq;
+ }
+}
+
/**
- * xe_guc_pc_init_early - Initialize RPx values and request a higher GT
+ * xe_guc_pc_raise_unslice - Initialize RPx values and request a higher GT
* frequency to allow faster GuC load times
* @pc: Xe_GuC_PC instance
*/
+void xe_guc_pc_raise_unslice(struct xe_guc_pc *pc)
+{
+ struct xe_gt *gt = pc_to_gt(pc);
+
+ xe_force_wake_assert_held(gt_to_fw(gt), XE_FW_GT);
+ pc_set_cur_freq(pc, pc_max_freq_cap(pc));
+}
+
+/**
+ * xe_guc_pc_init_early - Initialize RPx values
+ * @pc: Xe_GuC_PC instance
+ */
void xe_guc_pc_init_early(struct xe_guc_pc *pc)
{
struct xe_gt *gt = pc_to_gt(pc);
xe_force_wake_assert_held(gt_to_fw(gt), XE_FW_GT);
pc_init_fused_rp_values(pc);
- pc_set_cur_freq(pc, pc->rp0_freq);
}
static int pc_adjust_freq_bounds(struct xe_guc_pc *pc)
@@ -741,6 +793,56 @@ static int pc_adjust_requested_freq(struct xe_guc_pc *pc)
return ret;
}
+static int pc_set_mert_freq_cap(struct xe_guc_pc *pc)
+{
+ int ret = 0;
+
+ if (XE_WA(pc_to_gt(pc), 22019338487)) {
+ /*
+ * Get updated min/max and stash them.
+ */
+ ret = xe_guc_pc_get_min_freq(pc, &pc->stashed_min_freq);
+ if (!ret)
+ ret = xe_guc_pc_get_max_freq(pc, &pc->stashed_max_freq);
+ if (ret)
+ return ret;
+
+ /*
+ * Ensure min and max are bound by MERT_FREQ_CAP until driver loads.
+ */
+ mutex_lock(&pc->freq_lock);
+ ret = pc_set_min_freq(pc, min(pc->rpe_freq, pc_max_freq_cap(pc)));
+ if (!ret)
+ ret = pc_set_max_freq(pc, min(pc->rp0_freq, pc_max_freq_cap(pc)));
+ mutex_unlock(&pc->freq_lock);
+ }
+
+ return ret;
+}
+
+/**
+ * xe_guc_pc_restore_stashed_freq - Set min/max back to stashed values
+ * @pc: The GuC PC
+ *
+ * Returns: 0 on success,
+ * error code on failure
+ */
+int xe_guc_pc_restore_stashed_freq(struct xe_guc_pc *pc)
+{
+ int ret = 0;
+
+ if (IS_SRIOV_VF(pc_to_xe(pc)) || pc_to_xe(pc)->info.skip_guc_pc)
+ return 0;
+
+ mutex_lock(&pc->freq_lock);
+ ret = pc_set_max_freq(pc, pc->stashed_max_freq);
+ if (!ret)
+ ret = pc_set_min_freq(pc, pc->stashed_min_freq);
+ mutex_unlock(&pc->freq_lock);
+
+ return ret;
+}
+
/**
* xe_guc_pc_gucrc_disable - Disable GuC RC
* @pc: Xe_GuC_PC instance
@@ -758,7 +860,7 @@ int xe_guc_pc_gucrc_disable(struct xe_guc_pc *pc)
if (xe->info.skip_guc_pc)
return 0;
- ret = pc_action_setup_gucrc(pc, XE_GUCRC_HOST_CONTROL);
+ ret = pc_action_setup_gucrc(pc, GUCRC_HOST_CONTROL);
if (ret)
return ret;
@@ -773,6 +875,41 @@ int xe_guc_pc_gucrc_disable(struct xe_guc_pc *pc)
return 0;
}
+/**
+ * xe_guc_pc_override_gucrc_mode - override GUCRC mode
+ * @pc: Xe_GuC_PC instance
+ * @mode: new value of the mode.
+ *
+ * Return: 0 on success, negative error code on error
+ */
+int xe_guc_pc_override_gucrc_mode(struct xe_guc_pc *pc, enum slpc_gucrc_mode mode)
+{
+ int ret;
+
+ xe_pm_runtime_get(pc_to_xe(pc));
+ ret = pc_action_set_param(pc, SLPC_PARAM_PWRGATE_RC_MODE, mode);
+ xe_pm_runtime_put(pc_to_xe(pc));
+
+ return ret;
+}
+
+/**
+ * xe_guc_pc_unset_gucrc_mode - unset GUCRC mode override
+ * @pc: Xe_GuC_PC instance
+ *
+ * Return: 0 on success, negative error code on error
+ */
+int xe_guc_pc_unset_gucrc_mode(struct xe_guc_pc *pc)
+{
+ int ret;
+
+ xe_pm_runtime_get(pc_to_xe(pc));
+ ret = pc_action_unset_param(pc, SLPC_PARAM_PWRGATE_RC_MODE);
+ xe_pm_runtime_put(pc_to_xe(pc));
+
+ return ret;
+}
+
static void pc_init_pcode_freq(struct xe_guc_pc *pc)
{
u32 min = DIV_ROUND_CLOSEST(pc->rpn_freq, GT_FREQUENCY_MULTIPLIER);
@@ -846,7 +983,7 @@ int xe_guc_pc_start(struct xe_guc_pc *pc)
goto out;
if (wait_for_pc_state(pc, SLPC_GLOBAL_STATE_RUNNING)) {
- drm_err(&pc_to_xe(pc)->drm, "GuC PC Start failed\n");
+ xe_gt_err(gt, "GuC PC Start failed\n");
ret = -EIO;
goto out;
}
@@ -855,13 +992,17 @@ int xe_guc_pc_start(struct xe_guc_pc *pc)
if (ret)
goto out;
+ ret = pc_set_mert_freq_cap(pc);
+ if (ret)
+ goto out;
+
if (xe->info.platform == XE_PVC) {
xe_guc_pc_gucrc_disable(pc);
ret = 0;
goto out;
}
- ret = pc_action_setup_gucrc(pc, XE_GUCRC_FIRMWARE_CONTROL);
+ ret = pc_action_setup_gucrc(pc, GUCRC_FIRMWARE_CONTROL);
out:
XE_WARN_ON(xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL));
@@ -903,6 +1044,10 @@ static void xe_guc_pc_fini_hw(void *arg)
XE_WARN_ON(xe_force_wake_get(gt_to_fw(pc_to_gt(pc)), XE_FORCEWAKE_ALL));
XE_WARN_ON(xe_guc_pc_gucrc_disable(pc));
XE_WARN_ON(xe_guc_pc_stop(pc));
+
+ /* Bind requested freq to mert_freq_cap before unload */
+ pc_set_cur_freq(pc, min(pc_max_freq_cap(pc), pc->rpe_freq));
+
xe_force_wake_put(gt_to_fw(pc_to_gt(pc)), XE_FORCEWAKE_ALL);
}
diff --git a/drivers/gpu/drm/xe/xe_guc_pc.h b/drivers/gpu/drm/xe/xe_guc_pc.h
index 532cac985a6d..efda432fadfc 100644
--- a/drivers/gpu/drm/xe/xe_guc_pc.h
+++ b/drivers/gpu/drm/xe/xe_guc_pc.h
@@ -9,11 +9,14 @@
#include <linux/types.h>
struct xe_guc_pc;
+enum slpc_gucrc_mode;
int xe_guc_pc_init(struct xe_guc_pc *pc);
int xe_guc_pc_start(struct xe_guc_pc *pc);
int xe_guc_pc_stop(struct xe_guc_pc *pc);
int xe_guc_pc_gucrc_disable(struct xe_guc_pc *pc);
+int xe_guc_pc_override_gucrc_mode(struct xe_guc_pc *pc, enum slpc_gucrc_mode mode);
+int xe_guc_pc_unset_gucrc_mode(struct xe_guc_pc *pc);
u32 xe_guc_pc_get_act_freq(struct xe_guc_pc *pc);
int xe_guc_pc_get_cur_freq(struct xe_guc_pc *pc, u32 *freq);
@@ -29,5 +32,7 @@ enum xe_gt_idle_state xe_guc_pc_c_status(struct xe_guc_pc *pc);
u64 xe_guc_pc_rc6_residency(struct xe_guc_pc *pc);
u64 xe_guc_pc_mc6_residency(struct xe_guc_pc *pc);
void xe_guc_pc_init_early(struct xe_guc_pc *pc);
+int xe_guc_pc_restore_stashed_freq(struct xe_guc_pc *pc);
+void xe_guc_pc_raise_unslice(struct xe_guc_pc *pc);
#endif /* _XE_GUC_PC_H_ */
diff --git a/drivers/gpu/drm/xe/xe_guc_pc_types.h b/drivers/gpu/drm/xe/xe_guc_pc_types.h
index 2afd0dbc3542..13810be015db 100644
--- a/drivers/gpu/drm/xe/xe_guc_pc_types.h
+++ b/drivers/gpu/drm/xe/xe_guc_pc_types.h
@@ -25,6 +25,10 @@ struct xe_guc_pc {
u32 user_requested_min;
/** @user_requested_max: Stash the maximum requested freq by user */
u32 user_requested_max;
+ /** @stashed_min_freq: Stash the current minimum freq */
+ u32 stashed_min_freq;
+ /** @stashed_max_freq: Stash the current maximum freq */
+ u32 stashed_max_freq;
/** @freq_lock: Let's protect the frequencies */
struct mutex freq_lock;
/** @freq_ready: Only handle freq changes, if they are really ready */
diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c
index 47aab04cf34f..8d7e7f4bbff7 100644
--- a/drivers/gpu/drm/xe/xe_guc_submit.c
+++ b/drivers/gpu/drm/xe/xe_guc_submit.c
@@ -10,6 +10,7 @@
#include <linux/circ_buf.h>
#include <linux/delay.h>
#include <linux/dma-fence-array.h>
+#include <linux/math64.h>
#include <drm/drm_managed.h>
@@ -23,6 +24,7 @@
#include "xe_force_wake.h"
#include "xe_gpu_scheduler.h"
#include "xe_gt.h"
+#include "xe_gt_clock.h"
#include "xe_gt_printk.h"
#include "xe_guc.h"
#include "xe_guc_ct.h"
@@ -61,6 +63,9 @@ exec_queue_to_guc(struct xe_exec_queue *q)
#define EXEC_QUEUE_STATE_RESET (1 << 6)
#define EXEC_QUEUE_STATE_KILLED (1 << 7)
#define EXEC_QUEUE_STATE_WEDGED (1 << 8)
+#define EXEC_QUEUE_STATE_BANNED (1 << 9)
+#define EXEC_QUEUE_STATE_CHECK_TIMEOUT (1 << 10)
+#define EXEC_QUEUE_STATE_EXTRA_REF (1 << 11)
static bool exec_queue_registered(struct xe_exec_queue *q)
{
@@ -134,12 +139,12 @@ static void set_exec_queue_destroyed(struct xe_exec_queue *q)
static bool exec_queue_banned(struct xe_exec_queue *q)
{
- return (q->flags & EXEC_QUEUE_FLAG_BANNED);
+ return atomic_read(&q->guc->state) & EXEC_QUEUE_STATE_BANNED;
}
static void set_exec_queue_banned(struct xe_exec_queue *q)
{
- q->flags |= EXEC_QUEUE_FLAG_BANNED;
+ atomic_or(EXEC_QUEUE_STATE_BANNED, &q->guc->state);
}
static bool exec_queue_suspended(struct xe_exec_queue *q)
@@ -187,10 +192,36 @@ static void set_exec_queue_wedged(struct xe_exec_queue *q)
atomic_or(EXEC_QUEUE_STATE_WEDGED, &q->guc->state);
}
+static bool exec_queue_check_timeout(struct xe_exec_queue *q)
+{
+ return atomic_read(&q->guc->state) & EXEC_QUEUE_STATE_CHECK_TIMEOUT;
+}
+
+static void set_exec_queue_check_timeout(struct xe_exec_queue *q)
+{
+ atomic_or(EXEC_QUEUE_STATE_CHECK_TIMEOUT, &q->guc->state);
+}
+
+static void clear_exec_queue_check_timeout(struct xe_exec_queue *q)
+{
+ atomic_and(~EXEC_QUEUE_STATE_CHECK_TIMEOUT, &q->guc->state);
+}
+
+static bool exec_queue_extra_ref(struct xe_exec_queue *q)
+{
+ return atomic_read(&q->guc->state) & EXEC_QUEUE_STATE_EXTRA_REF;
+}
+
+static void set_exec_queue_extra_ref(struct xe_exec_queue *q)
+{
+ atomic_or(EXEC_QUEUE_STATE_EXTRA_REF, &q->guc->state);
+}
+
static bool exec_queue_killed_or_banned_or_wedged(struct xe_exec_queue *q)
{
- return exec_queue_banned(q) || (atomic_read(&q->guc->state) &
- (EXEC_QUEUE_STATE_WEDGED | EXEC_QUEUE_STATE_KILLED));
+ return (atomic_read(&q->guc->state) &
+ (EXEC_QUEUE_STATE_WEDGED | EXEC_QUEUE_STATE_KILLED |
+ EXEC_QUEUE_STATE_BANNED));
}
#ifdef CONFIG_PROVE_LOCKING
@@ -830,29 +861,27 @@ static void xe_guc_exec_queue_trigger_cleanup(struct xe_exec_queue *q)
xe_sched_tdr_queue_imm(&q->guc->sched);
}
-static bool guc_submit_hint_wedged(struct xe_guc *guc)
+/**
+ * xe_guc_submit_wedge() - Wedge GuC submission
+ * @guc: the GuC object
+ *
+ * Save exec queue's registered with GuC state by taking a ref to each queue.
+ * Register a DRMM handler to drop refs upon driver unload.
+ */
+void xe_guc_submit_wedge(struct xe_guc *guc)
{
struct xe_device *xe = guc_to_xe(guc);
struct xe_exec_queue *q;
unsigned long index;
int err;
- if (xe->wedged.mode != 2)
- return false;
-
- if (xe_device_wedged(xe))
- return true;
-
- xe_device_declare_wedged(xe);
-
- xe_guc_submit_reset_prepare(guc);
- xe_guc_ct_stop(&guc->ct);
+ xe_gt_assert(guc_to_gt(guc), guc_to_xe(guc)->wedged.mode);
err = drmm_add_action_or_reset(&guc_to_xe(guc)->drm,
guc_submit_wedged_fini, guc);
if (err) {
drm_err(&xe->drm, "Failed to register xe_guc_submit clean-up on wedged.mode=2. Although device is wedged.\n");
- return true; /* Device is wedged anyway */
+ return;
}
mutex_lock(&guc->submission_state.lock);
@@ -860,6 +889,19 @@ static bool guc_submit_hint_wedged(struct xe_guc *guc)
if (xe_exec_queue_get_unless_zero(q))
set_exec_queue_wedged(q);
mutex_unlock(&guc->submission_state.lock);
+}
+
+static bool guc_submit_hint_wedged(struct xe_guc *guc)
+{
+ struct xe_device *xe = guc_to_xe(guc);
+
+ if (xe->wedged.mode != 2)
+ return false;
+
+ if (xe_device_wedged(xe))
+ return true;
+
+ xe_device_declare_wedged(xe);
return true;
}
@@ -918,6 +960,109 @@ static void xe_guc_exec_queue_lr_cleanup(struct work_struct *w)
xe_sched_submission_start(sched);
}
+#define ADJUST_FIVE_PERCENT(__t) mul_u64_u32_div(__t, 105, 100)
+
+static bool check_timeout(struct xe_exec_queue *q, struct xe_sched_job *job)
+{
+ struct xe_gt *gt = guc_to_gt(exec_queue_to_guc(q));
+ u32 ctx_timestamp = xe_lrc_ctx_timestamp(q->lrc[0]);
+ u32 ctx_job_timestamp = xe_lrc_ctx_job_timestamp(q->lrc[0]);
+ u32 timeout_ms = q->sched_props.job_timeout_ms;
+ u32 diff;
+ u64 running_time_ms;
+
+ /*
+ * Counter wraps at ~223s at the usual 19.2MHz, be paranoid catch
+ * possible overflows with a high timeout.
+ */
+ xe_gt_assert(gt, timeout_ms < 100 * MSEC_PER_SEC);
+
+ if (ctx_timestamp < ctx_job_timestamp)
+ diff = ctx_timestamp + U32_MAX - ctx_job_timestamp;
+ else
+ diff = ctx_timestamp - ctx_job_timestamp;
+
+ /*
+ * Ensure timeout is within 5% to account for an GuC scheduling latency
+ */
+ running_time_ms =
+ ADJUST_FIVE_PERCENT(xe_gt_clock_interval_to_ms(gt, diff));
+
+ xe_gt_dbg(gt,
+ "Check job timeout: seqno=%u, lrc_seqno=%u, guc_id=%d, running_time_ms=%llu, timeout_ms=%u, diff=0x%08x",
+ xe_sched_job_seqno(job), xe_sched_job_lrc_seqno(job),
+ q->guc->id, running_time_ms, timeout_ms, diff);
+
+ return running_time_ms >= timeout_ms;
+}
+
+static void enable_scheduling(struct xe_exec_queue *q)
+{
+ MAKE_SCHED_CONTEXT_ACTION(q, ENABLE);
+ struct xe_guc *guc = exec_queue_to_guc(q);
+ int ret;
+
+ xe_gt_assert(guc_to_gt(guc), !exec_queue_destroyed(q));
+ xe_gt_assert(guc_to_gt(guc), exec_queue_registered(q));
+ xe_gt_assert(guc_to_gt(guc), !exec_queue_pending_disable(q));
+ xe_gt_assert(guc_to_gt(guc), !exec_queue_pending_enable(q));
+
+ set_exec_queue_pending_enable(q);
+ set_exec_queue_enabled(q);
+ trace_xe_exec_queue_scheduling_enable(q);
+
+ xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action),
+ G2H_LEN_DW_SCHED_CONTEXT_MODE_SET, 1);
+
+ ret = wait_event_timeout(guc->ct.wq,
+ !exec_queue_pending_enable(q) ||
+ guc_read_stopped(guc), HZ * 5);
+ if (!ret || guc_read_stopped(guc)) {
+ xe_gt_warn(guc_to_gt(guc), "Schedule enable failed to respond");
+ set_exec_queue_banned(q);
+ xe_gt_reset_async(q->gt);
+ xe_sched_tdr_queue_imm(&q->guc->sched);
+ }
+}
+
+static void disable_scheduling(struct xe_exec_queue *q, bool immediate)
+{
+ MAKE_SCHED_CONTEXT_ACTION(q, DISABLE);
+ struct xe_guc *guc = exec_queue_to_guc(q);
+
+ xe_gt_assert(guc_to_gt(guc), !exec_queue_destroyed(q));
+ xe_gt_assert(guc_to_gt(guc), exec_queue_registered(q));
+ xe_gt_assert(guc_to_gt(guc), !exec_queue_pending_disable(q));
+
+ if (immediate)
+ set_min_preemption_timeout(guc, q);
+ clear_exec_queue_enabled(q);
+ set_exec_queue_pending_disable(q);
+ trace_xe_exec_queue_scheduling_disable(q);
+
+ xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action),
+ G2H_LEN_DW_SCHED_CONTEXT_MODE_SET, 1);
+}
+
+static void __deregister_exec_queue(struct xe_guc *guc, struct xe_exec_queue *q)
+{
+ u32 action[] = {
+ XE_GUC_ACTION_DEREGISTER_CONTEXT,
+ q->guc->id,
+ };
+
+ xe_gt_assert(guc_to_gt(guc), !exec_queue_destroyed(q));
+ xe_gt_assert(guc_to_gt(guc), exec_queue_registered(q));
+ xe_gt_assert(guc_to_gt(guc), !exec_queue_pending_enable(q));
+ xe_gt_assert(guc_to_gt(guc), !exec_queue_pending_disable(q));
+
+ set_exec_queue_destroyed(q);
+ trace_xe_exec_queue_deregister(q);
+
+ xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action),
+ G2H_LEN_DW_DEREGISTER_CONTEXT, 1);
+}
+
static enum drm_gpu_sched_stat
guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
{
@@ -925,10 +1070,10 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
struct xe_sched_job *tmp_job;
struct xe_exec_queue *q = job->q;
struct xe_gpu_scheduler *sched = &q->guc->sched;
- struct xe_device *xe = guc_to_xe(exec_queue_to_guc(q));
+ struct xe_guc *guc = exec_queue_to_guc(q);
int err = -ETIME;
int i = 0;
- bool wedged;
+ bool wedged, skip_timeout_check;
/*
* TDR has fired before free job worker. Common if exec queue
@@ -940,49 +1085,53 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
return DRM_GPU_SCHED_STAT_NOMINAL;
}
- drm_notice(&xe->drm, "Timedout job: seqno=%u, lrc_seqno=%u, guc_id=%d, flags=0x%lx",
- xe_sched_job_seqno(job), xe_sched_job_lrc_seqno(job),
- q->guc->id, q->flags);
- xe_gt_WARN(q->gt, q->flags & EXEC_QUEUE_FLAG_KERNEL,
- "Kernel-submitted job timed out\n");
- xe_gt_WARN(q->gt, q->flags & EXEC_QUEUE_FLAG_VM && !exec_queue_killed(q),
- "VM job timed out on non-killed execqueue\n");
-
- if (!exec_queue_killed(q))
- xe_devcoredump(job);
-
- trace_xe_sched_job_timedout(job);
-
- wedged = guc_submit_hint_wedged(exec_queue_to_guc(q));
-
/* Kill the run_job entry point */
xe_sched_submission_stop(sched);
+ /* Must check all state after stopping scheduler */
+ skip_timeout_check = exec_queue_reset(q) ||
+ exec_queue_killed_or_banned_or_wedged(q) ||
+ exec_queue_destroyed(q);
+
+ /* Job hasn't started, can't be timed out */
+ if (!skip_timeout_check && !xe_sched_job_started(job))
+ goto rearm;
+
/*
- * Kernel jobs should never fail, nor should VM jobs if they do
- * somethings has gone wrong and the GT needs a reset
+ * XXX: Sampling timeout doesn't work in wedged mode as we have to
+ * modify scheduling state to read timestamp. We could read the
+ * timestamp from a register to accumulate current running time but this
+ * doesn't work for SRIOV. For now assuming timeouts in wedged mode are
+ * genuine timeouts.
*/
- if (!wedged && (q->flags & EXEC_QUEUE_FLAG_KERNEL ||
- (q->flags & EXEC_QUEUE_FLAG_VM && !exec_queue_killed(q)))) {
- if (!xe_sched_invalidate_job(job, 2)) {
- xe_sched_add_pending_job(sched, job);
- xe_sched_submission_start(sched);
- xe_gt_reset_async(q->gt);
- goto out;
- }
- }
+ wedged = guc_submit_hint_wedged(exec_queue_to_guc(q));
- /* Engine state now stable, disable scheduling if needed */
+ /* Engine state now stable, disable scheduling to check timestamp */
if (!wedged && exec_queue_registered(q)) {
- struct xe_guc *guc = exec_queue_to_guc(q);
int ret;
if (exec_queue_reset(q))
err = -EIO;
- set_exec_queue_banned(q);
+
if (!exec_queue_destroyed(q)) {
- xe_exec_queue_get(q);
- disable_scheduling_deregister(guc, q);
+ /*
+ * Wait for any pending G2H to flush out before
+ * modifying state
+ */
+ ret = wait_event_timeout(guc->ct.wq,
+ !exec_queue_pending_enable(q) ||
+ guc_read_stopped(guc), HZ * 5);
+ if (!ret || guc_read_stopped(guc))
+ goto trigger_reset;
+
+ /*
+ * Flag communicates to G2H handler that schedule
+ * disable originated from a timeout check. The G2H then
+ * avoid triggering cleanup or deregistering the exec
+ * queue.
+ */
+ set_exec_queue_check_timeout(q);
+ disable_scheduling(q, skip_timeout_check);
}
/*
@@ -998,15 +1147,60 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
!exec_queue_pending_disable(q) ||
guc_read_stopped(guc), HZ * 5);
if (!ret || guc_read_stopped(guc)) {
- drm_warn(&xe->drm, "Schedule disable failed to respond");
- xe_sched_add_pending_job(sched, job);
- xe_sched_submission_start(sched);
+trigger_reset:
+ if (!ret)
+ xe_gt_warn(guc_to_gt(guc), "Schedule disable failed to respond");
+ set_exec_queue_extra_ref(q);
+ xe_exec_queue_get(q); /* GT reset owns this */
+ set_exec_queue_banned(q);
xe_gt_reset_async(q->gt);
xe_sched_tdr_queue_imm(sched);
- goto out;
+ goto rearm;
+ }
+ }
+
+ /*
+ * Check if job is actually timed out, if so restart job execution and TDR
+ */
+ if (!wedged && !skip_timeout_check && !check_timeout(q, job) &&
+ !exec_queue_reset(q) && exec_queue_registered(q)) {
+ clear_exec_queue_check_timeout(q);
+ goto sched_enable;
+ }
+
+ xe_gt_notice(guc_to_gt(guc), "Timedout job: seqno=%u, lrc_seqno=%u, guc_id=%d, flags=0x%lx",
+ xe_sched_job_seqno(job), xe_sched_job_lrc_seqno(job),
+ q->guc->id, q->flags);
+ trace_xe_sched_job_timedout(job);
+
+ if (!exec_queue_killed(q))
+ xe_devcoredump(job);
+
+ /*
+ * Kernel jobs should never fail, nor should VM jobs if they do
+ * somethings has gone wrong and the GT needs a reset
+ */
+ xe_gt_WARN(q->gt, q->flags & EXEC_QUEUE_FLAG_KERNEL,
+ "Kernel-submitted job timed out\n");
+ xe_gt_WARN(q->gt, q->flags & EXEC_QUEUE_FLAG_VM && !exec_queue_killed(q),
+ "VM job timed out on non-killed execqueue\n");
+ if (!wedged && (q->flags & EXEC_QUEUE_FLAG_KERNEL ||
+ (q->flags & EXEC_QUEUE_FLAG_VM && !exec_queue_killed(q)))) {
+ if (!xe_sched_invalidate_job(job, 2)) {
+ clear_exec_queue_check_timeout(q);
+ xe_gt_reset_async(q->gt);
+ goto rearm;
}
}
+ /* Finish cleaning up exec queue via deregister */
+ set_exec_queue_banned(q);
+ if (!wedged && exec_queue_registered(q) && !exec_queue_destroyed(q)) {
+ set_exec_queue_extra_ref(q);
+ xe_exec_queue_get(q);
+ __deregister_exec_queue(guc, q);
+ }
+
/* Stop fence signaling */
xe_hw_fence_irq_stop(q->fence_irq);
@@ -1028,7 +1222,19 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
/* Start fence signaling */
xe_hw_fence_irq_start(q->fence_irq);
-out:
+ return DRM_GPU_SCHED_STAT_NOMINAL;
+
+sched_enable:
+ enable_scheduling(q);
+rearm:
+ /*
+ * XXX: Ideally want to adjust timeout based on current exection time
+ * but there is not currently an easy way to do in DRM scheduler. With
+ * some thought, do this in a follow up.
+ */
+ xe_sched_add_pending_job(sched, job);
+ xe_sched_submission_start(sched);
+
return DRM_GPU_SCHED_STAT_NOMINAL;
}
@@ -1131,7 +1337,6 @@ static void __guc_exec_queue_process_msg_suspend(struct xe_sched_msg *msg)
guc_read_stopped(guc));
if (!guc_read_stopped(guc)) {
- MAKE_SCHED_CONTEXT_ACTION(q, DISABLE);
s64 since_resume_ms =
ktime_ms_delta(ktime_get(),
q->guc->resume_time);
@@ -1142,12 +1347,7 @@ static void __guc_exec_queue_process_msg_suspend(struct xe_sched_msg *msg)
msleep(wait_ms);
set_exec_queue_suspended(q);
- clear_exec_queue_enabled(q);
- set_exec_queue_pending_disable(q);
- trace_xe_exec_queue_scheduling_disable(q);
-
- xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action),
- G2H_LEN_DW_SCHED_CONTEXT_MODE_SET, 1);
+ disable_scheduling(q, false);
}
} else if (q->guc->suspend_pending) {
set_exec_queue_suspended(q);
@@ -1158,19 +1358,11 @@ static void __guc_exec_queue_process_msg_suspend(struct xe_sched_msg *msg)
static void __guc_exec_queue_process_msg_resume(struct xe_sched_msg *msg)
{
struct xe_exec_queue *q = msg->private_data;
- struct xe_guc *guc = exec_queue_to_guc(q);
if (guc_exec_queue_allowed_to_change_state(q)) {
- MAKE_SCHED_CONTEXT_ACTION(q, ENABLE);
-
q->guc->resume_time = RESUME_PENDING;
clear_exec_queue_suspended(q);
- set_exec_queue_pending_enable(q);
- set_exec_queue_enabled(q);
- trace_xe_exec_queue_scheduling_enable(q);
-
- xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action),
- G2H_LEN_DW_SCHED_CONTEXT_MODE_SET, 1);
+ enable_scheduling(q);
} else {
clear_exec_queue_suspended(q);
}
@@ -1432,8 +1624,7 @@ static void guc_exec_queue_stop(struct xe_guc *guc, struct xe_exec_queue *q)
/* Clean up lost G2H + reset engine state */
if (exec_queue_registered(q)) {
- if ((exec_queue_banned(q) && exec_queue_destroyed(q)) ||
- xe_exec_queue_is_lr(q))
+ if (exec_queue_extra_ref(q) || xe_exec_queue_is_lr(q))
xe_exec_queue_put(q);
else if (exec_queue_destroyed(q))
__guc_exec_queue_fini(guc, q);
@@ -1442,7 +1633,9 @@ static void guc_exec_queue_stop(struct xe_guc *guc, struct xe_exec_queue *q)
set_exec_queue_suspended(q);
suspend_fence_signal(q);
}
- atomic_and(EXEC_QUEUE_STATE_DESTROYED | EXEC_QUEUE_STATE_SUSPENDED,
+ atomic_and(EXEC_QUEUE_STATE_WEDGED | EXEC_QUEUE_STATE_BANNED |
+ EXEC_QUEUE_STATE_KILLED | EXEC_QUEUE_STATE_DESTROYED |
+ EXEC_QUEUE_STATE_SUSPENDED,
&q->guc->state);
q->guc->resume_time = 0;
trace_xe_exec_queue_stop(q);
@@ -1495,7 +1688,8 @@ int xe_guc_submit_reset_prepare(struct xe_guc *guc)
void xe_guc_submit_reset_wait(struct xe_guc *guc)
{
- wait_event(guc->ct.wq, !guc_read_stopped(guc));
+ wait_event(guc->ct.wq, xe_device_wedged(guc_to_xe(guc)) ||
+ !guc_read_stopped(guc));
}
void xe_guc_submit_stop(struct xe_guc *guc)
@@ -1585,30 +1779,44 @@ static void deregister_exec_queue(struct xe_guc *guc, struct xe_exec_queue *q)
q->guc->id,
};
+ xe_gt_assert(guc_to_gt(guc), exec_queue_destroyed(q));
+ xe_gt_assert(guc_to_gt(guc), exec_queue_registered(q));
+ xe_gt_assert(guc_to_gt(guc), !exec_queue_pending_disable(q));
+ xe_gt_assert(guc_to_gt(guc), !exec_queue_pending_enable(q));
+
trace_xe_exec_queue_deregister(q);
xe_guc_ct_send_g2h_handler(&guc->ct, action, ARRAY_SIZE(action));
}
-static void handle_sched_done(struct xe_guc *guc, struct xe_exec_queue *q)
+static void handle_sched_done(struct xe_guc *guc, struct xe_exec_queue *q,
+ u32 runnable_state)
{
trace_xe_exec_queue_scheduling_done(q);
- if (exec_queue_pending_enable(q)) {
+ if (runnable_state == 1) {
+ xe_gt_assert(guc_to_gt(guc), exec_queue_pending_enable(q));
+
q->guc->resume_time = ktime_get();
clear_exec_queue_pending_enable(q);
smp_wmb();
wake_up_all(&guc->ct.wq);
} else {
+ bool check_timeout = exec_queue_check_timeout(q);
+
+ xe_gt_assert(guc_to_gt(guc), runnable_state == 0);
+ xe_gt_assert(guc_to_gt(guc), exec_queue_pending_disable(q));
+
clear_exec_queue_pending_disable(q);
if (q->guc->suspend_pending) {
suspend_fence_signal(q);
} else {
- if (exec_queue_banned(q)) {
+ if (exec_queue_banned(q) || check_timeout) {
smp_wmb();
wake_up_all(&guc->ct.wq);
}
- deregister_exec_queue(guc, q);
+ if (!check_timeout)
+ deregister_exec_queue(guc, q);
}
}
}
@@ -1618,6 +1826,7 @@ int xe_guc_sched_done_handler(struct xe_guc *guc, u32 *msg, u32 len)
struct xe_device *xe = guc_to_xe(guc);
struct xe_exec_queue *q;
u32 guc_id = msg[0];
+ u32 runnable_state = msg[1];
if (unlikely(len < 2)) {
drm_err(&xe->drm, "Invalid length %u", len);
@@ -1630,12 +1839,14 @@ int xe_guc_sched_done_handler(struct xe_guc *guc, u32 *msg, u32 len)
if (unlikely(!exec_queue_pending_enable(q) &&
!exec_queue_pending_disable(q))) {
- drm_err(&xe->drm, "Unexpected engine state 0x%04x",
- atomic_read(&q->guc->state));
+ xe_gt_err(guc_to_gt(guc),
+ "SCHED_DONE: Unexpected engine state 0x%04x, guc_id=%d, runnable_state=%u",
+ atomic_read(&q->guc->state), q->guc->id,
+ runnable_state);
return -EPROTO;
}
- handle_sched_done(guc, q);
+ handle_sched_done(guc, q, runnable_state);
return 0;
}
@@ -1646,7 +1857,7 @@ static void handle_deregister_done(struct xe_guc *guc, struct xe_exec_queue *q)
clear_exec_queue_registered(q);
- if (exec_queue_banned(q) || xe_exec_queue_is_lr(q))
+ if (exec_queue_extra_ref(q) || xe_exec_queue_is_lr(q))
xe_exec_queue_put(q);
else
__guc_exec_queue_fini(guc, q);
@@ -1669,8 +1880,9 @@ int xe_guc_deregister_done_handler(struct xe_guc *guc, u32 *msg, u32 len)
if (!exec_queue_destroyed(q) || exec_queue_pending_disable(q) ||
exec_queue_pending_enable(q) || exec_queue_enabled(q)) {
- drm_err(&xe->drm, "Unexpected engine state 0x%04x",
- atomic_read(&q->guc->state));
+ xe_gt_err(guc_to_gt(guc),
+ "DEREGISTER_DONE: Unexpected engine state 0x%04x, guc_id=%d",
+ atomic_read(&q->guc->state), q->guc->id);
return -EPROTO;
}
@@ -1709,7 +1921,7 @@ int xe_guc_exec_queue_reset_handler(struct xe_guc *guc, u32 *msg, u32 len)
* guc_exec_queue_timedout_job.
*/
set_exec_queue_reset(q);
- if (!exec_queue_banned(q))
+ if (!exec_queue_banned(q) && !exec_queue_check_timeout(q))
xe_guc_exec_queue_trigger_cleanup(q);
return 0;
@@ -1739,7 +1951,7 @@ int xe_guc_exec_queue_memory_cat_error_handler(struct xe_guc *guc, u32 *msg,
/* Treat the same as engine reset */
set_exec_queue_reset(q);
- if (!exec_queue_banned(q))
+ if (!exec_queue_banned(q) && !exec_queue_check_timeout(q))
xe_guc_exec_queue_trigger_cleanup(q);
return 0;
diff --git a/drivers/gpu/drm/xe/xe_guc_submit.h b/drivers/gpu/drm/xe/xe_guc_submit.h
index 4ad5f4c1b084..bdf8c9f3d24a 100644
--- a/drivers/gpu/drm/xe/xe_guc_submit.h
+++ b/drivers/gpu/drm/xe/xe_guc_submit.h
@@ -18,6 +18,7 @@ int xe_guc_submit_reset_prepare(struct xe_guc *guc);
void xe_guc_submit_reset_wait(struct xe_guc *guc);
void xe_guc_submit_stop(struct xe_guc *guc);
int xe_guc_submit_start(struct xe_guc *guc);
+void xe_guc_submit_wedge(struct xe_guc *guc);
int xe_guc_sched_done_handler(struct xe_guc *guc, u32 *msg, u32 len);
int xe_guc_deregister_done_handler(struct xe_guc *guc, u32 *msg, u32 len);
diff --git a/drivers/gpu/drm/xe/xe_huc.c b/drivers/gpu/drm/xe/xe_huc.c
index b039ff49341b..bec4366e5513 100644
--- a/drivers/gpu/drm/xe/xe_huc.c
+++ b/drivers/gpu/drm/xe/xe_huc.c
@@ -18,9 +18,11 @@
#include "xe_force_wake.h"
#include "xe_gsc_submit.h"
#include "xe_gt.h"
+#include "xe_gt_printk.h"
#include "xe_guc.h"
#include "xe_map.h"
#include "xe_mmio.h"
+#include "xe_sriov.h"
#include "xe_uc_fw.h"
static struct xe_gt *
@@ -92,6 +94,9 @@ int xe_huc_init(struct xe_huc *huc)
if (!xe_uc_fw_is_enabled(&huc->fw))
return 0;
+ if (IS_SRIOV_VF(xe))
+ return 0;
+
if (huc->fw.has_gsc_headers) {
ret = huc_alloc_gsc_pkt(huc);
if (ret)
@@ -103,7 +108,7 @@ int xe_huc_init(struct xe_huc *huc)
return 0;
out:
- drm_err(&xe->drm, "HuC init failed with %d", ret);
+ xe_gt_err(gt, "HuC: initialization failed: %pe\n", ERR_PTR(ret));
return ret;
}
@@ -191,14 +196,14 @@ static int huc_auth_via_gsccs(struct xe_huc *huc)
} while (--retry && err == -EBUSY);
if (err) {
- drm_err(&xe->drm, "failed to submit GSC request to auth: %d\n", err);
+ xe_gt_err(gt, "HuC: failed to submit GSC request to auth: %pe\n", ERR_PTR(err));
return err;
}
err = xe_gsc_read_out_header(xe, &pkt->vmap, PXP43_HUC_AUTH_INOUT_SIZE,
sizeof(struct pxp43_huc_auth_out), &rd_offset);
if (err) {
- drm_err(&xe->drm, "HuC: invalid GSC reply for auth (err=%d)\n", err);
+ xe_gt_err(gt, "HuC: invalid GSC reply for auth: %pe\n", ERR_PTR(err));
return err;
}
@@ -209,7 +214,7 @@ static int huc_auth_via_gsccs(struct xe_huc *huc)
*/
out_status = huc_auth_msg_rd(xe, &pkt->vmap, rd_offset, header.status);
if (out_status != PXP_STATUS_SUCCESS && out_status != PXP_STATUS_OP_NOT_PERMITTED) {
- drm_err(&xe->drm, "auth failed with GSC error = 0x%x\n", out_status);
+ xe_gt_err(gt, "HuC: authentication failed with GSC error = %#x\n", out_status);
return -EIO;
}
@@ -238,7 +243,6 @@ bool xe_huc_is_authenticated(struct xe_huc *huc, enum xe_huc_auth_types type)
int xe_huc_auth(struct xe_huc *huc, enum xe_huc_auth_types type)
{
- struct xe_device *xe = huc_to_xe(huc);
struct xe_gt *gt = huc_to_gt(huc);
struct xe_guc *guc = huc_to_guc(huc);
int ret;
@@ -268,26 +272,26 @@ int xe_huc_auth(struct xe_huc *huc, enum xe_huc_auth_types type)
return -EINVAL;
}
if (ret) {
- drm_err(&xe->drm, "Failed to trigger HuC auth via %s: %d\n",
- huc_auth_modes[type].name, ret);
+ xe_gt_err(gt, "HuC: failed to trigger auth via %s: %pe\n",
+ huc_auth_modes[type].name, ERR_PTR(ret));
goto fail;
}
ret = xe_mmio_wait32(gt, huc_auth_modes[type].reg, huc_auth_modes[type].val,
huc_auth_modes[type].val, 100000, NULL, false);
if (ret) {
- drm_err(&xe->drm, "HuC: Firmware not verified %d\n", ret);
+ xe_gt_err(gt, "HuC: firmware not verified: %pe\n", ERR_PTR(ret));
goto fail;
}
xe_uc_fw_change_status(&huc->fw, XE_UC_FIRMWARE_RUNNING);
- drm_dbg(&xe->drm, "HuC authenticated via %s\n", huc_auth_modes[type].name);
+ xe_gt_dbg(gt, "HuC: authenticated via %s\n", huc_auth_modes[type].name);
return 0;
fail:
- drm_err(&xe->drm, "HuC: Auth via %s failed: %d\n",
- huc_auth_modes[type].name, ret);
+ xe_gt_err(gt, "HuC: authentication via %s failed: %pe\n",
+ huc_auth_modes[type].name, ERR_PTR(ret));
xe_uc_fw_change_status(&huc->fw, XE_UC_FIRMWARE_LOAD_FAIL);
return ret;
@@ -295,9 +299,7 @@ fail:
void xe_huc_sanitize(struct xe_huc *huc)
{
- if (!xe_uc_fw_is_loadable(&huc->fw))
- return;
- xe_uc_fw_change_status(&huc->fw, XE_UC_FIRMWARE_LOADABLE);
+ xe_uc_fw_sanitize(&huc->fw);
}
void xe_huc_print_info(struct xe_huc *huc, struct drm_printer *p)
diff --git a/drivers/gpu/drm/xe/xe_hw_engine.c b/drivers/gpu/drm/xe/xe_hw_engine.c
index 0a83506e1ad8..07ed9fd28f19 100644
--- a/drivers/gpu/drm/xe/xe_hw_engine.c
+++ b/drivers/gpu/drm/xe/xe_hw_engine.c
@@ -26,6 +26,7 @@
#include "xe_macros.h"
#include "xe_mmio.h"
#include "xe_reg_sr.h"
+#include "xe_reg_whitelist.h"
#include "xe_rtp.h"
#include "xe_sched_job.h"
#include "xe_sriov.h"
@@ -546,7 +547,8 @@ static int hw_engine_init(struct xe_gt *gt, struct xe_hw_engine *hwe,
if (hwe->class == XE_ENGINE_CLASS_OTHER)
hwe->irq_handler = xe_gsc_hwe_irq_handler;
- xe_hw_engine_enable_ring(hwe);
+ if (!IS_SRIOV_VF(xe))
+ xe_hw_engine_enable_ring(hwe);
}
/* We reserve the highest BCS instance for USM */
@@ -1128,3 +1130,8 @@ u64 xe_hw_engine_read_timestamp(struct xe_hw_engine *hwe)
{
return xe_mmio_read64_2x32(hwe->gt, RING_TIMESTAMP(hwe->mmio_base));
}
+
+enum xe_force_wake_domains xe_hw_engine_to_fw_domain(struct xe_hw_engine *hwe)
+{
+ return engine_infos[hwe->engine_id].domain;
+}
diff --git a/drivers/gpu/drm/xe/xe_hw_engine.h b/drivers/gpu/drm/xe/xe_hw_engine.h
index 7f2d27c0ba1a..900c8c991430 100644
--- a/drivers/gpu/drm/xe/xe_hw_engine.h
+++ b/drivers/gpu/drm/xe/xe_hw_engine.h
@@ -69,5 +69,6 @@ static inline bool xe_hw_engine_is_valid(struct xe_hw_engine *hwe)
const char *xe_hw_engine_class_to_str(enum xe_engine_class class);
u64 xe_hw_engine_read_timestamp(struct xe_hw_engine *hwe);
+enum xe_force_wake_domains xe_hw_engine_to_fw_domain(struct xe_hw_engine *hwe);
#endif
diff --git a/drivers/gpu/drm/xe/xe_hw_engine_types.h b/drivers/gpu/drm/xe/xe_hw_engine_types.h
index 580bbd7e83b2..70e6434f150d 100644
--- a/drivers/gpu/drm/xe/xe_hw_engine_types.h
+++ b/drivers/gpu/drm/xe/xe_hw_engine_types.h
@@ -148,6 +148,8 @@ struct xe_hw_engine {
enum xe_hw_engine_id engine_id;
/** @eclass: pointer to per hw engine class interface */
struct xe_hw_engine_class_intf *eclass;
+ /** @oa_unit: oa unit for this hw engine */
+ struct xe_oa_unit *oa_unit;
};
/**
diff --git a/drivers/gpu/drm/xe/xe_hw_fence.c b/drivers/gpu/drm/xe/xe_hw_fence.c
index 35c0063a831a..45a9789cf501 100644
--- a/drivers/gpu/drm/xe/xe_hw_fence.c
+++ b/drivers/gpu/drm/xe/xe_hw_fence.c
@@ -187,7 +187,6 @@ static void xe_hw_fence_release(struct dma_fence *dma_fence)
{
struct xe_hw_fence *fence = to_xe_hw_fence(dma_fence);
- trace_xe_hw_fence_free(fence);
XE_WARN_ON(!list_empty(&fence->irq_link));
call_rcu(&dma_fence->rcu, fence_free);
}
diff --git a/drivers/gpu/drm/xe/xe_hwmon.c b/drivers/gpu/drm/xe/xe_hwmon.c
index 222c651ee1f8..0c8ce09e5025 100644
--- a/drivers/gpu/drm/xe/xe_hwmon.c
+++ b/drivers/gpu/drm/xe/xe_hwmon.c
@@ -137,34 +137,6 @@ static struct xe_reg xe_hwmon_get_reg(struct xe_hwmon *hwmon, enum xe_hwmon_reg
return XE_REG(0);
}
-static void xe_hwmon_process_reg(struct xe_hwmon *hwmon, enum xe_hwmon_reg hwmon_reg,
- enum xe_hwmon_reg_operation operation, u64 *value,
- u32 clr, u32 set, int channel)
-{
- struct xe_reg reg;
-
- reg = xe_hwmon_get_reg(hwmon, hwmon_reg, channel);
-
- if (!xe_reg_is_valid(reg))
- return;
-
- switch (operation) {
- case REG_READ32:
- *value = xe_mmio_read32(hwmon->gt, reg);
- break;
- case REG_RMW32:
- *value = xe_mmio_rmw32(hwmon->gt, reg, clr, set);
- break;
- case REG_READ64:
- *value = xe_mmio_read64_2x32(hwmon->gt, reg);
- break;
- default:
- drm_warn(&gt_to_xe(hwmon->gt)->drm, "Invalid xe hwmon reg operation: %d\n",
- operation);
- break;
- }
-}
-
#define PL1_DISABLE 0
/*
@@ -176,10 +148,25 @@ static void xe_hwmon_process_reg(struct xe_hwmon *hwmon, enum xe_hwmon_reg hwmon
static void xe_hwmon_power_max_read(struct xe_hwmon *hwmon, int channel, long *value)
{
u64 reg_val, min, max;
+ struct xe_device *xe = gt_to_xe(hwmon->gt);
+ struct xe_reg rapl_limit, pkg_power_sku;
+
+ rapl_limit = xe_hwmon_get_reg(hwmon, REG_PKG_RAPL_LIMIT, channel);
+ pkg_power_sku = xe_hwmon_get_reg(hwmon, REG_PKG_POWER_SKU, channel);
+
+ /*
+ * Valid check of REG_PKG_RAPL_LIMIT is already done in xe_hwmon_power_is_visible.
+ * So not checking it again here.
+ */
+ if (!xe_reg_is_valid(pkg_power_sku)) {
+ drm_warn(&xe->drm, "pkg_power_sku invalid\n");
+ *value = 0;
+ return;
+ }
mutex_lock(&hwmon->hwmon_lock);
- xe_hwmon_process_reg(hwmon, REG_PKG_RAPL_LIMIT, REG_READ32, &reg_val, 0, 0, channel);
+ reg_val = xe_mmio_read32(hwmon->gt, rapl_limit);
/* Check if PL1 limit is disabled */
if (!(reg_val & PKG_PWR_LIM_1_EN)) {
*value = PL1_DISABLE;
@@ -189,7 +176,7 @@ static void xe_hwmon_power_max_read(struct xe_hwmon *hwmon, int channel, long *v
reg_val = REG_FIELD_GET(PKG_PWR_LIM_1, reg_val);
*value = mul_u64_u32_shr(reg_val, SF_POWER, hwmon->scl_shift_power);
- xe_hwmon_process_reg(hwmon, REG_PKG_POWER_SKU, REG_READ64, &reg_val, 0, 0, channel);
+ reg_val = xe_mmio_read64_2x32(hwmon->gt, pkg_power_sku);
min = REG_FIELD_GET(PKG_MIN_PWR, reg_val);
min = mul_u64_u32_shr(min, SF_POWER, hwmon->scl_shift_power);
max = REG_FIELD_GET(PKG_MAX_PWR, reg_val);
@@ -205,16 +192,16 @@ static int xe_hwmon_power_max_write(struct xe_hwmon *hwmon, int channel, long va
{
int ret = 0;
u64 reg_val;
+ struct xe_reg rapl_limit;
+
+ rapl_limit = xe_hwmon_get_reg(hwmon, REG_PKG_RAPL_LIMIT, channel);
mutex_lock(&hwmon->hwmon_lock);
/* Disable PL1 limit and verify, as limit cannot be disabled on all platforms */
if (value == PL1_DISABLE) {
- xe_hwmon_process_reg(hwmon, REG_PKG_RAPL_LIMIT, REG_RMW32, &reg_val,
- PKG_PWR_LIM_1_EN, 0, channel);
- xe_hwmon_process_reg(hwmon, REG_PKG_RAPL_LIMIT, REG_READ32, &reg_val,
- PKG_PWR_LIM_1_EN, 0, channel);
-
+ reg_val = xe_mmio_rmw32(hwmon->gt, rapl_limit, PKG_PWR_LIM_1_EN, 0);
+ reg_val = xe_mmio_read32(hwmon->gt, rapl_limit);
if (reg_val & PKG_PWR_LIM_1_EN) {
ret = -EOPNOTSUPP;
goto unlock;
@@ -224,9 +211,8 @@ static int xe_hwmon_power_max_write(struct xe_hwmon *hwmon, int channel, long va
/* Computation in 64-bits to avoid overflow. Round to nearest. */
reg_val = DIV_ROUND_CLOSEST_ULL((u64)value << hwmon->scl_shift_power, SF_POWER);
reg_val = PKG_PWR_LIM_1_EN | REG_FIELD_PREP(PKG_PWR_LIM_1, reg_val);
+ reg_val = xe_mmio_rmw32(hwmon->gt, rapl_limit, PKG_PWR_LIM_1_EN | PKG_PWR_LIM_1, reg_val);
- xe_hwmon_process_reg(hwmon, REG_PKG_RAPL_LIMIT, REG_RMW32, &reg_val,
- PKG_PWR_LIM_1_EN | PKG_PWR_LIM_1, reg_val, channel);
unlock:
mutex_unlock(&hwmon->hwmon_lock);
return ret;
@@ -234,9 +220,15 @@ unlock:
static void xe_hwmon_power_rated_max_read(struct xe_hwmon *hwmon, int channel, long *value)
{
+ struct xe_reg reg = xe_hwmon_get_reg(hwmon, REG_PKG_POWER_SKU, channel);
u64 reg_val;
- xe_hwmon_process_reg(hwmon, REG_PKG_POWER_SKU, REG_READ32, &reg_val, 0, 0, channel);
+ /*
+ * This sysfs file won't be visible if REG_PKG_POWER_SKU is invalid, so valid check
+ * for this register can be skipped.
+ * See xe_hwmon_power_is_visible.
+ */
+ reg_val = xe_mmio_read32(hwmon->gt, reg);
reg_val = REG_FIELD_GET(PKG_TDP, reg_val);
*value = mul_u64_u32_shr(reg_val, SF_POWER, hwmon->scl_shift_power);
}
@@ -267,8 +259,8 @@ xe_hwmon_energy_get(struct xe_hwmon *hwmon, int channel, long *energy)
struct xe_hwmon_energy_info *ei = &hwmon->ei[channel];
u64 reg_val;
- xe_hwmon_process_reg(hwmon, REG_PKG_ENERGY_STATUS, REG_READ32,
- &reg_val, 0, 0, channel);
+ reg_val = xe_mmio_read32(hwmon->gt, xe_hwmon_get_reg(hwmon, REG_PKG_ENERGY_STATUS,
+ channel));
if (reg_val >= ei->reg_val_prev)
ei->accum_energy += reg_val - ei->reg_val_prev;
@@ -294,8 +286,7 @@ xe_hwmon_power_max_interval_show(struct device *dev, struct device_attribute *at
mutex_lock(&hwmon->hwmon_lock);
- xe_hwmon_process_reg(hwmon, REG_PKG_RAPL_LIMIT,
- REG_READ32, &r, 0, 0, sensor_index);
+ r = xe_mmio_read32(hwmon->gt, xe_hwmon_get_reg(hwmon, REG_PKG_RAPL_LIMIT, sensor_index));
mutex_unlock(&hwmon->hwmon_lock);
@@ -383,8 +374,8 @@ xe_hwmon_power_max_interval_store(struct device *dev, struct device_attribute *a
mutex_lock(&hwmon->hwmon_lock);
- xe_hwmon_process_reg(hwmon, REG_PKG_RAPL_LIMIT, REG_RMW32, (u64 *)&r,
- PKG_PWR_LIM_1_TIME, rxy, sensor_index);
+ r = xe_mmio_rmw32(hwmon->gt, xe_hwmon_get_reg(hwmon, REG_PKG_RAPL_LIMIT, sensor_index),
+ PKG_PWR_LIM_1_TIME, rxy);
mutex_unlock(&hwmon->hwmon_lock);
@@ -499,8 +490,7 @@ static void xe_hwmon_get_voltage(struct xe_hwmon *hwmon, int channel, long *valu
{
u64 reg_val;
- xe_hwmon_process_reg(hwmon, REG_GT_PERF_STATUS,
- REG_READ32, &reg_val, 0, 0, channel);
+ reg_val = xe_mmio_read32(hwmon->gt, xe_hwmon_get_reg(hwmon, REG_GT_PERF_STATUS, channel));
/* HW register value in units of 2.5 millivolt */
*value = DIV_ROUND_CLOSEST(REG_FIELD_GET(VOLTAGE_MASK, reg_val) * 2500, SF_VOLTAGE);
}
@@ -784,14 +774,15 @@ xe_hwmon_get_preregistration_info(struct xe_device *xe)
long energy;
u64 val_sku_unit = 0;
int channel;
+ struct xe_reg pkg_power_sku_unit;
/*
* The contents of register PKG_POWER_SKU_UNIT do not change,
* so read it once and store the shift values.
*/
- if (xe_reg_is_valid(xe_hwmon_get_reg(hwmon, REG_PKG_POWER_SKU_UNIT, 0))) {
- xe_hwmon_process_reg(hwmon, REG_PKG_POWER_SKU_UNIT,
- REG_READ32, &val_sku_unit, 0, 0, 0);
+ pkg_power_sku_unit = xe_hwmon_get_reg(hwmon, REG_PKG_POWER_SKU_UNIT, 0);
+ if (xe_reg_is_valid(pkg_power_sku_unit)) {
+ val_sku_unit = xe_mmio_read32(hwmon->gt, pkg_power_sku_unit);
hwmon->scl_shift_power = REG_FIELD_GET(PKG_PWR_UNIT, val_sku_unit);
hwmon->scl_shift_energy = REG_FIELD_GET(PKG_ENERGY_UNIT, val_sku_unit);
hwmon->scl_shift_time = REG_FIELD_GET(PKG_TIME_UNIT, val_sku_unit);
diff --git a/drivers/gpu/drm/xe/xe_irq.c b/drivers/gpu/drm/xe/xe_irq.c
index 8ee3c300c5e4..85733f993d09 100644
--- a/drivers/gpu/drm/xe/xe_irq.c
+++ b/drivers/gpu/drm/xe/xe_irq.c
@@ -134,6 +134,9 @@ void xe_irq_enable_hwe(struct xe_gt *gt)
u32 gsc_mask = 0;
u32 heci_mask = 0;
+ if (IS_SRIOV_VF(xe) && xe_device_has_memirq(xe))
+ return;
+
if (xe_device_uc_enabled(xe)) {
irqs = GT_RENDER_USER_INTERRUPT |
GT_RENDER_PIPECTL_NOTIFY_INTERRUPT;
@@ -735,11 +738,6 @@ free_irq_handler:
return err;
}
-void xe_irq_shutdown(struct xe_device *xe)
-{
- irq_uninstall(xe);
-}
-
void xe_irq_suspend(struct xe_device *xe)
{
int irq = to_pci_dev(xe->drm.dev)->irq;
diff --git a/drivers/gpu/drm/xe/xe_irq.h b/drivers/gpu/drm/xe/xe_irq.h
index bc42bc90d967..067514e13675 100644
--- a/drivers/gpu/drm/xe/xe_irq.h
+++ b/drivers/gpu/drm/xe/xe_irq.h
@@ -11,7 +11,6 @@ struct xe_tile;
struct xe_gt;
int xe_irq_install(struct xe_device *xe);
-void xe_irq_shutdown(struct xe_device *xe);
void xe_irq_suspend(struct xe_device *xe);
void xe_irq_resume(struct xe_device *xe);
void xe_irq_enable_hwe(struct xe_gt *gt);
diff --git a/drivers/gpu/drm/xe/xe_lrc.c b/drivers/gpu/drm/xe/xe_lrc.c
index c1bb85d2e243..94ff62e1d95e 100644
--- a/drivers/gpu/drm/xe/xe_lrc.c
+++ b/drivers/gpu/drm/xe/xe_lrc.c
@@ -49,6 +49,8 @@ struct xe_lrc_snapshot {
} tail;
u32 start_seqno;
u32 seqno;
+ u32 ctx_timestamp;
+ u32 ctx_job_timestamp;
};
static struct xe_device *
@@ -649,12 +651,19 @@ u32 xe_lrc_pphwsp_offset(struct xe_lrc *lrc)
/* Make the magic macros work */
#define __xe_lrc_pphwsp_offset xe_lrc_pphwsp_offset
+#define __xe_lrc_regs_offset xe_lrc_regs_offset
#define LRC_SEQNO_PPHWSP_OFFSET 512
#define LRC_START_SEQNO_PPHWSP_OFFSET (LRC_SEQNO_PPHWSP_OFFSET + 8)
+#define LRC_CTX_JOB_TIMESTAMP_OFFSET (LRC_START_SEQNO_PPHWSP_OFFSET + 8)
#define LRC_PARALLEL_PPHWSP_OFFSET 2048
#define LRC_PPHWSP_SIZE SZ_4K
+u32 xe_lrc_regs_offset(struct xe_lrc *lrc)
+{
+ return xe_lrc_pphwsp_offset(lrc) + LRC_PPHWSP_SIZE;
+}
+
static size_t lrc_reg_size(struct xe_device *xe)
{
if (GRAPHICS_VERx100(xe) >= 1250)
@@ -680,15 +689,21 @@ static inline u32 __xe_lrc_start_seqno_offset(struct xe_lrc *lrc)
return xe_lrc_pphwsp_offset(lrc) + LRC_START_SEQNO_PPHWSP_OFFSET;
}
+static u32 __xe_lrc_ctx_job_timestamp_offset(struct xe_lrc *lrc)
+{
+ /* The start seqno is stored in the driver-defined portion of PPHWSP */
+ return xe_lrc_pphwsp_offset(lrc) + LRC_CTX_JOB_TIMESTAMP_OFFSET;
+}
+
static inline u32 __xe_lrc_parallel_offset(struct xe_lrc *lrc)
{
/* The parallel is stored in the driver-defined portion of PPHWSP */
return xe_lrc_pphwsp_offset(lrc) + LRC_PARALLEL_PPHWSP_OFFSET;
}
-static inline u32 __xe_lrc_regs_offset(struct xe_lrc *lrc)
+static u32 __xe_lrc_ctx_timestamp_offset(struct xe_lrc *lrc)
{
- return xe_lrc_pphwsp_offset(lrc) + LRC_PPHWSP_SIZE;
+ return __xe_lrc_regs_offset(lrc) + CTX_TIMESTAMP * sizeof(u32);
}
static inline u32 __xe_lrc_indirect_ring_offset(struct xe_lrc *lrc)
@@ -716,11 +731,65 @@ DECL_MAP_ADDR_HELPERS(pphwsp)
DECL_MAP_ADDR_HELPERS(seqno)
DECL_MAP_ADDR_HELPERS(regs)
DECL_MAP_ADDR_HELPERS(start_seqno)
+DECL_MAP_ADDR_HELPERS(ctx_job_timestamp)
+DECL_MAP_ADDR_HELPERS(ctx_timestamp)
DECL_MAP_ADDR_HELPERS(parallel)
DECL_MAP_ADDR_HELPERS(indirect_ring)
#undef DECL_MAP_ADDR_HELPERS
+/**
+ * xe_lrc_ctx_timestamp_ggtt_addr() - Get ctx timestamp GGTT address
+ * @lrc: Pointer to the lrc.
+ *
+ * Returns: ctx timestamp GGTT address
+ */
+u32 xe_lrc_ctx_timestamp_ggtt_addr(struct xe_lrc *lrc)
+{
+ return __xe_lrc_ctx_timestamp_ggtt_addr(lrc);
+}
+
+/**
+ * xe_lrc_ctx_timestamp() - Read ctx timestamp value
+ * @lrc: Pointer to the lrc.
+ *
+ * Returns: ctx timestamp value
+ */
+u32 xe_lrc_ctx_timestamp(struct xe_lrc *lrc)
+{
+ struct xe_device *xe = lrc_to_xe(lrc);
+ struct iosys_map map;
+
+ map = __xe_lrc_ctx_timestamp_map(lrc);
+ return xe_map_read32(xe, &map);
+}
+
+/**
+ * xe_lrc_ctx_job_timestamp_ggtt_addr() - Get ctx job timestamp GGTT address
+ * @lrc: Pointer to the lrc.
+ *
+ * Returns: ctx timestamp job GGTT address
+ */
+u32 xe_lrc_ctx_job_timestamp_ggtt_addr(struct xe_lrc *lrc)
+{
+ return __xe_lrc_ctx_job_timestamp_ggtt_addr(lrc);
+}
+
+/**
+ * xe_lrc_ctx_job_timestamp() - Read ctx job timestamp value
+ * @lrc: Pointer to the lrc.
+ *
+ * Returns: ctx timestamp job value
+ */
+u32 xe_lrc_ctx_job_timestamp(struct xe_lrc *lrc)
+{
+ struct xe_device *xe = lrc_to_xe(lrc);
+ struct iosys_map map;
+
+ map = __xe_lrc_ctx_job_timestamp_map(lrc);
+ return xe_map_read32(xe, &map);
+}
+
u32 xe_lrc_ggtt_addr(struct xe_lrc *lrc)
{
return __xe_lrc_pphwsp_ggtt_addr(lrc);
@@ -1576,6 +1645,8 @@ struct xe_lrc_snapshot *xe_lrc_snapshot_capture(struct xe_lrc *lrc)
snapshot->lrc_offset = xe_lrc_pphwsp_offset(lrc);
snapshot->lrc_size = lrc->bo->size - snapshot->lrc_offset;
snapshot->lrc_snapshot = NULL;
+ snapshot->ctx_timestamp = xe_lrc_ctx_timestamp(lrc);
+ snapshot->ctx_job_timestamp = xe_lrc_ctx_job_timestamp(lrc);
return snapshot;
}
@@ -1624,6 +1695,8 @@ void xe_lrc_snapshot_print(struct xe_lrc_snapshot *snapshot, struct drm_printer
snapshot->tail.internal, snapshot->tail.memory);
drm_printf(p, "\tStart seqno: (memory) %d\n", snapshot->start_seqno);
drm_printf(p, "\tSeqno: (memory) %d\n", snapshot->seqno);
+ drm_printf(p, "\tTimestamp: 0x%08x\n", snapshot->ctx_timestamp);
+ drm_printf(p, "\tJob Timestamp: 0x%08x\n", snapshot->ctx_job_timestamp);
if (!snapshot->lrc_snapshot)
return;
@@ -1659,11 +1732,21 @@ void xe_lrc_snapshot_free(struct xe_lrc_snapshot *snapshot)
kfree(snapshot);
}
+/**
+ * xe_lrc_update_timestamp() - Update ctx timestamp
+ * @lrc: Pointer to the lrc.
+ * @old_ts: Old timestamp value
+ *
+ * Populate @old_ts current saved ctx timestamp, read new ctx timestamp and
+ * update saved value.
+ *
+ * Returns: New ctx timestamp value
+ */
u32 xe_lrc_update_timestamp(struct xe_lrc *lrc, u32 *old_ts)
{
*old_ts = lrc->ctx_timestamp;
- lrc->ctx_timestamp = xe_lrc_read_ctx_reg(lrc, CTX_TIMESTAMP);
+ lrc->ctx_timestamp = xe_lrc_ctx_timestamp(lrc);
return lrc->ctx_timestamp;
}
diff --git a/drivers/gpu/drm/xe/xe_lrc.h b/drivers/gpu/drm/xe/xe_lrc.h
index 882c3437ba5c..c24542e89318 100644
--- a/drivers/gpu/drm/xe/xe_lrc.h
+++ b/drivers/gpu/drm/xe/xe_lrc.h
@@ -52,6 +52,7 @@ static inline void xe_lrc_put(struct xe_lrc *lrc)
size_t xe_gt_lrc_size(struct xe_gt *gt, enum xe_engine_class class);
u32 xe_lrc_pphwsp_offset(struct xe_lrc *lrc);
+u32 xe_lrc_regs_offset(struct xe_lrc *lrc);
void xe_lrc_set_ring_tail(struct xe_lrc *lrc, u32 tail);
u32 xe_lrc_ring_tail(struct xe_lrc *lrc);
@@ -94,6 +95,11 @@ void xe_lrc_snapshot_capture_delayed(struct xe_lrc_snapshot *snapshot);
void xe_lrc_snapshot_print(struct xe_lrc_snapshot *snapshot, struct drm_printer *p);
void xe_lrc_snapshot_free(struct xe_lrc_snapshot *snapshot);
+u32 xe_lrc_ctx_timestamp_ggtt_addr(struct xe_lrc *lrc);
+u32 xe_lrc_ctx_timestamp(struct xe_lrc *lrc);
+u32 xe_lrc_ctx_job_timestamp_ggtt_addr(struct xe_lrc *lrc);
+u32 xe_lrc_ctx_job_timestamp(struct xe_lrc *lrc);
+
/**
* xe_lrc_update_timestamp - readout LRC timestamp and update cached value
* @lrc: logical ring context for this exec queue
diff --git a/drivers/gpu/drm/xe/xe_migrate.c b/drivers/gpu/drm/xe/xe_migrate.c
index 7e3fb33110d9..c9f5673353ee 100644
--- a/drivers/gpu/drm/xe/xe_migrate.c
+++ b/drivers/gpu/drm/xe/xe_migrate.c
@@ -32,7 +32,7 @@
#include "xe_res_cursor.h"
#include "xe_sched_job.h"
#include "xe_sync.h"
-#include "xe_trace.h"
+#include "xe_trace_bo.h"
#include "xe_vm.h"
/**
@@ -647,12 +647,6 @@ static void emit_copy(struct xe_gt *gt, struct xe_bb *bb,
bb->cs[bb->len++] = upper_32_bits(src_ofs);
}
-static int job_add_deps(struct xe_sched_job *job, struct dma_resv *resv,
- enum dma_resv_usage usage)
-{
- return drm_sched_job_add_resv_dependencies(&job->drm, resv, usage);
-}
-
static u64 xe_migrate_batch_base(struct xe_migrate *m, bool usm)
{
return usm ? m->usm_batch_base_ofs : m->batch_base_ofs;
@@ -849,11 +843,11 @@ struct dma_fence *xe_migrate_copy(struct xe_migrate *m,
xe_sched_job_add_migrate_flush(job, flush_flags);
if (!fence) {
- err = job_add_deps(job, src_bo->ttm.base.resv,
- DMA_RESV_USAGE_BOOKKEEP);
+ err = xe_sched_job_add_deps(job, src_bo->ttm.base.resv,
+ DMA_RESV_USAGE_BOOKKEEP);
if (!err && src_bo != dst_bo)
- err = job_add_deps(job, dst_bo->ttm.base.resv,
- DMA_RESV_USAGE_BOOKKEEP);
+ err = xe_sched_job_add_deps(job, dst_bo->ttm.base.resv,
+ DMA_RESV_USAGE_BOOKKEEP);
if (err)
goto err_job;
}
@@ -1091,8 +1085,8 @@ struct dma_fence *xe_migrate_clear(struct xe_migrate *m,
* fences, which are always tracked as
* DMA_RESV_USAGE_KERNEL.
*/
- err = job_add_deps(job, bo->ttm.base.resv,
- DMA_RESV_USAGE_KERNEL);
+ err = xe_sched_job_add_deps(job, bo->ttm.base.resv,
+ DMA_RESV_USAGE_KERNEL);
if (err)
goto err_job;
}
@@ -1364,7 +1358,7 @@ xe_migrate_update_pgtables(struct xe_migrate *m,
GFP_KERNEL, true, 0);
if (IS_ERR(sa_bo)) {
err = PTR_ERR(sa_bo);
- goto err;
+ goto err_bb;
}
ppgtt_ofs = NUM_KERNEL_PDE +
@@ -1412,13 +1406,13 @@ xe_migrate_update_pgtables(struct xe_migrate *m,
update_idx);
if (IS_ERR(job)) {
err = PTR_ERR(job);
- goto err_bb;
+ goto err_sa;
}
/* Wait on BO move */
if (bo) {
- err = job_add_deps(job, bo->ttm.base.resv,
- DMA_RESV_USAGE_KERNEL);
+ err = xe_sched_job_add_deps(job, bo->ttm.base.resv,
+ DMA_RESV_USAGE_KERNEL);
if (err)
goto err_job;
}
@@ -1428,8 +1422,8 @@ xe_migrate_update_pgtables(struct xe_migrate *m,
* trigger preempts before moving forward
*/
if (first_munmap_rebind) {
- err = job_add_deps(job, xe_vm_resv(vm),
- DMA_RESV_USAGE_BOOKKEEP);
+ err = xe_sched_job_add_deps(job, xe_vm_resv(vm),
+ DMA_RESV_USAGE_BOOKKEEP);
if (err)
goto err_job;
}
@@ -1464,10 +1458,10 @@ xe_migrate_update_pgtables(struct xe_migrate *m,
err_job:
xe_sched_job_put(job);
+err_sa:
+ drm_suballoc_free(sa_bo, NULL);
err_bb:
xe_bb_free(bb, NULL);
-err:
- drm_suballoc_free(sa_bo, NULL);
return ERR_PTR(err);
}
diff --git a/drivers/gpu/drm/xe/xe_mmio.c b/drivers/gpu/drm/xe/xe_mmio.c
index 7962eeb9adb7..f92faad4b96d 100644
--- a/drivers/gpu/drm/xe/xe_mmio.c
+++ b/drivers/gpu/drm/xe/xe_mmio.c
@@ -21,6 +21,7 @@
#include "xe_gt_sriov_vf.h"
#include "xe_macros.h"
#include "xe_sriov.h"
+#include "xe_trace.h"
static void tiles_fini(void *arg)
{
@@ -124,16 +125,24 @@ u8 xe_mmio_read8(struct xe_gt *gt, struct xe_reg reg)
{
struct xe_tile *tile = gt_to_tile(gt);
u32 addr = xe_mmio_adjusted_addr(gt, reg.addr);
+ u8 val;
- return readb((reg.ext ? tile->mmio_ext.regs : tile->mmio.regs) + addr);
+ val = readb((reg.ext ? tile->mmio_ext.regs : tile->mmio.regs) + addr);
+ trace_xe_reg_rw(gt, false, addr, val, sizeof(val));
+
+ return val;
}
u16 xe_mmio_read16(struct xe_gt *gt, struct xe_reg reg)
{
struct xe_tile *tile = gt_to_tile(gt);
u32 addr = xe_mmio_adjusted_addr(gt, reg.addr);
+ u16 val;
+
+ val = readw((reg.ext ? tile->mmio_ext.regs : tile->mmio.regs) + addr);
+ trace_xe_reg_rw(gt, false, addr, val, sizeof(val));
- return readw((reg.ext ? tile->mmio_ext.regs : tile->mmio.regs) + addr);
+ return val;
}
void xe_mmio_write32(struct xe_gt *gt, struct xe_reg reg, u32 val)
@@ -141,6 +150,7 @@ void xe_mmio_write32(struct xe_gt *gt, struct xe_reg reg, u32 val)
struct xe_tile *tile = gt_to_tile(gt);
u32 addr = xe_mmio_adjusted_addr(gt, reg.addr);
+ trace_xe_reg_rw(gt, true, addr, val, sizeof(val));
writel(val, (reg.ext ? tile->mmio_ext.regs : tile->mmio.regs) + addr);
}
@@ -148,11 +158,16 @@ u32 xe_mmio_read32(struct xe_gt *gt, struct xe_reg reg)
{
struct xe_tile *tile = gt_to_tile(gt);
u32 addr = xe_mmio_adjusted_addr(gt, reg.addr);
+ u32 val;
if (!reg.vf && IS_SRIOV_VF(gt_to_xe(gt)))
- return xe_gt_sriov_vf_read32(gt, reg);
+ val = xe_gt_sriov_vf_read32(gt, reg);
+ else
+ val = readl((reg.ext ? tile->mmio_ext.regs : tile->mmio.regs) + addr);
+
+ trace_xe_reg_rw(gt, false, addr, val, sizeof(val));
- return readl((reg.ext ? tile->mmio_ext.regs : tile->mmio.regs) + addr);
+ return val;
}
u32 xe_mmio_rmw32(struct xe_gt *gt, struct xe_reg reg, u32 clr, u32 set)
diff --git a/drivers/gpu/drm/xe/xe_mocs.c b/drivers/gpu/drm/xe/xe_mocs.c
index de3f2d3f1b04..7ff0ac5b799a 100644
--- a/drivers/gpu/drm/xe/xe_mocs.c
+++ b/drivers/gpu/drm/xe/xe_mocs.c
@@ -47,8 +47,16 @@ struct xe_mocs_ops {
};
struct xe_mocs_info {
- unsigned int size;
- unsigned int n_entries;
+ /*
+ * Size of the spec's suggested MOCS programming table. The list of
+ * table entries from the spec can potentially be smaller than the
+ * number of hardware registers used to program the MOCS table; in such
+ * cases the registers for the remaining indices will be programmed to
+ * match unused_entries_index.
+ */
+ unsigned int table_size;
+ /* Number of MOCS entries supported by the hardware */
+ unsigned int num_mocs_regs;
const struct xe_mocs_entry *table;
const struct xe_mocs_ops *ops;
u8 uc_index;
@@ -266,7 +274,7 @@ static void xelp_lncf_dump(struct xe_mocs_info *info, struct xe_gt *gt, struct d
drm_printf(p, "LNCFCMOCS[idx] = [ESC, SCC, L3CC] (value)\n\n");
- for (i = 0, j = 0; i < (info->n_entries + 1) / 2; i++, j++) {
+ for (i = 0, j = 0; i < (info->num_mocs_regs + 1) / 2; i++, j++) {
if (regs_are_mcr(gt))
reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_LNCFCMOCS(i));
else
@@ -298,7 +306,7 @@ static void xelp_mocs_dump(struct xe_mocs_info *info, unsigned int flags,
drm_printf(p, "Global mocs table configuration:\n");
drm_printf(p, "GLOB_MOCS[idx] = [LeCC, TC, LRUM, AOM, RSC, SCC, PFM, SCF, CoS, SSE] (value)\n\n");
- for (i = 0; i < info->n_entries; i++) {
+ for (i = 0; i < info->num_mocs_regs; i++) {
if (regs_are_mcr(gt))
reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_GLOBAL_MOCS(i));
else
@@ -371,7 +379,7 @@ static void xehp_lncf_dump(struct xe_mocs_info *info, unsigned int flags,
drm_printf(p, "LNCFCMOCS[idx] = [UCL3LOOKUP, GLBGO, L3CC] (value)\n\n");
- for (i = 0, j = 0; i < (info->n_entries + 1) / 2; i++, j++) {
+ for (i = 0, j = 0; i < (info->num_mocs_regs + 1) / 2; i++, j++) {
if (regs_are_mcr(gt))
reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_LNCFCMOCS(i));
else
@@ -416,7 +424,7 @@ static void pvc_mocs_dump(struct xe_mocs_info *info, unsigned int flags, struct
drm_printf(p, "LNCFCMOCS[idx] = [ L3CC ] (value)\n\n");
- for (i = 0, j = 0; i < (info->n_entries + 1) / 2; i++, j++) {
+ for (i = 0, j = 0; i < (info->num_mocs_regs + 1) / 2; i++, j++) {
if (regs_are_mcr(gt))
reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_LNCFCMOCS(i));
else
@@ -498,7 +506,7 @@ static void mtl_mocs_dump(struct xe_mocs_info *info, unsigned int flags,
drm_printf(p, "Global mocs table configuration:\n");
drm_printf(p, "GLOB_MOCS[idx] = [IG_PAT, L4_CACHE_POLICY] (value)\n\n");
- for (i = 0; i < info->n_entries; i++) {
+ for (i = 0; i < info->num_mocs_regs; i++) {
if (regs_are_mcr(gt))
reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_GLOBAL_MOCS(i));
else
@@ -541,7 +549,7 @@ static void xe2_mocs_dump(struct xe_mocs_info *info, unsigned int flags,
drm_printf(p, "Global mocs table configuration:\n");
drm_printf(p, "GLOB_MOCS[idx] = [IG_PAT, L3_CLOS, L3_CACHE_POLICY, L4_CACHE_POLICY] (value)\n\n");
- for (i = 0; i < info->n_entries; i++) {
+ for (i = 0; i < info->num_mocs_regs; i++) {
if (regs_are_mcr(gt))
reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_GLOBAL_MOCS(i));
else
@@ -571,48 +579,48 @@ static unsigned int get_mocs_settings(struct xe_device *xe,
case XE_LUNARLAKE:
case XE_BATTLEMAGE:
info->ops = &xe2_mocs_ops;
- info->size = ARRAY_SIZE(xe2_mocs_table);
+ info->table_size = ARRAY_SIZE(xe2_mocs_table);
info->table = xe2_mocs_table;
- info->n_entries = XE2_NUM_MOCS_ENTRIES;
+ info->num_mocs_regs = XE2_NUM_MOCS_ENTRIES;
info->uc_index = 3;
info->wb_index = 4;
info->unused_entries_index = 4;
break;
case XE_PVC:
info->ops = &pvc_mocs_ops;
- info->size = ARRAY_SIZE(pvc_mocs_desc);
+ info->table_size = ARRAY_SIZE(pvc_mocs_desc);
info->table = pvc_mocs_desc;
- info->n_entries = PVC_NUM_MOCS_ENTRIES;
+ info->num_mocs_regs = PVC_NUM_MOCS_ENTRIES;
info->uc_index = 1;
info->wb_index = 2;
info->unused_entries_index = 2;
break;
case XE_METEORLAKE:
info->ops = &mtl_mocs_ops;
- info->size = ARRAY_SIZE(mtl_mocs_desc);
+ info->table_size = ARRAY_SIZE(mtl_mocs_desc);
info->table = mtl_mocs_desc;
- info->n_entries = MTL_NUM_MOCS_ENTRIES;
+ info->num_mocs_regs = MTL_NUM_MOCS_ENTRIES;
info->uc_index = 9;
info->unused_entries_index = 1;
break;
case XE_DG2:
info->ops = &xehp_mocs_ops;
- info->size = ARRAY_SIZE(dg2_mocs_desc);
+ info->table_size = ARRAY_SIZE(dg2_mocs_desc);
info->table = dg2_mocs_desc;
info->uc_index = 1;
/*
* Last entry is RO on hardware, don't bother with what was
* written when checking later
*/
- info->n_entries = XELP_NUM_MOCS_ENTRIES - 1;
+ info->num_mocs_regs = XELP_NUM_MOCS_ENTRIES - 1;
info->unused_entries_index = 3;
break;
case XE_DG1:
info->ops = &xelp_mocs_ops;
- info->size = ARRAY_SIZE(dg1_mocs_desc);
+ info->table_size = ARRAY_SIZE(dg1_mocs_desc);
info->table = dg1_mocs_desc;
info->uc_index = 1;
- info->n_entries = XELP_NUM_MOCS_ENTRIES;
+ info->num_mocs_regs = XELP_NUM_MOCS_ENTRIES;
info->unused_entries_index = 5;
break;
case XE_TIGERLAKE:
@@ -621,9 +629,9 @@ static unsigned int get_mocs_settings(struct xe_device *xe,
case XE_ALDERLAKE_P:
case XE_ALDERLAKE_N:
info->ops = &xelp_mocs_ops;
- info->size = ARRAY_SIZE(gen12_mocs_desc);
+ info->table_size = ARRAY_SIZE(gen12_mocs_desc);
info->table = gen12_mocs_desc;
- info->n_entries = XELP_NUM_MOCS_ENTRIES;
+ info->num_mocs_regs = XELP_NUM_MOCS_ENTRIES;
info->uc_index = 3;
info->unused_entries_index = 2;
break;
@@ -642,12 +650,8 @@ static unsigned int get_mocs_settings(struct xe_device *xe,
*/
xe_assert(xe, info->unused_entries_index != 0);
- xe_assert(xe, !info->ops || info->ops->dump);
-
- if (XE_WARN_ON(info->size > info->n_entries)) {
- info->table = NULL;
- return 0;
- }
+ xe_assert(xe, info->ops && info->ops->dump);
+ xe_assert(xe, info->table_size <= info->num_mocs_regs);
if (!IS_DGFX(xe) || GRAPHICS_VER(xe) >= 20)
flags |= HAS_GLOBAL_MOCS;
@@ -664,7 +668,7 @@ static unsigned int get_mocs_settings(struct xe_device *xe,
static u32 get_entry_control(const struct xe_mocs_info *info,
unsigned int index)
{
- if (index < info->size && info->table[index].used)
+ if (index < info->table_size && info->table[index].used)
return info->table[index].control_value;
return info->table[info->unused_entries_index].control_value;
}
@@ -675,12 +679,9 @@ static void __init_mocs_table(struct xe_gt *gt,
unsigned int i;
u32 mocs;
- xe_gt_WARN_ONCE(gt, !info->unused_entries_index,
- "Unused entries index should have been defined\n");
-
- mocs_dbg(gt, "mocs entries: %d\n", info->n_entries);
+ mocs_dbg(gt, "mocs entries: %d\n", info->num_mocs_regs);
- for (i = 0; i < info->n_entries; i++) {
+ for (i = 0; i < info->num_mocs_regs; i++) {
mocs = get_entry_control(info, i);
mocs_dbg(gt, "GLOB_MOCS[%d] 0x%x 0x%x\n", i,
@@ -701,7 +702,7 @@ static void __init_mocs_table(struct xe_gt *gt,
static u16 get_entry_l3cc(const struct xe_mocs_info *info,
unsigned int index)
{
- if (index < info->size && info->table[index].used)
+ if (index < info->table_size && info->table[index].used)
return info->table[index].l3cc_value;
return info->table[info->unused_entries_index].l3cc_value;
}
@@ -717,9 +718,9 @@ static void init_l3cc_table(struct xe_gt *gt,
unsigned int i;
u32 l3cc;
- mocs_dbg(gt, "l3cc entries: %d\n", info->n_entries);
+ mocs_dbg(gt, "l3cc entries: %d\n", info->num_mocs_regs);
- for (i = 0; i < (info->n_entries + 1) / 2; i++) {
+ for (i = 0; i < (info->num_mocs_regs + 1) / 2; i++) {
l3cc = l3cc_combine(get_entry_l3cc(info, 2 * i),
get_entry_l3cc(info, 2 * i + 1));
@@ -779,9 +780,6 @@ void xe_mocs_dump(struct xe_gt *gt, struct drm_printer *p)
flags = get_mocs_settings(xe, &table);
- if (!table.ops->dump)
- return;
-
xe_pm_runtime_get_noresume(xe);
ret = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
diff --git a/drivers/gpu/drm/xe/xe_module.c b/drivers/gpu/drm/xe/xe_module.c
index 3edeb30d5ccb..499540add465 100644
--- a/drivers/gpu/drm/xe/xe_module.c
+++ b/drivers/gpu/drm/xe/xe_module.c
@@ -11,6 +11,7 @@
#include "xe_drv.h"
#include "xe_hw_fence.h"
#include "xe_pci.h"
+#include "xe_observation.h"
#include "xe_sched_job.h"
struct xe_modparam xe_modparam = {
@@ -78,6 +79,10 @@ static const struct init_funcs init_funcs[] = {
.init = xe_register_pci_driver,
.exit = xe_unregister_pci_driver,
},
+ {
+ .init = xe_observation_sysctl_register,
+ .exit = xe_observation_sysctl_unregister,
+ },
};
static int __init xe_init(void)
diff --git a/drivers/gpu/drm/xe/xe_oa.c b/drivers/gpu/drm/xe/xe_oa.c
new file mode 100644
index 000000000000..6d69f751bf78
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_oa.c
@@ -0,0 +1,2512 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2023-2024 Intel Corporation
+ */
+
+#include <linux/anon_inodes.h>
+#include <linux/delay.h>
+#include <linux/nospec.h>
+#include <linux/poll.h>
+
+#include <drm/drm_drv.h>
+#include <drm/drm_managed.h>
+#include <drm/xe_drm.h>
+
+#include "abi/guc_actions_slpc_abi.h"
+#include "instructions/xe_mi_commands.h"
+#include "regs/xe_engine_regs.h"
+#include "regs/xe_gt_regs.h"
+#include "regs/xe_lrc_layout.h"
+#include "regs/xe_oa_regs.h"
+#include "xe_assert.h"
+#include "xe_bb.h"
+#include "xe_bo.h"
+#include "xe_device.h"
+#include "xe_exec_queue.h"
+#include "xe_force_wake.h"
+#include "xe_gt.h"
+#include "xe_gt_mcr.h"
+#include "xe_gt_printk.h"
+#include "xe_guc_pc.h"
+#include "xe_lrc.h"
+#include "xe_macros.h"
+#include "xe_mmio.h"
+#include "xe_oa.h"
+#include "xe_observation.h"
+#include "xe_pm.h"
+#include "xe_sched_job.h"
+#include "xe_sriov.h"
+
+#define DEFAULT_POLL_FREQUENCY_HZ 200
+#define DEFAULT_POLL_PERIOD_NS (NSEC_PER_SEC / DEFAULT_POLL_FREQUENCY_HZ)
+#define XE_OA_UNIT_INVALID U32_MAX
+
+struct xe_oa_reg {
+ struct xe_reg addr;
+ u32 value;
+};
+
+struct xe_oa_config {
+ struct xe_oa *oa;
+
+ char uuid[UUID_STRING_LEN + 1];
+ int id;
+
+ const struct xe_oa_reg *regs;
+ u32 regs_len;
+
+ struct attribute_group sysfs_metric;
+ struct attribute *attrs[2];
+ struct kobj_attribute sysfs_metric_id;
+
+ struct kref ref;
+ struct rcu_head rcu;
+};
+
+struct flex {
+ struct xe_reg reg;
+ u32 offset;
+ u32 value;
+};
+
+struct xe_oa_open_param {
+ u32 oa_unit_id;
+ bool sample;
+ u32 metric_set;
+ enum xe_oa_format_name oa_format;
+ int period_exponent;
+ bool disabled;
+ int exec_queue_id;
+ int engine_instance;
+ struct xe_exec_queue *exec_q;
+ struct xe_hw_engine *hwe;
+ bool no_preempt;
+};
+
+struct xe_oa_config_bo {
+ struct llist_node node;
+
+ struct xe_oa_config *oa_config;
+ struct xe_bb *bb;
+};
+
+#define DRM_FMT(x) DRM_XE_OA_FMT_TYPE_##x
+
+static const struct xe_oa_format oa_formats[] = {
+ [XE_OA_FORMAT_C4_B8] = { 7, 64, DRM_FMT(OAG) },
+ [XE_OA_FORMAT_A12] = { 0, 64, DRM_FMT(OAG) },
+ [XE_OA_FORMAT_A12_B8_C8] = { 2, 128, DRM_FMT(OAG) },
+ [XE_OA_FORMAT_A32u40_A4u32_B8_C8] = { 5, 256, DRM_FMT(OAG) },
+ [XE_OAR_FORMAT_A32u40_A4u32_B8_C8] = { 5, 256, DRM_FMT(OAR) },
+ [XE_OA_FORMAT_A24u40_A14u32_B8_C8] = { 5, 256, DRM_FMT(OAG) },
+ [XE_OAC_FORMAT_A24u64_B8_C8] = { 1, 320, DRM_FMT(OAC), HDR_64_BIT },
+ [XE_OAC_FORMAT_A22u32_R2u32_B8_C8] = { 2, 192, DRM_FMT(OAC), HDR_64_BIT },
+ [XE_OAM_FORMAT_MPEC8u64_B8_C8] = { 1, 192, DRM_FMT(OAM_MPEC), HDR_64_BIT },
+ [XE_OAM_FORMAT_MPEC8u32_B8_C8] = { 2, 128, DRM_FMT(OAM_MPEC), HDR_64_BIT },
+ [XE_OA_FORMAT_PEC64u64] = { 1, 576, DRM_FMT(PEC), HDR_64_BIT, 1, 0 },
+ [XE_OA_FORMAT_PEC64u64_B8_C8] = { 1, 640, DRM_FMT(PEC), HDR_64_BIT, 1, 1 },
+ [XE_OA_FORMAT_PEC64u32] = { 1, 320, DRM_FMT(PEC), HDR_64_BIT },
+ [XE_OA_FORMAT_PEC32u64_G1] = { 5, 320, DRM_FMT(PEC), HDR_64_BIT, 1, 0 },
+ [XE_OA_FORMAT_PEC32u32_G1] = { 5, 192, DRM_FMT(PEC), HDR_64_BIT },
+ [XE_OA_FORMAT_PEC32u64_G2] = { 6, 320, DRM_FMT(PEC), HDR_64_BIT, 1, 0 },
+ [XE_OA_FORMAT_PEC32u32_G2] = { 6, 192, DRM_FMT(PEC), HDR_64_BIT },
+ [XE_OA_FORMAT_PEC36u64_G1_32_G2_4] = { 3, 320, DRM_FMT(PEC), HDR_64_BIT, 1, 0 },
+ [XE_OA_FORMAT_PEC36u64_G1_4_G2_32] = { 4, 320, DRM_FMT(PEC), HDR_64_BIT, 1, 0 },
+};
+
+static u32 xe_oa_circ_diff(struct xe_oa_stream *stream, u32 tail, u32 head)
+{
+ return tail >= head ? tail - head :
+ tail + stream->oa_buffer.circ_size - head;
+}
+
+static u32 xe_oa_circ_incr(struct xe_oa_stream *stream, u32 ptr, u32 n)
+{
+ return ptr + n >= stream->oa_buffer.circ_size ?
+ ptr + n - stream->oa_buffer.circ_size : ptr + n;
+}
+
+static void xe_oa_config_release(struct kref *ref)
+{
+ struct xe_oa_config *oa_config =
+ container_of(ref, typeof(*oa_config), ref);
+
+ kfree(oa_config->regs);
+
+ kfree_rcu(oa_config, rcu);
+}
+
+static void xe_oa_config_put(struct xe_oa_config *oa_config)
+{
+ if (!oa_config)
+ return;
+
+ kref_put(&oa_config->ref, xe_oa_config_release);
+}
+
+static struct xe_oa_config *xe_oa_config_get(struct xe_oa_config *oa_config)
+{
+ return kref_get_unless_zero(&oa_config->ref) ? oa_config : NULL;
+}
+
+static struct xe_oa_config *xe_oa_get_oa_config(struct xe_oa *oa, int metrics_set)
+{
+ struct xe_oa_config *oa_config;
+
+ rcu_read_lock();
+ oa_config = idr_find(&oa->metrics_idr, metrics_set);
+ if (oa_config)
+ oa_config = xe_oa_config_get(oa_config);
+ rcu_read_unlock();
+
+ return oa_config;
+}
+
+static void free_oa_config_bo(struct xe_oa_config_bo *oa_bo)
+{
+ xe_oa_config_put(oa_bo->oa_config);
+ xe_bb_free(oa_bo->bb, NULL);
+ kfree(oa_bo);
+}
+
+static const struct xe_oa_regs *__oa_regs(struct xe_oa_stream *stream)
+{
+ return &stream->hwe->oa_unit->regs;
+}
+
+static u32 xe_oa_hw_tail_read(struct xe_oa_stream *stream)
+{
+ return xe_mmio_read32(stream->gt, __oa_regs(stream)->oa_tail_ptr) &
+ OAG_OATAILPTR_MASK;
+}
+
+#define oa_report_header_64bit(__s) \
+ ((__s)->oa_buffer.format->header == HDR_64_BIT)
+
+static u64 oa_report_id(struct xe_oa_stream *stream, void *report)
+{
+ return oa_report_header_64bit(stream) ? *(u64 *)report : *(u32 *)report;
+}
+
+static void oa_report_id_clear(struct xe_oa_stream *stream, u32 *report)
+{
+ if (oa_report_header_64bit(stream))
+ *(u64 *)report = 0;
+ else
+ *report = 0;
+}
+
+static u64 oa_timestamp(struct xe_oa_stream *stream, void *report)
+{
+ return oa_report_header_64bit(stream) ?
+ *((u64 *)report + 1) :
+ *((u32 *)report + 1);
+}
+
+static void oa_timestamp_clear(struct xe_oa_stream *stream, u32 *report)
+{
+ if (oa_report_header_64bit(stream))
+ *(u64 *)&report[2] = 0;
+ else
+ report[1] = 0;
+}
+
+static bool xe_oa_buffer_check_unlocked(struct xe_oa_stream *stream)
+{
+ u32 gtt_offset = xe_bo_ggtt_addr(stream->oa_buffer.bo);
+ int report_size = stream->oa_buffer.format->size;
+ u32 tail, hw_tail;
+ unsigned long flags;
+ bool pollin;
+ u32 partial_report_size;
+
+ spin_lock_irqsave(&stream->oa_buffer.ptr_lock, flags);
+
+ hw_tail = xe_oa_hw_tail_read(stream);
+ hw_tail -= gtt_offset;
+
+ /*
+ * The tail pointer increases in 64 byte (cacheline size), not in report_size
+ * increments. Also report size may not be a power of 2. Compute potential
+ * partially landed report in OA buffer.
+ */
+ partial_report_size = xe_oa_circ_diff(stream, hw_tail, stream->oa_buffer.tail);
+ partial_report_size %= report_size;
+
+ /* Subtract partial amount off the tail */
+ hw_tail = xe_oa_circ_diff(stream, hw_tail, partial_report_size);
+
+ tail = hw_tail;
+
+ /*
+ * Walk the stream backward until we find a report with report id and timestamp
+ * not 0. We can't tell whether a report has fully landed in memory before the
+ * report id and timestamp of the following report have landed.
+ *
+ * This is assuming that the writes of the OA unit land in memory in the order
+ * they were written. If not : (╯°□°)╯︵ ┻━┻
+ */
+ while (xe_oa_circ_diff(stream, tail, stream->oa_buffer.tail) >= report_size) {
+ void *report = stream->oa_buffer.vaddr + tail;
+
+ if (oa_report_id(stream, report) || oa_timestamp(stream, report))
+ break;
+
+ tail = xe_oa_circ_diff(stream, tail, report_size);
+ }
+
+ if (xe_oa_circ_diff(stream, hw_tail, tail) > report_size)
+ drm_dbg(&stream->oa->xe->drm,
+ "unlanded report(s) head=0x%x tail=0x%x hw_tail=0x%x\n",
+ stream->oa_buffer.head, tail, hw_tail);
+
+ stream->oa_buffer.tail = tail;
+
+ pollin = xe_oa_circ_diff(stream, stream->oa_buffer.tail,
+ stream->oa_buffer.head) >= report_size;
+
+ spin_unlock_irqrestore(&stream->oa_buffer.ptr_lock, flags);
+
+ return pollin;
+}
+
+static enum hrtimer_restart xe_oa_poll_check_timer_cb(struct hrtimer *hrtimer)
+{
+ struct xe_oa_stream *stream =
+ container_of(hrtimer, typeof(*stream), poll_check_timer);
+
+ if (xe_oa_buffer_check_unlocked(stream)) {
+ stream->pollin = true;
+ wake_up(&stream->poll_wq);
+ }
+
+ hrtimer_forward_now(hrtimer, ns_to_ktime(stream->poll_period_ns));
+
+ return HRTIMER_RESTART;
+}
+
+static int xe_oa_append_report(struct xe_oa_stream *stream, char __user *buf,
+ size_t count, size_t *offset, const u8 *report)
+{
+ int report_size = stream->oa_buffer.format->size;
+ int report_size_partial;
+ u8 *oa_buf_end;
+
+ if ((count - *offset) < report_size)
+ return -ENOSPC;
+
+ buf += *offset;
+
+ oa_buf_end = stream->oa_buffer.vaddr + stream->oa_buffer.circ_size;
+ report_size_partial = oa_buf_end - report;
+
+ if (report_size_partial < report_size) {
+ if (copy_to_user(buf, report, report_size_partial))
+ return -EFAULT;
+ buf += report_size_partial;
+
+ if (copy_to_user(buf, stream->oa_buffer.vaddr,
+ report_size - report_size_partial))
+ return -EFAULT;
+ } else if (copy_to_user(buf, report, report_size)) {
+ return -EFAULT;
+ }
+
+ *offset += report_size;
+
+ return 0;
+}
+
+static int xe_oa_append_reports(struct xe_oa_stream *stream, char __user *buf,
+ size_t count, size_t *offset)
+{
+ int report_size = stream->oa_buffer.format->size;
+ u8 *oa_buf_base = stream->oa_buffer.vaddr;
+ u32 gtt_offset = xe_bo_ggtt_addr(stream->oa_buffer.bo);
+ size_t start_offset = *offset;
+ unsigned long flags;
+ u32 head, tail;
+ int ret = 0;
+
+ spin_lock_irqsave(&stream->oa_buffer.ptr_lock, flags);
+ head = stream->oa_buffer.head;
+ tail = stream->oa_buffer.tail;
+ spin_unlock_irqrestore(&stream->oa_buffer.ptr_lock, flags);
+
+ xe_assert(stream->oa->xe,
+ head < stream->oa_buffer.circ_size && tail < stream->oa_buffer.circ_size);
+
+ for (; xe_oa_circ_diff(stream, tail, head);
+ head = xe_oa_circ_incr(stream, head, report_size)) {
+ u8 *report = oa_buf_base + head;
+
+ ret = xe_oa_append_report(stream, buf, count, offset, report);
+ if (ret)
+ break;
+
+ if (!(stream->oa_buffer.circ_size % report_size)) {
+ /* Clear out report id and timestamp to detect unlanded reports */
+ oa_report_id_clear(stream, (void *)report);
+ oa_timestamp_clear(stream, (void *)report);
+ } else {
+ u8 *oa_buf_end = stream->oa_buffer.vaddr + stream->oa_buffer.circ_size;
+ u32 part = oa_buf_end - report;
+
+ /* Zero out the entire report */
+ if (report_size <= part) {
+ memset(report, 0, report_size);
+ } else {
+ memset(report, 0, part);
+ memset(oa_buf_base, 0, report_size - part);
+ }
+ }
+ }
+
+ if (start_offset != *offset) {
+ struct xe_reg oaheadptr = __oa_regs(stream)->oa_head_ptr;
+
+ spin_lock_irqsave(&stream->oa_buffer.ptr_lock, flags);
+ xe_mmio_write32(stream->gt, oaheadptr,
+ (head + gtt_offset) & OAG_OAHEADPTR_MASK);
+ stream->oa_buffer.head = head;
+ spin_unlock_irqrestore(&stream->oa_buffer.ptr_lock, flags);
+ }
+
+ return ret;
+}
+
+static void xe_oa_init_oa_buffer(struct xe_oa_stream *stream)
+{
+ u32 gtt_offset = xe_bo_ggtt_addr(stream->oa_buffer.bo);
+ u32 oa_buf = gtt_offset | OABUFFER_SIZE_16M | OAG_OABUFFER_MEMORY_SELECT;
+ unsigned long flags;
+
+ spin_lock_irqsave(&stream->oa_buffer.ptr_lock, flags);
+
+ xe_mmio_write32(stream->gt, __oa_regs(stream)->oa_status, 0);
+ xe_mmio_write32(stream->gt, __oa_regs(stream)->oa_head_ptr,
+ gtt_offset & OAG_OAHEADPTR_MASK);
+ stream->oa_buffer.head = 0;
+ /*
+ * PRM says: "This MMIO must be set before the OATAILPTR register and after the
+ * OAHEADPTR register. This is to enable proper functionality of the overflow bit".
+ */
+ xe_mmio_write32(stream->gt, __oa_regs(stream)->oa_buffer, oa_buf);
+ xe_mmio_write32(stream->gt, __oa_regs(stream)->oa_tail_ptr,
+ gtt_offset & OAG_OATAILPTR_MASK);
+
+ /* Mark that we need updated tail pointer to read from */
+ stream->oa_buffer.tail = 0;
+
+ spin_unlock_irqrestore(&stream->oa_buffer.ptr_lock, flags);
+
+ /* Zero out the OA buffer since we rely on zero report id and timestamp fields */
+ memset(stream->oa_buffer.vaddr, 0, stream->oa_buffer.bo->size);
+}
+
+static u32 __format_to_oactrl(const struct xe_oa_format *format, int counter_sel_mask)
+{
+ return ((format->counter_select << (ffs(counter_sel_mask) - 1)) & counter_sel_mask) |
+ REG_FIELD_PREP(OA_OACONTROL_REPORT_BC_MASK, format->bc_report) |
+ REG_FIELD_PREP(OA_OACONTROL_COUNTER_SIZE_MASK, format->counter_size);
+}
+
+static u32 __oa_ccs_select(struct xe_oa_stream *stream)
+{
+ u32 val;
+
+ if (stream->hwe->class != XE_ENGINE_CLASS_COMPUTE)
+ return 0;
+
+ val = REG_FIELD_PREP(OAG_OACONTROL_OA_CCS_SELECT_MASK, stream->hwe->instance);
+ xe_assert(stream->oa->xe,
+ REG_FIELD_GET(OAG_OACONTROL_OA_CCS_SELECT_MASK, val) == stream->hwe->instance);
+ return val;
+}
+
+static void xe_oa_enable(struct xe_oa_stream *stream)
+{
+ const struct xe_oa_format *format = stream->oa_buffer.format;
+ const struct xe_oa_regs *regs;
+ u32 val;
+
+ /*
+ * BSpec: 46822: Bit 0. Even if stream->sample is 0, for OAR to function, the OA
+ * buffer must be correctly initialized
+ */
+ xe_oa_init_oa_buffer(stream);
+
+ regs = __oa_regs(stream);
+ val = __format_to_oactrl(format, regs->oa_ctrl_counter_select_mask) |
+ __oa_ccs_select(stream) | OAG_OACONTROL_OA_COUNTER_ENABLE;
+
+ xe_mmio_write32(stream->gt, regs->oa_ctrl, val);
+}
+
+static void xe_oa_disable(struct xe_oa_stream *stream)
+{
+ xe_mmio_write32(stream->gt, __oa_regs(stream)->oa_ctrl, 0);
+ if (xe_mmio_wait32(stream->gt, __oa_regs(stream)->oa_ctrl,
+ OAG_OACONTROL_OA_COUNTER_ENABLE, 0, 50000, NULL, false))
+ drm_err(&stream->oa->xe->drm,
+ "wait for OA to be disabled timed out\n");
+
+ if (GRAPHICS_VERx100(stream->oa->xe) <= 1270 && GRAPHICS_VERx100(stream->oa->xe) != 1260) {
+ /* <= XE_METEORLAKE except XE_PVC */
+ xe_mmio_write32(stream->gt, OA_TLB_INV_CR, 1);
+ if (xe_mmio_wait32(stream->gt, OA_TLB_INV_CR, 1, 0, 50000, NULL, false))
+ drm_err(&stream->oa->xe->drm,
+ "wait for OA tlb invalidate timed out\n");
+ }
+}
+
+static int xe_oa_wait_unlocked(struct xe_oa_stream *stream)
+{
+ /* We might wait indefinitely if periodic sampling is not enabled */
+ if (!stream->periodic)
+ return -EINVAL;
+
+ return wait_event_interruptible(stream->poll_wq,
+ xe_oa_buffer_check_unlocked(stream));
+}
+
+#define OASTATUS_RELEVANT_BITS (OASTATUS_MMIO_TRG_Q_FULL | OASTATUS_COUNTER_OVERFLOW | \
+ OASTATUS_BUFFER_OVERFLOW | OASTATUS_REPORT_LOST)
+
+static int __xe_oa_read(struct xe_oa_stream *stream, char __user *buf,
+ size_t count, size_t *offset)
+{
+ /* Only clear our bits to avoid side-effects */
+ stream->oa_status = xe_mmio_rmw32(stream->gt, __oa_regs(stream)->oa_status,
+ OASTATUS_RELEVANT_BITS, 0);
+ /*
+ * Signal to userspace that there is non-zero OA status to read via
+ * @DRM_XE_OBSERVATION_IOCTL_STATUS observation stream fd ioctl
+ */
+ if (stream->oa_status & OASTATUS_RELEVANT_BITS)
+ return -EIO;
+
+ return xe_oa_append_reports(stream, buf, count, offset);
+}
+
+static ssize_t xe_oa_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct xe_oa_stream *stream = file->private_data;
+ size_t offset = 0;
+ int ret;
+
+ /* Can't read from disabled streams */
+ if (!stream->enabled || !stream->sample)
+ return -EINVAL;
+
+ if (!(file->f_flags & O_NONBLOCK)) {
+ do {
+ ret = xe_oa_wait_unlocked(stream);
+ if (ret)
+ return ret;
+
+ mutex_lock(&stream->stream_lock);
+ ret = __xe_oa_read(stream, buf, count, &offset);
+ mutex_unlock(&stream->stream_lock);
+ } while (!offset && !ret);
+ } else {
+ mutex_lock(&stream->stream_lock);
+ ret = __xe_oa_read(stream, buf, count, &offset);
+ mutex_unlock(&stream->stream_lock);
+ }
+
+ /*
+ * Typically we clear pollin here in order to wait for the new hrtimer callback
+ * before unblocking. The exception to this is if __xe_oa_read returns -ENOSPC,
+ * which means that more OA data is available than could fit in the user provided
+ * buffer. In this case we want the next poll() call to not block.
+ *
+ * Also in case of -EIO, we have already waited for data before returning
+ * -EIO, so need to wait again
+ */
+ if (ret != -ENOSPC && ret != -EIO)
+ stream->pollin = false;
+
+ /* Possible values for ret are 0, -EFAULT, -ENOSPC, -EIO, -EINVAL, ... */
+ return offset ?: (ret ?: -EAGAIN);
+}
+
+static __poll_t xe_oa_poll_locked(struct xe_oa_stream *stream,
+ struct file *file, poll_table *wait)
+{
+ __poll_t events = 0;
+
+ poll_wait(file, &stream->poll_wq, wait);
+
+ /*
+ * We don't explicitly check whether there's something to read here since this
+ * path may be hot depending on what else userspace is polling, or on the timeout
+ * in use. We rely on hrtimer xe_oa_poll_check_timer_cb to notify us when there
+ * are samples to read
+ */
+ if (stream->pollin)
+ events |= EPOLLIN;
+
+ return events;
+}
+
+static __poll_t xe_oa_poll(struct file *file, poll_table *wait)
+{
+ struct xe_oa_stream *stream = file->private_data;
+ __poll_t ret;
+
+ mutex_lock(&stream->stream_lock);
+ ret = xe_oa_poll_locked(stream, file, wait);
+ mutex_unlock(&stream->stream_lock);
+
+ return ret;
+}
+
+static int xe_oa_submit_bb(struct xe_oa_stream *stream, struct xe_bb *bb)
+{
+ struct xe_sched_job *job;
+ struct dma_fence *fence;
+ long timeout;
+ int err = 0;
+
+ /* Kernel configuration is issued on stream->k_exec_q, not stream->exec_q */
+ job = xe_bb_create_job(stream->k_exec_q, bb);
+ if (IS_ERR(job)) {
+ err = PTR_ERR(job);
+ goto exit;
+ }
+
+ xe_sched_job_arm(job);
+ fence = dma_fence_get(&job->drm.s_fence->finished);
+ xe_sched_job_push(job);
+
+ timeout = dma_fence_wait_timeout(fence, false, HZ);
+ dma_fence_put(fence);
+ if (timeout < 0)
+ err = timeout;
+ else if (!timeout)
+ err = -ETIME;
+exit:
+ return err;
+}
+
+static void write_cs_mi_lri(struct xe_bb *bb, const struct xe_oa_reg *reg_data, u32 n_regs)
+{
+ u32 i;
+
+#define MI_LOAD_REGISTER_IMM_MAX_REGS (126)
+
+ for (i = 0; i < n_regs; i++) {
+ if ((i % MI_LOAD_REGISTER_IMM_MAX_REGS) == 0) {
+ u32 n_lri = min_t(u32, n_regs - i,
+ MI_LOAD_REGISTER_IMM_MAX_REGS);
+
+ bb->cs[bb->len++] = MI_LOAD_REGISTER_IMM | MI_LRI_NUM_REGS(n_lri);
+ }
+ bb->cs[bb->len++] = reg_data[i].addr.addr;
+ bb->cs[bb->len++] = reg_data[i].value;
+ }
+}
+
+static int num_lri_dwords(int num_regs)
+{
+ int count = 0;
+
+ if (num_regs > 0) {
+ count += DIV_ROUND_UP(num_regs, MI_LOAD_REGISTER_IMM_MAX_REGS);
+ count += num_regs * 2;
+ }
+
+ return count;
+}
+
+static void xe_oa_free_oa_buffer(struct xe_oa_stream *stream)
+{
+ xe_bo_unpin_map_no_vm(stream->oa_buffer.bo);
+}
+
+static void xe_oa_free_configs(struct xe_oa_stream *stream)
+{
+ struct xe_oa_config_bo *oa_bo, *tmp;
+
+ xe_oa_config_put(stream->oa_config);
+ llist_for_each_entry_safe(oa_bo, tmp, stream->oa_config_bos.first, node)
+ free_oa_config_bo(oa_bo);
+}
+
+static void xe_oa_store_flex(struct xe_oa_stream *stream, struct xe_lrc *lrc,
+ struct xe_bb *bb, const struct flex *flex, u32 count)
+{
+ u32 offset = xe_bo_ggtt_addr(lrc->bo);
+
+ do {
+ bb->cs[bb->len++] = MI_STORE_DATA_IMM | BIT(22) /* GGTT */ | 2;
+ bb->cs[bb->len++] = offset + flex->offset * sizeof(u32);
+ bb->cs[bb->len++] = 0;
+ bb->cs[bb->len++] = flex->value;
+
+ } while (flex++, --count);
+}
+
+static int xe_oa_modify_ctx_image(struct xe_oa_stream *stream, struct xe_lrc *lrc,
+ const struct flex *flex, u32 count)
+{
+ struct xe_bb *bb;
+ int err;
+
+ bb = xe_bb_new(stream->gt, 4 * count, false);
+ if (IS_ERR(bb)) {
+ err = PTR_ERR(bb);
+ goto exit;
+ }
+
+ xe_oa_store_flex(stream, lrc, bb, flex, count);
+
+ err = xe_oa_submit_bb(stream, bb);
+ xe_bb_free(bb, NULL);
+exit:
+ return err;
+}
+
+static int xe_oa_load_with_lri(struct xe_oa_stream *stream, struct xe_oa_reg *reg_lri)
+{
+ struct xe_bb *bb;
+ int err;
+
+ bb = xe_bb_new(stream->gt, 3, false);
+ if (IS_ERR(bb)) {
+ err = PTR_ERR(bb);
+ goto exit;
+ }
+
+ write_cs_mi_lri(bb, reg_lri, 1);
+
+ err = xe_oa_submit_bb(stream, bb);
+ xe_bb_free(bb, NULL);
+exit:
+ return err;
+}
+
+static int xe_oa_configure_oar_context(struct xe_oa_stream *stream, bool enable)
+{
+ const struct xe_oa_format *format = stream->oa_buffer.format;
+ struct xe_lrc *lrc = stream->exec_q->lrc[0];
+ u32 regs_offset = xe_lrc_regs_offset(lrc) / sizeof(u32);
+ u32 oacontrol = __format_to_oactrl(format, OAR_OACONTROL_COUNTER_SEL_MASK) |
+ (enable ? OAR_OACONTROL_COUNTER_ENABLE : 0);
+
+ struct flex regs_context[] = {
+ {
+ OACTXCONTROL(stream->hwe->mmio_base),
+ stream->oa->ctx_oactxctrl_offset[stream->hwe->class] + 1,
+ enable ? OA_COUNTER_RESUME : 0,
+ },
+ {
+ RING_CONTEXT_CONTROL(stream->hwe->mmio_base),
+ regs_offset + CTX_CONTEXT_CONTROL,
+ _MASKED_FIELD(CTX_CTRL_OAC_CONTEXT_ENABLE,
+ enable ? CTX_CTRL_OAC_CONTEXT_ENABLE : 0)
+ },
+ };
+ struct xe_oa_reg reg_lri = { OAR_OACONTROL, oacontrol };
+ int err;
+
+ /* Modify stream hwe context image with regs_context */
+ err = xe_oa_modify_ctx_image(stream, stream->exec_q->lrc[0],
+ regs_context, ARRAY_SIZE(regs_context));
+ if (err)
+ return err;
+
+ /* Apply reg_lri using LRI */
+ return xe_oa_load_with_lri(stream, &reg_lri);
+}
+
+static int xe_oa_configure_oac_context(struct xe_oa_stream *stream, bool enable)
+{
+ const struct xe_oa_format *format = stream->oa_buffer.format;
+ struct xe_lrc *lrc = stream->exec_q->lrc[0];
+ u32 regs_offset = xe_lrc_regs_offset(lrc) / sizeof(u32);
+ u32 oacontrol = __format_to_oactrl(format, OAR_OACONTROL_COUNTER_SEL_MASK) |
+ (enable ? OAR_OACONTROL_COUNTER_ENABLE : 0);
+ struct flex regs_context[] = {
+ {
+ OACTXCONTROL(stream->hwe->mmio_base),
+ stream->oa->ctx_oactxctrl_offset[stream->hwe->class] + 1,
+ enable ? OA_COUNTER_RESUME : 0,
+ },
+ {
+ RING_CONTEXT_CONTROL(stream->hwe->mmio_base),
+ regs_offset + CTX_CONTEXT_CONTROL,
+ _MASKED_FIELD(CTX_CTRL_OAC_CONTEXT_ENABLE,
+ enable ? CTX_CTRL_OAC_CONTEXT_ENABLE : 0) |
+ _MASKED_FIELD(CTX_CTRL_RUN_ALONE,
+ enable ? CTX_CTRL_RUN_ALONE : 0),
+ },
+ };
+ struct xe_oa_reg reg_lri = { OAC_OACONTROL, oacontrol };
+ int err;
+
+ /* Set ccs select to enable programming of OAC_OACONTROL */
+ xe_mmio_write32(stream->gt, __oa_regs(stream)->oa_ctrl, __oa_ccs_select(stream));
+
+ /* Modify stream hwe context image with regs_context */
+ err = xe_oa_modify_ctx_image(stream, stream->exec_q->lrc[0],
+ regs_context, ARRAY_SIZE(regs_context));
+ if (err)
+ return err;
+
+ /* Apply reg_lri using LRI */
+ return xe_oa_load_with_lri(stream, &reg_lri);
+}
+
+static int xe_oa_configure_oa_context(struct xe_oa_stream *stream, bool enable)
+{
+ switch (stream->hwe->class) {
+ case XE_ENGINE_CLASS_RENDER:
+ return xe_oa_configure_oar_context(stream, enable);
+ case XE_ENGINE_CLASS_COMPUTE:
+ return xe_oa_configure_oac_context(stream, enable);
+ default:
+ /* Video engines do not support MI_REPORT_PERF_COUNT */
+ return 0;
+ }
+}
+
+#define HAS_OA_BPC_REPORTING(xe) (GRAPHICS_VERx100(xe) >= 1255)
+
+static u32 oag_configure_mmio_trigger(const struct xe_oa_stream *stream, bool enable)
+{
+ return _MASKED_FIELD(OAG_OA_DEBUG_DISABLE_MMIO_TRG,
+ enable && stream && stream->sample ?
+ 0 : OAG_OA_DEBUG_DISABLE_MMIO_TRG);
+}
+
+static void xe_oa_disable_metric_set(struct xe_oa_stream *stream)
+{
+ u32 sqcnt1;
+
+ /*
+ * Wa_1508761755:xehpsdv, dg2
+ * Enable thread stall DOP gating and EU DOP gating.
+ */
+ if (stream->oa->xe->info.platform == XE_DG2) {
+ xe_gt_mcr_multicast_write(stream->gt, ROW_CHICKEN,
+ _MASKED_BIT_DISABLE(STALL_DOP_GATING_DISABLE));
+ xe_gt_mcr_multicast_write(stream->gt, ROW_CHICKEN2,
+ _MASKED_BIT_DISABLE(DISABLE_DOP_GATING));
+ }
+
+ xe_mmio_write32(stream->gt, __oa_regs(stream)->oa_debug,
+ oag_configure_mmio_trigger(stream, false));
+
+ /* disable the context save/restore or OAR counters */
+ if (stream->exec_q)
+ xe_oa_configure_oa_context(stream, false);
+
+ /* Make sure we disable noa to save power. */
+ xe_mmio_rmw32(stream->gt, RPM_CONFIG1, GT_NOA_ENABLE, 0);
+
+ sqcnt1 = SQCNT1_PMON_ENABLE |
+ (HAS_OA_BPC_REPORTING(stream->oa->xe) ? SQCNT1_OABPC : 0);
+
+ /* Reset PMON Enable to save power. */
+ xe_mmio_rmw32(stream->gt, XELPMP_SQCNT1, sqcnt1, 0);
+}
+
+static void xe_oa_stream_destroy(struct xe_oa_stream *stream)
+{
+ struct xe_oa_unit *u = stream->hwe->oa_unit;
+ struct xe_gt *gt = stream->hwe->gt;
+
+ if (WARN_ON(stream != u->exclusive_stream))
+ return;
+
+ WRITE_ONCE(u->exclusive_stream, NULL);
+
+ mutex_destroy(&stream->stream_lock);
+
+ xe_oa_disable_metric_set(stream);
+ xe_exec_queue_put(stream->k_exec_q);
+
+ xe_oa_free_oa_buffer(stream);
+
+ XE_WARN_ON(xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL));
+ xe_pm_runtime_put(stream->oa->xe);
+
+ /* Wa_1509372804:pvc: Unset the override of GUCRC mode to enable rc6 */
+ if (stream->override_gucrc)
+ xe_gt_WARN_ON(gt, xe_guc_pc_unset_gucrc_mode(&gt->uc.guc.pc));
+
+ xe_oa_free_configs(stream);
+}
+
+static int xe_oa_alloc_oa_buffer(struct xe_oa_stream *stream)
+{
+ struct xe_bo *bo;
+
+ BUILD_BUG_ON_NOT_POWER_OF_2(XE_OA_BUFFER_SIZE);
+ BUILD_BUG_ON(XE_OA_BUFFER_SIZE < SZ_128K || XE_OA_BUFFER_SIZE > SZ_16M);
+
+ bo = xe_bo_create_pin_map(stream->oa->xe, stream->gt->tile, NULL,
+ XE_OA_BUFFER_SIZE, ttm_bo_type_kernel,
+ XE_BO_FLAG_SYSTEM | XE_BO_FLAG_GGTT);
+ if (IS_ERR(bo))
+ return PTR_ERR(bo);
+
+ stream->oa_buffer.bo = bo;
+ /* mmap implementation requires OA buffer to be in system memory */
+ xe_assert(stream->oa->xe, bo->vmap.is_iomem == 0);
+ stream->oa_buffer.vaddr = bo->vmap.vaddr;
+ return 0;
+}
+
+static struct xe_oa_config_bo *
+__xe_oa_alloc_config_buffer(struct xe_oa_stream *stream, struct xe_oa_config *oa_config)
+{
+ struct xe_oa_config_bo *oa_bo;
+ size_t config_length;
+ struct xe_bb *bb;
+
+ oa_bo = kzalloc(sizeof(*oa_bo), GFP_KERNEL);
+ if (!oa_bo)
+ return ERR_PTR(-ENOMEM);
+
+ config_length = num_lri_dwords(oa_config->regs_len);
+ config_length = ALIGN(sizeof(u32) * config_length, XE_PAGE_SIZE) / sizeof(u32);
+
+ bb = xe_bb_new(stream->gt, config_length, false);
+ if (IS_ERR(bb))
+ goto err_free;
+
+ write_cs_mi_lri(bb, oa_config->regs, oa_config->regs_len);
+
+ oa_bo->bb = bb;
+ oa_bo->oa_config = xe_oa_config_get(oa_config);
+ llist_add(&oa_bo->node, &stream->oa_config_bos);
+
+ return oa_bo;
+err_free:
+ kfree(oa_bo);
+ return ERR_CAST(bb);
+}
+
+static struct xe_oa_config_bo *
+xe_oa_alloc_config_buffer(struct xe_oa_stream *stream, struct xe_oa_config *oa_config)
+{
+ struct xe_oa_config_bo *oa_bo;
+
+ /* Look for the buffer in the already allocated BOs attached to the stream */
+ llist_for_each_entry(oa_bo, stream->oa_config_bos.first, node) {
+ if (oa_bo->oa_config == oa_config &&
+ memcmp(oa_bo->oa_config->uuid, oa_config->uuid,
+ sizeof(oa_config->uuid)) == 0)
+ goto out;
+ }
+
+ oa_bo = __xe_oa_alloc_config_buffer(stream, oa_config);
+out:
+ return oa_bo;
+}
+
+static int xe_oa_emit_oa_config(struct xe_oa_stream *stream, struct xe_oa_config *config)
+{
+#define NOA_PROGRAM_ADDITIONAL_DELAY_US 500
+ struct xe_oa_config_bo *oa_bo;
+ int err, us = NOA_PROGRAM_ADDITIONAL_DELAY_US;
+
+ oa_bo = xe_oa_alloc_config_buffer(stream, config);
+ if (IS_ERR(oa_bo)) {
+ err = PTR_ERR(oa_bo);
+ goto exit;
+ }
+
+ err = xe_oa_submit_bb(stream, oa_bo->bb);
+
+ /* Additional empirical delay needed for NOA programming after registers are written */
+ usleep_range(us, 2 * us);
+exit:
+ return err;
+}
+
+static u32 oag_report_ctx_switches(const struct xe_oa_stream *stream)
+{
+ /* If user didn't require OA reports, ask HW not to emit ctx switch reports */
+ return _MASKED_FIELD(OAG_OA_DEBUG_DISABLE_CTX_SWITCH_REPORTS,
+ stream->sample ?
+ 0 : OAG_OA_DEBUG_DISABLE_CTX_SWITCH_REPORTS);
+}
+
+static int xe_oa_enable_metric_set(struct xe_oa_stream *stream)
+{
+ u32 oa_debug, sqcnt1;
+ int ret;
+
+ /*
+ * Wa_1508761755:xehpsdv, dg2
+ * EU NOA signals behave incorrectly if EU clock gating is enabled.
+ * Disable thread stall DOP gating and EU DOP gating.
+ */
+ if (stream->oa->xe->info.platform == XE_DG2) {
+ xe_gt_mcr_multicast_write(stream->gt, ROW_CHICKEN,
+ _MASKED_BIT_ENABLE(STALL_DOP_GATING_DISABLE));
+ xe_gt_mcr_multicast_write(stream->gt, ROW_CHICKEN2,
+ _MASKED_BIT_ENABLE(DISABLE_DOP_GATING));
+ }
+
+ /* Disable clk ratio reports */
+ oa_debug = OAG_OA_DEBUG_DISABLE_CLK_RATIO_REPORTS |
+ OAG_OA_DEBUG_INCLUDE_CLK_RATIO;
+
+ if (GRAPHICS_VER(stream->oa->xe) >= 20)
+ oa_debug |=
+ /* The three bits below are needed to get PEC counters running */
+ OAG_OA_DEBUG_START_TRIGGER_SCOPE_CONTROL |
+ OAG_OA_DEBUG_DISABLE_START_TRG_2_COUNT_QUAL |
+ OAG_OA_DEBUG_DISABLE_START_TRG_1_COUNT_QUAL;
+
+ xe_mmio_write32(stream->gt, __oa_regs(stream)->oa_debug,
+ _MASKED_BIT_ENABLE(oa_debug) |
+ oag_report_ctx_switches(stream) |
+ oag_configure_mmio_trigger(stream, true));
+
+ xe_mmio_write32(stream->gt, __oa_regs(stream)->oa_ctx_ctrl, stream->periodic ?
+ (OAG_OAGLBCTXCTRL_COUNTER_RESUME |
+ OAG_OAGLBCTXCTRL_TIMER_ENABLE |
+ REG_FIELD_PREP(OAG_OAGLBCTXCTRL_TIMER_PERIOD_MASK,
+ stream->period_exponent)) : 0);
+
+ /*
+ * Initialize Super Queue Internal Cnt Register
+ * Set PMON Enable in order to collect valid metrics
+ * Enable bytes per clock reporting
+ */
+ sqcnt1 = SQCNT1_PMON_ENABLE |
+ (HAS_OA_BPC_REPORTING(stream->oa->xe) ? SQCNT1_OABPC : 0);
+
+ xe_mmio_rmw32(stream->gt, XELPMP_SQCNT1, 0, sqcnt1);
+
+ /* Configure OAR/OAC */
+ if (stream->exec_q) {
+ ret = xe_oa_configure_oa_context(stream, true);
+ if (ret)
+ return ret;
+ }
+
+ return xe_oa_emit_oa_config(stream, stream->oa_config);
+}
+
+static void xe_oa_stream_enable(struct xe_oa_stream *stream)
+{
+ stream->pollin = false;
+
+ xe_oa_enable(stream);
+
+ if (stream->sample)
+ hrtimer_start(&stream->poll_check_timer,
+ ns_to_ktime(stream->poll_period_ns),
+ HRTIMER_MODE_REL_PINNED);
+}
+
+static void xe_oa_stream_disable(struct xe_oa_stream *stream)
+{
+ xe_oa_disable(stream);
+
+ if (stream->sample)
+ hrtimer_cancel(&stream->poll_check_timer);
+}
+
+static int xe_oa_enable_preempt_timeslice(struct xe_oa_stream *stream)
+{
+ struct xe_exec_queue *q = stream->exec_q;
+ int ret1, ret2;
+
+ /* Best effort recovery: try to revert both to original, irrespective of error */
+ ret1 = q->ops->set_timeslice(q, stream->hwe->eclass->sched_props.timeslice_us);
+ ret2 = q->ops->set_preempt_timeout(q, stream->hwe->eclass->sched_props.preempt_timeout_us);
+ if (ret1 || ret2)
+ goto err;
+ return 0;
+err:
+ drm_dbg(&stream->oa->xe->drm, "%s failed ret1 %d ret2 %d\n", __func__, ret1, ret2);
+ return ret1 ?: ret2;
+}
+
+static int xe_oa_disable_preempt_timeslice(struct xe_oa_stream *stream)
+{
+ struct xe_exec_queue *q = stream->exec_q;
+ int ret;
+
+ /* Setting values to 0 will disable timeslice and preempt_timeout */
+ ret = q->ops->set_timeslice(q, 0);
+ if (ret)
+ goto err;
+
+ ret = q->ops->set_preempt_timeout(q, 0);
+ if (ret)
+ goto err;
+
+ return 0;
+err:
+ xe_oa_enable_preempt_timeslice(stream);
+ drm_dbg(&stream->oa->xe->drm, "%s failed %d\n", __func__, ret);
+ return ret;
+}
+
+static int xe_oa_enable_locked(struct xe_oa_stream *stream)
+{
+ if (stream->enabled)
+ return 0;
+
+ if (stream->no_preempt) {
+ int ret = xe_oa_disable_preempt_timeslice(stream);
+
+ if (ret)
+ return ret;
+ }
+
+ xe_oa_stream_enable(stream);
+
+ stream->enabled = true;
+ return 0;
+}
+
+static int xe_oa_disable_locked(struct xe_oa_stream *stream)
+{
+ int ret = 0;
+
+ if (!stream->enabled)
+ return 0;
+
+ xe_oa_stream_disable(stream);
+
+ if (stream->no_preempt)
+ ret = xe_oa_enable_preempt_timeslice(stream);
+
+ stream->enabled = false;
+ return ret;
+}
+
+static long xe_oa_config_locked(struct xe_oa_stream *stream, u64 arg)
+{
+ struct drm_xe_ext_set_property ext;
+ long ret = stream->oa_config->id;
+ struct xe_oa_config *config;
+ int err;
+
+ err = __copy_from_user(&ext, u64_to_user_ptr(arg), sizeof(ext));
+ if (XE_IOCTL_DBG(stream->oa->xe, err))
+ return -EFAULT;
+
+ if (XE_IOCTL_DBG(stream->oa->xe, ext.pad) ||
+ XE_IOCTL_DBG(stream->oa->xe, ext.base.name != DRM_XE_OA_EXTENSION_SET_PROPERTY) ||
+ XE_IOCTL_DBG(stream->oa->xe, ext.base.next_extension) ||
+ XE_IOCTL_DBG(stream->oa->xe, ext.property != DRM_XE_OA_PROPERTY_OA_METRIC_SET))
+ return -EINVAL;
+
+ config = xe_oa_get_oa_config(stream->oa, ext.value);
+ if (!config)
+ return -ENODEV;
+
+ if (config != stream->oa_config) {
+ err = xe_oa_emit_oa_config(stream, config);
+ if (!err)
+ config = xchg(&stream->oa_config, config);
+ else
+ ret = err;
+ }
+
+ xe_oa_config_put(config);
+
+ return ret;
+}
+
+static long xe_oa_status_locked(struct xe_oa_stream *stream, unsigned long arg)
+{
+ struct drm_xe_oa_stream_status status = {};
+ void __user *uaddr = (void __user *)arg;
+
+ /* Map from register to uapi bits */
+ if (stream->oa_status & OASTATUS_REPORT_LOST)
+ status.oa_status |= DRM_XE_OASTATUS_REPORT_LOST;
+ if (stream->oa_status & OASTATUS_BUFFER_OVERFLOW)
+ status.oa_status |= DRM_XE_OASTATUS_BUFFER_OVERFLOW;
+ if (stream->oa_status & OASTATUS_COUNTER_OVERFLOW)
+ status.oa_status |= DRM_XE_OASTATUS_COUNTER_OVERFLOW;
+ if (stream->oa_status & OASTATUS_MMIO_TRG_Q_FULL)
+ status.oa_status |= DRM_XE_OASTATUS_MMIO_TRG_Q_FULL;
+
+ if (copy_to_user(uaddr, &status, sizeof(status)))
+ return -EFAULT;
+
+ return 0;
+}
+
+static long xe_oa_info_locked(struct xe_oa_stream *stream, unsigned long arg)
+{
+ struct drm_xe_oa_stream_info info = { .oa_buf_size = XE_OA_BUFFER_SIZE, };
+ void __user *uaddr = (void __user *)arg;
+
+ if (copy_to_user(uaddr, &info, sizeof(info)))
+ return -EFAULT;
+
+ return 0;
+}
+
+static long xe_oa_ioctl_locked(struct xe_oa_stream *stream,
+ unsigned int cmd,
+ unsigned long arg)
+{
+ switch (cmd) {
+ case DRM_XE_OBSERVATION_IOCTL_ENABLE:
+ return xe_oa_enable_locked(stream);
+ case DRM_XE_OBSERVATION_IOCTL_DISABLE:
+ return xe_oa_disable_locked(stream);
+ case DRM_XE_OBSERVATION_IOCTL_CONFIG:
+ return xe_oa_config_locked(stream, arg);
+ case DRM_XE_OBSERVATION_IOCTL_STATUS:
+ return xe_oa_status_locked(stream, arg);
+ case DRM_XE_OBSERVATION_IOCTL_INFO:
+ return xe_oa_info_locked(stream, arg);
+ }
+
+ return -EINVAL;
+}
+
+static long xe_oa_ioctl(struct file *file,
+ unsigned int cmd,
+ unsigned long arg)
+{
+ struct xe_oa_stream *stream = file->private_data;
+ long ret;
+
+ mutex_lock(&stream->stream_lock);
+ ret = xe_oa_ioctl_locked(stream, cmd, arg);
+ mutex_unlock(&stream->stream_lock);
+
+ return ret;
+}
+
+static void xe_oa_destroy_locked(struct xe_oa_stream *stream)
+{
+ if (stream->enabled)
+ xe_oa_disable_locked(stream);
+
+ xe_oa_stream_destroy(stream);
+
+ if (stream->exec_q)
+ xe_exec_queue_put(stream->exec_q);
+
+ kfree(stream);
+}
+
+static int xe_oa_release(struct inode *inode, struct file *file)
+{
+ struct xe_oa_stream *stream = file->private_data;
+ struct xe_gt *gt = stream->gt;
+
+ mutex_lock(&gt->oa.gt_lock);
+ xe_oa_destroy_locked(stream);
+ mutex_unlock(&gt->oa.gt_lock);
+
+ /* Release the reference the OA stream kept on the driver */
+ drm_dev_put(&gt_to_xe(gt)->drm);
+
+ return 0;
+}
+
+static int xe_oa_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct xe_oa_stream *stream = file->private_data;
+ struct xe_bo *bo = stream->oa_buffer.bo;
+ unsigned long start = vma->vm_start;
+ int i, ret;
+
+ if (xe_observation_paranoid && !perfmon_capable()) {
+ drm_dbg(&stream->oa->xe->drm, "Insufficient privilege to map OA buffer\n");
+ return -EACCES;
+ }
+
+ /* Can mmap the entire OA buffer or nothing (no partial OA buffer mmaps) */
+ if (vma->vm_end - vma->vm_start != XE_OA_BUFFER_SIZE) {
+ drm_dbg(&stream->oa->xe->drm, "Wrong mmap size, must be OA buffer size\n");
+ return -EINVAL;
+ }
+
+ /*
+ * Only support VM_READ, enforce MAP_PRIVATE by checking for
+ * VM_MAYSHARE, don't copy the vma on fork
+ */
+ if (vma->vm_flags & (VM_WRITE | VM_EXEC | VM_SHARED | VM_MAYSHARE)) {
+ drm_dbg(&stream->oa->xe->drm, "mmap must be read only\n");
+ return -EINVAL;
+ }
+ vm_flags_mod(vma, VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP | VM_DONTCOPY,
+ VM_MAYWRITE | VM_MAYEXEC);
+
+ xe_assert(stream->oa->xe, bo->ttm.ttm->num_pages ==
+ (vma->vm_end - vma->vm_start) >> PAGE_SHIFT);
+ for (i = 0; i < bo->ttm.ttm->num_pages; i++) {
+ ret = remap_pfn_range(vma, start, page_to_pfn(bo->ttm.ttm->pages[i]),
+ PAGE_SIZE, vma->vm_page_prot);
+ if (ret)
+ break;
+
+ start += PAGE_SIZE;
+ }
+
+ return ret;
+}
+
+static const struct file_operations xe_oa_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .release = xe_oa_release,
+ .poll = xe_oa_poll,
+ .read = xe_oa_read,
+ .unlocked_ioctl = xe_oa_ioctl,
+ .mmap = xe_oa_mmap,
+};
+
+static bool engine_supports_mi_query(struct xe_hw_engine *hwe)
+{
+ return hwe->class == XE_ENGINE_CLASS_RENDER ||
+ hwe->class == XE_ENGINE_CLASS_COMPUTE;
+}
+
+static bool xe_oa_find_reg_in_lri(u32 *state, u32 reg, u32 *offset, u32 end)
+{
+ u32 idx = *offset;
+ u32 len = min(MI_LRI_LEN(state[idx]) + idx, end);
+ bool found = false;
+
+ idx++;
+ for (; idx < len; idx += 2) {
+ if (state[idx] == reg) {
+ found = true;
+ break;
+ }
+ }
+
+ *offset = idx;
+ return found;
+}
+
+#define IS_MI_LRI_CMD(x) (REG_FIELD_GET(MI_OPCODE, (x)) == \
+ REG_FIELD_GET(MI_OPCODE, MI_LOAD_REGISTER_IMM))
+
+static u32 xe_oa_context_image_offset(struct xe_oa_stream *stream, u32 reg)
+{
+ struct xe_lrc *lrc = stream->exec_q->lrc[0];
+ u32 len = (xe_gt_lrc_size(stream->gt, stream->hwe->class) +
+ lrc->ring.size) / sizeof(u32);
+ u32 offset = xe_lrc_regs_offset(lrc) / sizeof(u32);
+ u32 *state = (u32 *)lrc->bo->vmap.vaddr;
+
+ if (drm_WARN_ON(&stream->oa->xe->drm, !state))
+ return U32_MAX;
+
+ for (; offset < len; ) {
+ if (IS_MI_LRI_CMD(state[offset])) {
+ /*
+ * We expect reg-value pairs in MI_LRI command, so
+ * MI_LRI_LEN() should be even
+ */
+ drm_WARN_ON(&stream->oa->xe->drm,
+ MI_LRI_LEN(state[offset]) & 0x1);
+
+ if (xe_oa_find_reg_in_lri(state, reg, &offset, len))
+ break;
+ } else {
+ offset++;
+ }
+ }
+
+ return offset < len ? offset : U32_MAX;
+}
+
+static int xe_oa_set_ctx_ctrl_offset(struct xe_oa_stream *stream)
+{
+ struct xe_reg reg = OACTXCONTROL(stream->hwe->mmio_base);
+ u32 offset = stream->oa->ctx_oactxctrl_offset[stream->hwe->class];
+
+ /* Do this only once. Failure is stored as offset of U32_MAX */
+ if (offset)
+ goto exit;
+
+ offset = xe_oa_context_image_offset(stream, reg.addr);
+ stream->oa->ctx_oactxctrl_offset[stream->hwe->class] = offset;
+
+ drm_dbg(&stream->oa->xe->drm, "%s oa ctx control at 0x%08x dword offset\n",
+ stream->hwe->name, offset);
+exit:
+ return offset && offset != U32_MAX ? 0 : -ENODEV;
+}
+
+static int xe_oa_stream_init(struct xe_oa_stream *stream,
+ struct xe_oa_open_param *param)
+{
+ struct xe_oa_unit *u = param->hwe->oa_unit;
+ struct xe_gt *gt = param->hwe->gt;
+ int ret;
+
+ stream->exec_q = param->exec_q;
+ stream->poll_period_ns = DEFAULT_POLL_PERIOD_NS;
+ stream->hwe = param->hwe;
+ stream->gt = stream->hwe->gt;
+ stream->oa_buffer.format = &stream->oa->oa_formats[param->oa_format];
+
+ stream->sample = param->sample;
+ stream->periodic = param->period_exponent > 0;
+ stream->period_exponent = param->period_exponent;
+ stream->no_preempt = param->no_preempt;
+
+ /*
+ * For Xe2+, when overrun mode is enabled, there are no partial reports at the end
+ * of buffer, making the OA buffer effectively a non-power-of-2 size circular
+ * buffer whose size, circ_size, is a multiple of the report size
+ */
+ if (GRAPHICS_VER(stream->oa->xe) >= 20 &&
+ stream->hwe->oa_unit->type == DRM_XE_OA_UNIT_TYPE_OAG && stream->sample)
+ stream->oa_buffer.circ_size =
+ XE_OA_BUFFER_SIZE - XE_OA_BUFFER_SIZE % stream->oa_buffer.format->size;
+ else
+ stream->oa_buffer.circ_size = XE_OA_BUFFER_SIZE;
+
+ if (stream->exec_q && engine_supports_mi_query(stream->hwe)) {
+ /* If we don't find the context offset, just return error */
+ ret = xe_oa_set_ctx_ctrl_offset(stream);
+ if (ret) {
+ drm_err(&stream->oa->xe->drm,
+ "xe_oa_set_ctx_ctrl_offset failed for %s\n",
+ stream->hwe->name);
+ goto exit;
+ }
+ }
+
+ stream->oa_config = xe_oa_get_oa_config(stream->oa, param->metric_set);
+ if (!stream->oa_config) {
+ drm_dbg(&stream->oa->xe->drm, "Invalid OA config id=%i\n", param->metric_set);
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ /*
+ * Wa_1509372804:pvc
+ *
+ * GuC reset of engines causes OA to lose configuration
+ * state. Prevent this by overriding GUCRC mode.
+ */
+ if (stream->oa->xe->info.platform == XE_PVC) {
+ ret = xe_guc_pc_override_gucrc_mode(&gt->uc.guc.pc,
+ SLPC_GUCRC_MODE_GUCRC_NO_RC6);
+ if (ret)
+ goto err_free_configs;
+
+ stream->override_gucrc = true;
+ }
+
+ /* Take runtime pm ref and forcewake to disable RC6 */
+ xe_pm_runtime_get(stream->oa->xe);
+ XE_WARN_ON(xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL));
+
+ ret = xe_oa_alloc_oa_buffer(stream);
+ if (ret)
+ goto err_fw_put;
+
+ stream->k_exec_q = xe_exec_queue_create(stream->oa->xe, NULL,
+ BIT(stream->hwe->logical_instance), 1,
+ stream->hwe, EXEC_QUEUE_FLAG_KERNEL, 0);
+ if (IS_ERR(stream->k_exec_q)) {
+ ret = PTR_ERR(stream->k_exec_q);
+ drm_err(&stream->oa->xe->drm, "gt%d, hwe %s, xe_exec_queue_create failed=%d",
+ stream->gt->info.id, stream->hwe->name, ret);
+ goto err_free_oa_buf;
+ }
+
+ ret = xe_oa_enable_metric_set(stream);
+ if (ret) {
+ drm_dbg(&stream->oa->xe->drm, "Unable to enable metric set\n");
+ goto err_put_k_exec_q;
+ }
+
+ drm_dbg(&stream->oa->xe->drm, "opening stream oa config uuid=%s\n",
+ stream->oa_config->uuid);
+
+ WRITE_ONCE(u->exclusive_stream, stream);
+
+ hrtimer_init(&stream->poll_check_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ stream->poll_check_timer.function = xe_oa_poll_check_timer_cb;
+ init_waitqueue_head(&stream->poll_wq);
+
+ spin_lock_init(&stream->oa_buffer.ptr_lock);
+ mutex_init(&stream->stream_lock);
+
+ return 0;
+
+err_put_k_exec_q:
+ xe_oa_disable_metric_set(stream);
+ xe_exec_queue_put(stream->k_exec_q);
+err_free_oa_buf:
+ xe_oa_free_oa_buffer(stream);
+err_fw_put:
+ XE_WARN_ON(xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL));
+ xe_pm_runtime_put(stream->oa->xe);
+ if (stream->override_gucrc)
+ xe_gt_WARN_ON(gt, xe_guc_pc_unset_gucrc_mode(&gt->uc.guc.pc));
+err_free_configs:
+ xe_oa_free_configs(stream);
+exit:
+ return ret;
+}
+
+static int xe_oa_stream_open_ioctl_locked(struct xe_oa *oa,
+ struct xe_oa_open_param *param)
+{
+ struct xe_oa_stream *stream;
+ int stream_fd;
+ int ret;
+
+ /* We currently only allow exclusive access */
+ if (param->hwe->oa_unit->exclusive_stream) {
+ drm_dbg(&oa->xe->drm, "OA unit already in use\n");
+ ret = -EBUSY;
+ goto exit;
+ }
+
+ stream = kzalloc(sizeof(*stream), GFP_KERNEL);
+ if (!stream) {
+ ret = -ENOMEM;
+ goto exit;
+ }
+
+ stream->oa = oa;
+ ret = xe_oa_stream_init(stream, param);
+ if (ret)
+ goto err_free;
+
+ if (!param->disabled) {
+ ret = xe_oa_enable_locked(stream);
+ if (ret)
+ goto err_destroy;
+ }
+
+ stream_fd = anon_inode_getfd("[xe_oa]", &xe_oa_fops, stream, 0);
+ if (stream_fd < 0) {
+ ret = stream_fd;
+ goto err_disable;
+ }
+
+ /* Hold a reference on the drm device till stream_fd is released */
+ drm_dev_get(&stream->oa->xe->drm);
+
+ return stream_fd;
+err_disable:
+ if (!param->disabled)
+ xe_oa_disable_locked(stream);
+err_destroy:
+ xe_oa_stream_destroy(stream);
+err_free:
+ kfree(stream);
+exit:
+ return ret;
+}
+
+/**
+ * xe_oa_timestamp_frequency - Return OA timestamp frequency
+ * @gt: @xe_gt
+ *
+ * OA timestamp frequency = CS timestamp frequency in most platforms. On some
+ * platforms OA unit ignores the CTC_SHIFT and the 2 timestamps differ. In such
+ * cases, return the adjusted CS timestamp frequency to the user.
+ */
+u32 xe_oa_timestamp_frequency(struct xe_gt *gt)
+{
+ u32 reg, shift;
+
+ /*
+ * Wa_18013179988:dg2
+ * Wa_14015568240:pvc
+ * Wa_14015846243:mtl
+ */
+ switch (gt_to_xe(gt)->info.platform) {
+ case XE_DG2:
+ case XE_PVC:
+ case XE_METEORLAKE:
+ xe_pm_runtime_get(gt_to_xe(gt));
+ reg = xe_mmio_read32(gt, RPM_CONFIG0);
+ xe_pm_runtime_put(gt_to_xe(gt));
+
+ shift = REG_FIELD_GET(RPM_CONFIG0_CTC_SHIFT_PARAMETER_MASK, reg);
+ return gt->info.reference_clock << (3 - shift);
+
+ default:
+ return gt->info.reference_clock;
+ }
+}
+
+static u64 oa_exponent_to_ns(struct xe_gt *gt, int exponent)
+{
+ u64 nom = (2ULL << exponent) * NSEC_PER_SEC;
+ u32 den = xe_oa_timestamp_frequency(gt);
+
+ return div_u64(nom + den - 1, den);
+}
+
+static bool engine_supports_oa_format(const struct xe_hw_engine *hwe, int type)
+{
+ switch (hwe->oa_unit->type) {
+ case DRM_XE_OA_UNIT_TYPE_OAG:
+ return type == DRM_XE_OA_FMT_TYPE_OAG || type == DRM_XE_OA_FMT_TYPE_OAR ||
+ type == DRM_XE_OA_FMT_TYPE_OAC || type == DRM_XE_OA_FMT_TYPE_PEC;
+ case DRM_XE_OA_UNIT_TYPE_OAM:
+ return type == DRM_XE_OA_FMT_TYPE_OAM || type == DRM_XE_OA_FMT_TYPE_OAM_MPEC;
+ default:
+ return false;
+ }
+}
+
+static int decode_oa_format(struct xe_oa *oa, u64 fmt, enum xe_oa_format_name *name)
+{
+ u32 counter_size = FIELD_GET(DRM_XE_OA_FORMAT_MASK_COUNTER_SIZE, fmt);
+ u32 counter_sel = FIELD_GET(DRM_XE_OA_FORMAT_MASK_COUNTER_SEL, fmt);
+ u32 bc_report = FIELD_GET(DRM_XE_OA_FORMAT_MASK_BC_REPORT, fmt);
+ u32 type = FIELD_GET(DRM_XE_OA_FORMAT_MASK_FMT_TYPE, fmt);
+ int idx;
+
+ for_each_set_bit(idx, oa->format_mask, __XE_OA_FORMAT_MAX) {
+ const struct xe_oa_format *f = &oa->oa_formats[idx];
+
+ if (counter_size == f->counter_size && bc_report == f->bc_report &&
+ type == f->type && counter_sel == f->counter_select) {
+ *name = idx;
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+/**
+ * xe_oa_unit_id - Return OA unit ID for a hardware engine
+ * @hwe: @xe_hw_engine
+ *
+ * Return OA unit ID for a hardware engine when available
+ */
+u16 xe_oa_unit_id(struct xe_hw_engine *hwe)
+{
+ return hwe->oa_unit && hwe->oa_unit->num_engines ?
+ hwe->oa_unit->oa_unit_id : U16_MAX;
+}
+
+static int xe_oa_assign_hwe(struct xe_oa *oa, struct xe_oa_open_param *param)
+{
+ struct xe_gt *gt;
+ int i, ret = 0;
+
+ if (param->exec_q) {
+ /* When we have an exec_q, get hwe from the exec_q */
+ param->hwe = xe_gt_hw_engine(param->exec_q->gt, param->exec_q->class,
+ param->engine_instance, true);
+ } else {
+ struct xe_hw_engine *hwe;
+ enum xe_hw_engine_id id;
+
+ /* Else just get the first hwe attached to the oa unit */
+ for_each_gt(gt, oa->xe, i) {
+ for_each_hw_engine(hwe, gt, id) {
+ if (xe_oa_unit_id(hwe) == param->oa_unit_id) {
+ param->hwe = hwe;
+ goto out;
+ }
+ }
+ }
+ }
+out:
+ if (!param->hwe || xe_oa_unit_id(param->hwe) != param->oa_unit_id) {
+ drm_dbg(&oa->xe->drm, "Unable to find hwe (%d, %d) for OA unit ID %d\n",
+ param->exec_q ? param->exec_q->class : -1,
+ param->engine_instance, param->oa_unit_id);
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int xe_oa_set_prop_oa_unit_id(struct xe_oa *oa, u64 value,
+ struct xe_oa_open_param *param)
+{
+ if (value >= oa->oa_unit_ids) {
+ drm_dbg(&oa->xe->drm, "OA unit ID out of range %lld\n", value);
+ return -EINVAL;
+ }
+ param->oa_unit_id = value;
+ return 0;
+}
+
+static int xe_oa_set_prop_sample_oa(struct xe_oa *oa, u64 value,
+ struct xe_oa_open_param *param)
+{
+ param->sample = value;
+ return 0;
+}
+
+static int xe_oa_set_prop_metric_set(struct xe_oa *oa, u64 value,
+ struct xe_oa_open_param *param)
+{
+ param->metric_set = value;
+ return 0;
+}
+
+static int xe_oa_set_prop_oa_format(struct xe_oa *oa, u64 value,
+ struct xe_oa_open_param *param)
+{
+ int ret = decode_oa_format(oa, value, &param->oa_format);
+
+ if (ret) {
+ drm_dbg(&oa->xe->drm, "Unsupported OA report format %#llx\n", value);
+ return ret;
+ }
+ return 0;
+}
+
+static int xe_oa_set_prop_oa_exponent(struct xe_oa *oa, u64 value,
+ struct xe_oa_open_param *param)
+{
+#define OA_EXPONENT_MAX 31
+
+ if (value > OA_EXPONENT_MAX) {
+ drm_dbg(&oa->xe->drm, "OA timer exponent too high (> %u)\n", OA_EXPONENT_MAX);
+ return -EINVAL;
+ }
+ param->period_exponent = value;
+ return 0;
+}
+
+static int xe_oa_set_prop_disabled(struct xe_oa *oa, u64 value,
+ struct xe_oa_open_param *param)
+{
+ param->disabled = value;
+ return 0;
+}
+
+static int xe_oa_set_prop_exec_queue_id(struct xe_oa *oa, u64 value,
+ struct xe_oa_open_param *param)
+{
+ param->exec_queue_id = value;
+ return 0;
+}
+
+static int xe_oa_set_prop_engine_instance(struct xe_oa *oa, u64 value,
+ struct xe_oa_open_param *param)
+{
+ param->engine_instance = value;
+ return 0;
+}
+
+static int xe_oa_set_no_preempt(struct xe_oa *oa, u64 value,
+ struct xe_oa_open_param *param)
+{
+ param->no_preempt = value;
+ return 0;
+}
+
+typedef int (*xe_oa_set_property_fn)(struct xe_oa *oa, u64 value,
+ struct xe_oa_open_param *param);
+static const xe_oa_set_property_fn xe_oa_set_property_funcs[] = {
+ [DRM_XE_OA_PROPERTY_OA_UNIT_ID] = xe_oa_set_prop_oa_unit_id,
+ [DRM_XE_OA_PROPERTY_SAMPLE_OA] = xe_oa_set_prop_sample_oa,
+ [DRM_XE_OA_PROPERTY_OA_METRIC_SET] = xe_oa_set_prop_metric_set,
+ [DRM_XE_OA_PROPERTY_OA_FORMAT] = xe_oa_set_prop_oa_format,
+ [DRM_XE_OA_PROPERTY_OA_PERIOD_EXPONENT] = xe_oa_set_prop_oa_exponent,
+ [DRM_XE_OA_PROPERTY_OA_DISABLED] = xe_oa_set_prop_disabled,
+ [DRM_XE_OA_PROPERTY_EXEC_QUEUE_ID] = xe_oa_set_prop_exec_queue_id,
+ [DRM_XE_OA_PROPERTY_OA_ENGINE_INSTANCE] = xe_oa_set_prop_engine_instance,
+ [DRM_XE_OA_PROPERTY_NO_PREEMPT] = xe_oa_set_no_preempt,
+};
+
+static int xe_oa_user_ext_set_property(struct xe_oa *oa, u64 extension,
+ struct xe_oa_open_param *param)
+{
+ u64 __user *address = u64_to_user_ptr(extension);
+ struct drm_xe_ext_set_property ext;
+ int err;
+ u32 idx;
+
+ err = __copy_from_user(&ext, address, sizeof(ext));
+ if (XE_IOCTL_DBG(oa->xe, err))
+ return -EFAULT;
+
+ if (XE_IOCTL_DBG(oa->xe, ext.property >= ARRAY_SIZE(xe_oa_set_property_funcs)) ||
+ XE_IOCTL_DBG(oa->xe, ext.pad))
+ return -EINVAL;
+
+ idx = array_index_nospec(ext.property, ARRAY_SIZE(xe_oa_set_property_funcs));
+ return xe_oa_set_property_funcs[idx](oa, ext.value, param);
+}
+
+typedef int (*xe_oa_user_extension_fn)(struct xe_oa *oa, u64 extension,
+ struct xe_oa_open_param *param);
+static const xe_oa_user_extension_fn xe_oa_user_extension_funcs[] = {
+ [DRM_XE_OA_EXTENSION_SET_PROPERTY] = xe_oa_user_ext_set_property,
+};
+
+#define MAX_USER_EXTENSIONS 16
+static int xe_oa_user_extensions(struct xe_oa *oa, u64 extension, int ext_number,
+ struct xe_oa_open_param *param)
+{
+ u64 __user *address = u64_to_user_ptr(extension);
+ struct drm_xe_user_extension ext;
+ int err;
+ u32 idx;
+
+ if (XE_IOCTL_DBG(oa->xe, ext_number >= MAX_USER_EXTENSIONS))
+ return -E2BIG;
+
+ err = __copy_from_user(&ext, address, sizeof(ext));
+ if (XE_IOCTL_DBG(oa->xe, err))
+ return -EFAULT;
+
+ if (XE_IOCTL_DBG(oa->xe, ext.pad) ||
+ XE_IOCTL_DBG(oa->xe, ext.name >= ARRAY_SIZE(xe_oa_user_extension_funcs)))
+ return -EINVAL;
+
+ idx = array_index_nospec(ext.name, ARRAY_SIZE(xe_oa_user_extension_funcs));
+ err = xe_oa_user_extension_funcs[idx](oa, extension, param);
+ if (XE_IOCTL_DBG(oa->xe, err))
+ return err;
+
+ if (ext.next_extension)
+ return xe_oa_user_extensions(oa, ext.next_extension, ++ext_number, param);
+
+ return 0;
+}
+
+/**
+ * xe_oa_stream_open_ioctl - Opens an OA stream
+ * @dev: @drm_device
+ * @data: pointer to struct @drm_xe_oa_config
+ * @file: @drm_file
+ *
+ * The functions opens an OA stream. An OA stream, opened with specified
+ * properties, enables OA counter samples to be collected, either
+ * periodically (time based sampling), or on request (using OA queries)
+ */
+int xe_oa_stream_open_ioctl(struct drm_device *dev, u64 data, struct drm_file *file)
+{
+ struct xe_device *xe = to_xe_device(dev);
+ struct xe_oa *oa = &xe->oa;
+ struct xe_file *xef = to_xe_file(file);
+ struct xe_oa_open_param param = {};
+ const struct xe_oa_format *f;
+ bool privileged_op = true;
+ int ret;
+
+ if (!oa->xe) {
+ drm_dbg(&xe->drm, "xe oa interface not available for this system\n");
+ return -ENODEV;
+ }
+
+ ret = xe_oa_user_extensions(oa, data, 0, &param);
+ if (ret)
+ return ret;
+
+ if (param.exec_queue_id > 0) {
+ param.exec_q = xe_exec_queue_lookup(xef, param.exec_queue_id);
+ if (XE_IOCTL_DBG(oa->xe, !param.exec_q))
+ return -ENOENT;
+
+ if (param.exec_q->width > 1)
+ drm_dbg(&oa->xe->drm, "exec_q->width > 1, programming only exec_q->lrc[0]\n");
+ }
+
+ /*
+ * Query based sampling (using MI_REPORT_PERF_COUNT) with OAR/OAC,
+ * without global stream access, can be an unprivileged operation
+ */
+ if (param.exec_q && !param.sample)
+ privileged_op = false;
+
+ if (param.no_preempt) {
+ if (!param.exec_q) {
+ drm_dbg(&oa->xe->drm, "Preemption disable without exec_q!\n");
+ ret = -EINVAL;
+ goto err_exec_q;
+ }
+ privileged_op = true;
+ }
+
+ if (privileged_op && xe_observation_paranoid && !perfmon_capable()) {
+ drm_dbg(&oa->xe->drm, "Insufficient privileges to open xe OA stream\n");
+ ret = -EACCES;
+ goto err_exec_q;
+ }
+
+ if (!param.exec_q && !param.sample) {
+ drm_dbg(&oa->xe->drm, "Only OA report sampling supported\n");
+ ret = -EINVAL;
+ goto err_exec_q;
+ }
+
+ ret = xe_oa_assign_hwe(oa, &param);
+ if (ret)
+ goto err_exec_q;
+
+ f = &oa->oa_formats[param.oa_format];
+ if (!param.oa_format || !f->size ||
+ !engine_supports_oa_format(param.hwe, f->type)) {
+ drm_dbg(&oa->xe->drm, "Invalid OA format %d type %d size %d for class %d\n",
+ param.oa_format, f->type, f->size, param.hwe->class);
+ ret = -EINVAL;
+ goto err_exec_q;
+ }
+
+ if (param.period_exponent > 0) {
+ u64 oa_period, oa_freq_hz;
+
+ /* Requesting samples from OAG buffer is a privileged operation */
+ if (!param.sample) {
+ drm_dbg(&oa->xe->drm, "OA_EXPONENT specified without SAMPLE_OA\n");
+ ret = -EINVAL;
+ goto err_exec_q;
+ }
+ oa_period = oa_exponent_to_ns(param.hwe->gt, param.period_exponent);
+ oa_freq_hz = div64_u64(NSEC_PER_SEC, oa_period);
+ drm_dbg(&oa->xe->drm, "Using periodic sampling freq %lld Hz\n", oa_freq_hz);
+ }
+
+ mutex_lock(&param.hwe->gt->oa.gt_lock);
+ ret = xe_oa_stream_open_ioctl_locked(oa, &param);
+ mutex_unlock(&param.hwe->gt->oa.gt_lock);
+err_exec_q:
+ if (ret < 0 && param.exec_q)
+ xe_exec_queue_put(param.exec_q);
+ return ret;
+}
+
+static bool xe_oa_is_valid_flex_addr(struct xe_oa *oa, u32 addr)
+{
+ static const struct xe_reg flex_eu_regs[] = {
+ EU_PERF_CNTL0,
+ EU_PERF_CNTL1,
+ EU_PERF_CNTL2,
+ EU_PERF_CNTL3,
+ EU_PERF_CNTL4,
+ EU_PERF_CNTL5,
+ EU_PERF_CNTL6,
+ };
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(flex_eu_regs); i++) {
+ if (flex_eu_regs[i].addr == addr)
+ return true;
+ }
+ return false;
+}
+
+static bool xe_oa_reg_in_range_table(u32 addr, const struct xe_mmio_range *table)
+{
+ while (table->start && table->end) {
+ if (addr >= table->start && addr <= table->end)
+ return true;
+
+ table++;
+ }
+
+ return false;
+}
+
+static const struct xe_mmio_range xehp_oa_b_counters[] = {
+ { .start = 0xdc48, .end = 0xdc48 }, /* OAA_ENABLE_REG */
+ { .start = 0xdd00, .end = 0xdd48 }, /* OAG_LCE0_0 - OAA_LENABLE_REG */
+ {}
+};
+
+static const struct xe_mmio_range gen12_oa_b_counters[] = {
+ { .start = 0x2b2c, .end = 0x2b2c }, /* OAG_OA_PESS */
+ { .start = 0xd900, .end = 0xd91c }, /* OAG_OASTARTTRIG[1-8] */
+ { .start = 0xd920, .end = 0xd93c }, /* OAG_OAREPORTTRIG1[1-8] */
+ { .start = 0xd940, .end = 0xd97c }, /* OAG_CEC[0-7][0-1] */
+ { .start = 0xdc00, .end = 0xdc3c }, /* OAG_SCEC[0-7][0-1] */
+ { .start = 0xdc40, .end = 0xdc40 }, /* OAG_SPCTR_CNF */
+ { .start = 0xdc44, .end = 0xdc44 }, /* OAA_DBG_REG */
+ {}
+};
+
+static const struct xe_mmio_range mtl_oam_b_counters[] = {
+ { .start = 0x393000, .end = 0x39301c }, /* OAM_STARTTRIG1[1-8] */
+ { .start = 0x393020, .end = 0x39303c }, /* OAM_REPORTTRIG1[1-8] */
+ { .start = 0x393040, .end = 0x39307c }, /* OAM_CEC[0-7][0-1] */
+ { .start = 0x393200, .end = 0x39323C }, /* MPES[0-7] */
+ {}
+};
+
+static const struct xe_mmio_range xe2_oa_b_counters[] = {
+ { .start = 0x393200, .end = 0x39323C }, /* MPES_0_MPES_SAG - MPES_7_UPPER_MPES_SAG */
+ { .start = 0x394200, .end = 0x39423C }, /* MPES_0_MPES_SCMI0 - MPES_7_UPPER_MPES_SCMI0 */
+ { .start = 0x394A00, .end = 0x394A3C }, /* MPES_0_MPES_SCMI1 - MPES_7_UPPER_MPES_SCMI1 */
+ {},
+};
+
+static bool xe_oa_is_valid_b_counter_addr(struct xe_oa *oa, u32 addr)
+{
+ return xe_oa_reg_in_range_table(addr, xehp_oa_b_counters) ||
+ xe_oa_reg_in_range_table(addr, gen12_oa_b_counters) ||
+ xe_oa_reg_in_range_table(addr, mtl_oam_b_counters) ||
+ (GRAPHICS_VER(oa->xe) >= 20 &&
+ xe_oa_reg_in_range_table(addr, xe2_oa_b_counters));
+}
+
+static const struct xe_mmio_range mtl_oa_mux_regs[] = {
+ { .start = 0x0d00, .end = 0x0d04 }, /* RPM_CONFIG[0-1] */
+ { .start = 0x0d0c, .end = 0x0d2c }, /* NOA_CONFIG[0-8] */
+ { .start = 0x9840, .end = 0x9840 }, /* GDT_CHICKEN_BITS */
+ { .start = 0x9884, .end = 0x9888 }, /* NOA_WRITE */
+ { .start = 0x38d100, .end = 0x38d114}, /* VISACTL */
+ {}
+};
+
+static const struct xe_mmio_range gen12_oa_mux_regs[] = {
+ { .start = 0x0d00, .end = 0x0d04 }, /* RPM_CONFIG[0-1] */
+ { .start = 0x0d0c, .end = 0x0d2c }, /* NOA_CONFIG[0-8] */
+ { .start = 0x9840, .end = 0x9840 }, /* GDT_CHICKEN_BITS */
+ { .start = 0x9884, .end = 0x9888 }, /* NOA_WRITE */
+ { .start = 0x20cc, .end = 0x20cc }, /* WAIT_FOR_RC6_EXIT */
+ {}
+};
+
+static const struct xe_mmio_range xe2_oa_mux_regs[] = {
+ { .start = 0x5194, .end = 0x5194 }, /* SYS_MEM_LAT_MEASURE_MERTF_GRP_3D */
+ { .start = 0x8704, .end = 0x8704 }, /* LMEM_LAT_MEASURE_MCFG_GRP */
+ { .start = 0xB1BC, .end = 0xB1BC }, /* L3_BANK_LAT_MEASURE_LBCF_GFX */
+ { .start = 0xE18C, .end = 0xE18C }, /* SAMPLER_MODE */
+ { .start = 0xE590, .end = 0xE590 }, /* TDL_LSC_LAT_MEASURE_TDL_GFX */
+ { .start = 0x13000, .end = 0x137FC }, /* PES_0_PESL0 - PES_63_UPPER_PESL3 */
+ {},
+};
+
+static bool xe_oa_is_valid_mux_addr(struct xe_oa *oa, u32 addr)
+{
+ if (GRAPHICS_VER(oa->xe) >= 20)
+ return xe_oa_reg_in_range_table(addr, xe2_oa_mux_regs);
+ else if (GRAPHICS_VERx100(oa->xe) >= 1270)
+ return xe_oa_reg_in_range_table(addr, mtl_oa_mux_regs);
+ else
+ return xe_oa_reg_in_range_table(addr, gen12_oa_mux_regs);
+}
+
+static bool xe_oa_is_valid_config_reg_addr(struct xe_oa *oa, u32 addr)
+{
+ return xe_oa_is_valid_flex_addr(oa, addr) ||
+ xe_oa_is_valid_b_counter_addr(oa, addr) ||
+ xe_oa_is_valid_mux_addr(oa, addr);
+}
+
+static struct xe_oa_reg *
+xe_oa_alloc_regs(struct xe_oa *oa, bool (*is_valid)(struct xe_oa *oa, u32 addr),
+ u32 __user *regs, u32 n_regs)
+{
+ struct xe_oa_reg *oa_regs;
+ int err;
+ u32 i;
+
+ oa_regs = kmalloc_array(n_regs, sizeof(*oa_regs), GFP_KERNEL);
+ if (!oa_regs)
+ return ERR_PTR(-ENOMEM);
+
+ for (i = 0; i < n_regs; i++) {
+ u32 addr, value;
+
+ err = get_user(addr, regs);
+ if (err)
+ goto addr_err;
+
+ if (!is_valid(oa, addr)) {
+ drm_dbg(&oa->xe->drm, "Invalid oa_reg address: %X\n", addr);
+ err = -EINVAL;
+ goto addr_err;
+ }
+
+ err = get_user(value, regs + 1);
+ if (err)
+ goto addr_err;
+
+ oa_regs[i].addr = XE_REG(addr);
+ oa_regs[i].value = value;
+
+ regs += 2;
+ }
+
+ return oa_regs;
+
+addr_err:
+ kfree(oa_regs);
+ return ERR_PTR(err);
+}
+
+static ssize_t show_dynamic_id(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf)
+{
+ struct xe_oa_config *oa_config =
+ container_of(attr, typeof(*oa_config), sysfs_metric_id);
+
+ return sysfs_emit(buf, "%d\n", oa_config->id);
+}
+
+static int create_dynamic_oa_sysfs_entry(struct xe_oa *oa,
+ struct xe_oa_config *oa_config)
+{
+ sysfs_attr_init(&oa_config->sysfs_metric_id.attr);
+ oa_config->sysfs_metric_id.attr.name = "id";
+ oa_config->sysfs_metric_id.attr.mode = 0444;
+ oa_config->sysfs_metric_id.show = show_dynamic_id;
+ oa_config->sysfs_metric_id.store = NULL;
+
+ oa_config->attrs[0] = &oa_config->sysfs_metric_id.attr;
+ oa_config->attrs[1] = NULL;
+
+ oa_config->sysfs_metric.name = oa_config->uuid;
+ oa_config->sysfs_metric.attrs = oa_config->attrs;
+
+ return sysfs_create_group(oa->metrics_kobj, &oa_config->sysfs_metric);
+}
+
+/**
+ * xe_oa_add_config_ioctl - Adds one OA config
+ * @dev: @drm_device
+ * @data: pointer to struct @drm_xe_oa_config
+ * @file: @drm_file
+ *
+ * The functions adds an OA config to the set of OA configs maintained in
+ * the kernel. The config determines which OA metrics are collected for an
+ * OA stream.
+ */
+int xe_oa_add_config_ioctl(struct drm_device *dev, u64 data, struct drm_file *file)
+{
+ struct xe_device *xe = to_xe_device(dev);
+ struct xe_oa *oa = &xe->oa;
+ struct drm_xe_oa_config param;
+ struct drm_xe_oa_config *arg = &param;
+ struct xe_oa_config *oa_config, *tmp;
+ struct xe_oa_reg *regs;
+ int err, id;
+
+ if (!oa->xe) {
+ drm_dbg(&xe->drm, "xe oa interface not available for this system\n");
+ return -ENODEV;
+ }
+
+ if (xe_observation_paranoid && !perfmon_capable()) {
+ drm_dbg(&oa->xe->drm, "Insufficient privileges to add xe OA config\n");
+ return -EACCES;
+ }
+
+ err = __copy_from_user(&param, u64_to_user_ptr(data), sizeof(param));
+ if (XE_IOCTL_DBG(oa->xe, err))
+ return -EFAULT;
+
+ if (XE_IOCTL_DBG(oa->xe, arg->extensions) ||
+ XE_IOCTL_DBG(oa->xe, !arg->regs_ptr) ||
+ XE_IOCTL_DBG(oa->xe, !arg->n_regs))
+ return -EINVAL;
+
+ oa_config = kzalloc(sizeof(*oa_config), GFP_KERNEL);
+ if (!oa_config)
+ return -ENOMEM;
+
+ oa_config->oa = oa;
+ kref_init(&oa_config->ref);
+
+ if (!uuid_is_valid(arg->uuid)) {
+ drm_dbg(&oa->xe->drm, "Invalid uuid format for OA config\n");
+ err = -EINVAL;
+ goto reg_err;
+ }
+
+ /* Last character in oa_config->uuid will be 0 because oa_config is kzalloc */
+ memcpy(oa_config->uuid, arg->uuid, sizeof(arg->uuid));
+
+ oa_config->regs_len = arg->n_regs;
+ regs = xe_oa_alloc_regs(oa, xe_oa_is_valid_config_reg_addr,
+ u64_to_user_ptr(arg->regs_ptr),
+ arg->n_regs);
+ if (IS_ERR(regs)) {
+ drm_dbg(&oa->xe->drm, "Failed to create OA config for mux_regs\n");
+ err = PTR_ERR(regs);
+ goto reg_err;
+ }
+ oa_config->regs = regs;
+
+ err = mutex_lock_interruptible(&oa->metrics_lock);
+ if (err)
+ goto reg_err;
+
+ /* We shouldn't have too many configs, so this iteration shouldn't be too costly */
+ idr_for_each_entry(&oa->metrics_idr, tmp, id) {
+ if (!strcmp(tmp->uuid, oa_config->uuid)) {
+ drm_dbg(&oa->xe->drm, "OA config already exists with this uuid\n");
+ err = -EADDRINUSE;
+ goto sysfs_err;
+ }
+ }
+
+ err = create_dynamic_oa_sysfs_entry(oa, oa_config);
+ if (err) {
+ drm_dbg(&oa->xe->drm, "Failed to create sysfs entry for OA config\n");
+ goto sysfs_err;
+ }
+
+ oa_config->id = idr_alloc(&oa->metrics_idr, oa_config, 1, 0, GFP_KERNEL);
+ if (oa_config->id < 0) {
+ drm_dbg(&oa->xe->drm, "Failed to create sysfs entry for OA config\n");
+ err = oa_config->id;
+ goto sysfs_err;
+ }
+
+ mutex_unlock(&oa->metrics_lock);
+
+ drm_dbg(&oa->xe->drm, "Added config %s id=%i\n", oa_config->uuid, oa_config->id);
+
+ return oa_config->id;
+
+sysfs_err:
+ mutex_unlock(&oa->metrics_lock);
+reg_err:
+ xe_oa_config_put(oa_config);
+ drm_dbg(&oa->xe->drm, "Failed to add new OA config\n");
+ return err;
+}
+
+/**
+ * xe_oa_remove_config_ioctl - Removes one OA config
+ * @dev: @drm_device
+ * @data: pointer to struct @drm_xe_observation_param
+ * @file: @drm_file
+ */
+int xe_oa_remove_config_ioctl(struct drm_device *dev, u64 data, struct drm_file *file)
+{
+ struct xe_device *xe = to_xe_device(dev);
+ struct xe_oa *oa = &xe->oa;
+ struct xe_oa_config *oa_config;
+ u64 arg, *ptr = u64_to_user_ptr(data);
+ int ret;
+
+ if (!oa->xe) {
+ drm_dbg(&xe->drm, "xe oa interface not available for this system\n");
+ return -ENODEV;
+ }
+
+ if (xe_observation_paranoid && !perfmon_capable()) {
+ drm_dbg(&oa->xe->drm, "Insufficient privileges to remove xe OA config\n");
+ return -EACCES;
+ }
+
+ ret = get_user(arg, ptr);
+ if (XE_IOCTL_DBG(oa->xe, ret))
+ return ret;
+
+ ret = mutex_lock_interruptible(&oa->metrics_lock);
+ if (ret)
+ return ret;
+
+ oa_config = idr_find(&oa->metrics_idr, arg);
+ if (!oa_config) {
+ drm_dbg(&oa->xe->drm, "Failed to remove unknown OA config\n");
+ ret = -ENOENT;
+ goto err_unlock;
+ }
+
+ WARN_ON(arg != oa_config->id);
+
+ sysfs_remove_group(oa->metrics_kobj, &oa_config->sysfs_metric);
+ idr_remove(&oa->metrics_idr, arg);
+
+ mutex_unlock(&oa->metrics_lock);
+
+ drm_dbg(&oa->xe->drm, "Removed config %s id=%i\n", oa_config->uuid, oa_config->id);
+
+ xe_oa_config_put(oa_config);
+
+ return 0;
+
+err_unlock:
+ mutex_unlock(&oa->metrics_lock);
+ return ret;
+}
+
+/**
+ * xe_oa_register - Xe OA registration
+ * @xe: @xe_device
+ *
+ * Exposes the metrics sysfs directory upon completion of module initialization
+ */
+void xe_oa_register(struct xe_device *xe)
+{
+ struct xe_oa *oa = &xe->oa;
+
+ if (!oa->xe)
+ return;
+
+ oa->metrics_kobj = kobject_create_and_add("metrics",
+ &xe->drm.primary->kdev->kobj);
+}
+
+/**
+ * xe_oa_unregister - Xe OA de-registration
+ * @xe: @xe_device
+ */
+void xe_oa_unregister(struct xe_device *xe)
+{
+ struct xe_oa *oa = &xe->oa;
+
+ if (!oa->metrics_kobj)
+ return;
+
+ kobject_put(oa->metrics_kobj);
+ oa->metrics_kobj = NULL;
+}
+
+static u32 num_oa_units_per_gt(struct xe_gt *gt)
+{
+ return 1;
+}
+
+static u32 __hwe_oam_unit(struct xe_hw_engine *hwe)
+{
+ if (GRAPHICS_VERx100(gt_to_xe(hwe->gt)) >= 1270) {
+ /*
+ * There's 1 SAMEDIA gt and 1 OAM per SAMEDIA gt. All media slices
+ * within the gt use the same OAM. All MTL/LNL SKUs list 1 SA MEDIA
+ */
+ xe_gt_WARN_ON(hwe->gt, hwe->gt->info.type != XE_GT_TYPE_MEDIA);
+
+ return 0;
+ }
+
+ return XE_OA_UNIT_INVALID;
+}
+
+static u32 __hwe_oa_unit(struct xe_hw_engine *hwe)
+{
+ switch (hwe->class) {
+ case XE_ENGINE_CLASS_RENDER:
+ case XE_ENGINE_CLASS_COMPUTE:
+ return 0;
+
+ case XE_ENGINE_CLASS_VIDEO_DECODE:
+ case XE_ENGINE_CLASS_VIDEO_ENHANCE:
+ return __hwe_oam_unit(hwe);
+
+ default:
+ return XE_OA_UNIT_INVALID;
+ }
+}
+
+static struct xe_oa_regs __oam_regs(u32 base)
+{
+ return (struct xe_oa_regs) {
+ base,
+ OAM_HEAD_POINTER(base),
+ OAM_TAIL_POINTER(base),
+ OAM_BUFFER(base),
+ OAM_CONTEXT_CONTROL(base),
+ OAM_CONTROL(base),
+ OAM_DEBUG(base),
+ OAM_STATUS(base),
+ OAM_CONTROL_COUNTER_SEL_MASK,
+ };
+}
+
+static struct xe_oa_regs __oag_regs(void)
+{
+ return (struct xe_oa_regs) {
+ 0,
+ OAG_OAHEADPTR,
+ OAG_OATAILPTR,
+ OAG_OABUFFER,
+ OAG_OAGLBCTXCTRL,
+ OAG_OACONTROL,
+ OAG_OA_DEBUG,
+ OAG_OASTATUS,
+ OAG_OACONTROL_OA_COUNTER_SEL_MASK,
+ };
+}
+
+static void __xe_oa_init_oa_units(struct xe_gt *gt)
+{
+ const u32 mtl_oa_base[] = { 0x13000 };
+ int i, num_units = gt->oa.num_oa_units;
+
+ for (i = 0; i < num_units; i++) {
+ struct xe_oa_unit *u = &gt->oa.oa_unit[i];
+
+ if (gt->info.type != XE_GT_TYPE_MEDIA) {
+ u->regs = __oag_regs();
+ u->type = DRM_XE_OA_UNIT_TYPE_OAG;
+ } else if (GRAPHICS_VERx100(gt_to_xe(gt)) >= 1270) {
+ u->regs = __oam_regs(mtl_oa_base[i]);
+ u->type = DRM_XE_OA_UNIT_TYPE_OAM;
+ }
+
+ /* Ensure MMIO trigger remains disabled till there is a stream */
+ xe_mmio_write32(gt, u->regs.oa_debug,
+ oag_configure_mmio_trigger(NULL, false));
+
+ /* Set oa_unit_ids now to ensure ids remain contiguous */
+ u->oa_unit_id = gt_to_xe(gt)->oa.oa_unit_ids++;
+ }
+}
+
+static int xe_oa_init_gt(struct xe_gt *gt)
+{
+ u32 num_oa_units = num_oa_units_per_gt(gt);
+ struct xe_hw_engine *hwe;
+ enum xe_hw_engine_id id;
+ struct xe_oa_unit *u;
+
+ u = drmm_kcalloc(&gt_to_xe(gt)->drm, num_oa_units, sizeof(*u), GFP_KERNEL);
+ if (!u)
+ return -ENOMEM;
+
+ for_each_hw_engine(hwe, gt, id) {
+ u32 index = __hwe_oa_unit(hwe);
+
+ hwe->oa_unit = NULL;
+ if (index < num_oa_units) {
+ u[index].num_engines++;
+ hwe->oa_unit = &u[index];
+ }
+ }
+
+ /*
+ * Fused off engines can result in oa_unit's with num_engines == 0. These units
+ * will appear in OA unit query, but no OA streams can be opened on them.
+ */
+ gt->oa.num_oa_units = num_oa_units;
+ gt->oa.oa_unit = u;
+
+ __xe_oa_init_oa_units(gt);
+
+ drmm_mutex_init(&gt_to_xe(gt)->drm, &gt->oa.gt_lock);
+
+ return 0;
+}
+
+static int xe_oa_init_oa_units(struct xe_oa *oa)
+{
+ struct xe_gt *gt;
+ int i, ret;
+
+ for_each_gt(gt, oa->xe, i) {
+ ret = xe_oa_init_gt(gt);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static void oa_format_add(struct xe_oa *oa, enum xe_oa_format_name format)
+{
+ __set_bit(format, oa->format_mask);
+}
+
+static void xe_oa_init_supported_formats(struct xe_oa *oa)
+{
+ if (GRAPHICS_VER(oa->xe) >= 20) {
+ /* Xe2+ */
+ oa_format_add(oa, XE_OAM_FORMAT_MPEC8u64_B8_C8);
+ oa_format_add(oa, XE_OAM_FORMAT_MPEC8u32_B8_C8);
+ oa_format_add(oa, XE_OA_FORMAT_PEC64u64);
+ oa_format_add(oa, XE_OA_FORMAT_PEC64u64_B8_C8);
+ oa_format_add(oa, XE_OA_FORMAT_PEC64u32);
+ oa_format_add(oa, XE_OA_FORMAT_PEC32u64_G1);
+ oa_format_add(oa, XE_OA_FORMAT_PEC32u32_G1);
+ oa_format_add(oa, XE_OA_FORMAT_PEC32u64_G2);
+ oa_format_add(oa, XE_OA_FORMAT_PEC32u32_G2);
+ oa_format_add(oa, XE_OA_FORMAT_PEC36u64_G1_32_G2_4);
+ oa_format_add(oa, XE_OA_FORMAT_PEC36u64_G1_4_G2_32);
+ } else if (GRAPHICS_VERx100(oa->xe) >= 1270) {
+ /* XE_METEORLAKE */
+ oa_format_add(oa, XE_OAR_FORMAT_A32u40_A4u32_B8_C8);
+ oa_format_add(oa, XE_OA_FORMAT_A24u40_A14u32_B8_C8);
+ oa_format_add(oa, XE_OAC_FORMAT_A24u64_B8_C8);
+ oa_format_add(oa, XE_OAC_FORMAT_A22u32_R2u32_B8_C8);
+ oa_format_add(oa, XE_OAM_FORMAT_MPEC8u64_B8_C8);
+ oa_format_add(oa, XE_OAM_FORMAT_MPEC8u32_B8_C8);
+ } else if (GRAPHICS_VERx100(oa->xe) >= 1255) {
+ /* XE_DG2, XE_PVC */
+ oa_format_add(oa, XE_OAR_FORMAT_A32u40_A4u32_B8_C8);
+ oa_format_add(oa, XE_OA_FORMAT_A24u40_A14u32_B8_C8);
+ oa_format_add(oa, XE_OAC_FORMAT_A24u64_B8_C8);
+ oa_format_add(oa, XE_OAC_FORMAT_A22u32_R2u32_B8_C8);
+ } else {
+ /* Gen12+ */
+ xe_assert(oa->xe, GRAPHICS_VER(oa->xe) >= 12);
+ oa_format_add(oa, XE_OA_FORMAT_A12);
+ oa_format_add(oa, XE_OA_FORMAT_A12_B8_C8);
+ oa_format_add(oa, XE_OA_FORMAT_A32u40_A4u32_B8_C8);
+ oa_format_add(oa, XE_OA_FORMAT_C4_B8);
+ }
+}
+
+/**
+ * xe_oa_init - OA initialization during device probe
+ * @xe: @xe_device
+ *
+ * Return: 0 on success or a negative error code on failure
+ */
+int xe_oa_init(struct xe_device *xe)
+{
+ struct xe_oa *oa = &xe->oa;
+ int ret;
+
+ /* Support OA only with GuC submission and Gen12+ */
+ if (!xe_device_uc_enabled(xe) || GRAPHICS_VER(xe) < 12)
+ return 0;
+
+ if (IS_SRIOV_VF(xe))
+ return 0;
+
+ oa->xe = xe;
+ oa->oa_formats = oa_formats;
+
+ drmm_mutex_init(&oa->xe->drm, &oa->metrics_lock);
+ idr_init_base(&oa->metrics_idr, 1);
+
+ ret = xe_oa_init_oa_units(oa);
+ if (ret) {
+ drm_err(&xe->drm, "OA initialization failed (%pe)\n", ERR_PTR(ret));
+ goto exit;
+ }
+
+ xe_oa_init_supported_formats(oa);
+ return 0;
+exit:
+ oa->xe = NULL;
+ return ret;
+}
+
+static int destroy_config(int id, void *p, void *data)
+{
+ xe_oa_config_put(p);
+ return 0;
+}
+
+/**
+ * xe_oa_fini - OA de-initialization during device remove
+ * @xe: @xe_device
+ */
+void xe_oa_fini(struct xe_device *xe)
+{
+ struct xe_oa *oa = &xe->oa;
+
+ if (!oa->xe)
+ return;
+
+ idr_for_each(&oa->metrics_idr, destroy_config, oa);
+ idr_destroy(&oa->metrics_idr);
+
+ oa->xe = NULL;
+}
diff --git a/drivers/gpu/drm/xe/xe_oa.h b/drivers/gpu/drm/xe/xe_oa.h
new file mode 100644
index 000000000000..87a38820c317
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_oa.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2023-2024 Intel Corporation
+ */
+
+#ifndef _XE_OA_H_
+#define _XE_OA_H_
+
+#include "xe_oa_types.h"
+
+struct drm_device;
+struct drm_file;
+struct xe_device;
+struct xe_gt;
+struct xe_hw_engine;
+
+int xe_oa_init(struct xe_device *xe);
+void xe_oa_fini(struct xe_device *xe);
+void xe_oa_register(struct xe_device *xe);
+void xe_oa_unregister(struct xe_device *xe);
+int xe_oa_stream_open_ioctl(struct drm_device *dev, u64 data, struct drm_file *file);
+int xe_oa_add_config_ioctl(struct drm_device *dev, u64 data, struct drm_file *file);
+int xe_oa_remove_config_ioctl(struct drm_device *dev, u64 data, struct drm_file *file);
+u32 xe_oa_timestamp_frequency(struct xe_gt *gt);
+u16 xe_oa_unit_id(struct xe_hw_engine *hwe);
+
+#endif
diff --git a/drivers/gpu/drm/xe/xe_oa_types.h b/drivers/gpu/drm/xe/xe_oa_types.h
new file mode 100644
index 000000000000..540c3ec53a6d
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_oa_types.h
@@ -0,0 +1,242 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2023-2024 Intel Corporation
+ */
+
+#ifndef _XE_OA_TYPES_H_
+#define _XE_OA_TYPES_H_
+
+#include <linux/bitops.h>
+#include <linux/idr.h>
+#include <linux/mutex.h>
+#include <linux/types.h>
+
+#include <drm/xe_drm.h>
+#include "regs/xe_reg_defs.h"
+#include "xe_hw_engine_types.h"
+
+#define XE_OA_BUFFER_SIZE SZ_16M
+
+enum xe_oa_report_header {
+ HDR_32_BIT = 0,
+ HDR_64_BIT,
+};
+
+enum xe_oa_format_name {
+ XE_OA_FORMAT_C4_B8,
+
+ /* Gen8+ */
+ XE_OA_FORMAT_A12,
+ XE_OA_FORMAT_A12_B8_C8,
+ XE_OA_FORMAT_A32u40_A4u32_B8_C8,
+
+ /* DG2 */
+ XE_OAR_FORMAT_A32u40_A4u32_B8_C8,
+ XE_OA_FORMAT_A24u40_A14u32_B8_C8,
+
+ /* DG2/MTL OAC */
+ XE_OAC_FORMAT_A24u64_B8_C8,
+ XE_OAC_FORMAT_A22u32_R2u32_B8_C8,
+
+ /* MTL OAM */
+ XE_OAM_FORMAT_MPEC8u64_B8_C8,
+ XE_OAM_FORMAT_MPEC8u32_B8_C8,
+
+ /* Xe2+ */
+ XE_OA_FORMAT_PEC64u64,
+ XE_OA_FORMAT_PEC64u64_B8_C8,
+ XE_OA_FORMAT_PEC64u32,
+ XE_OA_FORMAT_PEC32u64_G1,
+ XE_OA_FORMAT_PEC32u32_G1,
+ XE_OA_FORMAT_PEC32u64_G2,
+ XE_OA_FORMAT_PEC32u32_G2,
+ XE_OA_FORMAT_PEC36u64_G1_32_G2_4,
+ XE_OA_FORMAT_PEC36u64_G1_4_G2_32,
+
+ __XE_OA_FORMAT_MAX,
+};
+
+/**
+ * struct xe_oa_format - Format fields for supported OA formats. OA format
+ * properties are specified in PRM/Bspec 52198 and 60942
+ */
+struct xe_oa_format {
+ /** @counter_select: counter select value (see Bspec 52198/60942) */
+ u32 counter_select;
+ /** @size: record size as written by HW (multiple of 64 byte cachelines) */
+ int size;
+ /** @type: of enum @drm_xe_oa_format_type */
+ int type;
+ /** @header: 32 or 64 bit report headers */
+ enum xe_oa_report_header header;
+ /** @counter_size: counter size value (see Bspec 60942) */
+ u16 counter_size;
+ /** @bc_report: BC report value (see Bspec 60942) */
+ u16 bc_report;
+};
+
+/** struct xe_oa_regs - Registers for each OA unit */
+struct xe_oa_regs {
+ u32 base;
+ struct xe_reg oa_head_ptr;
+ struct xe_reg oa_tail_ptr;
+ struct xe_reg oa_buffer;
+ struct xe_reg oa_ctx_ctrl;
+ struct xe_reg oa_ctrl;
+ struct xe_reg oa_debug;
+ struct xe_reg oa_status;
+ u32 oa_ctrl_counter_select_mask;
+};
+
+/**
+ * struct xe_oa_unit - Hardware OA unit
+ */
+struct xe_oa_unit {
+ /** @oa_unit_id: identifier for the OA unit */
+ u16 oa_unit_id;
+
+ /** @type: Type of OA unit - OAM, OAG etc. */
+ enum drm_xe_oa_unit_type type;
+
+ /** @regs: OA registers for programming the OA unit */
+ struct xe_oa_regs regs;
+
+ /** @num_engines: number of engines attached to this OA unit */
+ u32 num_engines;
+
+ /** @exclusive_stream: The stream currently using the OA unit */
+ struct xe_oa_stream *exclusive_stream;
+};
+
+/**
+ * struct xe_oa_gt - OA per-gt information
+ */
+struct xe_oa_gt {
+ /** @gt_lock: lock protecting create/destroy OA streams */
+ struct mutex gt_lock;
+
+ /** @num_oa_units: number of oa units for each gt */
+ u32 num_oa_units;
+
+ /** @oa_unit: array of oa_units */
+ struct xe_oa_unit *oa_unit;
+};
+
+/**
+ * struct xe_oa - OA device level information
+ */
+struct xe_oa {
+ /** @xe: back pointer to xe device */
+ struct xe_device *xe;
+
+ /** @metrics_kobj: kobj for metrics sysfs */
+ struct kobject *metrics_kobj;
+
+ /** @metrics_lock: lock protecting add/remove configs */
+ struct mutex metrics_lock;
+
+ /** @metrics_idr: List of dynamic configurations (struct xe_oa_config) */
+ struct idr metrics_idr;
+
+ /** @ctx_oactxctrl_offset: offset of OACTXCONTROL register in context image */
+ u32 ctx_oactxctrl_offset[XE_ENGINE_CLASS_MAX];
+
+ /** @oa_formats: tracks all OA formats across platforms */
+ const struct xe_oa_format *oa_formats;
+
+ /** @format_mask: tracks valid OA formats for a platform */
+ unsigned long format_mask[BITS_TO_LONGS(__XE_OA_FORMAT_MAX)];
+
+ /** @oa_unit_ids: tracks oa unit ids assigned across gt's */
+ u16 oa_unit_ids;
+};
+
+/** @xe_oa_buffer: State of the stream OA buffer */
+struct xe_oa_buffer {
+ /** @format: data format */
+ const struct xe_oa_format *format;
+
+ /** @format: xe_bo backing the OA buffer */
+ struct xe_bo *bo;
+
+ /** @vaddr: mapped vaddr of the OA buffer */
+ u8 *vaddr;
+
+ /** @ptr_lock: Lock protecting reads/writes to head/tail pointers */
+ spinlock_t ptr_lock;
+
+ /** @head: Cached head to read from */
+ u32 head;
+
+ /** @tail: The last verified cached tail where HW has completed writing */
+ u32 tail;
+
+ /** @circ_size: The effective circular buffer size, for Xe2+ */
+ u32 circ_size;
+};
+
+/**
+ * struct xe_oa_stream - state for a single open stream FD
+ */
+struct xe_oa_stream {
+ /** @oa: xe_oa backpointer */
+ struct xe_oa *oa;
+
+ /** @gt: gt associated with the oa stream */
+ struct xe_gt *gt;
+
+ /** @hwe: hardware engine associated with this oa stream */
+ struct xe_hw_engine *hwe;
+
+ /** @stream_lock: Lock serializing stream operations */
+ struct mutex stream_lock;
+
+ /** @sample: true if DRM_XE_OA_PROP_SAMPLE_OA is provided */
+ bool sample;
+
+ /** @exec_q: Exec queue corresponding to DRM_XE_OA_PROPERTY_EXEC_QUEUE_ID */
+ struct xe_exec_queue *exec_q;
+
+ /** @k_exec_q: kernel exec_q used for OA programming batch submissions */
+ struct xe_exec_queue *k_exec_q;
+
+ /** @enabled: Whether the stream is currently enabled */
+ bool enabled;
+
+ /** @oa_config: OA configuration used by the stream */
+ struct xe_oa_config *oa_config;
+
+ /** @oa_config_bos: List of struct @xe_oa_config_bo's */
+ struct llist_head oa_config_bos;
+
+ /** @poll_check_timer: Timer to periodically check for data in the OA buffer */
+ struct hrtimer poll_check_timer;
+
+ /** @poll_wq: Wait queue for waiting for OA data to be available */
+ wait_queue_head_t poll_wq;
+
+ /** @pollin: Whether there is data available to read */
+ bool pollin;
+
+ /** @periodic: Whether periodic sampling is currently enabled */
+ bool periodic;
+
+ /** @period_exponent: OA unit sampling frequency is derived from this */
+ int period_exponent;
+
+ /** @oa_buffer: OA buffer for the stream */
+ struct xe_oa_buffer oa_buffer;
+
+ /** @poll_period_ns: hrtimer period for checking OA buffer for available data */
+ u64 poll_period_ns;
+
+ /** @override_gucrc: GuC RC has been overridden for the OA stream */
+ bool override_gucrc;
+
+ /** @oa_status: temporary storage for oa_status register value */
+ u32 oa_status;
+
+ /** @no_preempt: Whether preemption and timeslicing is disabled for stream exec_q */
+ u32 no_preempt;
+};
+#endif
diff --git a/drivers/gpu/drm/xe/xe_observation.c b/drivers/gpu/drm/xe/xe_observation.c
new file mode 100644
index 000000000000..fcb584b42a7d
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_observation.c
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2023-2024 Intel Corporation
+ */
+
+#include <linux/errno.h>
+#include <linux/sysctl.h>
+
+#include <drm/xe_drm.h>
+
+#include "xe_oa.h"
+#include "xe_observation.h"
+
+u32 xe_observation_paranoid = true;
+static struct ctl_table_header *sysctl_header;
+
+static int xe_oa_ioctl(struct drm_device *dev, struct drm_xe_observation_param *arg,
+ struct drm_file *file)
+{
+ switch (arg->observation_op) {
+ case DRM_XE_OBSERVATION_OP_STREAM_OPEN:
+ return xe_oa_stream_open_ioctl(dev, arg->param, file);
+ case DRM_XE_OBSERVATION_OP_ADD_CONFIG:
+ return xe_oa_add_config_ioctl(dev, arg->param, file);
+ case DRM_XE_OBSERVATION_OP_REMOVE_CONFIG:
+ return xe_oa_remove_config_ioctl(dev, arg->param, file);
+ default:
+ return -EINVAL;
+ }
+}
+
+/**
+ * xe_observation_ioctl - The top level observation layer ioctl
+ * @dev: @drm_device
+ * @data: pointer to struct @drm_xe_observation_param
+ * @file: @drm_file
+ *
+ * The function is called for different observation streams types and
+ * allows execution of different operations supported by those stream
+ * types.
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+int xe_observation_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
+{
+ struct drm_xe_observation_param *arg = data;
+
+ if (arg->extensions)
+ return -EINVAL;
+
+ switch (arg->observation_type) {
+ case DRM_XE_OBSERVATION_TYPE_OA:
+ return xe_oa_ioctl(dev, arg, file);
+ default:
+ return -EINVAL;
+ }
+}
+
+static struct ctl_table observation_ctl_table[] = {
+ {
+ .procname = "observation_paranoid",
+ .data = &xe_observation_paranoid,
+ .maxlen = sizeof(xe_observation_paranoid),
+ .mode = 0644,
+ .proc_handler = proc_dointvec_minmax,
+ .extra1 = SYSCTL_ZERO,
+ .extra2 = SYSCTL_ONE,
+ },
+ {}
+};
+
+/**
+ * xe_observation_sysctl_register - Register xe_observation_paranoid sysctl
+ *
+ * Normally only superuser/root can access observation stream
+ * data. However, superuser can set xe_observation_paranoid sysctl to 0 to
+ * allow non-privileged users to also access observation data.
+ *
+ * Return: always returns 0
+ */
+int xe_observation_sysctl_register(void)
+{
+ sysctl_header = register_sysctl("dev/xe", observation_ctl_table);
+ return 0;
+}
+
+/**
+ * xe_observation_sysctl_unregister - Unregister xe_observation_paranoid sysctl
+ */
+void xe_observation_sysctl_unregister(void)
+{
+ unregister_sysctl_table(sysctl_header);
+}
diff --git a/drivers/gpu/drm/xe/xe_observation.h b/drivers/gpu/drm/xe/xe_observation.h
new file mode 100644
index 000000000000..17816998e966
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_observation.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2023-2024 Intel Corporation
+ */
+
+#ifndef _XE_OBSERVATION_H_
+#define _XE_OBSERVATION_H_
+
+#include <linux/types.h>
+
+struct drm_device;
+struct drm_file;
+
+extern u32 xe_observation_paranoid;
+
+int xe_observation_ioctl(struct drm_device *dev, void *data, struct drm_file *file);
+int xe_observation_sysctl_register(void);
+void xe_observation_sysctl_unregister(void);
+
+#endif
diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c
index 973c14fbbbf3..732ee0d02124 100644
--- a/drivers/gpu/drm/xe/xe_pci.c
+++ b/drivers/gpu/drm/xe/xe_pci.c
@@ -340,7 +340,7 @@ static const struct xe_device_desc lnl_desc = {
.require_force_probe = true,
};
-static const struct xe_device_desc bmg_desc __maybe_unused = {
+static const struct xe_device_desc bmg_desc = {
DGFX_FEATURES,
PLATFORM(BATTLEMAGE),
.has_display = true,
@@ -390,6 +390,7 @@ static const struct pci_device_id pciidlist[] = {
XE_DG2_IDS(INTEL_VGA_DEVICE, &dg2_desc),
XE_MTL_IDS(INTEL_VGA_DEVICE, &mtl_desc),
XE_LNL_IDS(INTEL_VGA_DEVICE, &lnl_desc),
+ XE_BMG_IDS(INTEL_VGA_DEVICE, &bmg_desc),
{ }
};
MODULE_DEVICE_TABLE(pci, pciidlist);
@@ -747,6 +748,9 @@ static void xe_pci_remove(struct pci_dev *pdev)
if (!xe) /* driver load aborted, nothing to cleanup */
return;
+ if (IS_SRIOV_PF(xe))
+ xe_pci_sriov_configure(pdev, 0);
+
xe_device_remove(xe);
xe_pm_runtime_fini(xe);
pci_set_drvdata(pdev, NULL);
@@ -1003,9 +1007,7 @@ static struct pci_driver xe_pci_driver = {
.probe = xe_pci_probe,
.remove = xe_pci_remove,
.shutdown = xe_pci_shutdown,
-#ifdef CONFIG_PCI_IOV
.sriov_configure = xe_pci_sriov_configure,
-#endif
#ifdef CONFIG_PM_SLEEP
.driver.pm = &xe_pm_ops,
#endif
diff --git a/drivers/gpu/drm/xe/xe_pci_sriov.c b/drivers/gpu/drm/xe/xe_pci_sriov.c
index 06d0fceb5114..aaceee748287 100644
--- a/drivers/gpu/drm/xe/xe_pci_sriov.c
+++ b/drivers/gpu/drm/xe/xe_pci_sriov.c
@@ -6,12 +6,24 @@
#include "xe_assert.h"
#include "xe_device.h"
#include "xe_gt_sriov_pf_config.h"
+#include "xe_gt_sriov_pf_control.h"
#include "xe_pci_sriov.h"
#include "xe_pm.h"
#include "xe_sriov.h"
#include "xe_sriov_pf_helpers.h"
#include "xe_sriov_printk.h"
+static int pf_needs_provisioning(struct xe_gt *gt, unsigned int num_vfs)
+{
+ unsigned int n;
+
+ for (n = 1; n <= num_vfs; n++)
+ if (!xe_gt_sriov_pf_config_is_empty(gt, n))
+ return false;
+
+ return true;
+}
+
static int pf_provision_vfs(struct xe_device *xe, unsigned int num_vfs)
{
struct xe_gt *gt;
@@ -19,6 +31,8 @@ static int pf_provision_vfs(struct xe_device *xe, unsigned int num_vfs)
int result = 0, err;
for_each_gt(gt, xe, id) {
+ if (!pf_needs_provisioning(gt, num_vfs))
+ continue;
err = xe_gt_sriov_pf_config_set_fair(gt, VFID(1), num_vfs);
result = result ?: err;
}
@@ -37,6 +51,17 @@ static void pf_unprovision_vfs(struct xe_device *xe, unsigned int num_vfs)
xe_gt_sriov_pf_config_release(gt, n, true);
}
+static void pf_reset_vfs(struct xe_device *xe, unsigned int num_vfs)
+{
+ struct xe_gt *gt;
+ unsigned int id;
+ unsigned int n;
+
+ for_each_gt(gt, xe, id)
+ for (n = 1; n <= num_vfs; n++)
+ xe_gt_sriov_pf_control_trigger_flr(gt, n);
+}
+
static int pf_enable_vfs(struct xe_device *xe, int num_vfs)
{
struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
@@ -94,6 +119,8 @@ static int pf_disable_vfs(struct xe_device *xe)
pci_disable_sriov(pdev);
+ pf_reset_vfs(xe, num_vfs);
+
pf_unprovision_vfs(xe, num_vfs);
/* not needed anymore - see pf_enable_vfs() */
diff --git a/drivers/gpu/drm/xe/xe_pci_sriov.h b/drivers/gpu/drm/xe/xe_pci_sriov.h
index 3b8bfbf7e1d9..c76dd0d90495 100644
--- a/drivers/gpu/drm/xe/xe_pci_sriov.h
+++ b/drivers/gpu/drm/xe/xe_pci_sriov.h
@@ -8,6 +8,13 @@
struct pci_dev;
+#ifdef CONFIG_PCI_IOV
int xe_pci_sriov_configure(struct pci_dev *pdev, int num_vfs);
+#else
+static inline int xe_pci_sriov_configure(struct pci_dev *pdev, int num_vfs)
+{
+ return 0;
+}
+#endif
#endif
diff --git a/drivers/gpu/drm/xe/xe_preempt_fence.c b/drivers/gpu/drm/xe/xe_preempt_fence.c
index 5b243b7feb59..e8b8ae5c6485 100644
--- a/drivers/gpu/drm/xe/xe_preempt_fence.c
+++ b/drivers/gpu/drm/xe/xe_preempt_fence.c
@@ -129,7 +129,7 @@ xe_preempt_fence_arm(struct xe_preempt_fence *pfence, struct xe_exec_queue *q,
list_del_init(&pfence->link);
pfence->q = xe_exec_queue_get(q);
dma_fence_init(&pfence->base, &preempt_fence_ops,
- &q->compute.lock, context, seqno);
+ &q->lr.lock, context, seqno);
return &pfence->base;
}
diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
index cd60c009b679..ade9e7a3a0ad 100644
--- a/drivers/gpu/drm/xe/xe_pt.c
+++ b/drivers/gpu/drm/xe/xe_pt.c
@@ -1137,8 +1137,9 @@ static void invalidation_fence_cb(struct dma_fence *fence,
{
struct invalidation_fence *ifence =
container_of(cb, struct invalidation_fence, cb);
+ struct xe_device *xe = gt_to_xe(ifence->gt);
- trace_xe_gt_tlb_invalidation_fence_cb(&ifence->base);
+ trace_xe_gt_tlb_invalidation_fence_cb(xe, &ifence->base);
if (!ifence->fence->error) {
queue_work(system_wq, &ifence->work);
} else {
@@ -1153,8 +1154,9 @@ static void invalidation_fence_work_func(struct work_struct *w)
{
struct invalidation_fence *ifence =
container_of(w, struct invalidation_fence, work);
+ struct xe_device *xe = gt_to_xe(ifence->gt);
- trace_xe_gt_tlb_invalidation_fence_work_func(&ifence->base);
+ trace_xe_gt_tlb_invalidation_fence_work_func(xe, &ifence->base);
xe_gt_tlb_invalidation_range(ifence->gt, &ifence->base, ifence->start,
ifence->end, ifence->asid);
}
@@ -1166,7 +1168,7 @@ static int invalidation_fence_init(struct xe_gt *gt,
{
int ret;
- trace_xe_gt_tlb_invalidation_fence_create(&ifence->base);
+ trace_xe_gt_tlb_invalidation_fence_create(gt_to_xe(gt), &ifence->base);
spin_lock_irq(&gt->tlb_invalidation.lock);
dma_fence_init(&ifence->base.base, &invalidation_fence_ops,
diff --git a/drivers/gpu/drm/xe/xe_query.c b/drivers/gpu/drm/xe/xe_query.c
index 995effcb904b..4e01df6b1b7a 100644
--- a/drivers/gpu/drm/xe/xe_query.c
+++ b/drivers/gpu/drm/xe/xe_query.c
@@ -602,6 +602,82 @@ query_uc_fw_version(struct xe_device *xe, struct drm_xe_device_query *query)
return 0;
}
+static size_t calc_oa_unit_query_size(struct xe_device *xe)
+{
+ size_t size = sizeof(struct drm_xe_query_oa_units);
+ struct xe_gt *gt;
+ int i, id;
+
+ for_each_gt(gt, xe, id) {
+ for (i = 0; i < gt->oa.num_oa_units; i++) {
+ size += sizeof(struct drm_xe_oa_unit);
+ size += gt->oa.oa_unit[i].num_engines *
+ sizeof(struct drm_xe_engine_class_instance);
+ }
+ }
+
+ return size;
+}
+
+static int query_oa_units(struct xe_device *xe,
+ struct drm_xe_device_query *query)
+{
+ void __user *query_ptr = u64_to_user_ptr(query->data);
+ size_t size = calc_oa_unit_query_size(xe);
+ struct drm_xe_query_oa_units *qoa;
+ enum xe_hw_engine_id hwe_id;
+ struct drm_xe_oa_unit *du;
+ struct xe_hw_engine *hwe;
+ struct xe_oa_unit *u;
+ int gt_id, i, j, ret;
+ struct xe_gt *gt;
+ u8 *pdu;
+
+ if (query->size == 0) {
+ query->size = size;
+ return 0;
+ } else if (XE_IOCTL_DBG(xe, query->size != size)) {
+ return -EINVAL;
+ }
+
+ qoa = kzalloc(size, GFP_KERNEL);
+ if (!qoa)
+ return -ENOMEM;
+
+ pdu = (u8 *)&qoa->oa_units[0];
+ for_each_gt(gt, xe, gt_id) {
+ for (i = 0; i < gt->oa.num_oa_units; i++) {
+ u = &gt->oa.oa_unit[i];
+ du = (struct drm_xe_oa_unit *)pdu;
+
+ du->oa_unit_id = u->oa_unit_id;
+ du->oa_unit_type = u->type;
+ du->oa_timestamp_freq = xe_oa_timestamp_frequency(gt);
+ du->capabilities = DRM_XE_OA_CAPS_BASE;
+
+ j = 0;
+ for_each_hw_engine(hwe, gt, hwe_id) {
+ if (!xe_hw_engine_is_reserved(hwe) &&
+ xe_oa_unit_id(hwe) == u->oa_unit_id) {
+ du->eci[j].engine_class =
+ xe_to_user_engine_class[hwe->class];
+ du->eci[j].engine_instance = hwe->logical_instance;
+ du->eci[j].gt_id = gt->info.id;
+ j++;
+ }
+ }
+ du->num_engines = j;
+ pdu += sizeof(*du) + j * sizeof(du->eci[0]);
+ qoa->num_oa_units++;
+ }
+ }
+
+ ret = copy_to_user(query_ptr, qoa, size);
+ kfree(qoa);
+
+ return ret ? -EFAULT : 0;
+}
+
static int (* const xe_query_funcs[])(struct xe_device *xe,
struct drm_xe_device_query *query) = {
query_engines,
@@ -612,6 +688,7 @@ static int (* const xe_query_funcs[])(struct xe_device *xe,
query_gt_topology,
query_engine_cycles,
query_uc_fw_version,
+ query_oa_units,
};
int xe_query_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
diff --git a/drivers/gpu/drm/xe/xe_reg_whitelist.c b/drivers/gpu/drm/xe/xe_reg_whitelist.c
index 3fa2ece7d228..3996934974fa 100644
--- a/drivers/gpu/drm/xe/xe_reg_whitelist.c
+++ b/drivers/gpu/drm/xe/xe_reg_whitelist.c
@@ -7,6 +7,7 @@
#include "regs/xe_engine_regs.h"
#include "regs/xe_gt_regs.h"
+#include "regs/xe_oa_regs.h"
#include "regs/xe_regs.h"
#include "xe_gt_types.h"
#include "xe_platform_types.h"
@@ -63,7 +64,28 @@ static const struct xe_rtp_entry_sr register_whitelist[] = {
ENGINE_CLASS(RENDER)),
XE_RTP_ACTIONS(WHITELIST(CSBE_DEBUG_STATUS(RENDER_RING_BASE), 0))
},
-
+ { XE_RTP_NAME("oa_reg_render"),
+ XE_RTP_RULES(GRAPHICS_VERSION_RANGE(1200, XE_RTP_END_VERSION_UNDEFINED),
+ ENGINE_CLASS(RENDER)),
+ XE_RTP_ACTIONS(WHITELIST(OAG_MMIOTRIGGER,
+ RING_FORCE_TO_NONPRIV_ACCESS_RW),
+ WHITELIST(OAG_OASTATUS,
+ RING_FORCE_TO_NONPRIV_ACCESS_RD),
+ WHITELIST(OAG_OAHEADPTR,
+ RING_FORCE_TO_NONPRIV_ACCESS_RD |
+ RING_FORCE_TO_NONPRIV_RANGE_4))
+ },
+ { XE_RTP_NAME("oa_reg_compute"),
+ XE_RTP_RULES(GRAPHICS_VERSION_RANGE(1200, XE_RTP_END_VERSION_UNDEFINED),
+ ENGINE_CLASS(COMPUTE)),
+ XE_RTP_ACTIONS(WHITELIST(OAG_MMIOTRIGGER,
+ RING_FORCE_TO_NONPRIV_ACCESS_RW),
+ WHITELIST(OAG_OASTATUS,
+ RING_FORCE_TO_NONPRIV_ACCESS_RD),
+ WHITELIST(OAG_OAHEADPTR,
+ RING_FORCE_TO_NONPRIV_ACCESS_RD |
+ RING_FORCE_TO_NONPRIV_RANGE_4))
+ },
{}
};
diff --git a/drivers/gpu/drm/xe/xe_ring_ops.c b/drivers/gpu/drm/xe/xe_ring_ops.c
index db630d27beba..0be4f489d3e1 100644
--- a/drivers/gpu/drm/xe/xe_ring_ops.c
+++ b/drivers/gpu/drm/xe/xe_ring_ops.c
@@ -224,6 +224,19 @@ static u32 get_ppgtt_flag(struct xe_sched_job *job)
return job->q->vm ? BIT(8) : 0;
}
+static int emit_copy_timestamp(struct xe_lrc *lrc, u32 *dw, int i)
+{
+ dw[i++] = MI_COPY_MEM_MEM | MI_COPY_MEM_MEM_SRC_GGTT |
+ MI_COPY_MEM_MEM_DST_GGTT;
+ dw[i++] = xe_lrc_ctx_job_timestamp_ggtt_addr(lrc);
+ dw[i++] = 0;
+ dw[i++] = xe_lrc_ctx_timestamp_ggtt_addr(lrc);
+ dw[i++] = 0;
+ dw[i++] = MI_NOOP;
+
+ return i;
+}
+
/* for engines that don't require any special HW handling (no EUs, no aux inval, etc) */
static void __emit_job_gen12_simple(struct xe_sched_job *job, struct xe_lrc *lrc,
u64 batch_addr, u32 seqno)
@@ -232,6 +245,8 @@ static void __emit_job_gen12_simple(struct xe_sched_job *job, struct xe_lrc *lrc
u32 ppgtt_flag = get_ppgtt_flag(job);
struct xe_gt *gt = job->q->gt;
+ i = emit_copy_timestamp(lrc, dw, i);
+
if (job->ring_ops_flush_tlb) {
dw[i++] = preparser_disable(true);
i = emit_flush_imm_ggtt(xe_lrc_start_seqno_ggtt_addr(lrc),
@@ -283,6 +298,8 @@ static void __emit_job_gen12_video(struct xe_sched_job *job, struct xe_lrc *lrc,
struct xe_device *xe = gt_to_xe(gt);
bool decode = job->q->class == XE_ENGINE_CLASS_VIDEO_DECODE;
+ i = emit_copy_timestamp(lrc, dw, i);
+
dw[i++] = preparser_disable(true);
/* hsdes: 1809175790 */
@@ -332,6 +349,8 @@ static void __emit_job_gen12_render_compute(struct xe_sched_job *job,
bool lacks_render = !(gt->info.engine_mask & XE_HW_ENGINE_RCS_MASK);
u32 mask_flags = 0;
+ i = emit_copy_timestamp(lrc, dw, i);
+
dw[i++] = preparser_disable(true);
if (lacks_render)
mask_flags = PIPE_CONTROL_3D_ARCH_FLAGS;
@@ -375,6 +394,8 @@ static void emit_migration_job_gen12(struct xe_sched_job *job,
{
u32 dw[MAX_JOB_SIZE_DW], i = 0;
+ i = emit_copy_timestamp(lrc, dw, i);
+
i = emit_store_imm_ggtt(xe_lrc_start_seqno_ggtt_addr(lrc),
seqno, dw, i);
diff --git a/drivers/gpu/drm/xe/xe_rtp.c b/drivers/gpu/drm/xe/xe_rtp.c
index 01c32a932780..02e28274282f 100644
--- a/drivers/gpu/drm/xe/xe_rtp.c
+++ b/drivers/gpu/drm/xe/xe_rtp.c
@@ -13,6 +13,7 @@
#include "xe_gt_topology.h"
#include "xe_macros.h"
#include "xe_reg_sr.h"
+#include "xe_sriov.h"
/**
* DOC: Register Table Processing
@@ -35,11 +36,18 @@ static bool rule_matches(const struct xe_device *xe,
unsigned int n_rules)
{
const struct xe_rtp_rule *r;
- unsigned int i;
+ unsigned int i, rcount = 0;
bool match;
for (r = rules, i = 0; i < n_rules; r = &rules[++i]) {
switch (r->match_type) {
+ case XE_RTP_MATCH_OR:
+ /*
+ * This is only reached if a complete set of
+ * rules passed or none were evaluated. For both cases,
+ * shortcut the other rules and return the proper value.
+ */
+ goto done;
case XE_RTP_MATCH_PLATFORM:
match = xe->info.platform == r->platform;
break;
@@ -56,6 +64,9 @@ static bool rule_matches(const struct xe_device *xe,
xe->info.graphics_verx100 <= r->ver_end &&
(!has_samedia(xe) || !xe_gt_is_media_type(gt));
break;
+ case XE_RTP_MATCH_GRAPHICS_VERSION_ANY_GT:
+ match = xe->info.graphics_verx100 == r->ver_start;
+ break;
case XE_RTP_MATCH_GRAPHICS_STEP:
match = xe->info.step.graphics >= r->step_start &&
xe->info.step.graphics < r->step_end &&
@@ -75,6 +86,9 @@ static bool rule_matches(const struct xe_device *xe,
xe->info.step.media < r->step_end &&
(!has_samedia(xe) || xe_gt_is_media_type(gt));
break;
+ case XE_RTP_MATCH_MEDIA_VERSION_ANY_GT:
+ match = xe->info.media_verx100 == r->ver_start;
+ break;
case XE_RTP_MATCH_INTEGRATED:
match = !xe->info.is_dgfx;
break;
@@ -102,10 +116,27 @@ static bool rule_matches(const struct xe_device *xe,
match = false;
}
- if (!match)
- return false;
+ if (!match) {
+ /*
+ * Advance rules until we find XE_RTP_MATCH_OR to check
+ * if there's another set of conditions to check
+ */
+ while (++i < n_rules && rules[i].match_type != XE_RTP_MATCH_OR)
+ ;
+
+ if (i >= n_rules)
+ return false;
+
+ rcount = 0;
+ } else {
+ rcount++;
+ }
}
+done:
+ if (drm_WARN_ON(&xe->drm, !rcount))
+ return false;
+
return true;
}
@@ -227,6 +258,9 @@ void xe_rtp_process_to_sr(struct xe_rtp_process_ctx *ctx,
rtp_get_context(ctx, &hwe, &gt, &xe);
+ if (IS_SRIOV_VF(xe))
+ return;
+
for (entry = entries; entry && entry->name; entry++) {
bool match = false;
@@ -324,8 +358,3 @@ bool xe_rtp_match_first_gslice_fused_off(const struct xe_gt *gt,
return dss >= dss_per_gslice;
}
-bool xe_rtp_match_when_media2000(const struct xe_gt *gt,
- const struct xe_hw_engine *hwe)
-{
- return (gt_to_xe(gt))->info.media_verx100 == 2000;
-}
diff --git a/drivers/gpu/drm/xe/xe_rtp.h b/drivers/gpu/drm/xe/xe_rtp.h
index a32645f5f80b..ad446731192c 100644
--- a/drivers/gpu/drm/xe/xe_rtp.h
+++ b/drivers/gpu/drm/xe/xe_rtp.h
@@ -140,9 +140,23 @@ struct xe_reg_sr;
.ver_start = ver_start__, .ver_end = ver_end__, }
/**
- * XE_RTP_RULE_MEDIA_VERSION - Create rule matching media version
+ * XE_RTP_RULE_GRAPHICS_VERSION_ANY_GT - Create rule matching graphics version on any GT
* @ver__: Graphics IP version to match
*
+ * Like XE_RTP_RULE_GRAPHICS_VERSION, but it matches even if the current GT
+ * being checked is not of the graphics type. It allows to add RTP entries to
+ * another GT when the device contains a Graphics IP with that version.
+ *
+ * Refer to XE_RTP_RULES() for expected usage.
+ */
+#define XE_RTP_RULE_GRAPHICS_VERSION_ANY_GT(ver__) \
+ { .match_type = XE_RTP_MATCH_GRAPHICS_VERSION_ANY_GT, \
+ .ver_start = ver__, }
+
+/**
+ * XE_RTP_RULE_MEDIA_VERSION - Create rule matching media version
+ * @ver__: Media IP version to match
+ *
* Refer to XE_RTP_RULES() for expected usage.
*/
#define XE_RTP_RULE_MEDIA_VERSION(ver__) \
@@ -164,6 +178,20 @@ struct xe_reg_sr;
.ver_start = ver_start__, .ver_end = ver_end__, }
/**
+ * XE_RTP_RULE_MEDIA_VERSION_ANY_GT - Create rule matching media version on any GT
+ * @ver__: Media IP version to match
+ *
+ * Like XE_RTP_RULE_MEDIA_VERSION, but it matches even if the current GT being
+ * checked is not of the media type. It allows to add RTP entries to another
+ * GT when the device contains a Media IP with that version.
+ *
+ * Refer to XE_RTP_RULES() for expected usage.
+ */
+#define XE_RTP_RULE_MEDIA_VERSION_ANY_GT(ver__) \
+ { .match_type = XE_RTP_MATCH_MEDIA_VERSION_ANY_GT, \
+ .ver_start = ver__, }
+
+/**
* XE_RTP_RULE_IS_INTEGRATED - Create a rule matching integrated graphics devices
*
* Refer to XE_RTP_RULES() for expected usage.
@@ -180,6 +208,27 @@ struct xe_reg_sr;
{ .match_type = XE_RTP_MATCH_DISCRETE }
/**
+ * XE_RTP_RULE_OR - Create an OR condition for rtp rules
+ *
+ * RTP rules are AND'ed when evaluated and all of them need to match.
+ * XE_RTP_RULE_OR allows to create set of rules where any of them matching is
+ * sufficient for the action to trigger. Example:
+ *
+ * .. code-block:: c
+ *
+ * const struct xe_rtp_entry_sr entries[] = {
+ * ...
+ * { XE_RTP_NAME("test-entry"),
+ * XE_RTP_RULES(PLATFORM(DG2), OR, PLATFORM(TIGERLAKE)),
+ * ...
+ * },
+ * ...
+ * };
+ */
+#define XE_RTP_RULE_OR \
+ { .match_type = XE_RTP_MATCH_OR }
+
+/**
* XE_RTP_ACTION_WR - Helper to write a value to the register, overriding all
* the bits
* @reg_: Register
@@ -325,7 +374,7 @@ struct xe_reg_sr;
* XE_RTP_RULES - Helper to set multiple rules to a struct xe_rtp_entry_sr entry
* @...: Rules
*
- * At least one rule is needed and up to 4 are supported. Multiple rules are
+ * At least one rule is needed and up to 6 are supported. Multiple rules are
* AND'ed together, i.e. all the rules must evaluate to true for the entry to
* be processed. See XE_RTP_MATCH_* for the possible match rules. Example:
*
@@ -350,7 +399,7 @@ struct xe_reg_sr;
* XE_RTP_ACTIONS - Helper to set multiple actions to a struct xe_rtp_entry_sr
* @...: Actions to be taken
*
- * At least one action is needed and up to 4 are supported. See XE_RTP_ACTION_*
+ * At least one action is needed and up to 6 are supported. See XE_RTP_ACTION_*
* for the possible actions. Example:
*
* .. code-block:: c
@@ -427,18 +476,4 @@ bool xe_rtp_match_first_render_or_compute(const struct xe_gt *gt,
bool xe_rtp_match_first_gslice_fused_off(const struct xe_gt *gt,
const struct xe_hw_engine *hwe);
-/*
- * xe_rtp_match_when_media2000 - Match when media GT version 2000
- *
- * @gt: GT structure
- * @hwe: Engine instance
- *
- * Its one of the case where we need to apply workaround on primary GT
- * based on if media GT version 2000 is present. Thus this API will help
- * us to match media version 2000.
- *
- * Returns: true if media GT version 2000, false otherwise.
- */
-bool xe_rtp_match_when_media2000(const struct xe_gt *gt,
- const struct xe_hw_engine *hwe);
#endif
diff --git a/drivers/gpu/drm/xe/xe_rtp_helpers.h b/drivers/gpu/drm/xe/xe_rtp_helpers.h
index 7735f217ba71..c59e40fd7fff 100644
--- a/drivers/gpu/drm/xe/xe_rtp_helpers.h
+++ b/drivers/gpu/drm/xe/xe_rtp_helpers.h
@@ -58,6 +58,8 @@
#define XE_RTP_PASTE_2(prefix_, sep_, args_) _XE_RTP_CONCAT(prefix_, FIRST_ARG args_) __XE_RTP_PASTE_SEP_ ## sep_ XE_RTP_PASTE_1(prefix_, sep_, _XE_TUPLE_TAIL args_)
#define XE_RTP_PASTE_3(prefix_, sep_, args_) _XE_RTP_CONCAT(prefix_, FIRST_ARG args_) __XE_RTP_PASTE_SEP_ ## sep_ XE_RTP_PASTE_2(prefix_, sep_, _XE_TUPLE_TAIL args_)
#define XE_RTP_PASTE_4(prefix_, sep_, args_) _XE_RTP_CONCAT(prefix_, FIRST_ARG args_) __XE_RTP_PASTE_SEP_ ## sep_ XE_RTP_PASTE_3(prefix_, sep_, _XE_TUPLE_TAIL args_)
+#define XE_RTP_PASTE_5(prefix_, sep_, args_) _XE_RTP_CONCAT(prefix_, FIRST_ARG args_) __XE_RTP_PASTE_SEP_ ## sep_ XE_RTP_PASTE_4(prefix_, sep_, _XE_TUPLE_TAIL args_)
+#define XE_RTP_PASTE_6(prefix_, sep_, args_) _XE_RTP_CONCAT(prefix_, FIRST_ARG args_) __XE_RTP_PASTE_SEP_ ## sep_ XE_RTP_PASTE_5(prefix_, sep_, _XE_TUPLE_TAIL args_)
/*
* XE_RTP_DROP_CAST - Drop cast to convert a compound statement to a initializer
diff --git a/drivers/gpu/drm/xe/xe_rtp_types.h b/drivers/gpu/drm/xe/xe_rtp_types.h
index 637acc7626a4..1b76b947c706 100644
--- a/drivers/gpu/drm/xe/xe_rtp_types.h
+++ b/drivers/gpu/drm/xe/xe_rtp_types.h
@@ -42,15 +42,18 @@ enum {
XE_RTP_MATCH_SUBPLATFORM,
XE_RTP_MATCH_GRAPHICS_VERSION,
XE_RTP_MATCH_GRAPHICS_VERSION_RANGE,
+ XE_RTP_MATCH_GRAPHICS_VERSION_ANY_GT,
XE_RTP_MATCH_GRAPHICS_STEP,
XE_RTP_MATCH_MEDIA_VERSION,
XE_RTP_MATCH_MEDIA_VERSION_RANGE,
+ XE_RTP_MATCH_MEDIA_VERSION_ANY_GT,
XE_RTP_MATCH_MEDIA_STEP,
XE_RTP_MATCH_INTEGRATED,
XE_RTP_MATCH_DISCRETE,
XE_RTP_MATCH_ENGINE_CLASS,
XE_RTP_MATCH_NOT_ENGINE_CLASS,
XE_RTP_MATCH_FUNC,
+ XE_RTP_MATCH_OR,
};
/** struct xe_rtp_rule - match rule for processing entry */
diff --git a/drivers/gpu/drm/xe/xe_sched_job.c b/drivers/gpu/drm/xe/xe_sched_job.c
index 5c013904877a..44d534e362cd 100644
--- a/drivers/gpu/drm/xe/xe_sched_job.c
+++ b/drivers/gpu/drm/xe/xe_sched_job.c
@@ -363,3 +363,9 @@ xe_sched_job_snapshot_print(struct xe_sched_job_snapshot *snapshot,
for (i = 0; i < snapshot->batch_addr_len; i++)
drm_printf(p, "batch_addr[%u]: 0x%016llx\n", i, snapshot->batch_addr[i]);
}
+
+int xe_sched_job_add_deps(struct xe_sched_job *job, struct dma_resv *resv,
+ enum dma_resv_usage usage)
+{
+ return drm_sched_job_add_resv_dependencies(&job->drm, resv, usage);
+}
diff --git a/drivers/gpu/drm/xe/xe_sched_job.h b/drivers/gpu/drm/xe/xe_sched_job.h
index f362e28455db..3dc72c5c1f13 100644
--- a/drivers/gpu/drm/xe/xe_sched_job.h
+++ b/drivers/gpu/drm/xe/xe_sched_job.h
@@ -90,4 +90,7 @@ struct xe_sched_job_snapshot *xe_sched_job_snapshot_capture(struct xe_sched_job
void xe_sched_job_snapshot_free(struct xe_sched_job_snapshot *snapshot);
void xe_sched_job_snapshot_print(struct xe_sched_job_snapshot *snapshot, struct drm_printer *p);
+int xe_sched_job_add_deps(struct xe_sched_job *job, struct dma_resv *resv,
+ enum dma_resv_usage usage);
+
#endif
diff --git a/drivers/gpu/drm/xe/xe_sriov.h b/drivers/gpu/drm/xe/xe_sriov.h
index 486bb21c3256..688fbabf08f1 100644
--- a/drivers/gpu/drm/xe/xe_sriov.h
+++ b/drivers/gpu/drm/xe/xe_sriov.h
@@ -19,18 +19,18 @@ void xe_sriov_probe_early(struct xe_device *xe);
void xe_sriov_print_info(struct xe_device *xe, struct drm_printer *p);
int xe_sriov_init(struct xe_device *xe);
-static inline enum xe_sriov_mode xe_device_sriov_mode(struct xe_device *xe)
+static inline enum xe_sriov_mode xe_device_sriov_mode(const struct xe_device *xe)
{
xe_assert(xe, xe->sriov.__mode);
return xe->sriov.__mode;
}
-static inline bool xe_device_is_sriov_pf(struct xe_device *xe)
+static inline bool xe_device_is_sriov_pf(const struct xe_device *xe)
{
return xe_device_sriov_mode(xe) == XE_SRIOV_MODE_PF;
}
-static inline bool xe_device_is_sriov_vf(struct xe_device *xe)
+static inline bool xe_device_is_sriov_vf(const struct xe_device *xe)
{
return xe_device_sriov_mode(xe) == XE_SRIOV_MODE_VF;
}
diff --git a/drivers/gpu/drm/xe/xe_trace.h b/drivers/gpu/drm/xe/xe_trace.h
index e4cba64474e6..baba14fb1e32 100644
--- a/drivers/gpu/drm/xe/xe_trace.h
+++ b/drivers/gpu/drm/xe/xe_trace.h
@@ -12,8 +12,6 @@
#include <linux/tracepoint.h>
#include <linux/types.h>
-#include "xe_bo.h"
-#include "xe_bo_types.h"
#include "xe_exec_queue_types.h"
#include "xe_gpu_scheduler_types.h"
#include "xe_gt_tlb_invalidation_types.h"
@@ -22,110 +20,64 @@
#include "xe_sched_job.h"
#include "xe_vm.h"
+#define __dev_name_xe(xe) dev_name((xe)->drm.dev)
+#define __dev_name_gt(gt) __dev_name_xe(gt_to_xe((gt)))
+#define __dev_name_eq(q) __dev_name_gt((q)->gt)
+
DECLARE_EVENT_CLASS(xe_gt_tlb_invalidation_fence,
- TP_PROTO(struct xe_gt_tlb_invalidation_fence *fence),
- TP_ARGS(fence),
+ TP_PROTO(struct xe_device *xe, struct xe_gt_tlb_invalidation_fence *fence),
+ TP_ARGS(xe, fence),
TP_STRUCT__entry(
+ __string(dev, __dev_name_xe(xe))
__field(struct xe_gt_tlb_invalidation_fence *, fence)
__field(int, seqno)
),
TP_fast_assign(
+ __assign_str(dev);
__entry->fence = fence;
__entry->seqno = fence->seqno;
),
- TP_printk("fence=%p, seqno=%d",
- __entry->fence, __entry->seqno)
+ TP_printk("dev=%s, fence=%p, seqno=%d",
+ __get_str(dev), __entry->fence, __entry->seqno)
);
DEFINE_EVENT(xe_gt_tlb_invalidation_fence, xe_gt_tlb_invalidation_fence_create,
- TP_PROTO(struct xe_gt_tlb_invalidation_fence *fence),
- TP_ARGS(fence)
+ TP_PROTO(struct xe_device *xe, struct xe_gt_tlb_invalidation_fence *fence),
+ TP_ARGS(xe, fence)
);
DEFINE_EVENT(xe_gt_tlb_invalidation_fence,
xe_gt_tlb_invalidation_fence_work_func,
- TP_PROTO(struct xe_gt_tlb_invalidation_fence *fence),
- TP_ARGS(fence)
+ TP_PROTO(struct xe_device *xe, struct xe_gt_tlb_invalidation_fence *fence),
+ TP_ARGS(xe, fence)
);
DEFINE_EVENT(xe_gt_tlb_invalidation_fence, xe_gt_tlb_invalidation_fence_cb,
- TP_PROTO(struct xe_gt_tlb_invalidation_fence *fence),
- TP_ARGS(fence)
+ TP_PROTO(struct xe_device *xe, struct xe_gt_tlb_invalidation_fence *fence),
+ TP_ARGS(xe, fence)
);
DEFINE_EVENT(xe_gt_tlb_invalidation_fence, xe_gt_tlb_invalidation_fence_send,
- TP_PROTO(struct xe_gt_tlb_invalidation_fence *fence),
- TP_ARGS(fence)
+ TP_PROTO(struct xe_device *xe, struct xe_gt_tlb_invalidation_fence *fence),
+ TP_ARGS(xe, fence)
);
DEFINE_EVENT(xe_gt_tlb_invalidation_fence, xe_gt_tlb_invalidation_fence_recv,
- TP_PROTO(struct xe_gt_tlb_invalidation_fence *fence),
- TP_ARGS(fence)
+ TP_PROTO(struct xe_device *xe, struct xe_gt_tlb_invalidation_fence *fence),
+ TP_ARGS(xe, fence)
);
DEFINE_EVENT(xe_gt_tlb_invalidation_fence, xe_gt_tlb_invalidation_fence_signal,
- TP_PROTO(struct xe_gt_tlb_invalidation_fence *fence),
- TP_ARGS(fence)
+ TP_PROTO(struct xe_device *xe, struct xe_gt_tlb_invalidation_fence *fence),
+ TP_ARGS(xe, fence)
);
DEFINE_EVENT(xe_gt_tlb_invalidation_fence, xe_gt_tlb_invalidation_fence_timeout,
- TP_PROTO(struct xe_gt_tlb_invalidation_fence *fence),
- TP_ARGS(fence)
-);
-
-DECLARE_EVENT_CLASS(xe_bo,
- TP_PROTO(struct xe_bo *bo),
- TP_ARGS(bo),
-
- TP_STRUCT__entry(
- __field(size_t, size)
- __field(u32, flags)
- __field(struct xe_vm *, vm)
- ),
-
- TP_fast_assign(
- __entry->size = bo->size;
- __entry->flags = bo->flags;
- __entry->vm = bo->vm;
- ),
-
- TP_printk("size=%zu, flags=0x%02x, vm=%p",
- __entry->size, __entry->flags, __entry->vm)
-);
-
-DEFINE_EVENT(xe_bo, xe_bo_cpu_fault,
- TP_PROTO(struct xe_bo *bo),
- TP_ARGS(bo)
-);
-
-TRACE_EVENT(xe_bo_move,
- TP_PROTO(struct xe_bo *bo, uint32_t new_placement, uint32_t old_placement,
- bool move_lacks_source),
- TP_ARGS(bo, new_placement, old_placement, move_lacks_source),
- TP_STRUCT__entry(
- __field(struct xe_bo *, bo)
- __field(size_t, size)
- __field(u32, new_placement)
- __field(u32, old_placement)
- __array(char, device_id, 12)
- __field(bool, move_lacks_source)
- ),
-
- TP_fast_assign(
- __entry->bo = bo;
- __entry->size = bo->size;
- __entry->new_placement = new_placement;
- __entry->old_placement = old_placement;
- strscpy(__entry->device_id, dev_name(xe_bo_device(__entry->bo)->drm.dev), 12);
- __entry->move_lacks_source = move_lacks_source;
- ),
- TP_printk("move_lacks_source:%s, migrate object %p [size %zu] from %s to %s device_id:%s",
- __entry->move_lacks_source ? "yes" : "no", __entry->bo, __entry->size,
- xe_mem_type_to_name[__entry->old_placement],
- xe_mem_type_to_name[__entry->new_placement], __entry->device_id)
+ TP_PROTO(struct xe_device *xe, struct xe_gt_tlb_invalidation_fence *fence),
+ TP_ARGS(xe, fence)
);
DECLARE_EVENT_CLASS(xe_exec_queue,
@@ -133,6 +85,7 @@ DECLARE_EVENT_CLASS(xe_exec_queue,
TP_ARGS(q),
TP_STRUCT__entry(
+ __string(dev, __dev_name_eq(q))
__field(enum xe_engine_class, class)
__field(u32, logical_mask)
__field(u8, gt_id)
@@ -143,6 +96,7 @@ DECLARE_EVENT_CLASS(xe_exec_queue,
),
TP_fast_assign(
+ __assign_str(dev);
__entry->class = q->class;
__entry->logical_mask = q->logical_mask;
__entry->gt_id = q->gt->info.id;
@@ -152,8 +106,8 @@ DECLARE_EVENT_CLASS(xe_exec_queue,
__entry->flags = q->flags;
),
- TP_printk("%d:0x%x, gt=%d, width=%d, guc_id=%d, guc_state=0x%x, flags=0x%x",
- __entry->class, __entry->logical_mask,
+ TP_printk("dev=%s, %d:0x%x, gt=%d, width=%d, guc_id=%d, guc_state=0x%x, flags=0x%x",
+ __get_str(dev), __entry->class, __entry->logical_mask,
__entry->gt_id, __entry->width, __entry->guc_id,
__entry->guc_state, __entry->flags)
);
@@ -253,6 +207,7 @@ DECLARE_EVENT_CLASS(xe_sched_job,
TP_ARGS(job),
TP_STRUCT__entry(
+ __string(dev, __dev_name_eq(job->q))
__field(u32, seqno)
__field(u32, lrc_seqno)
__field(u16, guc_id)
@@ -264,6 +219,7 @@ DECLARE_EVENT_CLASS(xe_sched_job,
),
TP_fast_assign(
+ __assign_str(dev);
__entry->seqno = xe_sched_job_seqno(job);
__entry->lrc_seqno = xe_sched_job_lrc_seqno(job);
__entry->guc_id = job->q->guc->id;
@@ -275,8 +231,8 @@ DECLARE_EVENT_CLASS(xe_sched_job,
__entry->batch_addr = (u64)job->ptrs[0].batch_addr;
),
- TP_printk("fence=%p, seqno=%u, lrc_seqno=%u, guc_id=%d, batch_addr=0x%012llx, guc_state=0x%x, flags=0x%x, error=%d",
- __entry->fence, __entry->seqno,
+ TP_printk("dev=%s, fence=%p, seqno=%u, lrc_seqno=%u, guc_id=%d, batch_addr=0x%012llx, guc_state=0x%x, flags=0x%x, error=%d",
+ __get_str(dev), __entry->fence, __entry->seqno,
__entry->lrc_seqno, __entry->guc_id,
__entry->batch_addr, __entry->guc_state,
__entry->flags, __entry->error)
@@ -322,17 +278,19 @@ DECLARE_EVENT_CLASS(xe_sched_msg,
TP_ARGS(msg),
TP_STRUCT__entry(
+ __string(dev, __dev_name_eq(((struct xe_exec_queue *)msg->private_data)))
__field(u32, opcode)
__field(u16, guc_id)
),
TP_fast_assign(
+ __assign_str(dev);
__entry->opcode = msg->opcode;
__entry->guc_id =
((struct xe_exec_queue *)msg->private_data)->guc->id;
),
- TP_printk("guc_id=%d, opcode=%u", __entry->guc_id,
+ TP_printk("dev=%s, guc_id=%d, opcode=%u", __get_str(dev), __entry->guc_id,
__entry->opcode)
);
@@ -351,19 +309,21 @@ DECLARE_EVENT_CLASS(xe_hw_fence,
TP_ARGS(fence),
TP_STRUCT__entry(
+ __string(dev, __dev_name_gt(fence->ctx->gt))
__field(u64, ctx)
__field(u32, seqno)
__field(struct xe_hw_fence *, fence)
),
TP_fast_assign(
+ __assign_str(dev);
__entry->ctx = fence->dma.context;
__entry->seqno = fence->dma.seqno;
__entry->fence = fence;
),
- TP_printk("ctx=0x%016llx, fence=%p, seqno=%u",
- __entry->ctx, __entry->fence, __entry->seqno)
+ TP_printk("dev=%s, ctx=0x%016llx, fence=%p, seqno=%u",
+ __get_str(dev), __entry->ctx, __entry->fence, __entry->seqno)
);
DEFINE_EVENT(xe_hw_fence, xe_hw_fence_create,
@@ -381,247 +341,32 @@ DEFINE_EVENT(xe_hw_fence, xe_hw_fence_try_signal,
TP_ARGS(fence)
);
-DEFINE_EVENT(xe_hw_fence, xe_hw_fence_free,
- TP_PROTO(struct xe_hw_fence *fence),
- TP_ARGS(fence)
-);
-
-DECLARE_EVENT_CLASS(xe_vma,
- TP_PROTO(struct xe_vma *vma),
- TP_ARGS(vma),
-
- TP_STRUCT__entry(
- __field(struct xe_vma *, vma)
- __field(u32, asid)
- __field(u64, start)
- __field(u64, end)
- __field(u64, ptr)
- ),
-
- TP_fast_assign(
- __entry->vma = vma;
- __entry->asid = xe_vma_vm(vma)->usm.asid;
- __entry->start = xe_vma_start(vma);
- __entry->end = xe_vma_end(vma) - 1;
- __entry->ptr = xe_vma_userptr(vma);
- ),
-
- TP_printk("vma=%p, asid=0x%05x, start=0x%012llx, end=0x%012llx, userptr=0x%012llx,",
- __entry->vma, __entry->asid, __entry->start,
- __entry->end, __entry->ptr)
-)
-
-DEFINE_EVENT(xe_vma, xe_vma_flush,
- TP_PROTO(struct xe_vma *vma),
- TP_ARGS(vma)
-);
-
-DEFINE_EVENT(xe_vma, xe_vma_pagefault,
- TP_PROTO(struct xe_vma *vma),
- TP_ARGS(vma)
-);
-
-DEFINE_EVENT(xe_vma, xe_vma_acc,
- TP_PROTO(struct xe_vma *vma),
- TP_ARGS(vma)
-);
-
-DEFINE_EVENT(xe_vma, xe_vma_fail,
- TP_PROTO(struct xe_vma *vma),
- TP_ARGS(vma)
-);
-
-DEFINE_EVENT(xe_vma, xe_vma_bind,
- TP_PROTO(struct xe_vma *vma),
- TP_ARGS(vma)
-);
-
-DEFINE_EVENT(xe_vma, xe_vma_pf_bind,
- TP_PROTO(struct xe_vma *vma),
- TP_ARGS(vma)
-);
-
-DEFINE_EVENT(xe_vma, xe_vma_unbind,
- TP_PROTO(struct xe_vma *vma),
- TP_ARGS(vma)
-);
-
-DEFINE_EVENT(xe_vma, xe_vma_userptr_rebind_worker,
- TP_PROTO(struct xe_vma *vma),
- TP_ARGS(vma)
-);
-
-DEFINE_EVENT(xe_vma, xe_vma_userptr_rebind_exec,
- TP_PROTO(struct xe_vma *vma),
- TP_ARGS(vma)
-);
-
-DEFINE_EVENT(xe_vma, xe_vma_rebind_worker,
- TP_PROTO(struct xe_vma *vma),
- TP_ARGS(vma)
-);
-
-DEFINE_EVENT(xe_vma, xe_vma_rebind_exec,
- TP_PROTO(struct xe_vma *vma),
- TP_ARGS(vma)
-);
-
-DEFINE_EVENT(xe_vma, xe_vma_userptr_invalidate,
- TP_PROTO(struct xe_vma *vma),
- TP_ARGS(vma)
-);
-
-DEFINE_EVENT(xe_vma, xe_vma_invalidate,
- TP_PROTO(struct xe_vma *vma),
- TP_ARGS(vma)
-);
-
-DEFINE_EVENT(xe_vma, xe_vma_evict,
- TP_PROTO(struct xe_vma *vma),
- TP_ARGS(vma)
-);
-
-DEFINE_EVENT(xe_vma, xe_vma_userptr_invalidate_complete,
- TP_PROTO(struct xe_vma *vma),
- TP_ARGS(vma)
-);
-
-DECLARE_EVENT_CLASS(xe_vm,
- TP_PROTO(struct xe_vm *vm),
- TP_ARGS(vm),
-
- TP_STRUCT__entry(
- __field(struct xe_vm *, vm)
- __field(u32, asid)
- ),
-
- TP_fast_assign(
- __entry->vm = vm;
- __entry->asid = vm->usm.asid;
- ),
-
- TP_printk("vm=%p, asid=0x%05x", __entry->vm,
- __entry->asid)
-);
-
-DEFINE_EVENT(xe_vm, xe_vm_kill,
- TP_PROTO(struct xe_vm *vm),
- TP_ARGS(vm)
-);
-
-DEFINE_EVENT(xe_vm, xe_vm_create,
- TP_PROTO(struct xe_vm *vm),
- TP_ARGS(vm)
-);
-
-DEFINE_EVENT(xe_vm, xe_vm_free,
- TP_PROTO(struct xe_vm *vm),
- TP_ARGS(vm)
-);
-
-DEFINE_EVENT(xe_vm, xe_vm_cpu_bind,
- TP_PROTO(struct xe_vm *vm),
- TP_ARGS(vm)
-);
-
-DEFINE_EVENT(xe_vm, xe_vm_restart,
- TP_PROTO(struct xe_vm *vm),
- TP_ARGS(vm)
-);
-
-DEFINE_EVENT(xe_vm, xe_vm_rebind_worker_enter,
- TP_PROTO(struct xe_vm *vm),
- TP_ARGS(vm)
-);
-
-DEFINE_EVENT(xe_vm, xe_vm_rebind_worker_retry,
- TP_PROTO(struct xe_vm *vm),
- TP_ARGS(vm)
-);
-
-DEFINE_EVENT(xe_vm, xe_vm_rebind_worker_exit,
- TP_PROTO(struct xe_vm *vm),
- TP_ARGS(vm)
-);
-
-/* GuC */
-DECLARE_EVENT_CLASS(xe_guc_ct_flow_control,
- TP_PROTO(u32 _head, u32 _tail, u32 size, u32 space, u32 len),
- TP_ARGS(_head, _tail, size, space, len),
-
- TP_STRUCT__entry(
- __field(u32, _head)
- __field(u32, _tail)
- __field(u32, size)
- __field(u32, space)
- __field(u32, len)
- ),
-
- TP_fast_assign(
- __entry->_head = _head;
- __entry->_tail = _tail;
- __entry->size = size;
- __entry->space = space;
- __entry->len = len;
- ),
-
- TP_printk("h2g flow control: head=%u, tail=%u, size=%u, space=%u, len=%u",
- __entry->_head, __entry->_tail, __entry->size,
- __entry->space, __entry->len)
-);
-
-DEFINE_EVENT(xe_guc_ct_flow_control, xe_guc_ct_h2g_flow_control,
- TP_PROTO(u32 _head, u32 _tail, u32 size, u32 space, u32 len),
- TP_ARGS(_head, _tail, size, space, len)
-);
-
-DEFINE_EVENT_PRINT(xe_guc_ct_flow_control, xe_guc_ct_g2h_flow_control,
- TP_PROTO(u32 _head, u32 _tail, u32 size, u32 space, u32 len),
- TP_ARGS(_head, _tail, size, space, len),
-
- TP_printk("g2h flow control: head=%u, tail=%u, size=%u, space=%u, len=%u",
- __entry->_head, __entry->_tail, __entry->size,
- __entry->space, __entry->len)
-);
-
-DECLARE_EVENT_CLASS(xe_guc_ctb,
- TP_PROTO(u8 gt_id, u32 action, u32 len, u32 _head, u32 tail),
- TP_ARGS(gt_id, action, len, _head, tail),
-
- TP_STRUCT__entry(
- __field(u8, gt_id)
- __field(u32, action)
- __field(u32, len)
- __field(u32, tail)
- __field(u32, _head)
- ),
-
- TP_fast_assign(
- __entry->gt_id = gt_id;
- __entry->action = action;
- __entry->len = len;
- __entry->tail = tail;
- __entry->_head = _head;
- ),
-
- TP_printk("gt%d: H2G CTB: action=0x%x, len=%d, tail=%d, head=%d\n",
- __entry->gt_id, __entry->action, __entry->len,
- __entry->tail, __entry->_head)
-);
-
-DEFINE_EVENT(xe_guc_ctb, xe_guc_ctb_h2g,
- TP_PROTO(u8 gt_id, u32 action, u32 len, u32 _head, u32 tail),
- TP_ARGS(gt_id, action, len, _head, tail)
-);
-
-DEFINE_EVENT_PRINT(xe_guc_ctb, xe_guc_ctb_g2h,
- TP_PROTO(u8 gt_id, u32 action, u32 len, u32 _head, u32 tail),
- TP_ARGS(gt_id, action, len, _head, tail),
-
- TP_printk("gt%d: G2H CTB: action=0x%x, len=%d, tail=%d, head=%d\n",
- __entry->gt_id, __entry->action, __entry->len,
- __entry->tail, __entry->_head)
-
+TRACE_EVENT(xe_reg_rw,
+ TP_PROTO(struct xe_gt *gt, bool write, u32 reg, u64 val, int len),
+
+ TP_ARGS(gt, write, reg, val, len),
+
+ TP_STRUCT__entry(
+ __string(dev, __dev_name_gt(gt))
+ __field(u64, val)
+ __field(u32, reg)
+ __field(u16, write)
+ __field(u16, len)
+ ),
+
+ TP_fast_assign(
+ __assign_str(dev);
+ __entry->val = val;
+ __entry->reg = reg;
+ __entry->write = write;
+ __entry->len = len;
+ ),
+
+ TP_printk("dev=%s, %s reg=0x%x, len=%d, val=(0x%x, 0x%x)",
+ __get_str(dev), __entry->write ? "write" : "read",
+ __entry->reg, __entry->len,
+ (u32)(__entry->val & 0xffffffff),
+ (u32)(__entry->val >> 32))
);
#endif
diff --git a/drivers/gpu/drm/xe/xe_trace_bo.c b/drivers/gpu/drm/xe/xe_trace_bo.c
new file mode 100644
index 000000000000..6d5e66ce4c50
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_trace_bo.c
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright © 2024 Intel Corporation
+ */
+
+#ifndef __CHECKER__
+#define CREATE_TRACE_POINTS
+#include "xe_trace_bo.h"
+#endif
diff --git a/drivers/gpu/drm/xe/xe_trace_bo.h b/drivers/gpu/drm/xe/xe_trace_bo.h
new file mode 100644
index 000000000000..f39f09ed3495
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_trace_bo.h
@@ -0,0 +1,247 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright © 2024 Intel Corporation
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM xe
+
+#if !defined(_XE_TRACE_BO_H_) || defined(TRACE_HEADER_MULTI_READ)
+#define _XE_TRACE_BO_H_
+
+#include <linux/tracepoint.h>
+#include <linux/types.h>
+
+#include "xe_bo.h"
+#include "xe_bo_types.h"
+#include "xe_vm.h"
+
+#define __dev_name_bo(bo) dev_name(xe_bo_device(bo)->drm.dev)
+#define __dev_name_vm(vm) dev_name((vm)->xe->drm.dev)
+#define __dev_name_vma(vma) __dev_name_vm(xe_vma_vm(vma))
+
+DECLARE_EVENT_CLASS(xe_bo,
+ TP_PROTO(struct xe_bo *bo),
+ TP_ARGS(bo),
+
+ TP_STRUCT__entry(
+ __string(dev, __dev_name_bo(bo))
+ __field(size_t, size)
+ __field(u32, flags)
+ __field(struct xe_vm *, vm)
+ ),
+
+ TP_fast_assign(
+ __assign_str(dev);
+ __entry->size = bo->size;
+ __entry->flags = bo->flags;
+ __entry->vm = bo->vm;
+ ),
+
+ TP_printk("dev=%s, size=%zu, flags=0x%02x, vm=%p",
+ __get_str(dev), __entry->size,
+ __entry->flags, __entry->vm)
+);
+
+DEFINE_EVENT(xe_bo, xe_bo_cpu_fault,
+ TP_PROTO(struct xe_bo *bo),
+ TP_ARGS(bo)
+);
+
+TRACE_EVENT(xe_bo_move,
+ TP_PROTO(struct xe_bo *bo, uint32_t new_placement, uint32_t old_placement,
+ bool move_lacks_source),
+ TP_ARGS(bo, new_placement, old_placement, move_lacks_source),
+ TP_STRUCT__entry(
+ __field(struct xe_bo *, bo)
+ __field(size_t, size)
+ __field(u32, new_placement)
+ __field(u32, old_placement)
+ __string(device_id, __dev_name_bo(bo))
+ __field(bool, move_lacks_source)
+ ),
+
+ TP_fast_assign(
+ __entry->bo = bo;
+ __entry->size = bo->size;
+ __entry->new_placement = new_placement;
+ __entry->old_placement = old_placement;
+ __assign_str(device_id);
+ __entry->move_lacks_source = move_lacks_source;
+ ),
+ TP_printk("move_lacks_source:%s, migrate object %p [size %zu] from %s to %s device_id:%s",
+ __entry->move_lacks_source ? "yes" : "no", __entry->bo, __entry->size,
+ xe_mem_type_to_name[__entry->old_placement],
+ xe_mem_type_to_name[__entry->new_placement], __get_str(device_id))
+);
+
+DECLARE_EVENT_CLASS(xe_vma,
+ TP_PROTO(struct xe_vma *vma),
+ TP_ARGS(vma),
+
+ TP_STRUCT__entry(
+ __string(dev, __dev_name_vma(vma))
+ __field(struct xe_vma *, vma)
+ __field(u32, asid)
+ __field(u64, start)
+ __field(u64, end)
+ __field(u64, ptr)
+ ),
+
+ TP_fast_assign(
+ __assign_str(dev);
+ __entry->vma = vma;
+ __entry->asid = xe_vma_vm(vma)->usm.asid;
+ __entry->start = xe_vma_start(vma);
+ __entry->end = xe_vma_end(vma) - 1;
+ __entry->ptr = xe_vma_userptr(vma);
+ ),
+
+ TP_printk("dev=%s, vma=%p, asid=0x%05x, start=0x%012llx, end=0x%012llx, userptr=0x%012llx,",
+ __get_str(dev), __entry->vma, __entry->asid, __entry->start,
+ __entry->end, __entry->ptr)
+)
+
+DEFINE_EVENT(xe_vma, xe_vma_flush,
+ TP_PROTO(struct xe_vma *vma),
+ TP_ARGS(vma)
+);
+
+DEFINE_EVENT(xe_vma, xe_vma_pagefault,
+ TP_PROTO(struct xe_vma *vma),
+ TP_ARGS(vma)
+);
+
+DEFINE_EVENT(xe_vma, xe_vma_acc,
+ TP_PROTO(struct xe_vma *vma),
+ TP_ARGS(vma)
+);
+
+DEFINE_EVENT(xe_vma, xe_vma_fail,
+ TP_PROTO(struct xe_vma *vma),
+ TP_ARGS(vma)
+);
+
+DEFINE_EVENT(xe_vma, xe_vma_bind,
+ TP_PROTO(struct xe_vma *vma),
+ TP_ARGS(vma)
+);
+
+DEFINE_EVENT(xe_vma, xe_vma_pf_bind,
+ TP_PROTO(struct xe_vma *vma),
+ TP_ARGS(vma)
+);
+
+DEFINE_EVENT(xe_vma, xe_vma_unbind,
+ TP_PROTO(struct xe_vma *vma),
+ TP_ARGS(vma)
+);
+
+DEFINE_EVENT(xe_vma, xe_vma_userptr_rebind_worker,
+ TP_PROTO(struct xe_vma *vma),
+ TP_ARGS(vma)
+);
+
+DEFINE_EVENT(xe_vma, xe_vma_userptr_rebind_exec,
+ TP_PROTO(struct xe_vma *vma),
+ TP_ARGS(vma)
+);
+
+DEFINE_EVENT(xe_vma, xe_vma_rebind_worker,
+ TP_PROTO(struct xe_vma *vma),
+ TP_ARGS(vma)
+);
+
+DEFINE_EVENT(xe_vma, xe_vma_rebind_exec,
+ TP_PROTO(struct xe_vma *vma),
+ TP_ARGS(vma)
+);
+
+DEFINE_EVENT(xe_vma, xe_vma_userptr_invalidate,
+ TP_PROTO(struct xe_vma *vma),
+ TP_ARGS(vma)
+);
+
+DEFINE_EVENT(xe_vma, xe_vma_invalidate,
+ TP_PROTO(struct xe_vma *vma),
+ TP_ARGS(vma)
+);
+
+DEFINE_EVENT(xe_vma, xe_vma_evict,
+ TP_PROTO(struct xe_vma *vma),
+ TP_ARGS(vma)
+);
+
+DEFINE_EVENT(xe_vma, xe_vma_userptr_invalidate_complete,
+ TP_PROTO(struct xe_vma *vma),
+ TP_ARGS(vma)
+);
+
+DECLARE_EVENT_CLASS(xe_vm,
+ TP_PROTO(struct xe_vm *vm),
+ TP_ARGS(vm),
+
+ TP_STRUCT__entry(
+ __string(dev, __dev_name_vm(vm))
+ __field(struct xe_vm *, vm)
+ __field(u32, asid)
+ ),
+
+ TP_fast_assign(
+ __assign_str(dev);
+ __entry->vm = vm;
+ __entry->asid = vm->usm.asid;
+ ),
+
+ TP_printk("dev=%s, vm=%p, asid=0x%05x", __get_str(dev),
+ __entry->vm, __entry->asid)
+);
+
+DEFINE_EVENT(xe_vm, xe_vm_kill,
+ TP_PROTO(struct xe_vm *vm),
+ TP_ARGS(vm)
+);
+
+DEFINE_EVENT(xe_vm, xe_vm_create,
+ TP_PROTO(struct xe_vm *vm),
+ TP_ARGS(vm)
+);
+
+DEFINE_EVENT(xe_vm, xe_vm_free,
+ TP_PROTO(struct xe_vm *vm),
+ TP_ARGS(vm)
+);
+
+DEFINE_EVENT(xe_vm, xe_vm_cpu_bind,
+ TP_PROTO(struct xe_vm *vm),
+ TP_ARGS(vm)
+);
+
+DEFINE_EVENT(xe_vm, xe_vm_restart,
+ TP_PROTO(struct xe_vm *vm),
+ TP_ARGS(vm)
+);
+
+DEFINE_EVENT(xe_vm, xe_vm_rebind_worker_enter,
+ TP_PROTO(struct xe_vm *vm),
+ TP_ARGS(vm)
+);
+
+DEFINE_EVENT(xe_vm, xe_vm_rebind_worker_retry,
+ TP_PROTO(struct xe_vm *vm),
+ TP_ARGS(vm)
+);
+
+DEFINE_EVENT(xe_vm, xe_vm_rebind_worker_exit,
+ TP_PROTO(struct xe_vm *vm),
+ TP_ARGS(vm)
+);
+
+#endif
+
+/* This part must be outside protection */
+#undef TRACE_INCLUDE_PATH
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_PATH ../../drivers/gpu/drm/xe
+#define TRACE_INCLUDE_FILE xe_trace_bo
+#include <trace/define_trace.h>
diff --git a/drivers/gpu/drm/xe/xe_trace_guc.c b/drivers/gpu/drm/xe/xe_trace_guc.c
new file mode 100644
index 000000000000..fcdf6888ff2f
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_trace_guc.c
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright © 2024 Intel Corporation
+ */
+
+#ifndef __CHECKER__
+#define CREATE_TRACE_POINTS
+#include "xe_trace_guc.h"
+#endif
diff --git a/drivers/gpu/drm/xe/xe_trace_guc.h b/drivers/gpu/drm/xe/xe_trace_guc.h
new file mode 100644
index 000000000000..23abdd55dc62
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_trace_guc.h
@@ -0,0 +1,110 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright © 2024 Intel Corporation
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM xe
+
+#if !defined(_XE_TRACE_GUC_H_) || defined(TRACE_HEADER_MULTI_READ)
+#define _XE_TRACE_GUC_H_
+
+#include <linux/tracepoint.h>
+#include <linux/types.h>
+
+#include "xe_device_types.h"
+#include "xe_guc_exec_queue_types.h"
+
+#define __dev_name_xe(xe) dev_name((xe)->drm.dev)
+
+DECLARE_EVENT_CLASS(xe_guc_ct_flow_control,
+ TP_PROTO(struct xe_device *xe, u32 _head, u32 _tail, u32 size, u32 space, u32 len),
+ TP_ARGS(xe, _head, _tail, size, space, len),
+
+ TP_STRUCT__entry(
+ __string(dev, __dev_name_xe(xe))
+ __field(u32, _head)
+ __field(u32, _tail)
+ __field(u32, size)
+ __field(u32, space)
+ __field(u32, len)
+ ),
+
+ TP_fast_assign(
+ __assign_str(dev);
+ __entry->_head = _head;
+ __entry->_tail = _tail;
+ __entry->size = size;
+ __entry->space = space;
+ __entry->len = len;
+ ),
+
+ TP_printk("h2g flow control: dev=%s, head=%u, tail=%u, size=%u, space=%u, len=%u",
+ __get_str(dev), __entry->_head, __entry->_tail, __entry->size,
+ __entry->space, __entry->len)
+);
+
+DEFINE_EVENT(xe_guc_ct_flow_control, xe_guc_ct_h2g_flow_control,
+ TP_PROTO(struct xe_device *xe, u32 _head, u32 _tail, u32 size, u32 space, u32 len),
+ TP_ARGS(xe, _head, _tail, size, space, len)
+);
+
+DEFINE_EVENT_PRINT(xe_guc_ct_flow_control, xe_guc_ct_g2h_flow_control,
+ TP_PROTO(struct xe_device *xe, u32 _head, u32 _tail, u32 size, u32 space, u32 len),
+ TP_ARGS(xe, _head, _tail, size, space, len),
+
+ TP_printk("g2h flow control: dev=%s, head=%u, tail=%u, size=%u, space=%u, len=%u",
+ __get_str(dev), __entry->_head, __entry->_tail, __entry->size,
+ __entry->space, __entry->len)
+);
+
+DECLARE_EVENT_CLASS(xe_guc_ctb,
+ TP_PROTO(struct xe_device *xe, u8 gt_id, u32 action, u32 len, u32 _head, u32 tail),
+ TP_ARGS(xe, gt_id, action, len, _head, tail),
+
+ TP_STRUCT__entry(
+ __string(dev, __dev_name_xe(xe))
+ __field(u8, gt_id)
+ __field(u32, action)
+ __field(u32, len)
+ __field(u32, tail)
+ __field(u32, _head)
+ ),
+
+ TP_fast_assign(
+ __assign_str(dev);
+ __entry->gt_id = gt_id;
+ __entry->action = action;
+ __entry->len = len;
+ __entry->tail = tail;
+ __entry->_head = _head;
+ ),
+
+ TP_printk("H2G CTB: dev=%s, gt%d: action=0x%x, len=%d, tail=%d, head=%d\n",
+ __get_str(dev), __entry->gt_id, __entry->action, __entry->len,
+ __entry->tail, __entry->_head)
+);
+
+DEFINE_EVENT(xe_guc_ctb, xe_guc_ctb_h2g,
+ TP_PROTO(struct xe_device *xe, u8 gt_id, u32 action, u32 len, u32 _head, u32 tail),
+ TP_ARGS(xe, gt_id, action, len, _head, tail)
+);
+
+DEFINE_EVENT_PRINT(xe_guc_ctb, xe_guc_ctb_g2h,
+ TP_PROTO(struct xe_device *xe, u8 gt_id, u32 action, u32 len, u32 _head, u32 tail),
+ TP_ARGS(xe, gt_id, action, len, _head, tail),
+
+ TP_printk("G2H CTB: dev=%s, gt%d: action=0x%x, len=%d, tail=%d, head=%d\n",
+ __get_str(dev), __entry->gt_id, __entry->action, __entry->len,
+ __entry->tail, __entry->_head)
+
+);
+
+#endif
+
+/* This part must be outside protection */
+#undef TRACE_INCLUDE_PATH
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_PATH ../../drivers/gpu/drm/xe
+#define TRACE_INCLUDE_FILE xe_trace_guc
+#include <trace/define_trace.h>
diff --git a/drivers/gpu/drm/xe/xe_uc.c b/drivers/gpu/drm/xe/xe_uc.c
index 0f240534fb72..0d073a9987c2 100644
--- a/drivers/gpu/drm/xe/xe_uc.c
+++ b/drivers/gpu/drm/xe/xe_uc.c
@@ -300,3 +300,17 @@ void xe_uc_remove(struct xe_uc *uc)
{
xe_gsc_remove(&uc->gsc);
}
+
+/**
+ * xe_uc_declare_wedged() - Declare UC wedged
+ * @uc: the UC object
+ *
+ * Wedge the UC which stops all submission, saves desired debug state, and
+ * cleans up anything which could timeout.
+ */
+void xe_uc_declare_wedged(struct xe_uc *uc)
+{
+ xe_gt_assert(uc_to_gt(uc), uc_to_xe(uc)->wedged.mode);
+
+ xe_guc_declare_wedged(&uc->guc);
+}
diff --git a/drivers/gpu/drm/xe/xe_uc.h b/drivers/gpu/drm/xe/xe_uc.h
index 11856f24e6f9..506517c11333 100644
--- a/drivers/gpu/drm/xe/xe_uc.h
+++ b/drivers/gpu/drm/xe/xe_uc.h
@@ -21,5 +21,6 @@ int xe_uc_start(struct xe_uc *uc);
int xe_uc_suspend(struct xe_uc *uc);
int xe_uc_sanitize_reset(struct xe_uc *uc);
void xe_uc_remove(struct xe_uc *uc);
+void xe_uc_declare_wedged(struct xe_uc *uc);
#endif
diff --git a/drivers/gpu/drm/xe/xe_uc_fw.h b/drivers/gpu/drm/xe/xe_uc_fw.h
index 35078038797e..c108e9d08e70 100644
--- a/drivers/gpu/drm/xe/xe_uc_fw.h
+++ b/drivers/gpu/drm/xe/xe_uc_fw.h
@@ -158,7 +158,7 @@ static inline bool xe_uc_fw_is_overridden(const struct xe_uc_fw *uc_fw)
static inline void xe_uc_fw_sanitize(struct xe_uc_fw *uc_fw)
{
- if (xe_uc_fw_is_loaded(uc_fw))
+ if (xe_uc_fw_is_loadable(uc_fw))
xe_uc_fw_change_status(uc_fw, XE_UC_FIRMWARE_LOADABLE);
}
diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index 99bf7412475c..5b166fa03684 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -36,7 +36,7 @@
#include "xe_pt.h"
#include "xe_res_cursor.h"
#include "xe_sync.h"
-#include "xe_trace.h"
+#include "xe_trace_bo.h"
#include "xe_wa.h"
#include "xe_hmm.h"
@@ -83,10 +83,10 @@ static bool preempt_fences_waiting(struct xe_vm *vm)
lockdep_assert_held(&vm->lock);
xe_vm_assert_held(vm);
- list_for_each_entry(q, &vm->preempt.exec_queues, compute.link) {
- if (!q->compute.pfence ||
+ list_for_each_entry(q, &vm->preempt.exec_queues, lr.link) {
+ if (!q->lr.pfence ||
test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT,
- &q->compute.pfence->flags)) {
+ &q->lr.pfence->flags)) {
return true;
}
}
@@ -129,14 +129,14 @@ static int wait_for_existing_preempt_fences(struct xe_vm *vm)
xe_vm_assert_held(vm);
- list_for_each_entry(q, &vm->preempt.exec_queues, compute.link) {
- if (q->compute.pfence) {
- long timeout = dma_fence_wait(q->compute.pfence, false);
+ list_for_each_entry(q, &vm->preempt.exec_queues, lr.link) {
+ if (q->lr.pfence) {
+ long timeout = dma_fence_wait(q->lr.pfence, false);
if (timeout < 0)
return -ETIME;
- dma_fence_put(q->compute.pfence);
- q->compute.pfence = NULL;
+ dma_fence_put(q->lr.pfence);
+ q->lr.pfence = NULL;
}
}
@@ -148,7 +148,7 @@ static bool xe_vm_is_idle(struct xe_vm *vm)
struct xe_exec_queue *q;
xe_vm_assert_held(vm);
- list_for_each_entry(q, &vm->preempt.exec_queues, compute.link) {
+ list_for_each_entry(q, &vm->preempt.exec_queues, lr.link) {
if (!xe_exec_queue_is_idle(q))
return false;
}
@@ -161,17 +161,17 @@ static void arm_preempt_fences(struct xe_vm *vm, struct list_head *list)
struct list_head *link;
struct xe_exec_queue *q;
- list_for_each_entry(q, &vm->preempt.exec_queues, compute.link) {
+ list_for_each_entry(q, &vm->preempt.exec_queues, lr.link) {
struct dma_fence *fence;
link = list->next;
xe_assert(vm->xe, link != list);
fence = xe_preempt_fence_arm(to_preempt_fence_from_link(link),
- q, q->compute.context,
- ++q->compute.seqno);
- dma_fence_put(q->compute.pfence);
- q->compute.pfence = fence;
+ q, q->lr.context,
+ ++q->lr.seqno);
+ dma_fence_put(q->lr.pfence);
+ q->lr.pfence = fence;
}
}
@@ -180,27 +180,23 @@ static int add_preempt_fences(struct xe_vm *vm, struct xe_bo *bo)
struct xe_exec_queue *q;
int err;
+ xe_bo_assert_held(bo);
+
if (!vm->preempt.num_exec_queues)
return 0;
- err = xe_bo_lock(bo, true);
- if (err)
- return err;
-
err = dma_resv_reserve_fences(bo->ttm.base.resv, vm->preempt.num_exec_queues);
if (err)
- goto out_unlock;
+ return err;
- list_for_each_entry(q, &vm->preempt.exec_queues, compute.link)
- if (q->compute.pfence) {
+ list_for_each_entry(q, &vm->preempt.exec_queues, lr.link)
+ if (q->lr.pfence) {
dma_resv_add_fence(bo->ttm.base.resv,
- q->compute.pfence,
+ q->lr.pfence,
DMA_RESV_USAGE_BOOKKEEP);
}
-out_unlock:
- xe_bo_unlock(bo);
- return err;
+ return 0;
}
static void resume_and_reinstall_preempt_fences(struct xe_vm *vm,
@@ -211,10 +207,10 @@ static void resume_and_reinstall_preempt_fences(struct xe_vm *vm,
lockdep_assert_held(&vm->lock);
xe_vm_assert_held(vm);
- list_for_each_entry(q, &vm->preempt.exec_queues, compute.link) {
+ list_for_each_entry(q, &vm->preempt.exec_queues, lr.link) {
q->ops->resume(q);
- drm_gpuvm_resv_add_fence(&vm->gpuvm, exec, q->compute.pfence,
+ drm_gpuvm_resv_add_fence(&vm->gpuvm, exec, q->lr.pfence,
DMA_RESV_USAGE_BOOKKEEP, DMA_RESV_USAGE_BOOKKEEP);
}
}
@@ -238,16 +234,16 @@ int xe_vm_add_compute_exec_queue(struct xe_vm *vm, struct xe_exec_queue *q)
if (err)
goto out_up_write;
- pfence = xe_preempt_fence_create(q, q->compute.context,
- ++q->compute.seqno);
+ pfence = xe_preempt_fence_create(q, q->lr.context,
+ ++q->lr.seqno);
if (!pfence) {
err = -ENOMEM;
goto out_fini;
}
- list_add(&q->compute.link, &vm->preempt.exec_queues);
+ list_add(&q->lr.link, &vm->preempt.exec_queues);
++vm->preempt.num_exec_queues;
- q->compute.pfence = pfence;
+ q->lr.pfence = pfence;
down_read(&vm->userptr.notifier_lock);
@@ -284,12 +280,12 @@ void xe_vm_remove_compute_exec_queue(struct xe_vm *vm, struct xe_exec_queue *q)
return;
down_write(&vm->lock);
- list_del(&q->compute.link);
+ list_del(&q->lr.link);
--vm->preempt.num_exec_queues;
- if (q->compute.pfence) {
- dma_fence_enable_sw_signaling(q->compute.pfence);
- dma_fence_put(q->compute.pfence);
- q->compute.pfence = NULL;
+ if (q->lr.pfence) {
+ dma_fence_enable_sw_signaling(q->lr.pfence);
+ dma_fence_put(q->lr.pfence);
+ q->lr.pfence = NULL;
}
up_write(&vm->lock);
}
@@ -327,7 +323,7 @@ static void xe_vm_kill(struct xe_vm *vm, bool unlocked)
vm->flags |= XE_VM_FLAG_BANNED;
trace_xe_vm_kill(vm);
- list_for_each_entry(q, &vm->preempt.exec_queues, compute.link)
+ list_for_each_entry(q, &vm->preempt.exec_queues, lr.link)
q->ops->kill(q);
if (unlocked)
@@ -2140,7 +2136,7 @@ static struct xe_vma *new_vma(struct xe_vm *vm, struct drm_gpuva_op_map *op,
struct xe_bo *bo = op->gem.obj ? gem_to_xe_bo(op->gem.obj) : NULL;
struct drm_exec exec;
struct xe_vma *vma;
- int err;
+ int err = 0;
lockdep_assert_held_write(&vm->lock);
@@ -2165,23 +2161,22 @@ static struct xe_vma *new_vma(struct xe_vm *vm, struct drm_gpuva_op_map *op,
vma = xe_vma_create(vm, bo, op->gem.offset,
op->va.addr, op->va.addr +
op->va.range - 1, pat_index, flags);
- if (bo)
- drm_exec_fini(&exec);
+ if (IS_ERR(vma))
+ goto err_unlock;
- if (xe_vma_is_userptr(vma)) {
+ if (xe_vma_is_userptr(vma))
err = xe_vma_userptr_pin_pages(to_userptr_vma(vma));
- if (err) {
- prep_vma_destroy(vm, vma, false);
- xe_vma_destroy_unlocked(vma);
- return ERR_PTR(err);
- }
- } else if (!xe_vma_has_no_bo(vma) && !bo->vm) {
+ else if (!xe_vma_has_no_bo(vma) && !bo->vm)
err = add_preempt_fences(vm, bo);
- if (err) {
- prep_vma_destroy(vm, vma, false);
- xe_vma_destroy_unlocked(vma);
- return ERR_PTR(err);
- }
+
+err_unlock:
+ if (bo)
+ drm_exec_fini(&exec);
+
+ if (err) {
+ prep_vma_destroy(vm, vma, false);
+ xe_vma_destroy_unlocked(vma);
+ vma = ERR_PTR(err);
}
return vma;
diff --git a/drivers/gpu/drm/xe/xe_wa.c b/drivers/gpu/drm/xe/xe_wa.c
index 26b170a0cdc7..c7bf0862b231 100644
--- a/drivers/gpu/drm/xe/xe_wa.c
+++ b/drivers/gpu/drm/xe/xe_wa.c
@@ -21,6 +21,7 @@
#include "xe_mmio.h"
#include "xe_platform_types.h"
#include "xe_rtp.h"
+#include "xe_sriov.h"
#include "xe_step.h"
/**
@@ -629,7 +630,7 @@ static const struct xe_rtp_entry_sr lrc_was[] = {
XE_RTP_ACTIONS(SET(CACHE_MODE_1, MSAA_OPTIMIZATION_REDUC_DISABLE))
},
{ XE_RTP_NAME("14019877138"),
- XE_RTP_RULES(GRAPHICS_VERSION_RANGE(1270, 1271), ENGINE_CLASS(RENDER)),
+ XE_RTP_RULES(GRAPHICS_VERSION_RANGE(1270, 1274), ENGINE_CLASS(RENDER)),
XE_RTP_ACTIONS(SET(XEHP_PSS_CHICKEN, FD_END_COLLECT))
},
@@ -678,9 +679,19 @@ static const struct xe_rtp_entry_sr lrc_was[] = {
XE_RTP_ACTIONS(SET(CHICKEN_RASTER_2, TBIMR_FAST_CLIP))
},
{ XE_RTP_NAME("14020756599"),
- XE_RTP_RULES(GRAPHICS_VERSION(2004), ENGINE_CLASS(RENDER)),
+ XE_RTP_RULES(GRAPHICS_VERSION(2004), ENGINE_CLASS(RENDER), OR,
+ MEDIA_VERSION_ANY_GT(2000), ENGINE_CLASS(RENDER)),
XE_RTP_ACTIONS(SET(WM_CHICKEN3, HIZ_PLANE_COMPRESSION_DIS))
},
+ { XE_RTP_NAME("14021490052"),
+ XE_RTP_RULES(GRAPHICS_VERSION(2004), ENGINE_CLASS(RENDER)),
+ XE_RTP_ACTIONS(SET(FF_MODE,
+ DIS_MESH_PARTIAL_AUTOSTRIP |
+ DIS_MESH_AUTOSTRIP),
+ SET(VFLSKPD,
+ DIS_PARTIAL_AUTOSTRIP |
+ DIS_AUTOSTRIP))
+ },
/* Xe2_HPG */
{ XE_RTP_NAME("15010599737"),
@@ -705,13 +716,6 @@ static const struct xe_rtp_entry_sr lrc_was[] = {
DIS_AUTOSTRIP))
},
- /* Xe2_LPM */
-
- { XE_RTP_NAME("14020756599"),
- XE_RTP_RULES(ENGINE_CLASS(RENDER), FUNC(xe_rtp_match_when_media2000)),
- XE_RTP_ACTIONS(SET(WM_CHICKEN3, HIZ_PLANE_COMPRESSION_DIS))
- },
-
{}
};
@@ -862,6 +866,9 @@ void xe_wa_apply_tile_workarounds(struct xe_tile *tile)
{
struct xe_gt *mmio = tile->primary_gt;
+ if (IS_SRIOV_VF(tile->xe))
+ return;
+
if (XE_WA(mmio, 22010954014))
xe_mmio_rmw32(mmio, XEHP_CLOCK_GATE_DIS, 0, SGSI_SIDECLK_DIS);
}
diff --git a/drivers/gpu/drm/xe/xe_wa.h b/drivers/gpu/drm/xe/xe_wa.h
index 1b24d66f9d80..db9ddeaf69bf 100644
--- a/drivers/gpu/drm/xe/xe_wa.h
+++ b/drivers/gpu/drm/xe/xe_wa.h
@@ -17,8 +17,6 @@ void xe_wa_process_gt(struct xe_gt *gt);
void xe_wa_process_engine(struct xe_hw_engine *hwe);
void xe_wa_process_lrc(struct xe_hw_engine *hwe);
void xe_wa_apply_tile_workarounds(struct xe_tile *tile);
-
-void xe_reg_whitelist_process_engine(struct xe_hw_engine *hwe);
void xe_wa_dump(struct xe_gt *gt, struct drm_printer *p);
/**
diff --git a/drivers/gpu/drm/xe/xe_wa_oob.rules b/drivers/gpu/drm/xe/xe_wa_oob.rules
index 12fe88796a49..26066beb4f6f 100644
--- a/drivers/gpu/drm/xe/xe_wa_oob.rules
+++ b/drivers/gpu/drm/xe/xe_wa_oob.rules
@@ -27,3 +27,5 @@
16022287689 GRAPHICS_VERSION(2001)
GRAPHICS_VERSION(2004)
13011645652 GRAPHICS_VERSION(2004)
+22019338487 MEDIA_VERSION(2000)
+ GRAPHICS_VERSION(2001)
diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp.c b/drivers/gpu/drm/xlnx/zynqmp_disp.c
index c9fb432d4cbd..9368acf56eaf 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_disp.c
+++ b/drivers/gpu/drm/xlnx/zynqmp_disp.c
@@ -141,24 +141,18 @@ struct zynqmp_disp_layer {
* struct zynqmp_disp - Display controller
* @dev: Device structure
* @dpsub: Display subsystem
- * @blend.base: Register I/O base address for the blender
- * @avbuf.base: Register I/O base address for the audio/video buffer manager
- * @audio.base: Registers I/O base address for the audio mixer
+ * @blend: Register I/O base address for the blender
+ * @avbuf: Register I/O base address for the audio/video buffer manager
+ * @audio: Registers I/O base address for the audio mixer
* @layers: Layers (planes)
*/
struct zynqmp_disp {
struct device *dev;
struct zynqmp_dpsub *dpsub;
- struct {
- void __iomem *base;
- } blend;
- struct {
- void __iomem *base;
- } avbuf;
- struct {
- void __iomem *base;
- } audio;
+ void __iomem *blend;
+ void __iomem *avbuf;
+ void __iomem *audio;
struct zynqmp_disp_layer layers[ZYNQMP_DPSUB_NUM_LAYERS];
};
@@ -410,12 +404,12 @@ static const struct zynqmp_disp_format avbuf_live_fmts[] = {
static u32 zynqmp_disp_avbuf_read(struct zynqmp_disp *disp, int reg)
{
- return readl(disp->avbuf.base + reg);
+ return readl(disp->avbuf + reg);
}
static void zynqmp_disp_avbuf_write(struct zynqmp_disp *disp, int reg, u32 val)
{
- writel(val, disp->avbuf.base + reg);
+ writel(val, disp->avbuf + reg);
}
static bool zynqmp_disp_layer_is_video(const struct zynqmp_disp_layer *layer)
@@ -651,7 +645,7 @@ static void zynqmp_disp_avbuf_disable(struct zynqmp_disp *disp)
static void zynqmp_disp_blend_write(struct zynqmp_disp *disp, int reg, u32 val)
{
- writel(val, disp->blend.base + reg);
+ writel(val, disp->blend + reg);
}
/*
@@ -877,7 +871,7 @@ static void zynqmp_disp_blend_layer_disable(struct zynqmp_disp *disp,
static void zynqmp_disp_audio_write(struct zynqmp_disp *disp, int reg, u32 val)
{
- writel(val, disp->audio.base + reg);
+ writel(val, disp->audio + reg);
}
/**
@@ -1412,21 +1406,21 @@ int zynqmp_disp_probe(struct zynqmp_dpsub *dpsub)
disp->dev = &pdev->dev;
disp->dpsub = dpsub;
- disp->blend.base = devm_platform_ioremap_resource_byname(pdev, "blend");
- if (IS_ERR(disp->blend.base)) {
- ret = PTR_ERR(disp->blend.base);
+ disp->blend = devm_platform_ioremap_resource_byname(pdev, "blend");
+ if (IS_ERR(disp->blend)) {
+ ret = PTR_ERR(disp->blend);
goto error;
}
- disp->avbuf.base = devm_platform_ioremap_resource_byname(pdev, "av_buf");
- if (IS_ERR(disp->avbuf.base)) {
- ret = PTR_ERR(disp->avbuf.base);
+ disp->avbuf = devm_platform_ioremap_resource_byname(pdev, "av_buf");
+ if (IS_ERR(disp->avbuf)) {
+ ret = PTR_ERR(disp->avbuf);
goto error;
}
- disp->audio.base = devm_platform_ioremap_resource_byname(pdev, "aud");
- if (IS_ERR(disp->audio.base)) {
- ret = PTR_ERR(disp->audio.base);
+ disp->audio = devm_platform_ioremap_resource_byname(pdev, "aud");
+ if (IS_ERR(disp->audio)) {
+ ret = PTR_ERR(disp->audio);
goto error;
}
diff --git a/drivers/gpu/drm/xlnx/zynqmp_dp.c b/drivers/gpu/drm/xlnx/zynqmp_dp.c
index 8c2d24809014..129beac4c073 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_dp.c
+++ b/drivers/gpu/drm/xlnx/zynqmp_dp.c
@@ -256,10 +256,10 @@ struct zynqmp_dp_link_config {
* @fmt: format identifier string
*/
struct zynqmp_dp_mode {
+ const char *fmt;
+ int pclock;
u8 bw_code;
u8 lane_cnt;
- int pclock;
- const char *fmt;
};
/**
@@ -296,27 +296,27 @@ struct zynqmp_dp_config {
* @train_set: set of training data
*/
struct zynqmp_dp {
+ struct drm_dp_aux aux;
+ struct drm_bridge bridge;
+ struct work_struct hpd_work;
+
+ struct drm_bridge *next_bridge;
struct device *dev;
struct zynqmp_dpsub *dpsub;
void __iomem *iomem;
struct reset_control *reset;
- int irq;
-
- struct drm_bridge bridge;
- struct drm_bridge *next_bridge;
-
- struct zynqmp_dp_config config;
- struct drm_dp_aux aux;
struct phy *phy[ZYNQMP_DP_MAX_LANES];
- u8 num_lanes;
- struct delayed_work hpd_work;
+
enum drm_connector_status status;
+ int irq;
bool enabled;
- u8 dpcd[DP_RECEIVER_CAP_SIZE];
- struct zynqmp_dp_link_config link_config;
struct zynqmp_dp_mode mode;
+ struct zynqmp_dp_link_config link_config;
+ struct zynqmp_dp_config config;
+ u8 dpcd[DP_RECEIVER_CAP_SIZE];
u8 train_set[ZYNQMP_DP_MAX_LANES];
+ u8 num_lanes;
};
static inline struct zynqmp_dp *bridge_to_dp(struct drm_bridge *bridge)
@@ -606,28 +606,21 @@ static void zynqmp_dp_adjust_train(struct zynqmp_dp *dp,
u8 link_status[DP_LINK_STATUS_SIZE])
{
u8 *train_set = dp->train_set;
- u8 voltage = 0, preemphasis = 0;
u8 i;
for (i = 0; i < dp->mode.lane_cnt; i++) {
- u8 v = drm_dp_get_adjust_request_voltage(link_status, i);
- u8 p = drm_dp_get_adjust_request_pre_emphasis(link_status, i);
+ u8 voltage = drm_dp_get_adjust_request_voltage(link_status, i);
+ u8 preemphasis =
+ drm_dp_get_adjust_request_pre_emphasis(link_status, i);
- if (v > voltage)
- voltage = v;
+ if (voltage >= DP_TRAIN_VOLTAGE_SWING_LEVEL_3)
+ voltage |= DP_TRAIN_MAX_SWING_REACHED;
- if (p > preemphasis)
- preemphasis = p;
- }
+ if (preemphasis >= DP_TRAIN_PRE_EMPH_LEVEL_2)
+ preemphasis |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
- if (voltage >= DP_TRAIN_VOLTAGE_SWING_LEVEL_3)
- voltage |= DP_TRAIN_MAX_SWING_REACHED;
-
- if (preemphasis >= DP_TRAIN_PRE_EMPH_LEVEL_2)
- preemphasis |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
-
- for (i = 0; i < dp->mode.lane_cnt; i++)
train_set[i] = voltage | preemphasis;
+ }
}
/**
@@ -1007,7 +1000,7 @@ zynqmp_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
msg->buffer, msg->size,
&msg->reply);
if (!ret) {
- dev_dbg(dp->dev, "aux %d retries\n", i);
+ dev_vdbg(dp->dev, "aux %d retries\n", i);
return msg->size;
}
@@ -1489,7 +1482,7 @@ static void zynqmp_dp_bridge_atomic_disable(struct drm_bridge *bridge,
struct zynqmp_dp *dp = bridge_to_dp(bridge);
dp->enabled = false;
- cancel_delayed_work(&dp->hpd_work);
+ cancel_work(&dp->hpd_work);
zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_ENABLE, 0);
drm_dp_dpcd_writeb(&dp->aux, DP_SET_POWER, DP_SET_POWER_D3);
zynqmp_dp_write(dp, ZYNQMP_DP_TX_PHY_POWER_DOWN,
@@ -1655,8 +1648,7 @@ void zynqmp_dp_disable_vblank(struct zynqmp_dp *dp)
static void zynqmp_dp_hpd_work_func(struct work_struct *work)
{
- struct zynqmp_dp *dp = container_of(work, struct zynqmp_dp,
- hpd_work.work);
+ struct zynqmp_dp *dp = container_of(work, struct zynqmp_dp, hpd_work);
enum drm_connector_status status;
status = zynqmp_dp_bridge_detect(&dp->bridge);
@@ -1692,7 +1684,7 @@ static irqreturn_t zynqmp_dp_irq_handler(int irq, void *data)
zynqmp_dpsub_drm_handle_vblank(dp->dpsub);
if (status & ZYNQMP_DP_INT_HPD_EVENT)
- schedule_delayed_work(&dp->hpd_work, 0);
+ schedule_work(&dp->hpd_work);
if (status & ZYNQMP_DP_INT_HPD_IRQ) {
int ret;
@@ -1734,7 +1726,7 @@ int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub)
dp->dpsub = dpsub;
dp->status = connector_status_disconnected;
- INIT_DELAYED_WORK(&dp->hpd_work, zynqmp_dp_hpd_work_func);
+ INIT_WORK(&dp->hpd_work, zynqmp_dp_hpd_work_func);
/* Acquire all resources (IOMEM, IRQ and PHYs). */
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dp");
@@ -1839,7 +1831,7 @@ void zynqmp_dp_remove(struct zynqmp_dpsub *dpsub)
zynqmp_dp_write(dp, ZYNQMP_DP_INT_DS, ZYNQMP_DP_INT_ALL);
disable_irq(dp->irq);
- cancel_delayed_work_sync(&dp->hpd_work);
+ cancel_work_sync(&dp->hpd_work);
zynqmp_dp_write(dp, ZYNQMP_DP_TRANSMITTER_ENABLE, 0);
zynqmp_dp_write(dp, ZYNQMP_DP_INT_DS, 0xffffffff);
diff --git a/drivers/gpu/drm/xlnx/zynqmp_dpsub.c b/drivers/gpu/drm/xlnx/zynqmp_dpsub.c
index face8d6b2a6f..f5781939de9c 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_dpsub.c
+++ b/drivers/gpu/drm/xlnx/zynqmp_dpsub.c
@@ -269,6 +269,7 @@ static int zynqmp_dpsub_probe(struct platform_device *pdev)
return 0;
err_disp:
+ drm_bridge_remove(dpsub->bridge);
zynqmp_disp_remove(dpsub);
err_dp:
zynqmp_dp_remove(dpsub);
diff --git a/drivers/gpu/drm/xlnx/zynqmp_dpsub.h b/drivers/gpu/drm/xlnx/zynqmp_dpsub.h
index 09ea01878f2a..b18554467e9c 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_dpsub.h
+++ b/drivers/gpu/drm/xlnx/zynqmp_dpsub.h
@@ -53,6 +53,7 @@ enum zynqmp_dpsub_format {
* @drm: The DRM/KMS device data
* @bridge: The DP encoder bridge
* @disp: The display controller
+ * @layers: Video and graphics layers
* @dp: The DisplayPort controller
* @dma_align: DMA alignment constraint (must be a power of 2)
*/
diff --git a/drivers/gpu/drm/xlnx/zynqmp_kms.c b/drivers/gpu/drm/xlnx/zynqmp_kms.c
index 43bf416b33d5..bd1368df7870 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_kms.c
+++ b/drivers/gpu/drm/xlnx/zynqmp_kms.c
@@ -120,9 +120,13 @@ static void zynqmp_dpsub_plane_atomic_update(struct drm_plane *plane,
zynqmp_disp_blend_set_global_alpha(dpsub->disp, true,
plane->state->alpha >> 8);
- /* Enable or re-enable the plane if the format has changed. */
- if (format_changed)
- zynqmp_disp_layer_enable(layer);
+ /*
+ * Unconditionally enable the layer, as it may have been disabled
+ * previously either explicitly to reconfigure layer format, or
+ * implicitly after DPSUB reset during display mode change. DRM
+ * framework calls this callback for enabled planes only.
+ */
+ zynqmp_disp_layer_enable(layer);
}
static const struct drm_plane_helper_funcs zynqmp_dpsub_plane_helper_funcs = {
@@ -433,23 +437,28 @@ static int zynqmp_dpsub_kms_init(struct zynqmp_dpsub *dpsub)
DRM_BRIDGE_ATTACH_NO_CONNECTOR);
if (ret) {
dev_err(dpsub->dev, "failed to attach bridge to encoder\n");
- return ret;
+ goto err_encoder;
}
/* Create the connector for the chain of bridges. */
connector = drm_bridge_connector_init(&dpsub->drm->dev, encoder);
if (IS_ERR(connector)) {
dev_err(dpsub->dev, "failed to created connector\n");
- return PTR_ERR(connector);
+ ret = PTR_ERR(connector);
+ goto err_encoder;
}
ret = drm_connector_attach_encoder(connector, encoder);
if (ret < 0) {
dev_err(dpsub->dev, "failed to attach connector to encoder\n");
- return ret;
+ goto err_encoder;
}
return 0;
+
+err_encoder:
+ drm_encoder_cleanup(encoder);
+ return ret;
}
static void zynqmp_dpsub_drm_release(struct drm_device *drm, void *res)
@@ -529,5 +538,6 @@ void zynqmp_dpsub_drm_cleanup(struct zynqmp_dpsub *dpsub)
drm_dev_unregister(drm);
drm_atomic_helper_shutdown(drm);
+ drm_encoder_cleanup(&dpsub->drm->encoder);
drm_kms_helper_poll_fini(drm);
}
diff --git a/drivers/gpu/drm/xlnx/zynqmp_kms.h b/drivers/gpu/drm/xlnx/zynqmp_kms.h
index 01be96b00e3f..cb13c6b8008e 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_kms.h
+++ b/drivers/gpu/drm/xlnx/zynqmp_kms.h
@@ -22,9 +22,9 @@
struct zynqmp_dpsub;
/**
- * struct zynqmp_dpsub - ZynqMP DisplayPort Subsystem DRM/KMS data
+ * struct zynqmp_dpsub_drm - ZynqMP DisplayPort Subsystem DRM/KMS data
* @dpsub: Backpointer to the DisplayPort subsystem
- * @drm: The DRM/KMS device
+ * @dev: The DRM/KMS device
* @planes: The DRM planes
* @crtc: The DRM CRTC
* @encoder: The dummy DRM encoder